realtek bt bringup
authorWeiguo Hu <hwg@rock-chips.com>
Mon, 30 Jul 2018 08:30:00 +0000 (16:30 +0800)
committerWeiguo Hu <hwg@rock-chips.com>
Tue, 31 Jul 2018 01:32:18 +0000 (09:32 +0800)
Change-Id: Iebf72692e2f20657aecfbe3e9e30fed6285f8774
Signed-off-by: Weiguo Hu <hwg@rock-chips.com>
71 files changed:
rtkbt/code/libbt-vendor/Android.mk [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/codec/msbc/sbc.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/msbc/sbc.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/msbc/sbc_math.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/msbc/sbc_tables.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/include/bt_list.h [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/include/bt_skbuff.h [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/include/bt_vendor_rtk.h [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/include/hardware.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/include/hci_h5_int.h [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/include/rtk_btservice.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/include/rtk_btsnoop_net.h [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/include/rtk_hcidefs.h [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/include/rtk_parse.h [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/include/rtk_poll.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/include/rtk_socket.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/include/unused.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/include/upio.h [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/include/userial_vendor.h [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/include/vnd_buildcfg.h [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/src/bt_list.c [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/src/bt_skbuff.c [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/src/bt_vendor_rtk.c [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/src/hardware.c [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/src/hardware_uart.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/src/hardware_usb.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/src/hci_h5.c [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/src/rtk_btservice.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/src/rtk_btsnoop_net.c [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/src/rtk_heartbeat.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/src/rtk_parse.c [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/src/rtk_poll.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/src/rtk_socket.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/src/upio.c [changed mode: 0644->0755]
rtkbt/code/libbt-vendor/src/userial_vendor.c [changed mode: 0644->0755]
rtkbt/code/rtkcmd/Android.mk [new file with mode: 0755]
rtkbt/code/rtkcmd/rtkcmd.c [new file with mode: 0755]
rtkbt/rtkbt.mk [changed mode: 0644->0755]
rtkbt/vendor/firmware_box/fw_info.txt [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723b_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723b_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723bs_VQ0_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723bs_VQ0_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723bs_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723bs_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723bu_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723d_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723d_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723ds_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8723ds_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8761a_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8761a_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8761at_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8761at_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8761au8192ee_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8761au8812ae_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8761au_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8761aw8192eu_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8761aw8192eu_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8821a_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8821a_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8821as_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8821as_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8821c_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8821c_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8821cs_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8821cs_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8822b_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8822b_fw [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8822bs_config [new file with mode: 0755]
rtkbt/vendor/firmware_box/rtl8822bs_fw [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index 1945150..ea5fdb6
@@ -5,6 +5,8 @@ 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 \
@@ -13,10 +15,16 @@ LOCAL_SRC_FILES := \
         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 := \
@@ -28,6 +36,5 @@ LOCAL_MODULE := libbt-vendor-realtek
 LOCAL_MODULE_TAGS := optional
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_CPPFLAGS := -Werror -Wunused-parameter
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/rtkbt/code/libbt-vendor/codec/msbc/sbc.c b/rtkbt/code/libbt-vendor/codec/msbc/sbc.c
new file mode 100755 (executable)
index 0000000..e138e9d
--- /dev/null
@@ -0,0 +1,1763 @@
+/*
+ *
+ *  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
new file mode 100755 (executable)
index 0000000..5e74751
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *
+ *  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
new file mode 100755 (executable)
index 0000000..d620822
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *
+ *  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
new file mode 100755 (executable)
index 0000000..f532cec
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ *
+ *  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) }
+};
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index d252976..3a3eca6
@@ -41,6 +41,7 @@
 #ifndef BT_SKBUFF_H
 #define BT_SKBUFF_H
 #include "bt_list.h"
+#include <stdbool.h>
 
 #ifndef EXTERN
 #define EXTERN
@@ -335,12 +336,11 @@ RtbQueueNextNode(
 /**
     check whether queue is empty
 */
-EXTERN unsigned char
+EXTERN bool
 RtbQueueIsEmpty(
    IN RTB_QUEUE_HEAD* RtkQueueHead
 );
 
-
 //annie_tmp
 EXTERN unsigned char
 RtbCheckQueueLen(
old mode 100644 (file)
new mode 100755 (executable)
index 7146c7a..b027fd9
 #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)
 
 /* Device port name where Bluetooth controller attached */
 #ifndef BLUETOOTH_UART_DEVICE_PORT
-#define BLUETOOTH_UART_DEVICE_PORT      "/dev/ttyO1"    /* maguro */
+#define BLUETOOTH_UART_DEVICE_PORT      "/dev/ttyS1"    /* maguro */
 #endif
 
 /* Location of firmware patch files */
  *  firmware patchram (.hcd) file.
  */
 #ifndef USE_CONTROLLER_BDADDR
-#define USE_CONTROLLER_BDADDR   FALSE
+#define USE_CONTROLLER_BDADDR   TRUE //FALSE
 #endif
 
 /* sleep mode
diff --git a/rtkbt/code/libbt-vendor/include/hardware.h b/rtkbt/code/libbt-vendor/include/hardware.h
new file mode 100755 (executable)
index 0000000..016d15f
--- /dev/null
@@ -0,0 +1,197 @@
+#ifndef HARDWARE_H
+#define HARDWARE_H
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define cpu_to_le16(d)  (d)
+#define cpu_to_le32(d)  (d)
+#define le16_to_cpu(d)  (d)
+#define le32_to_cpu(d)  (d)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define cpu_to_le16(d)  bswap_16(d)
+#define cpu_to_le32(d)  bswap_32(d)
+#define le16_to_cpu(d)  bswap_16(d)
+#define le32_to_cpu(d)  bswap_32(d)
+#else
+#error "Unknown byte order"
+#endif
+
+#define FIRMWARE_DIRECTORY  "/vendor//etc/firmware/%s"
+#define BT_CONFIG_DIRECTORY "/vendor/etc/firmware/%s"
+#define PATCH_DATA_FIELD_MAX_SIZE       252
+#define RTK_VENDOR_CONFIG_MAGIC         0x8723ab55
+#define MAX_PATCH_SIZE_24K            (1024*24)   //24K
+#define MAX_PATCH_SIZE_40K            (1024*40)   //40K
+
+#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;
+    uint8_t entry_data[0];
+} __attribute__ ((packed));
+
+struct rtk_bt_vendor_config{
+    uint32_t signature;
+    uint16_t data_len;
+    struct rtk_bt_vendor_config_entry entry[0];
+} __attribute__ ((packed));
+
+#define HCI_CMD_MAX_LEN             258
+
+#define HCI_VERSION_MASK_10     (1<<0)     //Bluetooth Core Spec 1.0b
+#define HCI_VERSION_MASK_11     (1<<1)     //Bluetooth Core Spec 1.1
+#define HCI_VERSION_MASK_12     (1<<2)     //Bluetooth Core Spec 1.2
+#define HCI_VERSION_MASK_20     (1<<3)     //Bluetooth Core Spec 2.0+EDR
+#define HCI_VERSION_MASK_21     (1<<4)     //Bluetooth Core Spec 2.1+EDR
+#define HCI_VERSION_MASK_30     (1<<5)     //Bluetooth Core Spec 3.0+HS
+#define HCI_VERSION_MASK_40     (1<<6)     //Bluetooth Core Spec 4.0
+#define HCI_VERSION_MASK_41     (1<<7)     //Bluetooth Core Spec 4.1
+#define HCI_VERSION_MASK_42     (1<<8)     //Bluetooth Core Spec 4.2
+#define HCI_VERSION_MASK_ALL    (0xFFFFFFFF)
+
+#define HCI_REVISION_MASK_ALL   (0xFFFFFFFF)
+
+#define LMP_SUBVERSION_NONE     (0x0)
+#define LMPSUBVERSION_8723a     (0x1200)
+
+#define CHIPTYPE_NONE           (0x1F)      //Chip Type's range: 0x0 ~ 0xF
+#define CHIP_TYPE_MASK_ALL      (0xFFFFFFFF)
+
+#define PROJECT_ID_MASK_ALL     (0xFFFFFFFF)    // temp used for unknow project id for a new chip
+
+#define PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE   (0x1)
+
+#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 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
+
+#define HCI_EVT_CMD_CMPL_OP1001_HCI_VERSION_OFFSET     (6)     //HCI_Version's offset in COMMAND Completed Event for OpCode 0x1001(Read Local Version Information Command)
+#define HCI_EVT_CMD_CMPL_OP1001_HCI_REVISION_OFFSET     (7)     //HCI_Revision's offset in COMMAND Completed Event for OpCode 0x1001(Read Local Version Information Command)
+#define HCI_EVT_CMD_CMPL_OP1001_LMP_SUBVERSION_OFFSET  (12)    //LMP Subversion's offset in COMMAND Completed Event for OpCode 0x1001(Read Local Version Information Command)
+#define HCI_EVT_CMD_CMPL_OP0C14_LOCAL_NAME_OFFSET      (6)     //Local Name's offset in COMMAND Completed Event for OpCode 0x0C14(Read Local Name Command)
+#define HCI_EVT_CMD_CMPL_OP1009_BDADDR_OFFSET    (6)     //BD_ADDR's offset in COMMAND Completed Event for OpCode 0x1009(Read BD_ADDR Command)
+#define HCI_EVT_CMD_CMPL_OPFC6D_EVERSION_OFFSET        (6)  //eversion's offset in COMMAND Completed Event for OpCode 0xfc6d(Read eVERSION Vendor Command)
+#define HCI_EVT_CMD_CMPL_OPFC61_CHIPTYPE_OFFSET        (6)  //chip type's offset in COMMAND Completed Event for OpCode 0xfc61(Read ChipType Vendor Command)
+
+//#define UPDATE_BAUDRATE_CMD_PARAM_SIZE          (6)
+#define HCI_CMD_PREAMBLE_SIZE                   (3)
+#define HCI_CMD_READ_CHIP_TYPE_SIZE             (5)
+//#define HCD_REC_PAYLOAD_LEN_BYTE                (2)
+//#define BD_ADDR_LEN                             (6)
+//#define LOCAL_NAME_BUFFER_LEN                   (32)
+//#define LOCAL_BDADDR_PATH_BUFFER_LEN            (256)
+
+#define H5_SYNC_REQ_SIZE (2)
+#define H5_SYNC_RESP_SIZE (2)
+#define H5_CONF_REQ_SIZE (3)
+#define H5_CONF_RESP_SIZE (2)
+
+/******************************************************************************
+**  Local type definitions
+******************************************************************************/
+
+/* Hardware Configuration State */
+enum {
+    HW_CFG_H5_INIT = 1,
+    HW_CFG_READ_LOCAL_VER,
+    HW_CFG_READ_ECO_VER,   //eco version
+    HW_CFG_READ_CHIP_TYPE,
+    HW_CFG_START,
+    HW_CFG_SET_UART_BAUD_HOST,//change FW baudrate
+    HW_CFG_SET_UART_BAUD_CONTROLLER,//change Host baudrate
+    HW_CFG_SET_UART_HW_FLOW_CONTROL,
+    HW_CFG_RESET_CHANNEL_CONTROLLER,
+    HW_RESET_CONTROLLER,
+    HARDWARE_INIT_COMPLETE,
+    HW_CFG_DL_FW_PATCH
+};
+
+/* h/w config control block */
+typedef struct
+{
+    uint32_t    max_patch_size;
+    uint32_t    baudrate;
+    uint16_t    lmp_subversion;
+    uint16_t    lmp_subversion_default;
+    uint16_t    lmp_sub_current;
+    uint8_t     state;          /* Hardware configuration state */
+    uint8_t     eversion;
+    uint32_t    project_id_mask;
+    uint8_t     hci_version;
+    uint8_t     hci_revision;
+    uint8_t     chip_type;
+    uint8_t     dl_fw_flag;
+    int         fw_len;          /* FW patch file len */
+    size_t         config_len;      /* Config patch file len */
+    unsigned int         total_len;       /* FW & config extracted buf len */
+    uint8_t     *fw_buf;         /* FW patch file buf */
+    uint8_t     *config_buf;     /* Config patch file buf */
+    uint8_t     *total_buf;      /* FW & config extracted buf */
+    uint8_t     patch_frag_cnt;  /* Patch fragment count download */
+    uint8_t     patch_frag_idx;  /* Current patch fragment index */
+    uint8_t     patch_frag_len;  /* Patch fragment length */
+    uint8_t     patch_frag_tail; /* Last patch fragment length */
+    uint8_t     hw_flow_cntrl;   /* Uart flow control, bit7:set, bit0:enable */
+    uint16_t    vid;   /* usb vendor id */
+    uint16_t    pid;   /* usb product id */
+    uint8_t     heartbeat; /*heartbeat*/
+} bt_hw_cfg_cb_t;
+
+/* low power mode parameters */
+typedef struct
+{
+    uint8_t sleep_mode;                     /* 0(disable),1(UART),9(H5) */
+    uint8_t host_stack_idle_threshold;      /* Unit scale 300ms/25ms */
+    uint8_t host_controller_idle_threshold; /* Unit scale 300ms/25ms */
+    uint8_t bt_wake_polarity;               /* 0=Active Low, 1= Active High */
+    uint8_t host_wake_polarity;             /* 0=Active Low, 1= Active High */
+    uint8_t allow_host_sleep_during_sco;
+    uint8_t combine_sleep_mode_and_lpm;
+    uint8_t enable_uart_txd_tri_state;      /* UART_TXD Tri-State */
+    uint8_t sleep_guard_time;               /* sleep guard time in 12.5ms */
+    uint8_t wakeup_guard_time;              /* wakeup guard time in 12.5ms */
+    uint8_t txd_config;                     /* TXD is high in sleep state */
+    uint8_t pulsed_host_wake;               /* pulsed host wake if mode = 1 */
+} bt_lpm_param_t;
+
+#define ROM_LMP_NONE                0x0000
+#define ROM_LMP_8723a               0x1200
+#define ROM_LMP_8723b               0x8723
+#define ROM_LMP_8821a               0X8821
+#define ROM_LMP_8761a               0X8761
+#define ROM_LMP_8703a               0x8723
+#define ROM_LMP_8763a               0x8763
+#define ROM_LMP_8703b               0x8703
+#define ROM_LMP_8723c               0x8703
+#define ROM_LMP_8822b               0x8822
+#define ROM_LMP_8723d               0x8723
+#define ROM_LMP_8821c               0x8821
+
+struct rtk_epatch_entry{
+    uint16_t chip_id;
+    uint16_t patch_length;
+    uint32_t patch_offset;
+    uint32_t svn_version;
+    uint32_t coex_version;
+} __attribute__ ((packed));
+
+struct rtk_epatch{
+    uint8_t signature[8];
+    uint32_t fw_version;
+    uint16_t number_of_patch;
+    struct rtk_epatch_entry entry[0];
+} __attribute__ ((packed));
+
+
+
+
+#endif
old mode 100644 (file)
new mode 100755 (executable)
index 99311c2..6d62c9b
@@ -43,6 +43,9 @@
 #define HCI_VSC_SET_WAKE_UP_DEVICE      0xFC7B
 #define HCI_VSC_BT_OFF                  0xFC28
 #define HCI_READ_LMP_VERSION            0x1001
+#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);}
diff --git a/rtkbt/code/libbt-vendor/include/rtk_btservice.h b/rtkbt/code/libbt-vendor/include/rtk_btservice.h
new file mode 100755 (executable)
index 0000000..f8529bb
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef RTK_BTSERVICE_H
+#define RTK_BTSERVICE_H
+
+#include <stdio.h>
+#include <cutils/log.h>
+
+#define HCI_RTKBT_AUTOPAIR_EVT                               0x30
+
+#define STREAM_TO_UINT8(u8, p) \
+      {                            \
+              (u8) = (uint8_t)(*(p));    \
+              (p) += 1;                  \
+            }
+
+
+#endif
+
+
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index f2dcc27..4de047c
@@ -87,7 +87,7 @@ typedef struct rtk_parse_manager_t {
 
 }rtk_parse_manager_t;
 
-const rtk_parse_manager_t *rtk_parse_manager_get_interface();
+rtk_parse_manager_t *rtk_parse_manager_get_interface();
 
 #ifdef __LITTLE_ENDIAN
 struct sbc_frame_hdr {
diff --git a/rtkbt/code/libbt-vendor/include/rtk_poll.h b/rtkbt/code/libbt-vendor/include/rtk_poll.h
new file mode 100755 (executable)
index 0000000..c449d24
--- /dev/null
@@ -0,0 +1,34 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Realtek, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "bt_vendor_lib.h"
+
+typedef void (*timed_out)(union sigval arg);
+
+
+void poll_init(timed_out ptr_timeout,uint32_t timeout);
+
+void poll_cleanup(void);
+
+void poll_enable(uint8_t turn_on);
+
+void poll_timer_flush(void);
diff --git a/rtkbt/code/libbt-vendor/include/rtk_socket.h b/rtkbt/code/libbt-vendor/include/rtk_socket.h
new file mode 100755 (executable)
index 0000000..b878559
--- /dev/null
@@ -0,0 +1,73 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Filename:      userial_vendor.h
+ *
+ *  Description:   Contains vendor-specific definitions used in serial port
+ *                 controls
+ *
+ ******************************************************************************/
+
+#ifndef RTK_SOCKET_H
+#define RTK_SOCKET_H
+
+#include "bt_vendor_rtk.h"
+#include "userial.h"
+#include <sys/poll.h>
+#include <assert.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/prctl.h>
+#include <sys/un.h>
+
+
+#ifdef CONFIG_SCO_OVER_HCI
+#define SCO_CTRL_PATH "/data/misc/bluedroid/.sco_ctrl"
+#define SCO_DATA_PATH "/data/misc/bluedroid/.sco_data"
+
+typedef enum {
+    SCO_CTRL_CMD_NONE,
+    SCO_CTRL_CMD_CHECK_READY,
+    SCO_CTRL_CMD_OUT_START,
+    SCO_CTRL_CMD_IN_START,
+    SCO_CTRL_CMD_OUT_STOP,
+    SCO_CTRL_CMD_IN_STOP,
+    SCO_CTRL_CMD_SUSPEND,
+    SCO_CTRL_GET_AUDIO_CONFIG,
+    SCO_CTRL_CMD_OFFLOAD_START,
+} tSCO_CTRL_CMD;
+
+#define SCO_SAMPLE_RATE_8K   1
+#define SCO_SAMPLE_RATE_16K   2
+
+#endif
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+/******************************************************************************
+**  Constants & Macros
+******************************************************************************/
+
+uint32_t Skt_Read(int fd, uint8_t *p_buf, uint32_t len);
+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);
+#endif
diff --git a/rtkbt/code/libbt-vendor/include/unused.h b/rtkbt/code/libbt-vendor/include/unused.h
new file mode 100755 (executable)
index 0000000..d44033e
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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
+ *
+ *      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.
+ *  - 1 control system sysfs proc env & property
+ */
+#ifndef BT_UNUSED_H
+#define BT_UNUSED_H
+#ifdef __GNUC__
+#  define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
+#else
+#  define UNUSED(x) UNUSED_ ## x
+#endif
+#endif /*BT_UNUSED_H*/
old mode 100644 (file)
new mode 100755 (executable)
index 20ed9bb..24427a9
@@ -101,7 +101,7 @@ int upio_set_bluetooth_power(int on);
 ** Returns         None
 **
 *******************************************************************************/
-void upio_set(uint8_t pio, uint8_t action, uint8_t polarity);
+void upio_set(uint8_t pio, uint8_t action);//void upio_set(uint8_t pio, uint8_t action, uint8_t polarity);
 
 
 /*******************************************************************************
old mode 100644 (file)
new mode 100755 (executable)
index 07bcf7d..573667b
@@ -39,6 +39,8 @@
 /******************************************************************************
 **  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
 
 /******************************************************************************
 **  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
@@ -195,8 +211,13 @@ void userial_vendor_set_hw_fctrl(uint8_t hw_fctrl);
 
 int userial_socket_open(void);
 
-int userial_vendor_usb_ioctl(int operation);
+int userial_vendor_usb_ioctl(int operation, void* param);
 
 int userial_vendor_usb_open(void);
 
+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
 #endif /* USERIAL_VENDOR_H */
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 2396949..8600d0e
@@ -77,7 +77,7 @@ typedef struct _RTB_QUEUE_HEAD{
     uint32_t  QueueLen;
     pthread_mutex_t Lock;
     uint8_t   Id[RTB_QUEUE_ID_LENGTH];
-}RTB_QUEUE_HEAD, *PRTB_QUEUE_HEAD;
+}*PRTB_QUEUE_HEAD;
 
 //****************************************************************************
 // FUNCTION
@@ -87,7 +87,7 @@ typedef struct _RTB_QUEUE_HEAD{
     \return :   FALSE   Queue is not empty
         TRU Queue is empty
 */
-unsigned char
+bool
 RtbQueueIsEmpty(
    IN RTB_QUEUE_HEAD* RtkQueueHead
 )
old mode 100644 (file)
new mode 100755 (executable)
index 59a551e..78f78d6
@@ -26,7 +26,7 @@
 
 #undef NDEBUG
 #define LOG_TAG "libbt_vendor"
-#define RTKBT_RELEASE_NAME "20171107_BT_ANDROID_8.x"
+#define RTKBT_RELEASE_NAME "20180525_BT_ANDROID_8.1"
 #include <utils/Log.h>
 #include "bt_vendor_rtk.h"
 #include "upio.h"
@@ -44,6 +44,8 @@ extern bool rtk_btsnoop_save_log;
 extern char rtk_btsnoop_path[];
 extern uint8_t coex_log_enable;
 extern void hw_config_start(char transtype);
+extern void hw_usb_config_start(char transtype,uint32_t val);
+extern void RTK_btservice_init();
 
 #if (HW_END_WITH_HCI_RESET == TRUE)
 void hw_epilog_process(void);
@@ -63,7 +65,6 @@ bool rtkbt_auto_restart = false;
 #define RTKBT_CONF_FILE         "/vendor/etc/bluetooth/rtkbt.conf"
 #define USB_DEVICE_DIR          "/sys/bus/usb/devices"
 #define DEBUG_SCAN_USB          FALSE
-#define DOWN_FW_CFG             _IOW('H', 201, int)
 
 /******************************************************************************
 **  Static Variables
@@ -197,7 +198,7 @@ static void load_rtkbt_stack_conf()
     }
     int line_num = 0;
     char line[1024];
-    char value[1024];
+    //char value[1024];
     while (fgets(line, sizeof(line), fp)) {
         char *line_ptr = rtk_trim(line);
         ++line_num;
@@ -263,7 +264,7 @@ static void load_rtkbt_conf()
     FILE *fp = fopen(RTKBT_CONF_FILE, "rt");
     if (!fp) {
       ALOGE("%s unable to open file '%s': %s", __func__, RTKBT_CONF_FILE, strerror(errno));
-      strcpy(rtkbt_device_node,"/dev/rtk_btusb");
+      strcpy(rtkbt_device_node,"/dev/rtkbt_dev");
       return;
     }
 
@@ -280,7 +281,7 @@ static void load_rtkbt_conf()
         split = strchr(line_ptr, '=');
         if (!split) {
         ALOGE("%s no key/value separator found on line %d.", __func__, line_num);
-        strcpy(rtkbt_device_node,"/dev/rtk_btusb");
+        strcpy(rtkbt_device_node,"/dev/rtkbt_dev");
         return;
       }
 
@@ -296,7 +297,7 @@ static void load_rtkbt_conf()
     if(rtkbt_device_node[0]=='?'){
         /*1.Scan_Usb_Device*/
         if(Scan_Usb_Devices_For_RTK(USB_DEVICE_DIR) == 0x01) {
-            strcpy(rtkbt_device_node,"/dev/rtk_btusb");
+            strcpy(rtkbt_device_node,"/dev/rtkbt_dev");
         }
         else{
             int i = 0;
@@ -307,7 +308,7 @@ static void load_rtkbt_conf()
         }
     }
 
-    if(split = strchr(rtkbt_device_node, ':')) {
+    if((split = strchr(rtkbt_device_node, ':')) != NULL) {
         *split = '\0';
         if(!strcmp(rtk_trim(split + 1), "H5")) {
             rtkbt_transtype |= RTKBT_TRANS_H5;
@@ -316,12 +317,12 @@ static void load_rtkbt_conf()
             rtkbt_transtype |= RTKBT_TRANS_H4;
         }
     }
-    else if(strcmp(rtkbt_device_node, "/dev/rtk_btusb")) {
+    else if(strcmp(rtkbt_device_node, "/dev/rtkbt_dev")) {
         //default use h5
         rtkbt_transtype |= RTKBT_TRANS_H5;
     }
 
-    if(strcmp(rtkbt_device_node, "/dev/rtk_btusb")) {
+    if(strcmp(rtkbt_device_node, "/dev/rtkbt_dev")) {
         rtkbt_transtype |= RTKBT_TRANS_UART;
     }
     else {
@@ -410,20 +411,10 @@ static int op(bt_vendor_opcode_t opcode, void *param)
                     hw_config_start(rtkbt_transtype);
                 }
                 else {
-                    BTVNDDBG("usb op for %d", opcode);
-                    ALOGE("Bt_vendor_rtk Op for BT_VND_OP_FW_CFG");
-                    retval = userial_vendor_usb_ioctl(DOWN_FW_CFG);
-                    if(retval>0){
-                        ALOGE("Bt_vendor_rtk Download Fw Success");
-                        bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
-                    }else{
-                        ALOGE("Bt_vendor_rtk Download Fw failed: %s(%d)", strerror(errno), errno);
-                        if(rtkbt_auto_restart) {
-                            bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
-                            kill(getpid(), SIGKILL);
-                        }
-                    }
+                  retval = userial_vendor_usb_ioctl(GET_USB_INFO, NULL);
+                  hw_usb_config_start(RTKBT_TRANS_H4,retval);
                 }
+                RTK_btservice_init();
             }
             break;
 
@@ -473,17 +464,16 @@ static int op(bt_vendor_opcode_t opcode, void *param)
                     BTVNDDBG("USB op for %d", opcode);
                     int fd, idx = 0;
                     int (*fd_array)[] = (int (*)[]) param;
-                    if(userial_vendor_usb_open() != -1){
-                        retval = 1;
+                    for(idx = 0; idx < 10; idx++) {
+                        if(userial_vendor_usb_open() != -1){
+                            retval = 1;
+                            break;
+                        }
                     }
-                    do {
-                        idx++;
-                        usleep(500000);
-                    }while(userial_vendor_usb_open() == -1 && idx < 10);
                     fd = userial_socket_open();
                     if (fd != -1)
                     {
-                        for (idx=0; idx < CH_MAX; idx++)
+                        for (idx = 0; idx < CH_MAX; idx++)
                             (*fd_array)[idx] = fd;
                     }
                     else
old mode 100644 (file)
new mode 100755 (executable)
index 28aac2a..7bcfee2
@@ -27,7 +27,7 @@
  ******************************************************************************/
 
 #define LOG_TAG "bt_hwcfg"
-#define RTKBT_RELEASE_NAME "20171107_BT_ANDROID_8.x"
+#define RTKBT_RELEASE_NAME "20180525_BT_ANDROID_8.1"
 
 #include <utils/Log.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <endian.h>
 #include <byteswap.h>
+#include <unistd.h>
 
 #include "bt_vendor_lib.h"
-
+#include "hardware.h"
 
 /******************************************************************************
 **  Constants &  Macros
 ******************************************************************************/
 #define RTK_VERSION "4.1.1"
 
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define cpu_to_le16(d)  (d)
-#define cpu_to_le32(d)  (d)
-#define le16_to_cpu(d)  (d)
-#define le32_to_cpu(d)  (d)
-#elif __BYTE_ORDER == __BIG_ENDIAN
-#define cpu_to_le16(d)  bswap_16(d)
-#define cpu_to_le32(d)  bswap_32(d)
-#define le16_to_cpu(d)  bswap_16(d)
-#define le32_to_cpu(d)  bswap_32(d)
-#else
-#error "Unknown byte order"
-#endif
-
-#define FIRMWARE_DIRECTORY  "/vendor/etc/firmware/%s"
-#define BT_CONFIG_DIRECTORY "/vendor/etc/firmware/%s"
-#define PATCH_DATA_FIELD_MAX_SIZE       252
-#define RTK_VENDOR_CONFIG_MAGIC         0x8723ab55
-#define MAX_PATCH_SIZE_24K            (1024*24)   //24K
-#define MAX_PATCH_SIZE_40K            (1024*40)   //40K
-
-#define MAX_ORG_CONFIG_SIZE     (0x100*14)
-#define MAX_ALT_CONFIG_SIZE     (0x100*2)
-
-struct rtk_bt_vendor_config_entry{
-    uint16_t offset;
-    uint8_t entry_len;
-    uint8_t entry_data[0];
-} __attribute__ ((packed));
-
-struct rtk_bt_vendor_config{
-    uint32_t signature;
-    uint16_t data_len;
-    struct rtk_bt_vendor_config_entry entry[0];
-} __attribute__ ((packed));
-
-#define HCI_CMD_MAX_LEN             258
-
-#define HCI_VERSION_MASK_10     (1<<0)     //Bluetooth Core Spec 1.0b
-#define HCI_VERSION_MASK_11     (1<<1)     //Bluetooth Core Spec 1.1
-#define HCI_VERSION_MASK_12     (1<<2)     //Bluetooth Core Spec 1.2
-#define HCI_VERSION_MASK_20     (1<<3)     //Bluetooth Core Spec 2.0+EDR
-#define HCI_VERSION_MASK_21     (1<<4)     //Bluetooth Core Spec 2.1+EDR
-#define HCI_VERSION_MASK_30     (1<<5)     //Bluetooth Core Spec 3.0+HS
-#define HCI_VERSION_MASK_40     (1<<6)     //Bluetooth Core Spec 4.0
-#define HCI_VERSION_MASK_41     (1<<7)     //Bluetooth Core Spec 4.1
-#define HCI_VERSION_MASK_42     (1<<8)     //Bluetooth Core Spec 4.2
-#define HCI_VERSION_MASK_ALL    (0xFFFFFFFF)
-
-#define HCI_REVISION_MASK_ALL   (0xFFFFFFFF)
-
-#define LMP_SUBVERSION_NONE     (0x0)
-#define LMPSUBVERSION_8723a     (0x1200)
-
-#define CHIPTYPE_NONE           (0x1F)      //Chip Type's range: 0x0 ~ 0xF
-#define CHIP_TYPE_MASK_ALL      (0xFFFFFFFF)
-
-#define PROJECT_ID_MASK_ALL     (0xFFFFFFFF)    // temp used for unknow project id for a new chip
-
-#define PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE   (0x1)
-
-#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 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
-
-#define HCI_EVT_CMD_CMPL_OP1001_HCI_VERSION_OFFSET     (6)     //HCI_Version's offset in COMMAND Completed Event for OpCode 0x1001(Read Local Version Information Command)
-#define HCI_EVT_CMD_CMPL_OP1001_HCI_REVISION_OFFSET     (7)     //HCI_Revision's offset in COMMAND Completed Event for OpCode 0x1001(Read Local Version Information Command)
-#define HCI_EVT_CMD_CMPL_OP1001_LMP_SUBVERSION_OFFSET  (12)    //LMP Subversion's offset in COMMAND Completed Event for OpCode 0x1001(Read Local Version Information Command)
-#define HCI_EVT_CMD_CMPL_OP0C14_LOCAL_NAME_OFFSET      (6)     //Local Name's offset in COMMAND Completed Event for OpCode 0x0C14(Read Local Name Command)
-#define HCI_EVT_CMD_CMPL_OP1009_BDADDR_OFFSET    (6)     //BD_ADDR's offset in COMMAND Completed Event for OpCode 0x1009(Read BD_ADDR Command)
-#define HCI_EVT_CMD_CMPL_OPFC6D_EVERSION_OFFSET        (6)  //eversion's offset in COMMAND Completed Event for OpCode 0xfc6d(Read eVERSION Vendor Command)
-#define HCI_EVT_CMD_CMPL_OPFC61_CHIPTYPE_OFFSET        (6)  //chip type's offset in COMMAND Completed Event for OpCode 0xfc61(Read ChipType Vendor Command)
-
-//#define UPDATE_BAUDRATE_CMD_PARAM_SIZE          (6)
-#define HCI_CMD_PREAMBLE_SIZE                   (3)
-#define HCI_CMD_READ_CHIP_TYPE_SIZE             (5)
-//#define HCD_REC_PAYLOAD_LEN_BYTE                (2)
-//#define BD_ADDR_LEN                             (6)
-//#define LOCAL_NAME_BUFFER_LEN                   (32)
-//#define LOCAL_BDADDR_PATH_BUFFER_LEN            (256)
-
-#define H5_SYNC_REQ_SIZE (2)
-#define H5_SYNC_RESP_SIZE (2)
-#define H5_CONF_REQ_SIZE (3)
-#define H5_CONF_RESP_SIZE (2)
-
-/******************************************************************************
-**  Local type definitions
-******************************************************************************/
-
-/* Hardware Configuration State */
-enum {
-    HW_CFG_H5_INIT = 1,
-    HW_CFG_READ_LOCAL_VER,
-    HW_CFG_READ_ECO_VER,   //eco version
-    HW_CFG_READ_CHIP_TYPE,
-    HW_CFG_START,
-    HW_CFG_SET_UART_BAUD_HOST,//change FW baudrate
-    HW_CFG_SET_UART_BAUD_CONTROLLER,//change Host baudrate
-    HW_CFG_SET_UART_HW_FLOW_CONTROL,
-    HW_CFG_DL_FW_PATCH
-};
-
-/* h/w config control block */
-typedef struct
-{
-    uint32_t    max_patch_size;
-    uint32_t    baudrate;
-    uint16_t    lmp_subversion;
-    uint8_t     state;          /* Hardware configuration state */
-    uint8_t     eversion;
-    uint32_t    project_id_mask;
-    uint8_t     hci_version;
-    uint8_t     hci_revision;
-    uint8_t     chip_type;
-    uint8_t     dl_fw_flag;
-    int         fw_len;          /* FW patch file len */
-    int         config_len;      /* Config patch file len */
-    int         total_len;       /* FW & config extracted buf len */
-    uint8_t     *fw_buf;         /* FW patch file buf */
-    uint8_t     *config_buf;     /* Config patch file buf */
-    uint8_t     *total_buf;      /* FW & config extracted buf */
-    uint8_t     patch_frag_cnt;  /* Patch fragment count download */
-    uint8_t     patch_frag_idx;  /* Current patch fragment index */
-    uint8_t     patch_frag_len;  /* Patch fragment length */
-    uint8_t     patch_frag_tail; /* Last patch fragment length */
-    uint8_t     hw_flow_cntrl;   /* Uart flow control, bit7:set, bit0:enable */
-} bt_hw_cfg_cb_t;
-
-/* low power mode parameters */
-typedef struct
-{
-    uint8_t sleep_mode;                     /* 0(disable),1(UART),9(H5) */
-    uint8_t host_stack_idle_threshold;      /* Unit scale 300ms/25ms */
-    uint8_t host_controller_idle_threshold; /* Unit scale 300ms/25ms */
-    uint8_t bt_wake_polarity;               /* 0=Active Low, 1= Active High */
-    uint8_t host_wake_polarity;             /* 0=Active Low, 1= Active High */
-    uint8_t allow_host_sleep_during_sco;
-    uint8_t combine_sleep_mode_and_lpm;
-    uint8_t enable_uart_txd_tri_state;      /* UART_TXD Tri-State */
-    uint8_t sleep_guard_time;               /* sleep guard time in 12.5ms */
-    uint8_t wakeup_guard_time;              /* wakeup guard time in 12.5ms */
-    uint8_t txd_config;                     /* TXD is high in sleep state */
-    uint8_t pulsed_host_wake;               /* pulsed host wake if mode = 1 */
-} bt_lpm_param_t;
-
 /******************************************************************************
 **  Externs
 ******************************************************************************/
 
-void hw_config_cback(void *p_evt_buf);
+//void hw_config_cback(void *p_evt_buf);
+//void hw_usb_config_cback(void *p_evt_buf);
+
 extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
 extern bool rtkbt_auto_restart;
 
 /******************************************************************************
 **  Static variables
 ******************************************************************************/
-static bt_hw_cfg_cb_t hw_cfg_cb;
+bt_hw_cfg_cb_t hw_cfg_cb;
 
-//#define BT_CHIP_PROBE_SIMULATION
-#ifdef BT_CHIP_PROBE_SIMULATION
-static bt_hw_cfg_cb_t hw_cfg_test;
-struct bt_chip_char{
-    uint16_t    lmp_subversion;
-    uint8_t     hci_version;
-    uint8_t     hci_revision;
-    uint8_t     chip_type;
-};
-struct bt_chip_char bt_chip_chars[] = \
-{
-        {0x8723, 0x4, 0xb, CHIPTYPE_NONE},      //8703as
-        {0x8723, 0x6, 0xb, CHIPTYPE_NONE},      //8723bs
-        {0x8703, 0x4, 0xd, 0x7},                //8703bs
-        {0x8703, 0x6, 0xb, 0x3},                //8723cs-cg
-        {0x8703, 0x6, 0xb, 0x4},                //8723cs-vf
-        {0x8703, 0x6, 0xb, 0x5},                //8723cs-xx
-        {0x8723, 0x6, 0xd, CHIPTYPE_NONE},      //8723ds
-};
-#endif
+/*
 static bt_lpm_param_t lpm_param =
 {
     LPM_SLEEP_MODE,
@@ -247,291 +83,14 @@ static bt_lpm_param_t lpm_param =
     LPM_HOST_WAKE_POLARITY,
     LPM_ALLOW_HOST_SLEEP_DURING_SCO,
     LPM_COMBINE_SLEEP_MODE_AND_LPM,
-    LPM_ENABLE_UART_TXD_TRI_STATE,
-    0,  /* not applicable */
-    0,  /* not applicable */
-    0,  /* not applicable */
-    LPM_PULSED_HOST_WAKE
-};
-
-//signature: realtech
-const uint8_t RTK_EPATCH_SIGNATURE[8]={0x52,0x65,0x61,0x6C,0x74,0x65,0x63,0x68};
-//Extension Section IGNATURE:0x77FD0451
-const uint8_t EXTENSION_SECTION_SIGNATURE[4]={0x51,0x04,0xFD,0x77};
-
-typedef struct {
-    uint16_t    lmp_subversion;
-    uint32_t     hci_version_mask;
-    uint32_t     hci_revision_mask;
-    uint32_t     chip_type_mask;
-    uint32_t     project_id_mask;
-    char        *patch_name;
-    char        *config_name;
-    uint16_t     mac_offset;
-    uint32_t    max_patch_size;
-} patch_info;
-
-static patch_info patch_table[] = {
-/*    lmp_subv                      hci_version_mask                    hci_revision_mask                chip_type_mask              project_id_mask                 fw name                                 config name                         mac offset                         max_patch_size  */
-    {0x1200,            HCI_VERSION_MASK_ALL,    HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL,  1<<0,                  "rtl8723as_fw",         "rtl8723as_config",     CONFIG_MAC_OFFSET_GEN_1_2,  MAX_PATCH_SIZE_24K},    //Rtl8723AS
-
-    {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
-    {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
-
-    {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
-    {0x8821,            HCI_VERSION_MASK_ALL,    (1<<0xc),              CHIP_TYPE_MASK_ALL,  1<<10,                 "rtl8821cs_fw",         "rtl8821cs_config",     CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_40K}, //RTL8821CS
-/*  todo: RTL8703CS */
-
-    {LMP_SUBVERSION_NONE,HCI_VERSION_MASK_ALL,   HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, PROJECT_ID_MASK_ALL,    "rtl_none_fw",          "rtl_none_config",      CONFIG_MAC_OFFSET_GEN_1_2,  MAX_PATCH_SIZE_24K}
-};
-
-struct rtk_epatch_entry{
-    uint16_t chip_id;
-    uint16_t patch_length;
-    uint32_t patch_offset;
-    uint32_t svn_version;
-    uint32_t coex_version;
-} __attribute__ ((packed));
-
-struct rtk_epatch{
-    uint8_t signature[8];
-    uint32_t fw_version;
-    uint16_t number_of_patch;
-    struct rtk_epatch_entry entry[0];
-} __attribute__ ((packed));
-
-
-int check_match_state(bt_hw_cfg_cb_t *cfg,uint32_t mask)
-{
-    patch_info  *patch_entry;
-    int res = 0;
-
-    for(patch_entry = patch_table; patch_entry->lmp_subversion != LMP_SUBVERSION_NONE; patch_entry++) {
-        if(patch_entry->lmp_subversion != cfg->lmp_subversion)
-            continue;
-        if((patch_entry->hci_version_mask!=HCI_VERSION_MASK_ALL)&&((patch_entry->hci_version_mask&(1<<cfg->hci_version))==0))
-             continue;
-        if((patch_entry->hci_revision_mask!=HCI_REVISION_MASK_ALL)&&((patch_entry->hci_revision_mask&(1<<cfg->hci_revision))==0))
-             continue;
-        if((mask&PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE)&&(patch_entry->chip_type_mask != CHIP_TYPE_MASK_ALL)&&((patch_entry->chip_type_mask&(1<<cfg->chip_type))==0))
-             continue;
-        res++;
-    }
-    ALOGI( "check_match_state return %d(cfg->lmp_subversion:0x%x cfg->hci_vesion:0x%x cfg->hci_revision:0x%x cfg->chip_type:0x%x mask:%08x)\n",
-            res, cfg->lmp_subversion, cfg->hci_version, cfg->hci_revision, cfg->chip_type, mask);
-    return res;
-}
-patch_info* get_patch_entry(bt_hw_cfg_cb_t *cfg)
-{
-    patch_info  *patch_entry;
-
-    ALOGI("get_patch_entry(lmp_subversion:0x%x hci_vesion:0x%x cfg->hci_revision:0x%x chip_type:0x%x)\n",
-            cfg->lmp_subversion, cfg->hci_version, cfg->hci_revision, cfg->chip_type);
-    for(patch_entry = patch_table; patch_entry->lmp_subversion != LMP_SUBVERSION_NONE; patch_entry++) {
-        if(patch_entry->lmp_subversion != cfg->lmp_subversion)
-            continue;
-        if((patch_entry->hci_version_mask != HCI_VERSION_MASK_ALL)&&((patch_entry->hci_version_mask&(1<<cfg->hci_version)) == 0))
-             continue;
-        if((patch_entry->hci_revision_mask != HCI_REVISION_MASK_ALL)&&((patch_entry->hci_revision_mask&(1<<cfg->hci_revision)) == 0))
-             continue;
-        if((patch_entry->chip_type_mask != CHIP_TYPE_MASK_ALL)&&((patch_entry->chip_type_mask&(1<<cfg->chip_type)) == 0))
-             continue;
-        break;
-    }
-    ALOGI("get_patch_entry return(patch_name:%s config_name:%s mac_offset:0x%x)\n",
-            patch_entry->patch_name, patch_entry->config_name, patch_entry->mac_offset);
-    return patch_entry;
-}
-
-/*******************************************************************************
-**
-** Function        line_speed_to_userial_baud
-**
-** Description     helper function converts line speed number into USERIAL baud
-**                 rate symbol
-**
-** Returns         unit8_t (USERIAL baud symbol)
-**
-*******************************************************************************/
-uint8_t line_speed_to_userial_baud(uint32_t line_speed)
-{
-    uint8_t baud;
-
-    if (line_speed == 4000000)
-        baud = USERIAL_BAUD_4M;
-    else if (line_speed == 3000000)
-        baud = USERIAL_BAUD_3M;
-    else if (line_speed == 2000000)
-        baud = USERIAL_BAUD_2M;
-    else if (line_speed == 1500000)
-        baud = USERIAL_BAUD_1_5M;
-    else if (line_speed == 1000000)
-        baud = USERIAL_BAUD_1M;
-    else if (line_speed == 921600)
-        baud = USERIAL_BAUD_921600;
-    else if (line_speed == 460800)
-        baud = USERIAL_BAUD_460800;
-    else if (line_speed == 230400)
-        baud = USERIAL_BAUD_230400;
-    else if (line_speed == 115200)
-        baud = USERIAL_BAUD_115200;
-    else if (line_speed == 57600)
-        baud = USERIAL_BAUD_57600;
-    else if (line_speed == 19200)
-        baud = USERIAL_BAUD_19200;
-    else if (line_speed == 9600)
-        baud = USERIAL_BAUD_9600;
-    else if (line_speed == 1200)
-        baud = USERIAL_BAUD_1200;
-    else if (line_speed == 600)
-        baud = USERIAL_BAUD_600;
-    else
-    {
-        ALOGE( "userial vendor: unsupported baud speed %d", line_speed);
-        baud = USERIAL_BAUD_115200;
-    }
-
-    return baud;
-}
-
-typedef struct _baudrate_ex
-{
-    uint32_t rtk_speed;
-    uint32_t uart_speed;
-}baudrate_ex;
-
-baudrate_ex baudrates[] =
-{
-    {0x00006004, 921600},
-    {0x05F75004, 921600},//RTL8723BS
-    {0x00004003, 1500000},
-    {0x04928002, 1500000},//RTL8723BS
-    {0x00005002, 2000000},//same as RTL8723AS
-    {0x00008001, 3000000},
-    {0x04928001, 3000000},//RTL8723BS
-    {0x06B58001, 3000000},//add RTL8703as
-    {0x00007001, 3500000},
-    {0x052A6001, 3500000},//RTL8723BS
-    {0x00005001, 4000000},//same as RTL8723AS
-    {0x0000701d, 115200},
-    {0x0252C014, 115200}//RTL8723BS
-};
-
-/**
-* Change realtek Bluetooth speed to uart speed. It is matching in the struct baudrates:
-*
-* @code
-* baudrate_ex baudrates[] =
-* {
-*   {0x7001, 3500000},
-*   {0x6004, 921600},
-*   {0x4003, 1500000},
-*   {0x5001, 4000000},
-*   {0x5002, 2000000},
-*   {0x8001, 3000000},
-*   {0x701d, 115200}
-* };
-* @endcode
-*
-* If there is no match in baudrates, uart speed will be set as #115200.
-*
-* @param rtk_speed realtek Bluetooth speed
-* @param uart_speed uart speed
-*
-*/
-static void rtk_speed_to_uart_speed(uint32_t rtk_speed, uint32_t* uart_speed)
-{
-    *uart_speed = 115200;
-
-    uint8_t i;
-    for (i=0; i< sizeof(baudrates)/sizeof(baudrate_ex); i++)
-    {
-        if (baudrates[i].rtk_speed == rtk_speed)
-        {
-            *uart_speed = baudrates[i].uart_speed;
-            return;
-        }
-    }
-    return;
-}
-
-/**
-* Change uart speed to realtek Bluetooth speed. It is matching in the struct baudrates:
-*
-* @code
-* baudrate_ex baudrates[] =
-* {
-*   {0x7001, 3500000},
-*   {0x6004, 921600},
-*   {0x4003, 1500000},
-*   {0x5001, 4000000},
-*   {0x5002, 2000000},
-*   {0x8001, 3000000},
-*   {0x701d, 115200}
-* };
-* @endcode
-*
-* If there is no match in baudrates, realtek Bluetooth speed will be set as #0x701D.
-*
-* @param uart_speed uart speed
-* @param rtk_speed realtek Bluetooth speed
-*
-*/
-static inline void uart_speed_to_rtk_speed(uint32_t uart_speed, uint32_t* rtk_speed)
-{
-    *rtk_speed = 0x701D;
-
-    unsigned int i;
-    for (i=0; i< sizeof(baudrates)/sizeof(baudrate_ex); i++)
-    {
-      if (baudrates[i].uart_speed == uart_speed)
-      {
-          *rtk_speed = baudrates[i].rtk_speed;
-          return;
-      }
-    }
-    return;
-}
-
-
-/*******************************************************************************
-**
-** Function         hw_config_set_bdaddr
-**
-** Description      Program controller's Bluetooth Device Address
-**
-** Returns          TRUE, if valid address is sent
-**                  FALSE, otherwise
-**
-*******************************************************************************/
-static uint8_t hw_config_set_controller_baudrate(HC_BT_HDR *p_buf, uint32_t baudrate)
-{
-    uint8_t retval = FALSE;
-    uint8_t *p = (uint8_t *) (p_buf + 1);
-
-    UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE);
-    *p++ = 4; /* parameter length */
-    UINT32_TO_STREAM(p, baudrate);
-
-    p_buf->len = HCI_CMD_PREAMBLE_SIZE + 4;
-
-    retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, p_buf, \
-                                 hw_config_cback);
-
-    return (retval);
-}
-
-static int getmacaddr(unsigned char * addr)
+    LPM_ENABLE_UART_TXD_TRI_STATE,*/
+    //0,  /* not applicable */
+   // 0,  /* not applicable */
+   // 0,  /* not applicable */
+    /*LPM_PULSED_HOST_WAKE
+};*/
+
+int getmacaddr(unsigned char * addr)
 {
     int i = 0;
     char data[256], *str;
@@ -551,246 +110,6 @@ static int getmacaddr(unsigned char * addr)
     return -1;
 }
 
-static inline int getAltSettings(patch_info *patch_entry, unsigned short *offset, int max_group_cnt)
-{
-    int n = 0;
-    if(patch_entry)
-        offset[n++] = patch_entry->mac_offset;
-/*
-//sample code, add special settings
-
-    offset[n++] = 0x15B;
-*/
-    return n;
-}
-static inline int getAltSettingVal(patch_info *patch_entry, unsigned short offset, unsigned char * val)
-{
-    int res = 0;
-
-    switch(offset)
-    {
-/*
-//sample code, add special settings
-        case 0x15B:
-            val[0] = 0x0B;
-            val[1] = 0x0B;
-            val[2] = 0x0B;
-            val[3] = 0x0B;
-            res = 4;
-            break;
-*/
-        default:
-            res = 0;
-            break;
-    }
-    if((patch_entry)&&(offset == patch_entry->mac_offset)&&(res == 0))
-    {
-        if(getmacaddr(val) == 0){
-            ALOGI("MAC: %02x:%02x:%02x:%02x:%02x:%02x", val[5], val[4], val[3], val[2], val[1], val[0]);
-            res = 6;
-        }
-    }
-    return res;
-}
-
-void rtk_update_altsettings(patch_info *patch_entry, unsigned char* config_buf_ptr, size_t *config_len_ptr)
-{
-    unsigned short offset[256], data_len;
-    unsigned char val[256];
-
-    struct rtk_bt_vendor_config* config = (struct rtk_bt_vendor_config*) config_buf_ptr;
-    struct rtk_bt_vendor_config_entry* entry = config->entry;
-    size_t config_len = *config_len_ptr;
-    int count = 0,temp = 0, i = 0, j;
-
-    ALOGI("ORG Config len=%08x:\n", config_len);
-    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], \
-            config_buf_ptr[i+8], config_buf_ptr[i+9], config_buf_ptr[i+10], config_buf_ptr[i+11], config_buf_ptr[i+12], config_buf_ptr[i+13], config_buf_ptr[i+14], config_buf_ptr[i+15]);
-    }
-
-    memset(offset, 0, sizeof(offset));
-    memset(val, 0, sizeof(val));
-    data_len = le16_to_cpu(config->data_len);
-
-    count = getAltSettings(patch_entry, offset, sizeof(offset)/sizeof(unsigned short));
-    if(count <= 0){
-        ALOGI("rtk_update_altsettings: No AltSettings");
-        return;
-    }else{
-        ALOGI("rtk_update_altsettings: %d AltSettings", count);
-    }
-
-    if (data_len != config_len - sizeof(struct rtk_bt_vendor_config))
-    {
-        ALOGE("rtk_update_altsettings: config len(%x) is not right(%x)", data_len, config_len-sizeof(struct rtk_bt_vendor_config));
-        return;
-    }
-
-    for (i=0; i<data_len;)
-    {
-        for(j = 0; j < count;j++)
-        {
-            if(le16_to_cpu(entry->offset) == offset[j])
-                offset[j] = 0;
-        }
-        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);
-            memcpy(entry->entry_data, val, entry->entry_len);
-        }
-        temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
-        i += temp;
-        entry = (struct rtk_bt_vendor_config_entry*)((uint8_t*)entry + temp);
-    }
-    for(j = 0; j < count;j++){
-        if(offset[j] == 0)
-            continue;
-        entry->entry_len = getAltSettingVal(patch_entry, offset[j], val);
-        if(entry->entry_len <= 0)
-            continue;
-        entry->offset = cpu_to_le16(offset[j]);
-        memcpy(entry->entry_data, val, entry->entry_len);
-        ALOGI("rtk_update_altsettings: add %04x[%02x]", le16_to_cpu(entry->offset), entry->entry_len);
-        temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
-        i += temp;
-        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);
-
-    ALOGI("NEW Config len=%08x:\n", *config_len_ptr);
-    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], \
-            config_buf_ptr[i+8], config_buf_ptr[i+9], config_buf_ptr[i+10], config_buf_ptr[i+11], config_buf_ptr[i+12], config_buf_ptr[i+13], config_buf_ptr[i+14], config_buf_ptr[i+15]);
-    }
-    return;
-}
-
-uint32_t rtk_parse_config_file(unsigned char** config_buf, size_t* filelen, uint8_t bt_addr[6], uint16_t mac_offset)
-{
-    struct rtk_bt_vendor_config* config = (struct rtk_bt_vendor_config*) *config_buf;
-    uint16_t config_len = le16_to_cpu(config->data_len), temp = 0;
-    struct rtk_bt_vendor_config_entry* entry = config->entry;
-    unsigned int i = 0;
-    uint32_t baudrate = 0;
-    uint32_t config_has_bdaddr = 0;
-    uint8_t *p;
-
-    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);
-        return 0;
-    }
-
-    if (config_len != *filelen - sizeof(struct rtk_bt_vendor_config))
-    {
-        ALOGE("config len(0x%x) is not right(0x%x)", config_len, *filelen-sizeof(struct rtk_bt_vendor_config));
-        return 0;
-    }
-
-    for (i=0; i<config_len;)
-    {
-        switch(le16_to_cpu(entry->offset))
-        {
-            case 0xc:
-            {
-                p = (uint8_t *)entry->entry_data;
-                STREAM_TO_UINT32(baudrate, p);
-                if (entry->entry_len >= 12)
-                {
-                    hw_cfg_cb.hw_flow_cntrl |= 0x80; /* bit7 set hw flow control */
-                    if (entry->entry_data[12] & 0x04) /* offset 0x18, bit2 */
-                        hw_cfg_cb.hw_flow_cntrl |= 1; /* bit0 enable hw flow control */
-                }
-
-                ALOGI("config baud rate to :0x%08x, hwflowcontrol:0x%x, 0x%x", baudrate, entry->entry_data[12], hw_cfg_cb.hw_flow_cntrl);
-                break;
-            }
-#if (USE_CONTROLLER_BDADDR == FALSE)
-            case 0x44:
-            case 0x3c:
-            {
-                 config_has_bdaddr = 1;
-                 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;
-        }
-        temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
-        i += temp;
-        entry = (struct rtk_bt_vendor_config_entry*)((uint8_t*)entry + temp);
-    }
-
-    return baudrate;
-}
-
-uint32_t rtk_get_bt_config(unsigned char** config_buf,
-        uint32_t* config_baud_rate, char * config_file_short_name, uint16_t mac_offset)
-{
-    char bt_config_file_name[PATH_MAX] = {0};
-    struct stat st;
-    size_t filelen;
-    int fd;
-    FILE* file = NULL;
-
-    sprintf(bt_config_file_name, BT_CONFIG_DIRECTORY, config_file_short_name);
-    ALOGI("BT config file: %s", bt_config_file_name);
-
-    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;
-    }
-
-    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;
-    }
-
-    if ((fd = open(bt_config_file_name, O_RDONLY)) < 0)
-    {
-        ALOGE("Can't open bt config file");
-        return -1;
-    }
-
-    if ((*config_buf = malloc(MAX_ORG_CONFIG_SIZE+MAX_ALT_CONFIG_SIZE)) == NULL)
-    {
-        ALOGE("malloc buffer for config file fail(0x%x)\n", filelen);
-        close(fd);
-        return -1;
-    }
-
-    if (read(fd, *config_buf, filelen) < (ssize_t)filelen)
-    {
-        ALOGE("Can't load bt config file");
-        free(*config_buf);
-        close(fd);
-        return -1;
-    }
-
-    *config_baud_rate = rtk_parse_config_file(config_buf, &filelen, vnd_local_bd_addr, mac_offset);
-    ALOGI("Get config baud rate from config file:0x%x", *config_baud_rate);
-
-    close(fd);
-    return filelen;
-}
-
 int rtk_get_bt_firmware(uint8_t** fw_buf, char* fw_short_name)
 {
     char filename[PATH_MAX] = {0};
@@ -869,6 +188,11 @@ uint8_t rtk_get_fw_project_id(uint8_t *p_buf)
     return data;
 }
 
+uint8_t get_heartbeat_from_hardware()
+{
+    return hw_cfg_cb.heartbeat;
+}
+
 struct rtk_epatch_entry *rtk_get_patch_entry(bt_hw_cfg_cb_t *cfg_cb)
 {
     uint16_t i;
@@ -917,523 +241,6 @@ struct rtk_epatch_entry *rtk_get_patch_entry(bt_hw_cfg_cb_t *cfg_cb)
     return entry;
 }
 
-void rtk_get_bt_final_patch(bt_hw_cfg_cb_t* cfg_cb)
-{
-    uint8_t proj_id = 0;
-    struct rtk_epatch_entry* entry = NULL;
-    struct rtk_epatch *patch = (struct rtk_epatch *)cfg_cb->fw_buf;
-    int iBtCalLen = 0;
-
-    if(cfg_cb->lmp_subversion == LMPSUBVERSION_8723a)
-    {
-        if(memcmp(cfg_cb->fw_buf, RTK_EPATCH_SIGNATURE, 8) == 0)
-        {
-            ALOGE("8723as check signature error!");
-            cfg_cb->dl_fw_flag = 0;
-            goto free_buf;
-        }
-        else
-        {
-            cfg_cb->total_len = cfg_cb->fw_len + cfg_cb->config_len;
-            if (!(cfg_cb->total_buf = malloc(cfg_cb->total_len)))
-            {
-                ALOGE("can't alloc memory for fw&config, errno:%d", errno);
-                cfg_cb->dl_fw_flag = 0;
-                goto free_buf;
-            }
-            else
-            {
-                ALOGI("8723as, fw copy direct");
-                memcpy(cfg_cb->total_buf, cfg_cb->fw_buf, cfg_cb->fw_len);
-                memcpy(cfg_cb->total_buf+cfg_cb->fw_len, cfg_cb->config_buf, cfg_cb->config_len);
-                cfg_cb->dl_fw_flag = 1;
-                goto free_buf;
-            }
-        }
-    }
-
-    if (memcmp(cfg_cb->fw_buf, RTK_EPATCH_SIGNATURE, 8))
-    {
-        ALOGE("check signature error");
-        cfg_cb->dl_fw_flag = 0;
-        goto free_buf;
-    }
-
-    /* check the extension section signature */
-    if (memcmp(cfg_cb->fw_buf + cfg_cb->fw_len - 4, EXTENSION_SECTION_SIGNATURE, 4))
-    {
-        ALOGE("check extension section signature error");
-        cfg_cb->dl_fw_flag = 0;
-        goto free_buf;
-    }
-
-    proj_id = rtk_get_fw_project_id(cfg_cb->fw_buf + cfg_cb->fw_len - 5);
-
-    if((hw_cfg_cb.project_id_mask != PROJECT_ID_MASK_ALL)&& ((hw_cfg_cb.project_id_mask&(1<<proj_id)) ==0))
-    {
-        ALOGE("hw_cfg_cb.project_id_mask is 0x%08x, fw project_id is %d, does not match!!!",
-                        hw_cfg_cb.project_id_mask, proj_id);
-        cfg_cb->dl_fw_flag = 0;
-        goto free_buf;
-    }
-
-    entry = rtk_get_patch_entry(cfg_cb);
-    if (entry)
-    {
-        cfg_cb->total_len = entry->patch_length + cfg_cb->config_len;
-    }
-    else
-    {
-        cfg_cb->dl_fw_flag = 0;
-        goto free_buf;
-    }
-
-    ALOGI("total_len = 0x%x", cfg_cb->total_len);
-
-    if (!(cfg_cb->total_buf = malloc(cfg_cb->total_len)))
-    {
-        ALOGE("Can't alloc memory for multi fw&config, errno:%d", errno);
-        cfg_cb->dl_fw_flag = 0;
-        goto free_buf;
-    }
-    else
-    {
-        memcpy(cfg_cb->total_buf, cfg_cb->fw_buf + entry->patch_offset, entry->patch_length);
-        memcpy(cfg_cb->total_buf + entry->patch_length - 4, &patch->fw_version, 4);
-        memcpy(&entry->svn_version, cfg_cb->total_buf + entry->patch_length - 8, 4);
-        memcpy(&entry->coex_version, cfg_cb->total_buf + entry->patch_length - 12, 4);
-        ALOGI("BTCOEX:20%06d-%04x svn_version:%d lmp_subversion:0x%x hci_version:0x%x hci_revision:0x%x chip_type:%d Cut:%d libbt-vendor_uart version:%s\n",
-        ((entry->coex_version >> 16) & 0x7ff) + ((entry->coex_version >> 27) * 10000),
-        (entry->coex_version & 0xffff), entry->svn_version, cfg_cb->lmp_subversion, cfg_cb->hci_version, cfg_cb->hci_revision, cfg_cb->chip_type, cfg_cb->eversion+1, RTK_VERSION);
-    }
-
-    if (cfg_cb->config_len)
-    {
-        memcpy(cfg_cb->total_buf+entry->patch_length, cfg_cb->config_buf, cfg_cb->config_len);
-    }
-
-    cfg_cb->dl_fw_flag = 1;
-    ALOGI("Fw:%s exists, config file:%s exists", (cfg_cb->fw_len>0)?"":"not", (cfg_cb->config_len>0)?"":"not");
-
-free_buf:
-    if (cfg_cb->fw_len > 0)
-    {
-        free(cfg_cb->fw_buf);
-        cfg_cb->fw_len = 0;
-    }
-
-    if (cfg_cb->config_len > 0)
-    {
-        free(cfg_cb->config_buf);
-        cfg_cb->config_len = 0;
-    }
-
-    if(entry)
-    {
-        free(entry);
-    }
-}
-
-static int hci_download_patch_h4(HC_BT_HDR *p_buf, int index, uint8_t *data, int len)
-{
-    uint8_t retval = FALSE;
-    uint8_t *p = (uint8_t *) (p_buf + 1);
-
-    UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_FW_PATCH);
-    *p++ = 1 + len;  /* parameter length */
-    *p++ = index;
-    memcpy(p, data, len);
-    p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1+len;
-
-    hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
-
-    retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_DOWNLOAD_FW_PATCH, p_buf, hw_config_cback);
-    return retval;
-}
-
-/*******************************************************************************
-**
-** Function         hw_config_cback
-**
-** Description      Callback function for controller configuration
-**
-** Returns          None
-**
-*******************************************************************************/
-void hw_config_cback(void *p_mem)
-{
-    HC_BT_HDR   *p_evt_buf = NULL;
-    uint8_t     *p = NULL, *pp=NULL;
-    uint8_t     status = 0;
-    uint16_t    opcode = 0;
-    HC_BT_HDR   *p_buf = NULL;
-    uint8_t     is_proceeding = FALSE;
-    int         i = 0;
-    uint8_t     iIndexRx = 0;
-    patch_info* prtk_patch_file_info = NULL;
-    uint32_t    host_baudrate = 0;
-
-#if (USE_CONTROLLER_BDADDR == TRUE)
-    const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
-#endif
-
-    if(p_mem != NULL)
-    {
-        p_evt_buf = (HC_BT_HDR *) p_mem;
-        status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET);
-        p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE_OFFSET;
-        STREAM_TO_UINT16(opcode,p);
-    }
-
-    if(opcode == HCI_VSC_H5_INIT) {
-        if(status != 0) {
-          ALOGE("%s, status = %d", __func__, status);
-          if ((bt_vendor_cbacks) && (p_evt_buf != NULL))
-          bt_vendor_cbacks->dealloc(p_evt_buf);
-          if(rtkbt_auto_restart) {
-              bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
-              kill(getpid(), SIGKILL);
-          }
-          return;
-        }
-    }
-
-    /* Ask a new buffer big enough to hold any HCI commands sent in here */
-    /*a cut fc6d status==1*/
-    if (((status == 0) ||(opcode == HCI_VSC_READ_ROM_VERSION)) && bt_vendor_cbacks)
-        p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_MAX_LEN);
-
-    if (p_buf != NULL)
-    {
-        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
-        p_buf->offset = 0;
-        p_buf->len = 0;
-        p_buf->layer_specific = 0;
-
-        BTVNDDBG("hw_cfg_cb.state = %i", hw_cfg_cb.state);
-        switch (hw_cfg_cb.state)
-        {
-            case HW_CFG_H5_INIT:
-            {
-                p = (uint8_t *)(p_buf + 1);
-                UINT16_TO_STREAM(p, HCI_READ_LMP_VERSION);
-                *p++ = 0;
-                p_buf->len = HCI_CMD_PREAMBLE_SIZE;
-
-                hw_cfg_cb.state = HW_CFG_READ_LOCAL_VER;
-                is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LMP_VERSION, p_buf, hw_config_cback);
-                break;
-            }
-            case HW_CFG_READ_LOCAL_VER:
-            {
-                if (status == 0)
-                {
-                    p = ((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OP1001_HCI_VERSION_OFFSET);
-                    STREAM_TO_UINT16(hw_cfg_cb.hci_version, p);
-                    p = ((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OP1001_HCI_REVISION_OFFSET);
-                    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);
-                    BTVNDDBG("lmp_subversion = 0x%x hw_cfg_cb.hci_version = 0x%x hw_cfg_cb.hci_revision = 0x%x", hw_cfg_cb.lmp_subversion, hw_cfg_cb.hci_version, hw_cfg_cb.hci_revision);
-                    if(hw_cfg_cb.lmp_subversion == LMPSUBVERSION_8723a)
-                    {
-                        hw_cfg_cb.state = HW_CFG_START;
-                        goto CFG_START;
-                    }
-                    else
-                    {
-                        hw_cfg_cb.state = HW_CFG_READ_ECO_VER;
-                        p = (uint8_t *) (p_buf + 1);
-                        UINT16_TO_STREAM(p, HCI_VSC_READ_ROM_VERSION);
-                        *p++ = 0;
-                        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
-                        is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_READ_ROM_VERSION, p_buf, hw_config_cback);
-                    }
-                }
-                break;
-            }
-            case HW_CFG_READ_ECO_VER:
-            {
-                if(status == 0)
-                {
-                    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);
-                }
-                else if(1 == status)
-                {
-                    hw_cfg_cb.eversion = 0;
-                }
-                else
-                {
-                    is_proceeding = FALSE;
-                    break;
-                }
-
-                if(check_match_state(&hw_cfg_cb, 0) > 1)    // check if have multiple matched patch_entry by lmp_subversion,hci_version, hci_revision
-                {
-                    hw_cfg_cb.state = HW_CFG_READ_CHIP_TYPE;
-                     p = (uint8_t *) (p_buf + 1);
-                    UINT16_TO_STREAM(p, HCI_VSC_READ_CHIP_TYPE);
-                    *p++ = 5;
-                    UINT8_TO_STREAM(p, 0x00);
-                    UINT32_TO_STREAM(p, 0xB000A094);
-                    p_buf->len = HCI_CMD_PREAMBLE_SIZE + HCI_CMD_READ_CHIP_TYPE_SIZE;
-
-                    pp = (uint8_t *) (p_buf + 1);
-                    for (i = 0; i < p_buf->len; i++)
-                        BTVNDDBG("get chip type command data[%d]= 0x%x", i, *(pp+i));
-
-                    is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_READ_CHIP_TYPE, p_buf, hw_config_cback);
-                    break;
-                }
-                else
-                {
-                    hw_cfg_cb.state = HW_CFG_START;
-                    goto CFG_START;
-                }
-            }
-            case HW_CFG_READ_CHIP_TYPE:
-            {
-                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++)
-                    BTVNDDBG("READ_CHIP_TYPE event data[%d]= 0x%x", i, *(p+i));
-                if(status == 0)
-                {
-                    hw_cfg_cb.chip_type = ((*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPFC61_CHIPTYPE_OFFSET))&0x0F);
-                    BTVNDDBG("READ_CHIP_TYPE hw_cfg_cb.lmp_subversion = 0x%x", hw_cfg_cb.lmp_subversion);
-                    BTVNDDBG("READ_CHIP_TYPE hw_cfg_cb.hci_version = 0x%x", hw_cfg_cb.hci_version);
-                    BTVNDDBG("READ_CHIP_TYPE hw_cfg_cb.hci_revision = 0x%x", hw_cfg_cb.hci_revision);
-                    BTVNDDBG("READ_CHIP_TYPE hw_cfg_cb.chip_type = 0x%x", hw_cfg_cb.chip_type);
-                }
-                else
-                {
-                    is_proceeding = FALSE;
-                    break;
-                }
-                if(check_match_state(&hw_cfg_cb, PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE) > 1)  // check if have multiple matched patch_entry by lmp_subversion,hci_version, hci_revision and chiptype
-                {
-                    BTVNDDBG("check_match_state(lmp_subversion:0x%04x, hci_version:%d, hci_revision:%d chip_type:%d): Multi Matched Patch\n", hw_cfg_cb.lmp_subversion, hw_cfg_cb.hci_version, hw_cfg_cb.hci_revision, hw_cfg_cb.chip_type);
-                    is_proceeding = FALSE;
-                    break;
-                }
-                hw_cfg_cb.state = HW_CFG_START;
-            }
-CFG_START:
-            case HW_CFG_START:
-            {
-#ifdef BT_CHIP_PROBE_SIMULATION
-                {
-                    int ii;
-                    memcpy(&hw_cfg_test, &hw_cfg_cb, sizeof(hw_cfg_test));
-                    for(i=0;i<sizeof(bt_chip_chars)/sizeof(bt_chip_chars[0]);i++)
-                    {
-                        BTVNDDBG("BT_CHIP_PROBE_SIMULATION loop:%d $$$ BEGIN $$$\n", i);
-                        hw_cfg_test.lmp_subversion = bt_chip_chars[i].lmp_subversion;
-                        hw_cfg_test.hci_version = bt_chip_chars[i].hci_version;
-                        hw_cfg_test.hci_revision = bt_chip_chars[i].hci_revision;
-                        hw_cfg_test.chip_type = CHIPTYPE_NONE;
-                        if(check_match_state(&hw_cfg_test, 0) > 1){
-                            BTVNDDBG("check_match_state hw_cfg_test(lmp_subversion:0x%04x, hci_version:%d, hci_revision:%d chip_type:%d): Multi Matched Patch\n", hw_cfg_test.lmp_subversion, hw_cfg_test.hci_version, hw_cfg_test.hci_revision, hw_cfg_test.chip_type);
-                            if(bt_chip_chars[i].chip_type != CHIPTYPE_NONE){
-                                BTVNDDBG("BT_CHIP_PROBE_SIMULATION loop:%d *** Include ChipType ***\n", i);
-                                hw_cfg_test.chip_type = bt_chip_chars[i].chip_type;
-                                if(check_match_state(&hw_cfg_test, PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE) > 1){
-                                    BTVNDDBG("check_match_state hw_cfg_test(lmp_subversion:0x%04x, hci_version:%d, hci_revision:%d chip_type:%d): Multi Matched Patch\n", hw_cfg_test.lmp_subversion, hw_cfg_test.hci_version, hw_cfg_test.hci_revision, hw_cfg_test.chip_type);
-                                }else{
-                                    prtk_patch_file_info = get_patch_entry(&hw_cfg_test);
-                                }
-                            }
-                        }else{
-                            prtk_patch_file_info = get_patch_entry(&hw_cfg_test);
-                        }
-                        BTVNDDBG("BT_CHIP_PROBE_SIMULATION loop:%d $$$ END $$$\n", i);
-                    }
-                }
-#endif
-                //get efuse config file and patch code file
-                prtk_patch_file_info = get_patch_entry(&hw_cfg_cb);
-
-
-                if((prtk_patch_file_info == NULL) || (prtk_patch_file_info->lmp_subversion == 0))
-                {
-                    ALOGE("get patch entry error");
-                    is_proceeding = FALSE;
-                    break;
-                }
-                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)
-                {
-                    ALOGE("Get Config file fail, just use efuse settings");
-                    hw_cfg_cb.config_len = 0;
-                }
-                rtk_update_altsettings(prtk_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_patch_file_info->patch_name);
-                if (hw_cfg_cb.fw_len < 0)
-                {
-                    ALOGE("Get BT firmware fail");
-                    hw_cfg_cb.fw_len = 0;
-                }
-                else{
-                    hw_cfg_cb.project_id_mask = prtk_patch_file_info->project_id_mask;
-                    rtk_get_bt_final_patch(&hw_cfg_cb);
-                }
-                BTVNDDBG("Check total_len(0x%08x) max_patch_size(0x%08x)", hw_cfg_cb.total_len, hw_cfg_cb.max_patch_size);
-                if (hw_cfg_cb.total_len > hw_cfg_cb.max_patch_size)
-                {
-                    ALOGE("total length of fw&config(0x%08x) larger than max_patch_size(0x%08x)", hw_cfg_cb.total_len, hw_cfg_cb.max_patch_size);
-                    is_proceeding = FALSE;
-                    break;
-                }
-
-                if ((hw_cfg_cb.total_len > 0) && hw_cfg_cb.dl_fw_flag)
-                {
-                    hw_cfg_cb.patch_frag_cnt = hw_cfg_cb.total_len / PATCH_DATA_FIELD_MAX_SIZE;
-                    hw_cfg_cb.patch_frag_tail = hw_cfg_cb.total_len % PATCH_DATA_FIELD_MAX_SIZE;
-                    if (hw_cfg_cb.patch_frag_tail)
-                        hw_cfg_cb.patch_frag_cnt += 1;
-                    else
-                        hw_cfg_cb.patch_frag_tail = PATCH_DATA_FIELD_MAX_SIZE;
-                    BTVNDDBG("patch fragment count %d, tail len %d", hw_cfg_cb.patch_frag_cnt, hw_cfg_cb.patch_frag_tail);
-                }
-                else
-                {
-                    is_proceeding = FALSE;
-                    break;
-                }
-
-                if ((hw_cfg_cb.baudrate == 0) && ((hw_cfg_cb.hw_flow_cntrl & 0x80) == 0))
-                {
-                    BTVNDDBG("no baudrate to set and no need to set hw flow control");
-                    goto DOWNLOAD_FW;
-                }
-
-                if ((hw_cfg_cb.baudrate == 0) && (hw_cfg_cb.hw_flow_cntrl & 0x80))
-                {
-                    BTVNDDBG("no baudrate to set but set hw flow control is needed");
-                    goto SET_HW_FLCNTRL;
-                }
-            }
-            /* fall through intentionally */
-            case HW_CFG_SET_UART_BAUD_CONTROLLER:
-                BTVNDDBG("bt vendor lib: set CONTROLLER UART baud 0x%x", hw_cfg_cb.baudrate);
-                hw_cfg_cb.state = HW_CFG_SET_UART_BAUD_HOST;
-                is_proceeding = hw_config_set_controller_baudrate(p_buf, hw_cfg_cb.baudrate);
-                break;
-
-            case HW_CFG_SET_UART_BAUD_HOST:
-                /* update baud rate of host's UART port */
-                rtk_speed_to_uart_speed(hw_cfg_cb.baudrate, &host_baudrate);
-                BTVNDDBG("bt vendor lib: set HOST UART baud %i", host_baudrate);
-                userial_vendor_set_baud(line_speed_to_userial_baud(host_baudrate));
-
-                if((hw_cfg_cb.hw_flow_cntrl & 0x80) == 0)
-                    goto DOWNLOAD_FW;
-
-SET_HW_FLCNTRL:
-            case HW_CFG_SET_UART_HW_FLOW_CONTROL:
-                BTVNDDBG("Change HW flowcontrol setting");
-                if(hw_cfg_cb.hw_flow_cntrl & 0x01)
-                {
-                    userial_vendor_set_hw_fctrl(1);
-                }
-                else
-                {
-                    userial_vendor_set_hw_fctrl(0);
-                }
-                ms_delay(100);
-                hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
-
-DOWNLOAD_FW:
-            case HW_CFG_DL_FW_PATCH:
-                BTVNDDBG("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, opcode:0x%x", status, opcode);
-
-                //recv command complete event for patch code download command
-                if(opcode == HCI_VSC_DOWNLOAD_FW_PATCH)
-                {
-                    iIndexRx = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET + 1);
-                    BTVNDDBG("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, iIndexRx:%i", status, iIndexRx);
-                    hw_cfg_cb.patch_frag_idx++;
-
-                    if(iIndexRx&0x80)
-                    {
-                        BTVNDDBG("vendor lib fwcfg completed");
-                        free(hw_cfg_cb.total_buf);
-                        hw_cfg_cb.total_len = 0;
-
-                        bt_vendor_cbacks->dealloc(p_buf);
-                        bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
-
-                        hw_cfg_cb.state = 0;
-                        is_proceeding = TRUE;
-                        break;
-                    }
-                }
-
-                if (hw_cfg_cb.patch_frag_idx < hw_cfg_cb.patch_frag_cnt)
-                {
-                    iIndexRx = hw_cfg_cb.patch_frag_idx?((hw_cfg_cb.patch_frag_idx-1)%0x7f+1):0;
-                    if (hw_cfg_cb.patch_frag_idx == hw_cfg_cb.patch_frag_cnt - 1)
-                    {
-                        BTVNDDBG("HW_CFG_DL_FW_PATCH: send last fw fragment");
-                        iIndexRx |= 0x80;
-                        hw_cfg_cb.patch_frag_len = hw_cfg_cb.patch_frag_tail;
-                    }
-                    else
-                    {
-                        iIndexRx &= 0x7F;
-                        hw_cfg_cb.patch_frag_len = PATCH_DATA_FIELD_MAX_SIZE;
-                    }
-                }
-
-                is_proceeding = hci_download_patch_h4(p_buf, iIndexRx,
-                                    hw_cfg_cb.total_buf+(hw_cfg_cb.patch_frag_idx*PATCH_DATA_FIELD_MAX_SIZE),
-                                    hw_cfg_cb.patch_frag_len);
-                break;
-
-            default:
-                break;
-        } // switch(hw_cfg_cb.state)
-    } // if (p_buf != NULL)
-
-    /* Free the RX event buffer */
-    if ((bt_vendor_cbacks) && (p_evt_buf != NULL))
-        bt_vendor_cbacks->dealloc(p_evt_buf);
-
-    if (is_proceeding == FALSE)
-    {
-        ALOGE("vendor lib fwcfg aborted!!!");
-        if (bt_vendor_cbacks)
-        {
-            if (p_buf != NULL)
-                bt_vendor_cbacks->dealloc(p_buf);
-
-            bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
-        }
-
-        if(hw_cfg_cb.config_len)
-        {
-            free(hw_cfg_cb.config_buf);
-            hw_cfg_cb.config_len = 0;
-        }
-
-        if(hw_cfg_cb.fw_len)
-        {
-            free(hw_cfg_cb.fw_buf);
-            hw_cfg_cb.fw_len= 0;
-        }
-
-        if(hw_cfg_cb.total_len)
-        {
-            free(hw_cfg_cb.total_buf);
-            hw_cfg_cb.total_len = 0;
-        }
-        hw_cfg_cb.state = 0;
-    }
-}
-
 /******************************************************************************
 **   LPM Static Functions
 ******************************************************************************/
@@ -1465,71 +272,6 @@ void hw_lpm_ctrl_cback(void *p_mem)
 }
 
 
-/*****************************************************************************
-**   Hardware Configuration Interface Functions
-*****************************************************************************/
-
-
-/*******************************************************************************
-**
-** Function        hw_config_start
-**
-** Description     Kick off controller initialization process
-**
-** Returns         None
-**
-*******************************************************************************/
-void hw_config_start(char 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;
-    BTVNDDBG("RTKBT_RELEASE_NAME: %s",RTKBT_RELEASE_NAME);
-    BTVNDDBG("\nRealtek libbt-vendor_uart Version %s \n",RTK_VERSION);
-    HC_BT_HDR  *p_buf = NULL;
-    uint8_t     *p;
-
-    BTVNDDBG("hw_config_start, transtype = 0x%x \n", transtype);
-    /* Start from sending H5 INIT */
-    if (bt_vendor_cbacks)
-    {
-        /* Must allocate command buffer via HC's alloc API */
-        p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
-                                                       HCI_CMD_PREAMBLE_SIZE);
-        if(p_buf)
-        {
-            p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
-            p_buf->offset = 0;
-            p_buf->layer_specific = 0;
-            p_buf->len = HCI_CMD_PREAMBLE_SIZE;
-
-            p = (uint8_t *) (p_buf + 1);
-
-            if(transtype & RTKBT_TRANS_H4) {
-                p = (uint8_t *)(p_buf + 1);
-                UINT16_TO_STREAM(p, HCI_READ_LMP_VERSION);
-                *p++ = 0;
-                p_buf->len = HCI_CMD_PREAMBLE_SIZE;
-
-                hw_cfg_cb.state = HW_CFG_READ_LOCAL_VER;
-                bt_vendor_cbacks->xmit_cb(HCI_READ_LMP_VERSION, p_buf, hw_config_cback);
-            }
-            else {
-                UINT16_TO_STREAM(p, HCI_VSC_H5_INIT);
-                *p = 0; /* parameter length */
-                hw_cfg_cb.state = HW_CFG_H5_INIT;
-
-                bt_vendor_cbacks->xmit_cb(HCI_VSC_H5_INIT, p_buf, hw_config_cback);
-            }
-        }
-        else {
-            ALOGE("%s buffer alloc fail!", __func__);
-        }
-    }
-    else
-        ALOGE("%s call back is null", __func__);
-}
-
 #if (HW_END_WITH_HCI_RESET == TRUE)
 /******************************************************************************
 *
diff --git a/rtkbt/code/libbt-vendor/src/hardware_uart.c b/rtkbt/code/libbt-vendor/src/hardware_uart.c
new file mode 100755 (executable)
index 0000000..d92630b
--- /dev/null
@@ -0,0 +1,1233 @@
+#define LOG_TAG "bt_hwcfg_uart"
+#define RTKBT_RELEASE_NAME     "20180525_BT_ANDROID_8.1"
+
+#include <utils/Log.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <cutils/properties.h>
+#include <stdlib.h>
+#include "bt_hci_bdroid.h"
+#include "bt_vendor_rtk.h"
+#include "userial.h"
+#include "userial_vendor.h"
+#include "upio.h"
+#include <unistd.h>
+#include <endian.h>
+#include <byteswap.h>
+#include <unistd.h>
+
+#include "bt_vendor_lib.h"
+#include "hardware.h"
+
+/******************************************************************************
+**  Constants &  Macros
+******************************************************************************/
+#define RTK_VERSION "4.1.1"
+
+extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
+extern bool rtkbt_auto_restart;
+extern bt_hw_cfg_cb_t hw_cfg_cb;
+void hw_config_cback(void *p_evt_buf);
+extern int getmacaddr(unsigned char * addr);
+extern uint8_t rtk_get_fw_project_id(uint8_t *p_buf);
+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);
+
+
+
+
+/******************************************************************************
+**  Static variables
+******************************************************************************/
+//static bt_hw_cfg_cb_t hw_cfg_cb;
+
+//#define BT_CHIP_PROBE_SIMULATION
+#ifdef BT_CHIP_PROBE_SIMULATION
+static bt_hw_cfg_cb_t hw_cfg_test;
+struct bt_chip_char{
+    uint16_t    lmp_subversion;
+    uint8_t     hci_version;
+    uint8_t     hci_revision;
+    uint8_t     chip_type;
+};
+struct bt_chip_char bt_chip_chars[] = \
+{
+        {0x8723, 0x4, 0xb, CHIPTYPE_NONE},      //8703as
+        {0x8723, 0x6, 0xb, CHIPTYPE_NONE},      //8723bs
+        {0x8703, 0x4, 0xd, 0x7},                //8703bs
+        {0x8703, 0x6, 0xb, 0x3},                //8723cs-cg
+        {0x8703, 0x6, 0xb, 0x4},                //8723cs-vf
+        {0x8703, 0x6, 0xb, 0x5},                //8723cs-xx
+        {0x8723, 0x6, 0xd, CHIPTYPE_NONE},      //8723ds
+};
+#endif
+
+typedef struct {
+    uint16_t    lmp_subversion;
+    uint32_t     hci_version_mask;
+    uint32_t     hci_revision_mask;
+    uint32_t     chip_type_mask;
+    uint32_t     project_id_mask;
+    char        *patch_name;
+    char        *config_name;
+    uint16_t     mac_offset;
+    uint32_t    max_patch_size;
+} patch_info;
+
+static patch_info patch_table[] = {
+/*    lmp_subv                      hci_version_mask                    hci_revision_mask                chip_type_mask              project_id_mask                 fw name                                 config name                         mac offset                         max_patch_size  */
+    {0x1200,            HCI_VERSION_MASK_ALL,    HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL,  1<<0,                  "rtl8723as_fw",         "rtl8723as_config",     CONFIG_MAC_OFFSET_GEN_1_2,  MAX_PATCH_SIZE_24K},    //Rtl8723AS
+
+    {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
+    {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
+
+    {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
+    {0x8821,            HCI_VERSION_MASK_ALL,    (1<<0xc),              CHIP_TYPE_MASK_ALL,  1<<10,                 "rtl8821cs_fw",         "rtl8821cs_config",     CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_40K}, //RTL8821CS
+/*  todo: RTL8703CS */
+
+    {LMP_SUBVERSION_NONE,HCI_VERSION_MASK_ALL,   HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, PROJECT_ID_MASK_ALL,    "rtl_none_fw",          "rtl_none_config",      CONFIG_MAC_OFFSET_GEN_1_2,  MAX_PATCH_SIZE_24K}
+};
+
+/*
+static bt_lpm_param_t lpm_param =
+{
+    LPM_SLEEP_MODE,
+    LPM_IDLE_THRESHOLD,
+    LPM_HC_IDLE_THRESHOLD,
+    LPM_BT_WAKE_POLARITY,
+    LPM_HOST_WAKE_POLARITY,
+    LPM_ALLOW_HOST_SLEEP_DURING_SCO,
+    LPM_COMBINE_SLEEP_MODE_AND_LPM,
+    LPM_ENABLE_UART_TXD_TRI_STATE,*/
+    //0,  /* not applicable */
+   // 0,  /* not applicable */
+   // 0,  /* not applicable */
+    /*LPM_PULSED_HOST_WAKE
+};*/
+//signature: realtech
+static const uint8_t RTK_EPATCH_SIGNATURE[8]={0x52,0x65,0x61,0x6C,0x74,0x65,0x63,0x68};
+//Extension Section IGNATURE:0x77FD0451
+static const uint8_t EXTENSION_SECTION_SIGNATURE[4]={0x51,0x04,0xFD,0x77};
+
+static int check_match_state(bt_hw_cfg_cb_t *cfg,uint32_t mask)
+{
+    patch_info  *patch_entry;
+    int res = 0;
+
+    for(patch_entry = patch_table; patch_entry->lmp_subversion != LMP_SUBVERSION_NONE; patch_entry++) {
+        if(patch_entry->lmp_subversion != cfg->lmp_subversion)
+            continue;
+        if((patch_entry->hci_version_mask!=HCI_VERSION_MASK_ALL)&&((patch_entry->hci_version_mask&(1<<cfg->hci_version))==0))
+             continue;
+        if((patch_entry->hci_revision_mask!=HCI_REVISION_MASK_ALL)&&((patch_entry->hci_revision_mask&(1<<cfg->hci_revision))==0))
+             continue;
+        if((mask&PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE)&&(patch_entry->chip_type_mask != CHIP_TYPE_MASK_ALL)&&((patch_entry->chip_type_mask&(1<<cfg->chip_type))==0))
+             continue;
+        res++;
+    }
+    ALOGI( "check_match_state return %d(cfg->lmp_subversion:0x%x cfg->hci_vesion:0x%x cfg->hci_revision:0x%x cfg->chip_type:0x%x mask:%08x)\n",
+            res, cfg->lmp_subversion, cfg->hci_version, cfg->hci_revision, cfg->chip_type, mask);
+    return res;
+}
+
+static patch_info* get_patch_entry(bt_hw_cfg_cb_t *cfg)
+{
+    patch_info  *patch_entry;
+
+    ALOGI("get_patch_entry(lmp_subversion:0x%x hci_vesion:0x%x cfg->hci_revision:0x%x chip_type:0x%x)\n",
+            cfg->lmp_subversion, cfg->hci_version, cfg->hci_revision, cfg->chip_type);
+    for(patch_entry = patch_table; patch_entry->lmp_subversion != LMP_SUBVERSION_NONE; patch_entry++) {
+        if(patch_entry->lmp_subversion != cfg->lmp_subversion)
+            continue;
+        if((patch_entry->hci_version_mask != HCI_VERSION_MASK_ALL)&&((patch_entry->hci_version_mask&(1<<cfg->hci_version)) == 0))
+             continue;
+        if((patch_entry->hci_revision_mask != HCI_REVISION_MASK_ALL)&&((patch_entry->hci_revision_mask&(1<<cfg->hci_revision)) == 0))
+             continue;
+        if((patch_entry->chip_type_mask != CHIP_TYPE_MASK_ALL)&&((patch_entry->chip_type_mask&(1<<cfg->chip_type)) == 0))
+             continue;
+        break;
+    }
+    ALOGI("get_patch_entry return(patch_name:%s config_name:%s mac_offset:0x%x)\n",
+            patch_entry->patch_name, patch_entry->config_name, patch_entry->mac_offset);
+    return patch_entry;
+}
+
+typedef struct _baudrate_ex
+{
+    uint32_t rtk_speed;
+    uint32_t uart_speed;
+}baudrate_ex;
+
+baudrate_ex baudrates[] =
+{
+    {0x00006004, 921600},
+    {0x05F75004, 921600},//RTL8723BS
+    {0x00004003, 1500000},
+    {0x04928002, 1500000},//RTL8723BS
+    {0x00005002, 2000000},//same as RTL8723AS
+    {0x00008001, 3000000},
+    {0x04928001, 3000000},//RTL8723BS
+    {0x06B58001, 3000000},//add RTL8703as
+    {0x00007001, 3500000},
+    {0x052A6001, 3500000},//RTL8723BS
+    {0x00005001, 4000000},//same as RTL8723AS
+    {0x0000701d, 115200},
+    {0x0252C014, 115200}//RTL8723BS
+};
+
+/**
+* Change realtek Bluetooth speed to uart speed. It is matching in the struct baudrates:
+*
+* @code
+* baudrate_ex baudrates[] =
+* {
+*   {0x7001, 3500000},
+*   {0x6004, 921600},
+*   {0x4003, 1500000},
+*   {0x5001, 4000000},
+*   {0x5002, 2000000},
+*   {0x8001, 3000000},
+*   {0x701d, 115200}
+* };
+* @endcode
+*
+* If there is no match in baudrates, uart speed will be set as #115200.
+*
+* @param rtk_speed realtek Bluetooth speed
+* @param uart_speed uart speed
+*
+*/
+static void rtk_speed_to_uart_speed(uint32_t rtk_speed, uint32_t* uart_speed)
+{
+    *uart_speed = 115200;
+
+    uint8_t i;
+    for (i=0; i< sizeof(baudrates)/sizeof(baudrate_ex); i++)
+    {
+        if (baudrates[i].rtk_speed == rtk_speed)
+        {
+            *uart_speed = baudrates[i].uart_speed;
+            return;
+        }
+    }
+    return;
+}
+
+/**
+* Change uart speed to realtek Bluetooth speed. It is matching in the struct baudrates:
+*
+* @code
+* baudrate_ex baudrates[] =
+* {
+*   {0x7001, 3500000},
+*   {0x6004, 921600},
+*   {0x4003, 1500000},
+*   {0x5001, 4000000},
+*   {0x5002, 2000000},
+*   {0x8001, 3000000},
+*   {0x701d, 115200}
+* };
+* @endcode
+*
+* If there is no match in baudrates, realtek Bluetooth speed will be set as #0x701D.
+*
+* @param uart_speed uart speed
+* @param rtk_speed realtek Bluetooth speed
+*
+*//*
+static inline void uart_speed_to_rtk_speed(uint32_t uart_speed, uint32_t* rtk_speed)
+{
+    *rtk_speed = 0x701D;
+
+    unsigned int i;
+    for (i=0; i< sizeof(baudrates)/sizeof(baudrate_ex); i++)
+    {
+      if (baudrates[i].uart_speed == uart_speed)
+      {
+          *rtk_speed = baudrates[i].rtk_speed;
+          return;
+      }
+    }
+    return;
+}
+*/
+
+/*******************************************************************************
+**
+** Function         hw_config_set_bdaddr
+**
+** Description      Program controller's Bluetooth Device Address
+**
+** Returns          TRUE, if valid address is sent
+**                  FALSE, otherwise
+**
+*******************************************************************************/
+static uint8_t hw_config_set_controller_baudrate(HC_BT_HDR *p_buf, uint32_t baudrate)
+{
+    uint8_t retval = FALSE;
+    uint8_t *p = (uint8_t *) (p_buf + 1);
+
+    UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE);
+    *p++ = 4; /* parameter length */
+    UINT32_TO_STREAM(p, baudrate);
+
+    p_buf->len = HCI_CMD_PREAMBLE_SIZE + 4;
+
+    retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, p_buf, \
+                                 hw_config_cback);
+
+    return (retval);
+}
+
+/*******************************************************************************
+**
+** Function        line_speed_to_userial_baud
+**
+** Description     helper function converts line speed number into USERIAL baud
+**                 rate symbol
+**
+** Returns         unit8_t (USERIAL baud symbol)
+**
+*******************************************************************************/
+static uint8_t line_speed_to_userial_baud(uint32_t line_speed)
+{
+    uint8_t baud;
+
+    if (line_speed == 4000000)
+        baud = USERIAL_BAUD_4M;
+    else if (line_speed == 3000000)
+        baud = USERIAL_BAUD_3M;
+    else if (line_speed == 2000000)
+        baud = USERIAL_BAUD_2M;
+    else if (line_speed == 1500000)
+        baud = USERIAL_BAUD_1_5M;
+    else if (line_speed == 1000000)
+        baud = USERIAL_BAUD_1M;
+    else if (line_speed == 921600)
+        baud = USERIAL_BAUD_921600;
+    else if (line_speed == 460800)
+        baud = USERIAL_BAUD_460800;
+    else if (line_speed == 230400)
+        baud = USERIAL_BAUD_230400;
+    else if (line_speed == 115200)
+        baud = USERIAL_BAUD_115200;
+    else if (line_speed == 57600)
+        baud = USERIAL_BAUD_57600;
+    else if (line_speed == 19200)
+        baud = USERIAL_BAUD_19200;
+    else if (line_speed == 9600)
+        baud = USERIAL_BAUD_9600;
+    else if (line_speed == 1200)
+        baud = USERIAL_BAUD_1200;
+    else if (line_speed == 600)
+        baud = USERIAL_BAUD_600;
+    else
+    {
+        ALOGE( "userial vendor: unsupported baud speed %d", line_speed);
+        baud = USERIAL_BAUD_115200;
+    }
+
+    return baud;
+}
+
+
+
+/**
+* Change uart speed to realtek Bluetooth speed. It is matching in the struct baudrates:
+*
+* @code
+* baudrate_ex baudrates[] =
+* {
+*   {0x7001, 3500000},
+*   {0x6004, 921600},
+*   {0x4003, 1500000},
+*   {0x5001, 4000000},
+*   {0x5002, 2000000},
+*   {0x8001, 3000000},
+*   {0x701d, 115200}
+* };
+* @endcode
+*
+* If there is no match in baudrates, realtek Bluetooth speed will be set as #0x701D.
+*
+* @param uart_speed uart speed
+* @param rtk_speed realtek Bluetooth speed
+*
+*//*
+static inline void uart_speed_to_rtk_speed(uint32_t uart_speed, uint32_t* rtk_speed)
+{
+    *rtk_speed = 0x701D;
+
+    unsigned int i;
+    for (i=0; i< sizeof(baudrates)/sizeof(baudrate_ex); i++)
+    {
+      if (baudrates[i].uart_speed == uart_speed)
+      {
+          *rtk_speed = baudrates[i].rtk_speed;
+          return;
+      }
+    }
+    return;
+}
+*/
+
+
+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;
+/*
+//sample code, add special settings
+
+    offset[n++] = 0x15B;
+*/
+    return n;
+}
+static inline int getAltSettingVal(patch_info *patch_entry, unsigned short offset, unsigned char * val)
+{
+    int res = 0;
+
+    switch(offset)
+    {
+/*
+//sample code, add special settings
+        case 0x15B:
+            val[0] = 0x0B;
+            val[1] = 0x0B;
+            val[2] = 0x0B;
+            val[3] = 0x0B;
+            res = 4;
+            break;
+*/
+        default:
+            res = 0;
+            break;
+    }
+    if((patch_entry)&&(offset == patch_entry->mac_offset)&&(res == 0))
+    {
+        if(getmacaddr(val) == 0){
+            ALOGI("MAC: %02x:%02x:%02x:%02x:%02x:%02x", val[5], val[4], val[3], val[2], val[1], val[0]);
+            res = 6;
+        }
+    }
+    return res;
+}
+
+
+static void rtk_update_altsettings(patch_info *patch_entry, unsigned char* config_buf_ptr, size_t *config_len_ptr)
+{
+    unsigned short offset[256], data_len;
+    unsigned char val[256];
+
+    struct rtk_bt_vendor_config* config = (struct rtk_bt_vendor_config*) config_buf_ptr;
+    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;
+
+    ALOGI("ORG Config len=%08zx:\n", config_len);
+    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], \
+            config_buf_ptr[i+8], config_buf_ptr[i+9], config_buf_ptr[i+10], config_buf_ptr[i+11], config_buf_ptr[i+12], config_buf_ptr[i+13], config_buf_ptr[i+14], config_buf_ptr[i+15]);
+    }
+
+    memset(offset, 0, sizeof(offset));
+    memset(val, 0, sizeof(val));
+    data_len = le16_to_cpu(config->data_len);
+
+    count = getAltSettings(patch_entry, offset);//getAltSettings(patch_entry, offset, sizeof(offset)/sizeof(unsigned short));
+    if(count <= 0){
+        ALOGI("rtk_update_altsettings: No AltSettings");
+        return;
+    }else{
+        ALOGI("rtk_update_altsettings: %d AltSettings", count);
+    }
+
+    if (data_len != config_len - sizeof(struct rtk_bt_vendor_config))
+    {
+        ALOGE("rtk_update_altsettings: config len(%x) is not right(%lx)", data_len, (unsigned long)(config_len-sizeof(struct rtk_bt_vendor_config)));
+        return;
+    }
+
+    for (i=0; i<data_len;)
+    {
+        for(j = 0; j < count;j++)
+        {
+            if(le16_to_cpu(entry->offset) == offset[j])
+                offset[j] = 0;
+        }
+        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);
+            memcpy(entry->entry_data, val, entry->entry_len);
+        }
+        temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
+        i += temp;
+        entry = (struct rtk_bt_vendor_config_entry*)((uint8_t*)entry + temp);
+    }
+    for(j = 0; j < count;j++){
+        if(offset[j] == 0)
+            continue;
+        entry->entry_len = getAltSettingVal(patch_entry, offset[j], val);
+        if(entry->entry_len <= 0)
+            continue;
+        entry->offset = cpu_to_le16(offset[j]);
+        memcpy(entry->entry_data, val, entry->entry_len);
+        ALOGI("rtk_update_altsettings: add %04x[%02x]", le16_to_cpu(entry->offset), entry->entry_len);
+        temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
+        i += temp;
+        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);
+
+    ALOGI("NEW Config len=%08zx:\n", *config_len_ptr);
+    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], \
+            config_buf_ptr[i+8], config_buf_ptr[i+9], config_buf_ptr[i+10], config_buf_ptr[i+11], config_buf_ptr[i+12], config_buf_ptr[i+13], config_buf_ptr[i+14], config_buf_ptr[i+15]);
+    }
+    return;
+}
+
+
+static uint32_t rtk_parse_config_file(unsigned char** config_buf, size_t* filelen, uint8_t bt_addr[6], uint16_t mac_offset)
+{
+    struct rtk_bt_vendor_config* config = (struct rtk_bt_vendor_config*) *config_buf;
+    uint16_t config_len = le16_to_cpu(config->data_len), temp = 0;
+    struct rtk_bt_vendor_config_entry* entry = config->entry;
+    unsigned int i = 0;
+    uint32_t baudrate = 0;
+    uint8_t  heartbeat_buf = 0;
+    //uint32_t config_has_bdaddr = 0;
+    uint8_t *p;
+
+       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);
+        return 0;
+    }
+
+    if (config_len != *filelen - sizeof(struct rtk_bt_vendor_config))
+    {
+        ALOGE("config len(0x%x) is not right(0x%lx)", config_len, (unsigned long)(*filelen-sizeof(struct rtk_bt_vendor_config)));
+        return 0;
+    }
+
+    hw_cfg_cb.heartbeat = 0;
+    for (i=0; i<config_len;)
+    {
+        switch(le16_to_cpu(entry->offset))
+        {
+            case 0xc:
+            {
+                p = (uint8_t *)entry->entry_data;
+                STREAM_TO_UINT32(baudrate, p);
+                if (entry->entry_len >= 12)
+                {
+                    hw_cfg_cb.hw_flow_cntrl |= 0x80; /* bit7 set hw flow control */
+                    if (entry->entry_data[12] & 0x04) /* offset 0x18, bit2 */
+                        hw_cfg_cb.hw_flow_cntrl |= 1; /* bit0 enable hw flow control */
+                }
+
+                ALOGI("config baud rate to :0x%08x, hwflowcontrol:0x%x, 0x%x", baudrate, entry->entry_data[12], hw_cfg_cb.hw_flow_cntrl);
+                break;
+            }
+            case 0x017a:
+            {
+                if(mac_offset == CONFIG_MAC_OFFSET_GEN_1_2)
+                {
+                    p = (uint8_t *)entry->entry_data;
+                    STREAM_TO_UINT8(heartbeat_buf, p);
+                    if((heartbeat_buf & 0x02) && (heartbeat_buf & 0x10))
+                        hw_cfg_cb.heartbeat = 1;
+                    else
+                        hw_cfg_cb.heartbeat = 0;
+
+                    ALOGI("config 0x017a heartbeat = %d",hw_cfg_cb.heartbeat);
+                }
+                break;
+            }
+            case 0x01be:
+            {
+                if(mac_offset == CONFIG_MAC_OFFSET_GEN_3PLUS)
+                {
+                    p = (uint8_t *)entry->entry_data;
+                    STREAM_TO_UINT8(heartbeat_buf, p);
+                    if((heartbeat_buf & 0x02) && (heartbeat_buf & 0x10))
+                        hw_cfg_cb.heartbeat = 1;
+                    else
+                        hw_cfg_cb.heartbeat = 0;
+
+                    ALOGI("config 0x01be heartbeat = %d",hw_cfg_cb.heartbeat);
+                }
+                break;
+            }
+            default:
+                ALOGI("config offset(0x%x),length(0x%x)", entry->offset, entry->entry_len);
+                break;
+        }
+        temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
+        i += temp;
+        entry = (struct rtk_bt_vendor_config_entry*)((uint8_t*)entry + temp);
+    }
+
+    return baudrate;
+}
+
+static void rtk_get_bt_final_patch(bt_hw_cfg_cb_t* cfg_cb)
+{
+    uint8_t proj_id = 0;
+    struct rtk_epatch_entry* entry = NULL;
+    struct rtk_epatch *patch = (struct rtk_epatch *)cfg_cb->fw_buf;
+    //int iBtCalLen = 0;
+
+    if(cfg_cb->lmp_subversion == LMPSUBVERSION_8723a)
+    {
+        if(memcmp(cfg_cb->fw_buf, RTK_EPATCH_SIGNATURE, 8) == 0)
+        {
+            ALOGE("8723as check signature error!");
+            cfg_cb->dl_fw_flag = 0;
+            goto free_buf;
+        }
+        else
+        {
+            cfg_cb->total_len = cfg_cb->fw_len + cfg_cb->config_len;
+            if (!(cfg_cb->total_buf = malloc(cfg_cb->total_len)))
+            {
+                ALOGE("can't alloc memory for fw&config, errno:%d", errno);
+                cfg_cb->dl_fw_flag = 0;
+                goto free_buf;
+            }
+            else
+            {
+                ALOGI("8723as, fw copy direct");
+                memcpy(cfg_cb->total_buf, cfg_cb->fw_buf, cfg_cb->fw_len);
+                memcpy(cfg_cb->total_buf+cfg_cb->fw_len, cfg_cb->config_buf, cfg_cb->config_len);
+                cfg_cb->dl_fw_flag = 1;
+                goto free_buf;
+            }
+        }
+    }
+
+    if (memcmp(cfg_cb->fw_buf, RTK_EPATCH_SIGNATURE, 8))
+    {
+        ALOGE("check signature error");
+        cfg_cb->dl_fw_flag = 0;
+        goto free_buf;
+    }
+
+    /* check the extension section signature */
+    if (memcmp(cfg_cb->fw_buf + cfg_cb->fw_len - 4, EXTENSION_SECTION_SIGNATURE, 4))
+    {
+        ALOGE("check extension section signature error");
+        cfg_cb->dl_fw_flag = 0;
+        goto free_buf;
+    }
+
+    proj_id = rtk_get_fw_project_id(cfg_cb->fw_buf + cfg_cb->fw_len - 5);
+
+    if((hw_cfg_cb.project_id_mask != PROJECT_ID_MASK_ALL)&& ((hw_cfg_cb.project_id_mask&(1<<proj_id)) ==0))
+    {
+        ALOGE("hw_cfg_cb.project_id_mask is 0x%08x, fw project_id is %d, does not match!!!",
+                        hw_cfg_cb.project_id_mask, proj_id);
+        cfg_cb->dl_fw_flag = 0;
+        goto free_buf;
+    }
+
+    entry = rtk_get_patch_entry(cfg_cb);
+    if (entry)
+    {
+        cfg_cb->total_len = entry->patch_length + cfg_cb->config_len;
+    }
+    else
+    {
+        cfg_cb->dl_fw_flag = 0;
+        goto free_buf;
+    }
+
+    ALOGI("total_len = 0x%x", cfg_cb->total_len);
+
+    if (!(cfg_cb->total_buf = malloc(cfg_cb->total_len)))
+    {
+        ALOGE("Can't alloc memory for multi fw&config, errno:%d", errno);
+        cfg_cb->dl_fw_flag = 0;
+        goto free_buf;
+    }
+    else
+    {
+        memcpy(cfg_cb->total_buf, cfg_cb->fw_buf + entry->patch_offset, entry->patch_length);
+        memcpy(cfg_cb->total_buf + entry->patch_length - 4, &patch->fw_version, 4);
+        memcpy(&entry->svn_version, cfg_cb->total_buf + entry->patch_length - 8, 4);
+        memcpy(&entry->coex_version, cfg_cb->total_buf + entry->patch_length - 12, 4);
+        ALOGI("BTCOEX:20%06d-%04x svn_version:%d lmp_subversion:0x%x hci_version:0x%x hci_revision:0x%x chip_type:%d Cut:%d libbt-vendor_uart version:%s\n",
+        ((entry->coex_version >> 16) & 0x7ff) + ((entry->coex_version >> 27) * 10000),
+        (entry->coex_version & 0xffff), entry->svn_version, cfg_cb->lmp_subversion, cfg_cb->hci_version, cfg_cb->hci_revision, cfg_cb->chip_type, cfg_cb->eversion+1, RTK_VERSION);
+    }
+
+    if (cfg_cb->config_len)
+    {
+        memcpy(cfg_cb->total_buf+entry->patch_length, cfg_cb->config_buf, cfg_cb->config_len);
+    }
+
+    cfg_cb->dl_fw_flag = 1;
+    ALOGI("Fw:%s exists, config file:%s exists", (cfg_cb->fw_len>0)?"":"not", (cfg_cb->config_len>0)?"":"not");
+
+free_buf:
+    if (cfg_cb->fw_len > 0)
+    {
+        free(cfg_cb->fw_buf);
+        cfg_cb->fw_len = 0;
+    }
+
+    if (cfg_cb->config_len > 0)
+    {
+        free(cfg_cb->config_buf);
+        cfg_cb->config_len = 0;
+    }
+
+    if(entry)
+    {
+        free(entry);
+    }
+}
+
+static uint32_t rtk_get_bt_config(unsigned char** config_buf,
+        uint32_t* config_baud_rate, char * config_file_short_name, uint16_t mac_offset)
+{
+    char bt_config_file_name[PATH_MAX] = {0};
+    struct stat st;
+    size_t filelen;
+    int fd;
+    //FILE* file = NULL;
+
+    sprintf(bt_config_file_name, BT_CONFIG_DIRECTORY, config_file_short_name);
+    ALOGI("BT config file: %s", bt_config_file_name);
+
+    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;
+    }
+
+    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;
+    }
+
+    if ((fd = open(bt_config_file_name, O_RDONLY)) < 0)
+    {
+        ALOGE("Can't open bt config file");
+        return -1;
+    }
+
+    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;
+    }
+
+    if (read(fd, *config_buf, filelen) < (ssize_t)filelen)
+    {
+        ALOGE("Can't load bt config file");
+        free(*config_buf);
+        close(fd);
+        return -1;
+    }
+
+    *config_baud_rate = rtk_parse_config_file(config_buf, &filelen, vnd_local_bd_addr, mac_offset);
+    ALOGI("Get config baud rate from config file:0x%x", *config_baud_rate);
+
+    close(fd);
+    return filelen;
+}
+
+
+static int hci_download_patch_h4(HC_BT_HDR *p_buf, int index, uint8_t *data, int len)
+{
+    uint8_t retval = FALSE;
+    uint8_t *p = (uint8_t *) (p_buf + 1);
+
+    UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_FW_PATCH);
+    *p++ = 1 + len;  /* parameter length */
+    *p++ = index;
+    memcpy(p, data, len);
+    p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1+len;
+
+    hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
+
+    retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_DOWNLOAD_FW_PATCH, p_buf, hw_config_cback);
+    return retval;
+}
+
+/*******************************************************************************
+**
+** Function         hw_config_cback
+**
+** Description      Callback function for controller configuration
+**
+** Returns          None
+**
+*******************************************************************************/
+void hw_config_cback(void *p_mem)
+{
+    HC_BT_HDR   *p_evt_buf = NULL;
+    uint8_t     *p = NULL, *pp=NULL;
+    uint8_t     status = 0;
+    uint16_t    opcode = 0;
+    HC_BT_HDR   *p_buf = NULL;
+    uint8_t     is_proceeding = FALSE;
+    int         i = 0;
+    uint8_t     iIndexRx = 0;
+    patch_info* prtk_patch_file_info = NULL;
+    uint32_t    host_baudrate = 0;
+
+#if (USE_CONTROLLER_BDADDR == TRUE)
+    //const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
+#endif
+
+    if(p_mem != NULL)
+    {
+        p_evt_buf = (HC_BT_HDR *) p_mem;
+        status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET);
+        p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE_OFFSET;
+        STREAM_TO_UINT16(opcode,p);
+    }
+
+    if(opcode == HCI_VSC_H5_INIT) {
+        if(status != 0) {
+          ALOGE("%s, status = %d", __func__, status);
+          if ((bt_vendor_cbacks) && (p_evt_buf != NULL))
+          bt_vendor_cbacks->dealloc(p_evt_buf);
+          if(rtkbt_auto_restart) {
+              bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
+              kill(getpid(), SIGKILL);
+          }
+          return;
+        }
+    }
+
+    /* Ask a new buffer big enough to hold any HCI commands sent in here */
+    /*a cut fc6d status==1*/
+    if (((status == 0) ||(opcode == HCI_VSC_READ_ROM_VERSION)) && bt_vendor_cbacks)
+        p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_MAX_LEN);
+
+    if (p_buf != NULL)
+    {
+        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+        p_buf->offset = 0;
+        p_buf->len = 0;
+        p_buf->layer_specific = 0;
+
+        BTVNDDBG("hw_cfg_cb.state = %i", hw_cfg_cb.state);
+        switch (hw_cfg_cb.state)
+        {
+            case HW_CFG_H5_INIT:
+            {
+                p = (uint8_t *)(p_buf + 1);
+                UINT16_TO_STREAM(p, HCI_READ_LMP_VERSION);
+                *p++ = 0;
+                p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+
+                hw_cfg_cb.state = HW_CFG_READ_LOCAL_VER;
+                is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LMP_VERSION, p_buf, hw_config_cback);
+                break;
+            }
+            case HW_CFG_READ_LOCAL_VER:
+            {
+                if (status == 0)
+                {
+                    p = ((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OP1001_HCI_VERSION_OFFSET);
+                    STREAM_TO_UINT16(hw_cfg_cb.hci_version, p);
+                    p = ((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OP1001_HCI_REVISION_OFFSET);
+                    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);
+                    BTVNDDBG("lmp_subversion = 0x%x hw_cfg_cb.hci_version = 0x%x hw_cfg_cb.hci_revision = 0x%x", hw_cfg_cb.lmp_subversion, hw_cfg_cb.hci_version, hw_cfg_cb.hci_revision);
+                    if(hw_cfg_cb.lmp_subversion == LMPSUBVERSION_8723a)
+                    {
+                        hw_cfg_cb.state = HW_CFG_START;
+                        goto CFG_START;
+                    }
+                    else
+                    {
+                        hw_cfg_cb.state = HW_CFG_READ_ECO_VER;
+                        p = (uint8_t *) (p_buf + 1);
+                        UINT16_TO_STREAM(p, HCI_VSC_READ_ROM_VERSION);
+                        *p++ = 0;
+                        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+                        is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_READ_ROM_VERSION, p_buf, hw_config_cback);
+                    }
+                }
+                break;
+            }
+            case HW_CFG_READ_ECO_VER:
+            {
+                if(status == 0)
+                {
+                    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);
+                }
+                else if(1 == status)
+                {
+                    hw_cfg_cb.eversion = 0;
+                }
+                else
+                {
+                    is_proceeding = FALSE;
+                    break;
+                }
+
+                if(check_match_state(&hw_cfg_cb, 0) > 1)    // check if have multiple matched patch_entry by lmp_subversion,hci_version, hci_revision
+                {
+                    hw_cfg_cb.state = HW_CFG_READ_CHIP_TYPE;
+                     p = (uint8_t *) (p_buf + 1);
+                    UINT16_TO_STREAM(p, HCI_VSC_READ_CHIP_TYPE);
+                    *p++ = 5;
+                    UINT8_TO_STREAM(p, 0x00);
+                    UINT32_TO_STREAM(p, 0xB000A094);
+                    p_buf->len = HCI_CMD_PREAMBLE_SIZE + HCI_CMD_READ_CHIP_TYPE_SIZE;
+
+                    pp = (uint8_t *) (p_buf + 1);
+                    for (i = 0; i < p_buf->len; i++)
+                        BTVNDDBG("get chip type command data[%d]= 0x%x", i, *(pp+i));
+
+                    is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_READ_CHIP_TYPE, p_buf, hw_config_cback);
+                    break;
+                }
+                else
+                {
+                    hw_cfg_cb.state = HW_CFG_START;
+                    goto CFG_START;
+                }
+            }
+            case HW_CFG_READ_CHIP_TYPE:
+            {
+                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++)
+                    BTVNDDBG("READ_CHIP_TYPE event data[%d]= 0x%x", i, *(p+i));
+                if(status == 0)
+                {
+                    hw_cfg_cb.chip_type = ((*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPFC61_CHIPTYPE_OFFSET))&0x0F);
+                    BTVNDDBG("READ_CHIP_TYPE hw_cfg_cb.lmp_subversion = 0x%x", hw_cfg_cb.lmp_subversion);
+                    BTVNDDBG("READ_CHIP_TYPE hw_cfg_cb.hci_version = 0x%x", hw_cfg_cb.hci_version);
+                    BTVNDDBG("READ_CHIP_TYPE hw_cfg_cb.hci_revision = 0x%x", hw_cfg_cb.hci_revision);
+                    BTVNDDBG("READ_CHIP_TYPE hw_cfg_cb.chip_type = 0x%x", hw_cfg_cb.chip_type);
+                }
+                else
+                {
+                    is_proceeding = FALSE;
+                    break;
+                }
+                if(check_match_state(&hw_cfg_cb, PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE) > 1)  // check if have multiple matched patch_entry by lmp_subversion,hci_version, hci_revision and chiptype
+                {
+                    BTVNDDBG("check_match_state(lmp_subversion:0x%04x, hci_version:%d, hci_revision:%d chip_type:%d): Multi Matched Patch\n", hw_cfg_cb.lmp_subversion, hw_cfg_cb.hci_version, hw_cfg_cb.hci_revision, hw_cfg_cb.chip_type);
+                    is_proceeding = FALSE;
+                    break;
+                }
+                hw_cfg_cb.state = HW_CFG_START;
+            }
+CFG_START:
+            case HW_CFG_START:
+            {
+#ifdef BT_CHIP_PROBE_SIMULATION
+                {
+                    int ii;
+                    memcpy(&hw_cfg_test, &hw_cfg_cb, sizeof(hw_cfg_test));
+                    for(i=0;i<sizeof(bt_chip_chars)/sizeof(bt_chip_chars[0]);i++)
+                    {
+                        BTVNDDBG("BT_CHIP_PROBE_SIMULATION loop:%d $$$ BEGIN $$$\n", i);
+                        hw_cfg_test.lmp_subversion = bt_chip_chars[i].lmp_subversion;
+                        hw_cfg_test.hci_version = bt_chip_chars[i].hci_version;
+                        hw_cfg_test.hci_revision = bt_chip_chars[i].hci_revision;
+                        hw_cfg_test.chip_type = CHIPTYPE_NONE;
+                        if(check_match_state(&hw_cfg_test, 0) > 1){
+                            BTVNDDBG("check_match_state hw_cfg_test(lmp_subversion:0x%04x, hci_version:%d, hci_revision:%d chip_type:%d): Multi Matched Patch\n", hw_cfg_test.lmp_subversion, hw_cfg_test.hci_version, hw_cfg_test.hci_revision, hw_cfg_test.chip_type);
+                            if(bt_chip_chars[i].chip_type != CHIPTYPE_NONE){
+                                BTVNDDBG("BT_CHIP_PROBE_SIMULATION loop:%d *** Include ChipType ***\n", i);
+                                hw_cfg_test.chip_type = bt_chip_chars[i].chip_type;
+                                if(check_match_state(&hw_cfg_test, PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE) > 1){
+                                    BTVNDDBG("check_match_state hw_cfg_test(lmp_subversion:0x%04x, hci_version:%d, hci_revision:%d chip_type:%d): Multi Matched Patch\n", hw_cfg_test.lmp_subversion, hw_cfg_test.hci_version, hw_cfg_test.hci_revision, hw_cfg_test.chip_type);
+                                }else{
+                                    prtk_patch_file_info = get_patch_entry(&hw_cfg_test);
+                                }
+                            }
+                        }else{
+                            prtk_patch_file_info = get_patch_entry(&hw_cfg_test);
+                        }
+                        BTVNDDBG("BT_CHIP_PROBE_SIMULATION loop:%d $$$ END $$$\n", i);
+                    }
+                }
+#endif
+                //get efuse config file and patch code file
+                prtk_patch_file_info = get_patch_entry(&hw_cfg_cb);
+
+
+                if((prtk_patch_file_info == NULL) || (prtk_patch_file_info->lmp_subversion == 0))
+                {
+                    ALOGE("get patch entry error");
+                    is_proceeding = FALSE;
+                    break;
+                }
+                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)
+                {
+                    ALOGE("Get Config file fail, just use efuse settings");
+                    hw_cfg_cb.config_len = 0;
+                }
+                rtk_update_altsettings(prtk_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_patch_file_info->patch_name);
+                if (hw_cfg_cb.fw_len < 0)
+                {
+                    ALOGE("Get BT firmware fail");
+                    hw_cfg_cb.fw_len = 0;
+                }
+                else{
+                    hw_cfg_cb.project_id_mask = prtk_patch_file_info->project_id_mask;
+                    rtk_get_bt_final_patch(&hw_cfg_cb);
+                }
+                BTVNDDBG("Check total_len(0x%08x) max_patch_size(0x%08x)", hw_cfg_cb.total_len, hw_cfg_cb.max_patch_size);
+                if (hw_cfg_cb.total_len > hw_cfg_cb.max_patch_size)
+                {
+                    ALOGE("total length of fw&config(0x%08x) larger than max_patch_size(0x%08x)", hw_cfg_cb.total_len, hw_cfg_cb.max_patch_size);
+                    is_proceeding = FALSE;
+                    break;
+                }
+
+                if ((hw_cfg_cb.total_len > 0) && hw_cfg_cb.dl_fw_flag)
+                {
+                    hw_cfg_cb.patch_frag_cnt = hw_cfg_cb.total_len / PATCH_DATA_FIELD_MAX_SIZE;
+                    hw_cfg_cb.patch_frag_tail = hw_cfg_cb.total_len % PATCH_DATA_FIELD_MAX_SIZE;
+                    if (hw_cfg_cb.patch_frag_tail)
+                        hw_cfg_cb.patch_frag_cnt += 1;
+                    else
+                        hw_cfg_cb.patch_frag_tail = PATCH_DATA_FIELD_MAX_SIZE;
+                    BTVNDDBG("patch fragment count %d, tail len %d", hw_cfg_cb.patch_frag_cnt, hw_cfg_cb.patch_frag_tail);
+                }
+                else
+                {
+                    is_proceeding = FALSE;
+                    break;
+                }
+
+                if ((hw_cfg_cb.baudrate == 0) && ((hw_cfg_cb.hw_flow_cntrl & 0x80) == 0))
+                {
+                    BTVNDDBG("no baudrate to set and no need to set hw flow control");
+                    goto DOWNLOAD_FW;
+                }
+
+                if ((hw_cfg_cb.baudrate == 0) && (hw_cfg_cb.hw_flow_cntrl & 0x80))
+                {
+                    BTVNDDBG("no baudrate to set but set hw flow control is needed");
+                    goto SET_HW_FLCNTRL;
+                }
+            }
+            /* fall through intentionally */
+            case HW_CFG_SET_UART_BAUD_CONTROLLER:
+                BTVNDDBG("bt vendor lib: set CONTROLLER UART baud 0x%x", hw_cfg_cb.baudrate);
+                hw_cfg_cb.state = HW_CFG_SET_UART_BAUD_HOST;
+                is_proceeding = hw_config_set_controller_baudrate(p_buf, hw_cfg_cb.baudrate);
+                break;
+
+            case HW_CFG_SET_UART_BAUD_HOST:
+                /* update baud rate of host's UART port */
+                rtk_speed_to_uart_speed(hw_cfg_cb.baudrate, &host_baudrate);
+                BTVNDDBG("bt vendor lib: set HOST UART baud %i", host_baudrate);
+                userial_vendor_set_baud(line_speed_to_userial_baud(host_baudrate));
+
+                if((hw_cfg_cb.hw_flow_cntrl & 0x80) == 0)
+                    goto DOWNLOAD_FW;
+
+SET_HW_FLCNTRL:
+            case HW_CFG_SET_UART_HW_FLOW_CONTROL:
+                BTVNDDBG("Change HW flowcontrol setting");
+                if(hw_cfg_cb.hw_flow_cntrl & 0x01)
+                {
+                    userial_vendor_set_hw_fctrl(1);
+                }
+                else
+                {
+                    userial_vendor_set_hw_fctrl(0);
+                }
+                ms_delay(100);
+                hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
+
+DOWNLOAD_FW:
+            case HW_CFG_DL_FW_PATCH:
+                BTVNDDBG("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, opcode:0x%x", status, opcode);
+
+                //recv command complete event for patch code download command
+                if(opcode == HCI_VSC_DOWNLOAD_FW_PATCH)
+                {
+                    iIndexRx = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET + 1);
+                    BTVNDDBG("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, iIndexRx:%i", status, iIndexRx);
+                    hw_cfg_cb.patch_frag_idx++;
+
+                    if(iIndexRx&0x80)
+                    {
+                        BTVNDDBG("vendor lib fwcfg completed");
+                        free(hw_cfg_cb.total_buf);
+                        hw_cfg_cb.total_len = 0;
+
+                        bt_vendor_cbacks->dealloc(p_buf);
+                        bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+
+                        hw_cfg_cb.state = 0;
+                        is_proceeding = TRUE;
+                        break;
+                    }
+                }
+
+                if (hw_cfg_cb.patch_frag_idx < hw_cfg_cb.patch_frag_cnt)
+                {
+                    iIndexRx = hw_cfg_cb.patch_frag_idx?((hw_cfg_cb.patch_frag_idx-1)%0x7f+1):0;
+                    if (hw_cfg_cb.patch_frag_idx == hw_cfg_cb.patch_frag_cnt - 1)
+                    {
+                        BTVNDDBG("HW_CFG_DL_FW_PATCH: send last fw fragment");
+                        iIndexRx |= 0x80;
+                        hw_cfg_cb.patch_frag_len = hw_cfg_cb.patch_frag_tail;
+                    }
+                    else
+                    {
+                        iIndexRx &= 0x7F;
+                        hw_cfg_cb.patch_frag_len = PATCH_DATA_FIELD_MAX_SIZE;
+                    }
+                }
+
+                is_proceeding = hci_download_patch_h4(p_buf, iIndexRx,
+                                    hw_cfg_cb.total_buf+(hw_cfg_cb.patch_frag_idx*PATCH_DATA_FIELD_MAX_SIZE),
+                                    hw_cfg_cb.patch_frag_len);
+                break;
+
+            default:
+                break;
+        } // switch(hw_cfg_cb.state)
+    } // if (p_buf != NULL)
+
+    /* Free the RX event buffer */
+    if ((bt_vendor_cbacks) && (p_evt_buf != NULL))
+        bt_vendor_cbacks->dealloc(p_evt_buf);
+
+    if (is_proceeding == FALSE)
+    {
+        ALOGE("vendor lib fwcfg aborted!!!");
+        if (bt_vendor_cbacks)
+        {
+            if (p_buf != NULL)
+                bt_vendor_cbacks->dealloc(p_buf);
+
+            bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
+        }
+
+        if(hw_cfg_cb.config_len)
+        {
+            free(hw_cfg_cb.config_buf);
+            hw_cfg_cb.config_len = 0;
+        }
+
+        if(hw_cfg_cb.fw_len)
+        {
+            free(hw_cfg_cb.fw_buf);
+            hw_cfg_cb.fw_len= 0;
+        }
+
+        if(hw_cfg_cb.total_len)
+        {
+            free(hw_cfg_cb.total_buf);
+            hw_cfg_cb.total_len = 0;
+        }
+        hw_cfg_cb.state = 0;
+    }
+}
+
+/*****************************************************************************
+**   Hardware Configuration Interface Functions
+*****************************************************************************/
+
+
+/*******************************************************************************
+**
+** Function        hw_config_start
+**
+** Description     Kick off controller initialization process
+**
+** Returns         None
+**
+*******************************************************************************/
+void hw_config_start(char 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;
+    BTVNDDBG("RTKBT_RELEASE_NAME: %s",RTKBT_RELEASE_NAME);
+    BTVNDDBG("\nRealtek libbt-vendor_uart Version %s \n",RTK_VERSION);
+    HC_BT_HDR  *p_buf = NULL;
+    uint8_t     *p;
+
+    BTVNDDBG("hw_config_start, transtype = 0x%x \n", transtype);
+    /* Start from sending H5 INIT */
+    if (bt_vendor_cbacks)
+    {
+        /* Must allocate command buffer via HC's alloc API */
+        p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
+                                                       HCI_CMD_PREAMBLE_SIZE);
+        if(p_buf)
+        {
+            p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+            p_buf->offset = 0;
+            p_buf->layer_specific = 0;
+            p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+
+            p = (uint8_t *) (p_buf + 1);
+
+            if(transtype & RTKBT_TRANS_H4) {
+                p = (uint8_t *)(p_buf + 1);
+                UINT16_TO_STREAM(p, HCI_READ_LMP_VERSION);
+                *p++ = 0;
+                p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+
+                hw_cfg_cb.state = HW_CFG_READ_LOCAL_VER;
+                bt_vendor_cbacks->xmit_cb(HCI_READ_LMP_VERSION, p_buf, hw_config_cback);
+            }
+            else {
+                UINT16_TO_STREAM(p, HCI_VSC_H5_INIT);
+                *p = 0; /* parameter length */
+                hw_cfg_cb.state = HW_CFG_H5_INIT;
+
+                bt_vendor_cbacks->xmit_cb(HCI_VSC_H5_INIT, p_buf, hw_config_cback);
+            }
+        }
+        else {
+            ALOGE("%s buffer alloc fail!", __func__);
+        }
+    }
+    else
+        ALOGE("%s call back is null", __func__);
+}
+
diff --git a/rtkbt/code/libbt-vendor/src/hardware_usb.c b/rtkbt/code/libbt-vendor/src/hardware_usb.c
new file mode 100755 (executable)
index 0000000..cf8aa77
--- /dev/null
@@ -0,0 +1,930 @@
+#define LOG_TAG "bt_hwcfg_usb"
+#define RTKBT_RELEASE_NAME     "Test"
+
+#include <utils/Log.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <cutils/properties.h>
+#include <stdlib.h>
+#include "bt_hci_bdroid.h"
+#include "bt_vendor_rtk.h"
+#include "userial.h"
+#include "userial_vendor.h"
+#include "upio.h"
+#include <unistd.h>
+#include <endian.h>
+#include <byteswap.h>
+#include <unistd.h>
+
+#include "bt_vendor_lib.h"
+#include "hardware.h"
+
+/******************************************************************************
+**  Constants &  Macros
+******************************************************************************/
+#define RTK_VERSION "4.1.1"
+
+extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
+extern bool rtkbt_auto_restart;
+void hw_usb_config_cback(void *p_evt_buf);
+extern bt_hw_cfg_cb_t hw_cfg_cb;
+extern int getmacaddr(unsigned char * addr);
+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);
+
+
+/******************************************************************************
+**  Static variables
+******************************************************************************/
+//static bt_hw_cfg_cb_t hw_cfg_cb;
+
+typedef struct {
+    uint16_t    vid;
+    uint16_t    pid;
+    uint16_t    lmp_sub_default;
+    uint16_t    lmp_sub;
+    uint16_t    eversion;
+    char        *mp_patch_name;
+    char        *patch_name;
+    char        *config_name;
+    uint8_t     *fw_cache;
+    int         fw_len;
+    uint16_t    mac_offset;
+    uint32_t    max_patch_size;
+} usb_patch_info;
+
+static usb_patch_info usb_fw_patch_table[] = {
+/* { vid, pid, lmp_sub_default, lmp_sub, everion, mp_fw_name, fw_name, config_name, fw_cache, fw_len, mac_offset } */
+{ 0x0BDA, 0x1724, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723A */
+{ 0x0BDA, 0x8723, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE */
+{ 0x0BDA, 0xA723, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE for LI */
+{ 0x0BDA, 0x0723, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE */
+{ 0x13D3, 0x3394, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE for Azurewave*/
+
+{ 0x0BDA, 0x0724, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AU */
+{ 0x0BDA, 0x8725, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AU */
+{ 0x0BDA, 0x872A, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AU */
+{ 0x0BDA, 0x872B, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AU */
+
+{ 0x0BDA, 0xb720, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723bu_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BU */
+{ 0x0BDA, 0xb72A, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723bu_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BU */
+{ 0x0BDA, 0xb728, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE for LC */
+{ 0x0BDA, 0xb723, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE */
+{ 0x0BDA, 0xb72B, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE */
+{ 0x0BDA, 0xb001, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE for HP */
+{ 0x0BDA, 0xb002, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE */
+{ 0x0BDA, 0xb003, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE */
+{ 0x0BDA, 0xb004, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE */
+{ 0x0BDA, 0xb005, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE */
+
+{ 0x13D3, 0x3410, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE for Azurewave */
+{ 0x13D3, 0x3416, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE for Azurewave */
+{ 0x13D3, 0x3459, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE for Azurewave */
+{ 0x0489, 0xE085, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE for Foxconn */
+{ 0x0489, 0xE08B, 0x8723, 0, 0, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723BE for Foxconn */
+
+{ 0x0BDA, 0x2850, 0x8761, 0, 0, "mp_rtl8761a_fw", "rtl8761au_fw", "rtl8761a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8761AU */
+{ 0x0BDA, 0xA761, 0x8761, 0, 0, "mp_rtl8761a_fw", "rtl8761au_fw", "rtl8761a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8761AU only */
+{ 0x0BDA, 0x818B, 0x8761, 0, 0, "mp_rtl8761a_fw", "rtl8761aw8192eu_fw", "rtl8761aw8192eu_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8761AW + 8192EU */
+{ 0x0BDA, 0x818C, 0x8761, 0, 0, "mp_rtl8761a_fw", "rtl8761aw8192eu_fw", "rtl8761aw8192eu_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8761AW + 8192EU */
+{ 0x0BDA, 0x8760, 0x8761, 0, 0, "mp_rtl8761a_fw", "rtl8761au8192ee_fw", "rtl8761a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8761AU + 8192EE */
+{ 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, 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 */
+{ 0x0BDA, 0x0823, 0x8821, 0, 0, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8821AU */
+{ 0x13D3, 0x3414, 0x8821, 0, 0, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8821AE */
+{ 0x13D3, 0x3458, 0x8821, 0, 0, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8821AE */
+{ 0x13D3, 0x3461, 0x8821, 0, 0, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8821AE */
+{ 0x13D3, 0x3462, 0x8821, 0, 0, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8821AE */
+
+{ 0x0BDA, 0xB822, 0x8822, 0, 0, "mp_rtl8822b_fw", "rtl8822b_fw", "rtl8822b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, /* RTL8822BE */
+{ 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 */
+/* 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 */
+{ 0x0BDA, 0xD720, 0x8723, 0, 0, "mp_rtl8723d_fw", "rtl8723d_fw", "rtl8723d_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, /* RTL8723DE */
+{ 0x0BDA, 0xB820, 0x8821, 0, 0, "mp_rtl8821c_fw", "rtl8821c_fw", "rtl8821c_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, /* RTL8821CU */
+{ 0x0BDA, 0xC820, 0x8821, 0, 0, "mp_rtl8821c_fw", "rtl8821c_fw", "rtl8821c_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, /* RTL8821CU */
+{ 0x0BDA, 0xC821, 0x8821, 0, 0, "mp_rtl8821c_fw", "rtl8821c_fw", "rtl8821c_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, /* RTL8821CE */
+/* todo: RTL8703CU */
+
+/* NOTE: must append patch entries above the null entry */
+{ 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, 0, 0, 0 }
+};
+
+
+uint16_t usb_project_id[] = {
+    ROM_LMP_8723a,
+    ROM_LMP_8723b,
+    ROM_LMP_8821a,
+    ROM_LMP_8761a,
+    ROM_LMP_8703a,
+    ROM_LMP_8763a,
+    ROM_LMP_8703b,
+    ROM_LMP_8723c,
+    ROM_LMP_8822b,
+    ROM_LMP_8723d,
+    ROM_LMP_8821c,
+    ROM_LMP_NONE
+};
+//signature: realtech
+static const uint8_t RTK_EPATCH_SIGNATURE[8]={0x52,0x65,0x61,0x6C,0x74,0x65,0x63,0x68};
+//Extension Section IGNATURE:0x77FD0451
+static const uint8_t EXTENSION_SECTION_SIGNATURE[4]={0x51,0x04,0xFD,0x77};
+
+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;
+/*
+//sample code, add special settings
+
+    offset[n++] = 0x15B;
+*/
+    return n;
+}
+
+static inline int getUsbAltSettingVal(usb_patch_info *patch_entry, unsigned short offset, unsigned char * val)
+{
+    int res = 0;
+
+    switch(offset)
+    {
+/*
+//sample code, add special settings
+        case 0x15B:
+            val[0] = 0x0B;
+            val[1] = 0x0B;
+            val[2] = 0x0B;
+            val[3] = 0x0B;
+            res = 4;
+            break;
+*/
+        default:
+            res = 0;
+            break;
+    }
+    if((patch_entry)&&(offset == patch_entry->mac_offset)&&(res == 0))
+    {
+        if(getmacaddr(val) == 0){
+            ALOGI("MAC: %02x:%02x:%02x:%02x:%02x:%02x", val[5], val[4], val[3], val[2], val[1], val[0]);
+            res = 6;
+        }
+    }
+    return res;
+}
+
+static void rtk_usb_update_altsettings(usb_patch_info *patch_entry, unsigned char* config_buf_ptr, size_t *config_len_ptr)
+{
+    unsigned short offset[256], data_len;
+    unsigned char val[256];
+
+    struct rtk_bt_vendor_config* config = (struct rtk_bt_vendor_config*) config_buf_ptr;
+    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;
+
+    ALOGI("ORG Config len=%08zx:\n", config_len);
+    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], \
+            config_buf_ptr[i+8], config_buf_ptr[i+9], config_buf_ptr[i+10], config_buf_ptr[i+11], config_buf_ptr[i+12], config_buf_ptr[i+13], config_buf_ptr[i+14], config_buf_ptr[i+15]);
+    }
+
+    memset(offset, 0, sizeof(offset));
+    memset(val, 0, sizeof(val));
+    data_len = le16_to_cpu(config->data_len);
+
+    count = getUsbAltSettings(patch_entry, offset);//getAltSettings(patch_entry, offset, sizeof(offset)/sizeof(unsigned short));
+    if(count <= 0){
+        ALOGI("rtk_update_altsettings: No AltSettings");
+        return;
+    }else{
+        ALOGI("rtk_update_altsettings: %d AltSettings", count);
+    }
+
+    if (data_len != config_len - sizeof(struct rtk_bt_vendor_config))
+    {
+        ALOGE("rtk_update_altsettings: config len(%x) is not right(%lx)", data_len, (unsigned long)(config_len-sizeof(struct rtk_bt_vendor_config)));
+        return;
+    }
+
+    for (i=0; i<data_len;)
+    {
+        for(j = 0; j < count;j++)
+        {
+            if(le16_to_cpu(entry->offset) == offset[j])
+                offset[j] = 0;
+        }
+        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);
+            memcpy(entry->entry_data, val, entry->entry_len);
+        }
+        temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
+        i += temp;
+        entry = (struct rtk_bt_vendor_config_entry*)((uint8_t*)entry + temp);
+    }
+    for(j = 0; j < count;j++){
+        if(offset[j] == 0)
+            continue;
+        entry->entry_len = getUsbAltSettingVal(patch_entry, offset[j], val);
+        if(entry->entry_len <= 0)
+            continue;
+        entry->offset = cpu_to_le16(offset[j]);
+        memcpy(entry->entry_data, val, entry->entry_len);
+        ALOGI("rtk_update_altsettings: add %04x[%02x]", le16_to_cpu(entry->offset), entry->entry_len);
+        temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
+        i += temp;
+        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);
+
+    ALOGI("NEW Config len=%08zx:\n", *config_len_ptr);
+    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], \
+            config_buf_ptr[i+8], config_buf_ptr[i+9], config_buf_ptr[i+10], config_buf_ptr[i+11], config_buf_ptr[i+12], config_buf_ptr[i+13], config_buf_ptr[i+14], config_buf_ptr[i+15]);
+    }
+    return;
+}
+
+
+static void rtk_usb_parse_config_file(unsigned char** config_buf, size_t* filelen, uint8_t bt_addr[6], uint16_t mac_offset)
+{
+    struct rtk_bt_vendor_config* config = (struct rtk_bt_vendor_config*) *config_buf;
+    uint16_t config_len = le16_to_cpu(config->data_len), temp = 0;
+    struct rtk_bt_vendor_config_entry* entry = config->entry;
+    unsigned int i = 0;
+    uint8_t  heartbeat_buf = 0;
+    //uint32_t config_has_bdaddr = 0;
+    uint8_t *p;
+
+       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);
+        return;
+    }
+
+    if (config_len != *filelen - sizeof(struct rtk_bt_vendor_config))
+    {
+        ALOGE("config len(0x%x) is not right(0x%zx)", config_len, *filelen-sizeof(struct rtk_bt_vendor_config));
+        return;
+    }
+
+    hw_cfg_cb.heartbeat = 0;
+    for (i=0; i<config_len;)
+    {
+        switch(le16_to_cpu(entry->offset))
+        {
+            case 0x017a:
+            {
+                if(mac_offset == CONFIG_MAC_OFFSET_GEN_1_2)
+                {
+                    p = (uint8_t *)entry->entry_data;
+                    STREAM_TO_UINT8(heartbeat_buf, p);
+                    if((heartbeat_buf & 0x02) && (heartbeat_buf & 0x10))
+                        hw_cfg_cb.heartbeat = 1;
+                    else
+                        hw_cfg_cb.heartbeat = 0;
+
+                    ALOGI("config 0x017a heartbeat = %d",hw_cfg_cb.heartbeat);
+                }
+                break;
+            }
+            case 0x01be:
+            {
+                if(mac_offset == CONFIG_MAC_OFFSET_GEN_3PLUS)
+                {
+                    p = (uint8_t *)entry->entry_data;
+                    STREAM_TO_UINT8(heartbeat_buf, p);
+                    if((heartbeat_buf & 0x02) && (heartbeat_buf & 0x10))
+                        hw_cfg_cb.heartbeat = 1;
+                    else
+                        hw_cfg_cb.heartbeat = 0;
+
+                    ALOGI("config 0x01be heartbeat = %d",hw_cfg_cb.heartbeat);
+                }
+                break;
+            }
+            default:
+                ALOGI("config offset(0x%x),length(0x%x)", entry->offset, entry->entry_len);
+                break;
+        }
+        temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
+        i += temp;
+        entry = (struct rtk_bt_vendor_config_entry*)((uint8_t*)entry + temp);
+    }
+
+    return;
+}
+
+static uint32_t rtk_usb_get_bt_config(unsigned char** config_buf,
+        char * config_file_short_name, uint16_t mac_offset)
+{
+    char bt_config_file_name[PATH_MAX] = {0};
+    struct stat st;
+    size_t filelen;
+    int fd;
+    //FILE* file = NULL;
+
+    sprintf(bt_config_file_name, BT_CONFIG_DIRECTORY, config_file_short_name);
+    ALOGI("BT config file: %s", bt_config_file_name);
+
+    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;
+    }
+
+    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;
+    }
+
+    if ((fd = open(bt_config_file_name, O_RDONLY)) < 0)
+    {
+        ALOGE("Can't open bt config file");
+        return -1;
+    }
+
+    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;
+    }
+
+    if (read(fd, *config_buf, filelen) < (ssize_t)filelen)
+    {
+        ALOGE("Can't load bt config file");
+        free(*config_buf);
+        close(fd);
+        return -1;
+    }
+
+    rtk_usb_parse_config_file(config_buf, &filelen, vnd_local_bd_addr, mac_offset);
+
+    close(fd);
+    return filelen;
+}
+
+static usb_patch_info *rtk_usb_get_fw_table_entry(uint16_t vid, uint16_t pid)
+{
+    usb_patch_info *patch_entry = usb_fw_patch_table;
+
+    uint32_t entry_size = sizeof(usb_fw_patch_table) / sizeof(usb_fw_patch_table[0]);
+    uint32_t i;
+
+    for (i = 0; i < entry_size; i++, patch_entry++) {
+        if ((vid == patch_entry->vid)&&(pid == patch_entry->pid))
+            break;
+    }
+
+    if (i == entry_size) {
+        ALOGE("%s: No fw table entry found", __func__);
+        return NULL;
+    }
+
+    return patch_entry;
+}
+
+static void rtk_usb_get_bt_final_patch(bt_hw_cfg_cb_t* cfg_cb)
+{
+    uint8_t proj_id = 0;
+    struct rtk_epatch_entry* entry = NULL;
+    struct rtk_epatch *patch = (struct rtk_epatch *)cfg_cb->fw_buf;
+    //int iBtCalLen = 0;
+
+    if(cfg_cb->lmp_subversion == LMPSUBVERSION_8723a)
+    {
+        if(memcmp(cfg_cb->fw_buf, RTK_EPATCH_SIGNATURE, 8) == 0)
+        {
+            ALOGE("8723as check signature error!");
+            cfg_cb->dl_fw_flag = 0;
+            goto free_buf;
+        }
+        else
+        {
+            cfg_cb->total_len = cfg_cb->fw_len + cfg_cb->config_len;
+            if (!(cfg_cb->total_buf = malloc(cfg_cb->total_len)))
+            {
+                ALOGE("can't alloc memory for fw&config, errno:%d", errno);
+                cfg_cb->dl_fw_flag = 0;
+                goto free_buf;
+            }
+            else
+            {
+                ALOGI("8723as, fw copy direct");
+                memcpy(cfg_cb->total_buf, cfg_cb->fw_buf, cfg_cb->fw_len);
+                memcpy(cfg_cb->total_buf+cfg_cb->fw_len, cfg_cb->config_buf, cfg_cb->config_len);
+                //cfg_cb->lmp_sub_current = *(uint16_t *)(cfg_cb->total_buf + cfg_cb->total_len - cfg_cb->config_len - 4);
+                cfg_cb->dl_fw_flag = 1;
+                goto free_buf;
+            }
+        }
+    }
+
+    if (memcmp(cfg_cb->fw_buf, RTK_EPATCH_SIGNATURE, 8))
+    {
+        ALOGE("check signature error");
+        cfg_cb->dl_fw_flag = 0;
+        goto free_buf;
+    }
+
+    /* check the extension section signature */
+    if (memcmp(cfg_cb->fw_buf + cfg_cb->fw_len - 4, EXTENSION_SECTION_SIGNATURE, 4))
+    {
+        ALOGE("check extension section signature error");
+        cfg_cb->dl_fw_flag = 0;
+        goto free_buf;
+    }
+
+    proj_id = rtk_get_fw_project_id(cfg_cb->fw_buf + cfg_cb->fw_len - 5);
+    if(usb_project_id[proj_id] != hw_cfg_cb.lmp_subversion_default)
+    {
+        ALOGE("usb_project_id is 0x%08x, fw project_id is %d, does not match!!!",
+                        usb_project_id[proj_id], hw_cfg_cb.lmp_subversion);
+        cfg_cb->dl_fw_flag = 0;
+        goto free_buf;
+    }
+
+    entry = rtk_get_patch_entry(cfg_cb);
+    if (entry)
+    {
+        cfg_cb->total_len = entry->patch_length + cfg_cb->config_len;
+    }
+    else
+    {
+        cfg_cb->dl_fw_flag = 0;
+        goto free_buf;
+    }
+
+    ALOGI("total_len = 0x%x", cfg_cb->total_len);
+
+    if (!(cfg_cb->total_buf = malloc(cfg_cb->total_len)))
+    {
+        ALOGE("Can't alloc memory for multi fw&config, errno:%d", errno);
+        cfg_cb->dl_fw_flag = 0;
+        goto free_buf;
+    }
+    else
+    {
+        memcpy(cfg_cb->total_buf, cfg_cb->fw_buf + entry->patch_offset, entry->patch_length);
+        memcpy(cfg_cb->total_buf + entry->patch_length - 4, &patch->fw_version, 4);
+        memcpy(&entry->svn_version, cfg_cb->total_buf + entry->patch_length - 8, 4);
+        memcpy(&entry->coex_version, cfg_cb->total_buf + entry->patch_length - 12, 4);
+
+        ALOGI("BTCOEX:20%06d-%04x svn_version:%d lmp_subversion:0x%x hci_version:0x%x hci_revision:0x%x chip_type:%d Cut:%d libbt-vendor_uart version:%s, patch->fw_version = %x\n",
+        ((entry->coex_version >> 16) & 0x7ff) + ((entry->coex_version >> 27) * 10000),
+        (entry->coex_version & 0xffff), entry->svn_version, cfg_cb->lmp_subversion, cfg_cb->hci_version, cfg_cb->hci_revision, cfg_cb->chip_type, cfg_cb->eversion+1, RTK_VERSION, patch->fw_version);
+    }
+
+    if (cfg_cb->config_len)
+    {
+        memcpy(cfg_cb->total_buf+entry->patch_length, cfg_cb->config_buf, cfg_cb->config_len);
+    }
+
+    cfg_cb->dl_fw_flag = 1;
+    ALOGI("Fw:%s exists, config file:%s exists", (cfg_cb->fw_len>0)?"":"not", (cfg_cb->config_len>0)?"":"not");
+
+free_buf:
+    if (cfg_cb->fw_len > 0)
+    {
+        free(cfg_cb->fw_buf);
+        cfg_cb->fw_len = 0;
+    }
+
+    if (cfg_cb->config_len > 0)
+    {
+        free(cfg_cb->config_buf);
+        cfg_cb->config_len = 0;
+    }
+
+    if(entry)
+    {
+        free(entry);
+    }
+}
+
+static int usb_hci_download_patch_h4(HC_BT_HDR *p_buf, int index, uint8_t *data, int len)
+{
+    uint8_t retval = FALSE;
+    uint8_t *p = (uint8_t *) (p_buf + 1);
+
+    UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_FW_PATCH);
+    *p++ = 1 + len;  /* parameter length */
+    *p++ = index;
+    memcpy(p, data, len);
+    p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1+len;
+
+    hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
+
+    retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_DOWNLOAD_FW_PATCH, p_buf, hw_usb_config_cback);
+    return retval;
+}
+
+static void rtk_usb_get_fw_version(bt_hw_cfg_cb_t* cfg_cb)
+{
+    struct rtk_epatch *patch = (struct rtk_epatch *)cfg_cb->fw_buf;
+
+    if(cfg_cb->lmp_subversion == LMPSUBVERSION_8723a)
+    {
+        cfg_cb->lmp_sub_current = 0;
+    }
+    else
+    {
+        cfg_cb->lmp_sub_current = (uint16_t)patch->fw_version;
+    }
+
+}
+/*******************************************************************************
+**
+** Function         hw_usb_config_cback
+**
+** Description      Callback function for controller configuration
+**
+** Returns          None
+**
+*******************************************************************************/
+void hw_usb_config_cback(void *p_mem)
+{
+    HC_BT_HDR   *p_evt_buf = NULL;
+    uint8_t     *p = NULL;//, *pp=NULL;
+    uint8_t     status = 0;
+    uint16_t    opcode = 0;
+    HC_BT_HDR   *p_buf = NULL;
+    uint8_t     is_proceeding = FALSE;
+    //int         i = 0;
+    uint8_t     iIndexRx = 0;
+    //patch_info* prtk_patch_file_info = NULL;
+    usb_patch_info* prtk_usb_patch_file_info = NULL;
+    //uint32_t    host_baudrate = 0;
+
+#if (USE_CONTROLLER_BDADDR == TRUE)
+    //const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
+#endif
+
+    if(p_mem != NULL)
+    {
+        p_evt_buf = (HC_BT_HDR *) p_mem;
+        status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET);
+        p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE_OFFSET;
+        STREAM_TO_UINT16(opcode,p);
+    }
+
+    /* Ask a new buffer big enough to hold any HCI commands sent in here */
+    /*a cut fc6d status==1*/
+    if (((status == 0) ||(opcode == HCI_VSC_READ_ROM_VERSION)) && bt_vendor_cbacks)
+        p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_MAX_LEN);
+
+    if (p_buf != NULL)
+    {
+        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+        p_buf->offset = 0;
+        p_buf->len = 0;
+        p_buf->layer_specific = 0;
+
+        BTVNDDBG("hw_cfg_cb.state = %i", hw_cfg_cb.state);
+        switch (hw_cfg_cb.state)
+        {
+            case HW_CFG_RESET_CHANNEL_CONTROLLER:
+            {
+                usleep(300000);
+                hw_cfg_cb.state = HW_CFG_READ_LOCAL_VER;
+                p = (uint8_t *) (p_buf + 1);
+                UINT16_TO_STREAM(p, HCI_READ_LMP_VERSION);
+                *p++ = 0;
+                p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+                is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LMP_VERSION, p_buf, hw_usb_config_cback);
+                break;
+            }
+            case HW_CFG_READ_LOCAL_VER:
+            {
+                if (status == 0)
+                {
+                    p = ((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OP1001_HCI_VERSION_OFFSET);
+                    STREAM_TO_UINT16(hw_cfg_cb.hci_version, p);
+                    p = ((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OP1001_HCI_REVISION_OFFSET);
+                    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))
+                    {
+                        ALOGE("get patch entry error");
+                        is_proceeding = FALSE;
+                        break;
+                    }
+                    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);
+                    hw_cfg_cb.fw_len = rtk_get_bt_firmware(&hw_cfg_cb.fw_buf, prtk_usb_patch_file_info->patch_name);
+                    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);
+
+                    if(prtk_usb_patch_file_info->lmp_sub_default == hw_cfg_cb.lmp_subversion)
+                    {
+                        BTVNDDBG("%s: Cold BT controller startup", __func__);
+                        //hw_cfg_cb.state = HW_CFG_START;
+                        //goto CFG_USB_START;
+                        hw_cfg_cb.state = HW_CFG_READ_ECO_VER;
+                        p = (uint8_t *) (p_buf + 1);
+                        UINT16_TO_STREAM(p, HCI_VSC_READ_ROM_VERSION);
+                        *p++ = 0;
+                        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+                        is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_READ_ROM_VERSION, p_buf, hw_usb_config_cback);
+                    }
+                    else if (hw_cfg_cb.lmp_subversion != hw_cfg_cb.lmp_sub_current)
+                    {
+                        BTVNDDBG("%s: Warm BT controller startup with updated lmp", __func__);
+                        goto RESET_HW_CONTROLLER;
+                    }
+                    else
+                    {
+                        BTVNDDBG("%s: Warm BT controller startup with same lmp", __func__);
+                        free(hw_cfg_cb.total_buf);
+                        hw_cfg_cb.total_len = 0;
+
+                        bt_vendor_cbacks->dealloc(p_buf);
+                        bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+
+                        hw_cfg_cb.state = 0;
+                        is_proceeding = TRUE;
+                    }
+                    
+ /*                   if(hw_cfg_cb.lmp_subversion == LMPSUBVERSION_8723a)
+                    {
+                        hw_cfg_cb.state = HW_CFG_START;
+                        goto CFG_USB_START;
+                    }
+                    else
+                    {
+                        hw_cfg_cb.state = HW_CFG_READ_ECO_VER;
+                        p = (uint8_t *) (p_buf + 1);
+                        UINT16_TO_STREAM(p, HCI_VSC_READ_ROM_VERSION);
+                        *p++ = 0;
+                        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+                        is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_READ_ROM_VERSION, p_buf, hw_usb_config_cback);
+                    }*/
+                }
+                break;
+            }
+RESET_HW_CONTROLLER:
+            case HW_RESET_CONTROLLER:
+            {
+                if (status == 0)
+                {
+                    //usleep(300000);//300ms
+                    userial_vendor_usb_ioctl(RESET_CONTROLLER, NULL);//reset controller
+                    hw_cfg_cb.state = HW_CFG_READ_ECO_VER;
+                    p = (uint8_t *) (p_buf + 1);
+                    UINT16_TO_STREAM(p, HCI_VSC_READ_ROM_VERSION);
+                    *p++ = 0;
+                    p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+                    is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_READ_ROM_VERSION, p_buf, hw_usb_config_cback);
+                }
+                break;
+            }
+            case HW_CFG_READ_ECO_VER:
+            {
+                if(status == 0)
+                {
+                    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);
+                }
+                else if(1 == status)
+                {
+                    hw_cfg_cb.eversion = 0;
+                }
+                else
+                {
+                    is_proceeding = FALSE;
+                    break;
+                }
+
+                hw_cfg_cb.state = HW_CFG_START;
+                    goto CFG_USB_START;
+
+            }
+CFG_USB_START:
+            case HW_CFG_START:
+            {
+                //get efuse config file and patch code file
+                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))
+                {
+                    ALOGE("get patch entry error");
+                    is_proceeding = FALSE;
+                    break;
+                }
+                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)
+                {
+                    ALOGE("Get Config file fail, just use efuse settings");
+                    hw_cfg_cb.config_len = 0;
+                }
+                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;
+                }
+                else{
+                    //hw_cfg_cb.project_id_mask = prtk_usb_patch_file_info->project_id_mask;
+                    rtk_usb_get_bt_final_patch(&hw_cfg_cb);
+                }
+
+                BTVNDDBG("Check total_len(0x%08x) max_patch_size(0x%08x)", hw_cfg_cb.total_len, hw_cfg_cb.max_patch_size);
+                if (hw_cfg_cb.total_len > hw_cfg_cb.max_patch_size)
+                {
+                    ALOGE("total length of fw&config(0x%08x) larger than max_patch_size(0x%08x)", hw_cfg_cb.total_len, hw_cfg_cb.max_patch_size);
+                    is_proceeding = FALSE;
+                    break;
+                }
+
+                if ((hw_cfg_cb.total_len > 0) && hw_cfg_cb.dl_fw_flag)
+                {
+                    hw_cfg_cb.patch_frag_cnt = hw_cfg_cb.total_len / PATCH_DATA_FIELD_MAX_SIZE;
+                    hw_cfg_cb.patch_frag_tail = hw_cfg_cb.total_len % PATCH_DATA_FIELD_MAX_SIZE;
+                    if (hw_cfg_cb.patch_frag_tail)
+                        hw_cfg_cb.patch_frag_cnt += 1;
+                    else
+                        hw_cfg_cb.patch_frag_tail = PATCH_DATA_FIELD_MAX_SIZE;
+                    BTVNDDBG("patch fragment count %d, tail len %d", hw_cfg_cb.patch_frag_cnt, hw_cfg_cb.patch_frag_tail);
+                }
+                else
+                {
+                    is_proceeding = FALSE;
+                    break;
+                }
+
+                goto DOWNLOAD_USB_FW;
+
+            }
+            /* fall through intentionally */
+
+DOWNLOAD_USB_FW:
+            case HW_CFG_DL_FW_PATCH:
+                BTVNDDBG("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, opcode:0x%x", status, opcode);
+
+                //recv command complete event for patch code download command
+                if(opcode == HCI_VSC_DOWNLOAD_FW_PATCH)
+                {
+                    iIndexRx = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET + 1);
+                    BTVNDDBG("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, iIndexRx:%i", status, iIndexRx);
+                    hw_cfg_cb.patch_frag_idx++;
+
+                    if(iIndexRx&0x80)
+                    {
+                        BTVNDDBG("vendor lib fwcfg completed");
+                        free(hw_cfg_cb.total_buf);
+                        hw_cfg_cb.total_len = 0;
+
+                        bt_vendor_cbacks->dealloc(p_buf);
+                        bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+
+                        hw_cfg_cb.state = 0;
+                        is_proceeding = TRUE;
+                        break;
+                    }
+                }
+
+                if (hw_cfg_cb.patch_frag_idx < hw_cfg_cb.patch_frag_cnt)
+                {
+                    iIndexRx = hw_cfg_cb.patch_frag_idx?((hw_cfg_cb.patch_frag_idx-1)%0x7f+1):0;
+                    if (hw_cfg_cb.patch_frag_idx == hw_cfg_cb.patch_frag_cnt - 1)
+                    {
+                        BTVNDDBG("HW_CFG_DL_FW_PATCH: send last fw fragment");
+                        iIndexRx |= 0x80;
+                        hw_cfg_cb.patch_frag_len = hw_cfg_cb.patch_frag_tail;
+                    }
+                    else
+                    {
+                        iIndexRx &= 0x7F;
+                        hw_cfg_cb.patch_frag_len = PATCH_DATA_FIELD_MAX_SIZE;
+                    }
+                }
+
+                is_proceeding = usb_hci_download_patch_h4(p_buf, iIndexRx,
+                                    hw_cfg_cb.total_buf+(hw_cfg_cb.patch_frag_idx*PATCH_DATA_FIELD_MAX_SIZE),
+                                    hw_cfg_cb.patch_frag_len);
+                break;
+            default:
+                break;
+        } // switch(hw_cfg_cb.state)
+    } // if (p_buf != NULL)
+
+    /* Free the RX event buffer */
+    if ((bt_vendor_cbacks) && (p_evt_buf != NULL))
+        bt_vendor_cbacks->dealloc(p_evt_buf);
+
+    if (is_proceeding == FALSE)
+    {
+        ALOGE("vendor lib fwcfg aborted!!!");
+        if (bt_vendor_cbacks)
+        {
+            if (p_buf != NULL)
+                bt_vendor_cbacks->dealloc(p_buf);
+
+            bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
+        }
+
+        if(hw_cfg_cb.config_len)
+        {
+            free(hw_cfg_cb.config_buf);
+            hw_cfg_cb.config_len = 0;
+        }
+
+        if(hw_cfg_cb.fw_len)
+        {
+            free(hw_cfg_cb.fw_buf);
+            hw_cfg_cb.fw_len= 0;
+        }
+
+        if(hw_cfg_cb.total_len)
+        {
+            free(hw_cfg_cb.total_buf);
+            hw_cfg_cb.total_len = 0;
+        }
+        hw_cfg_cb.state = 0;
+    }
+}
+
+/*******************************************************************************
+**
+** Function        hw__usb_config_start
+**
+** Description     Kick off controller initialization process
+**
+** Returns         None
+**
+*******************************************************************************/
+void hw_usb_config_start(char transtype, uint32_t usb_id)
+{
+    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;
+    BTVNDDBG("RTKBT_RELEASE_NAME: %s",RTKBT_RELEASE_NAME);
+    BTVNDDBG("\nRealtek libbt-vendor_usb Version %s \n",RTK_VERSION);
+    HC_BT_HDR  *p_buf = NULL;
+    uint8_t     *p;
+
+    BTVNDDBG("hw_usb_config_start, transtype = 0x%x, pid = 0x%04x, vid = 0x%04x \n", transtype, hw_cfg_cb.pid, hw_cfg_cb.vid);
+
+    if (bt_vendor_cbacks)
+    {
+        /* Must allocate command buffer via HC's alloc API */
+        p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
+                                                       HCI_CMD_PREAMBLE_SIZE);
+        if(p_buf)
+        {
+            p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+            p_buf->offset = 0;
+            p_buf->layer_specific = 0;
+            p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+
+            p = (uint8_t *) (p_buf + 1);
+
+            p = (uint8_t *)(p_buf + 1);
+            UINT16_TO_STREAM(p, HCI_VENDOR_RESET);
+            *p++ = 0;
+            p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+
+            hw_cfg_cb.state = HW_CFG_RESET_CHANNEL_CONTROLLER;
+            bt_vendor_cbacks->xmit_cb(HCI_VENDOR_RESET, p_buf, hw_usb_config_cback);
+        }
+        else {
+            ALOGE("%s buffer alloc fail!", __func__);
+        }
+    }
+    else
+        ALOGE("%s call back is null", __func__);
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index aae2bb6..d8e5bd8
@@ -61,8 +61,6 @@
 #define H5_TRACE_DATA_ENABLE 0//if you want to see data tx and rx, set H5_TRACE_DATA_ENABLE 1
 #define H5_LOG_VERBOSE      0
 
-#define ENABLE_BLEADV_DISCONNECT 1
-
 unsigned int h5_log_enable = 1;
 
 #ifndef H5_LOG_BUF_SIZE
@@ -140,14 +138,14 @@ unsigned int h5_log_enable = 1;
 /******************************************************************************
 **  Local type definitions
 ******************************************************************************/
-
-static const uint16_t msg_evt_table[] =
-{
-    MSG_HC_TO_STACK_HCI_ERR,       /* H4_TYPE_COMMAND */
-    MSG_HC_TO_STACK_HCI_ACL,       /* H4_TYPE_ACL_DATA */
-    MSG_HC_TO_STACK_HCI_SCO,       /* H4_TYPE_SCO_DATA */
-    MSG_HC_TO_STACK_HCI_EVT        /* H4_TYPE_EVENT */
-};
+//
+//static const uint16_t msg_evt_table[] =
+//{
+//    MSG_HC_TO_STACK_HCI_ERR,       /* H4_TYPE_COMMAND */
+//   MSG_HC_TO_STACK_HCI_ACL,       /* H4_TYPE_ACL_DATA */
+//    MSG_HC_TO_STACK_HCI_SCO,       /* H4_TYPE_SCO_DATA */
+//    MSG_HC_TO_STACK_HCI_EVT        /* H4_TYPE_EVENT */
+//};
 
 /* Callback function for the returned event of internal issued command */
 typedef void (*tTIMER_HANDLE_CBACK)(union sigval sigval_value);
@@ -276,7 +274,7 @@ struct patch_struct {
     int nRxIndex;   // ack index from board
     int nNeedRetry; // if no response from board
 };
-static struct patch_struct rtk_patch;
+//static struct patch_struct rtk_patch;
 
 /******************************************************************************
 **  Static function
@@ -387,11 +385,11 @@ static void H5LogMsg(const char *fmt_str, ...)
         return;
      }
 }
-
+/*
 static void H5LogMsgVerbose(const char *fmt_str, ...)
 {
-    static char buffer[H5_LOG_BUF_SIZE];
 #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);
@@ -399,9 +397,12 @@ static void H5LogMsgVerbose(const char *fmt_str, ...)
 
     LOGI0("H5: ", buffer);
 #else
+       va_list ap;
+       va_start(ap, fmt_str);
+    va_end(ap);
     return;
 #endif
-}
+}*/
 
 // reverse bit
 static __inline uint8_t bit_rev8(uint8_t byte)
@@ -581,17 +582,17 @@ static void h5_crc_update(uint16_t *crc, uint8_t d)
 }
 
 struct __una_u16 { uint16_t x; };
-static __inline uint16_t __get_unaligned_cpu16(const void *p)
+/*static __inline uint16_t __get_unaligned_cpu16(const void *p)
 {
     const struct __una_u16 *ptr = (const struct __una_u16 *)p;
     return ptr->x;
-}
-
+}*/
 
+/*
 static __inline uint16_t get_unaligned_be16(const void *p)
 {
     return __get_unaligned_cpu16((const uint8_t *)p);
-}
+}*/
 /**
 * Get crc data.
 *
@@ -933,7 +934,7 @@ static void h5_remove_acked_pkt(tHCI_H5_CB *h5)
 * @param fd uart file descriptor
 *
 */
-
+/*
 static void hci_h5_send_pure_ack(void)
 {
     //uint16_t bytes_sent = 0;
@@ -985,7 +986,7 @@ static void hci_h5_send_pure_ack(void)
 #endif
     return;
 
-}
+}*/
 
 static void hci_h5_send_sync_req()
 {
@@ -1198,33 +1199,7 @@ static void rtk_notify_hw_h5_init_result(uint8_t status)
     pthread_cond_signal(&rtk_h5.data_cond);
     pthread_mutex_unlock(&rtk_h5.data_mutex);
 }
-static uint8_t *acl_pack = NULL;
-static uint32_t acl_len=0;
-int loopbackmode = 0;
-
-static timer_t loopacltimer=0;
-
-static void loop_acl_cb()
-{
-    sk_buff     *rx_skb;
-    rx_skb = skb_alloc_and_init(HCI_ACLDATA_PKT, acl_pack, acl_len);
 
-    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);
-}
-static void loopacl_timer_handler(union sigval sigev_value)
-{
-       loop_acl_cb();
-}
-static void start_loopacktimer()
-{
-       if(loopacltimer == 0)
-               loopacltimer = OsAllocateTimer(loopacl_timer_handler);
-       OsStartTimer(loopacltimer, 10, 0);
-       
-}
 
 static sk_buff * h5_dequeue()
 {
@@ -1361,17 +1336,17 @@ static uint16_t h5_wake_up()
 void h5_process_ctl_pkts(void)
 {
     //process h5 link establish
-    int len;
+    //int len;
     uint8_t cfg;
 
-    tHCI_H5_CB *p_cb = &rtk_h5;
+    //tHCI_H5_CB *p_cb = &rtk_h5;
     sk_buff * skb = rtk_h5.rx_skb;
 
     unsigned char   h5sync[2]     = {0x01, 0x7E},
                     h5syncresp[2] = {0x02, 0x7D},
                     h5conf[3]     = {0x03, 0xFC, 0x14},
-                    h5confresp[2] = {0x04, 0x7B},
-                    h5InitOk[2] = {0xF1, 0xF1};
+                    h5confresp[2] = {0x04, 0x7B};
+                    //h5InitOk[2] = {0xF1, 0xF1};
 
     //uint8_t *ph5_payload = NULL;
     //ph5_payload = (uint8_t *)(p_cb->p_rcv_msg + 1);
@@ -1562,54 +1537,13 @@ uint8_t internal_event_intercept_h5(void)
 * @param skb socket buffer
 *
 */
-#if  ENABLE_BLEADV_DISCONNECT
-uint16_t rk_h5_send_cmd(serial_data_type_t type, uint8_t *data, uint16_t length)
-{
-    sk_buff * skb = NULL;
-    uint16_t bytes_to_send, opcode;
-
-
-    skb = skb_alloc_and_init(type, data, length);
-    if(!skb) {
-        ALOGE("send cmd skb_alloc_and_init fail!");
-        return -1;
-    }
-
-    h5_enqueue(skb);
-
-    num_hci_cmd_pkts--;
-
-
-    STREAM_TO_UINT16(opcode, data);
-    ALOGE("HCI Command opcode(0x%04X)", opcode);
-
-    bytes_to_send = h5_wake_up();
-    return length;
-}
-
-static void adv_timer_handler(union sigval sigev_value)
-{
-       uint8_t sendData[4]={0x0a,0x20,0x01,0x01};
-       rk_h5_send_cmd(1, sendData, 4);
-}
-static void start_enableAdvtimer()
-{
-       if(loopacltimer == 0)
-               loopacltimer = OsAllocateTimer(adv_timer_handler);
-       OsStartTimer(loopacltimer, 100, 0);
-       
-}
-
-
-static uint16_t bleConHandle = 0x0000;
-static uint8_t  bleConnected = 0x00;
-static uint8_t bleAdvEnable = 0x00;
-#endif
 static uint8_t hci_recv_frame(sk_buff *skb, uint8_t pkt_type)
 {
     uint8_t intercepted = 0;
-    uint32_t i = 0 ;
+    //uint32_t i = 0 ;
+#if H5_TRACE_DATA_ENABLE
     uint8_t *data = skb_get_data(skb);
+#endif
     uint32_t data_len = skb_get_data_length(skb);
 
     H5LogMsg("UART H5 RX: length = %d", data_len);
@@ -1636,34 +1570,10 @@ static uint8_t hci_recv_frame(sk_buff *skb, uint8_t pkt_type)
         uint8_t     event_code;
         uint16_t    opcode, len;
         p = (uint8_t *)skb_get_data(skb);
-#if  ENABLE_BLEADV_DISCONNECT
 
-        if(p[0]==0x3e //ble meta
-           && p[2]==0x01 //le connect complete
-           && p[3]==0x00)//success
-        {
-           bleConHandle = (uint16_t)p[4] + ((uint16_t)p[5] << 8);
-           ALOGE("bleConHandle 0x%x", bleConHandle);
-           bleConnected = 0x01;
-        }
-               
-        if(p[0]==0x05 //discon complete
-           && p[2]==0x00 //success
-          )
-        {
-           if( bleConnected && bleAdvEnable && bleConHandle == ((uint16_t)p[3] + ((uint16_t)p[4] << 8)) ){
-                ALOGE("blediscon restart ble adv");
-                bleConnected = 0x00;
-                bleConHandle = 0x0000;
-                start_enableAdvtimer();
-           }
-        }
-#endif
         event_code = *p++;
         len = *p++;
         H5LogMsg("hci_recv_frame event_code(0x%x), len = %d", event_code, len);
-        if(event_code == HCI_COMMAND_STATUS_EVT && len==0x04 && p[0]==0x01&&p[1]==0x02&&p[2]==0xff&&p[3]==0x3b)
-           { *( p-2)=HCI_COMMAND_COMPLETE_EVT  ;p[0]=0x02;p[1]=0xff;p[2]=0x3b;p[3]=0x01;}
         if (event_code == HCI_COMMAND_COMPLETE_EVT)
         {
             num_hci_cmd_pkts = *p++;
@@ -1676,10 +1586,7 @@ static uint8_t hci_recv_frame(sk_buff *skb, uint8_t pkt_type)
                 H5LogMsg("CommandCompleteEvent for command h5_start_wait_controller_baudrate_ready_timer (0x%04X)", opcode);
                 h5_start_wait_controller_baudrate_ready_timer();
             }
-        }else if(event_code == 0xff){
-                 intercepted = 1;
-           skb_free(&skb);
-}
+        }
 
     }
 
@@ -1704,9 +1611,9 @@ static uint8_t h5_complete_rx_pkt(tHCI_H5_CB *h5)
     int pass_up = 1;
     uint16_t eventtype = 0;
     uint8_t *h5_hdr = NULL;
-    uint8_t complete_pkt = true;
+    //uint8_t complete_pkt = true;
     uint8_t pkt_type = 0;
-    tHCI_H5_CB *p_cb=&rtk_h5;
+    //tHCI_H5_CB *p_cb=&rtk_h5;
     uint8_t status = 0;
 
     //H5LogMsg("HCI 3wire h5_complete_rx_pkt");
@@ -1987,16 +1894,7 @@ 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(void *arg)
+static void data_ready_cb_thread()
 {
     sk_buff *skb;
     uint8_t pkt_type = 0;
@@ -2009,15 +1907,12 @@ static void data_ready_cb_thread(void *arg)
     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 ((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) {
             rtk_h5.data_skb = skb;
         }
@@ -2027,15 +1922,15 @@ static void data_ready_cb_thread(void *arg)
         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)
 {
     uint16_t events;
-    uint32_t i = 0;
+    //uint32_t i = 0;
 
     H5LogMsg("data_retransfer_thread started");
 
@@ -2093,7 +1988,7 @@ static void data_retransfer_thread(void *arg)
 
 }
 
-    ALOGE("data_retransfer_thread exiting");
+    H5LogMsg("data_retransfer_thread exiting");
     pthread_exit(NULL);
 
 }
@@ -2108,8 +2003,8 @@ void h5_retransfer_signal_event(uint16_t event)
 
 static int create_data_retransfer_thread()
 {
-    struct sched_param param;
-    int policy;
+    //struct sched_param param;
+    //int policy;
 
     pthread_attr_t thread_attr;
 
@@ -2156,8 +2051,8 @@ static int create_data_retransfer_thread()
 
 static int create_data_ready_cb_thread()
 {
-    struct sched_param param;
-    int policy;
+    //struct sched_param param;
+    //int policy;
 
     pthread_attr_t thread_attr;
 
@@ -2246,12 +2141,11 @@ void hci_h5_int_init(hci_h5_callbacks_t* h5_callbacks)
 *******************************************************************************/
 void hci_h5_cleanup(void)
 {
-    ALOGE("hci_h5_cleanup");
-    uint8_t try_cnt=10;
+    H5LogMsg("hci_h5_cleanup");
+    //uint8_t try_cnt=10;
     int result;
 
     rtk_h5.cleanuping = 1;
-       ms_delay(200);
 
 
     //btsnoop_cleanup();
@@ -2266,10 +2160,6 @@ void hci_h5_cleanup(void)
     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);
@@ -2277,10 +2167,6 @@ void hci_h5_cleanup(void)
 
     ms_delay(200);
 
-
-    pthread_mutex_destroy(&rtk_h5.data_mutex);
-    pthread_cond_destroy(&rtk_h5.data_cond);
-
     pthread_mutex_destroy(&rtk_h5.mutex);
     pthread_cond_destroy(&rtk_h5.cond);
 
@@ -2305,7 +2191,7 @@ void hci_h5_cleanup(void)
 *******************************************************************************/
 uint16_t  hci_h5_parse_msg(uint8_t *byte, uint16_t count)
 {
-    uint16_t bytes_needed = 0;
+    //uint16_t bytes_needed = 0;
     uint8_t     h5_byte;
     h5_byte  = *byte;
     //H5LogMsg("hci_h5_receive_msg byte:%d",h5_byte);
@@ -2374,7 +2260,6 @@ 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;
 
-
     skb = skb_alloc_and_init(type, data, length);
     if(!skb) {
         ALOGE("send cmd skb_alloc_and_init fail!");
@@ -2396,15 +2281,6 @@ uint16_t hci_h5_send_cmd(serial_data_type_t type, uint8_t *data, uint16_t length
         H5LogMsg("RX HCI RESET Command, stop hw init timer");
         h5_stop_hw_init_ready_timer();
     }
-    if(opcode == 0x1802)
-        loopbackmode =1;
-#if  ENABLE_BLEADV_DISCONNECT
-    if(opcode == 0x200a)//adv enalbe
-    {
-        ALOGE("setbleAdvEnable %x", data[1]);
-        bleAdvEnable = data[1];
-    }
-#endif
     bytes_to_send = h5_wake_up();
     return length;
 }
@@ -2421,20 +2297,9 @@ uint16_t hci_h5_send_cmd(serial_data_type_t type, uint8_t *data, uint16_t length
 *******************************************************************************/
 uint16_t hci_h5_send_acl_data(serial_data_type_t type, uint8_t *data, uint16_t length)
 {
-    uint16_t bytes_to_send, lay_spec;
+    uint16_t bytes_to_send;//, lay_spec;
     sk_buff * skb = NULL;
 
-       if(loopbackmode == 1){
-               acl_len = length;
-               if(!acl_pack)
-                       acl_pack = malloc(2050);
-               if(acl_len>2050)
-                       acl_len = 2050;
-           memcpy(acl_pack,data,acl_len); 
-               start_loopacktimer();
-               return length;
-       }
-
     skb = skb_alloc_and_init(type, data, length);
     if(!skb) {
         ALOGE("hci_h5_send_acl_data, alloc skb buffer fail!");
@@ -2460,7 +2325,7 @@ uint16_t hci_h5_send_acl_data(serial_data_type_t type, uint8_t *data, uint16_t l
 uint16_t hci_h5_send_sco_data(serial_data_type_t type, uint8_t *data, uint16_t length)
 {
     sk_buff * skb = NULL;
-    uint16_t bytes_to_send, lay_spec;
+    uint16_t bytes_to_send;//, lay_spec;
 
     skb = skb_alloc_and_init(type, data, length);
     if(!skb) {
@@ -2487,6 +2352,10 @@ uint16_t hci_h5_send_sco_data(serial_data_type_t type, uint8_t *data, uint16_t l
 *******************************************************************************/
 uint8_t hci_h5_send_sync_cmd(uint16_t opcode, uint8_t *p_buf, uint16_t length)
 {
+       if(p_buf != NULL)
+       {
+               H5LogMsg("hci_h5_send_sync_cmd buf is not null");
+       }
     if(rtk_h5.link_estab_state == H5_UNINITIALIZED)
     {
         if(opcode == HCI_VSC_H5_INIT)
@@ -2498,7 +2367,7 @@ uint8_t hci_h5_send_sync_cmd(uint16_t opcode, uint8_t *p_buf, uint16_t length)
     }
     else if(rtk_h5.link_estab_state == H5_ACTIVE)
     {
-        H5LogMsg("hci_h5_send_sync_cmd(0x%x), link_estab_state = %d", opcode, rtk_h5.link_estab_state);
+        H5LogMsg("hci_h5_send_sync_cmd(0x%x), link_estab_state = %d, length = %d", opcode, rtk_h5.link_estab_state, length);
         return false;
     }
 
@@ -2581,7 +2450,7 @@ 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) {
     H5LogMsg("h5_retransfer_timeout_handler");
     if(rtk_h5.cleanuping)
     {
@@ -2591,7 +2460,7 @@ 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) {
     H5LogMsg("h5_sync_retrans_timeout_handler");
     if(rtk_h5.cleanuping)
     {
@@ -2613,7 +2482,7 @@ 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) {
     H5LogMsg("h5_conf_retrans_timeout_handler");
     if(rtk_h5.cleanuping)
     {
@@ -2637,7 +2506,7 @@ 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) {
     H5LogMsg("h5_wait_ct_baundrate_ready_timeout_handler");
     if(rtk_h5.cleanuping)
     {
@@ -2655,7 +2524,7 @@ static void h5_wait_controller_baudrate_ready_timeout_handler(union sigval sigev
     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) {
     H5LogMsg("h5_hw_init_ready_timeout_handler");
     if(rtk_h5.cleanuping)
     {
diff --git a/rtkbt/code/libbt-vendor/src/rtk_btservice.c b/rtkbt/code/libbt-vendor/src/rtk_btservice.c
new file mode 100755 (executable)
index 0000000..814427d
--- /dev/null
@@ -0,0 +1,765 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Filename:      rtk_btservice.c
+ *
+ *  Description:   start unix socketc
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_service"
+#define RTKBT_RELEASE_NAME     "20180525_BT_ANDROID_8.1"
+
+#include <utils/Log.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <termios.h>
+#include <sys/syscall.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <cutils/properties.h>
+#include <stdlib.h>
+#include "bt_hci_bdroid.h"
+#include "bt_vendor_rtk.h"
+#include "userial.h"
+#include "userial_vendor.h"
+#include "rtk_btservice.h"
+#include "upio.h"
+#include <unistd.h>
+#include <sys/eventfd.h>
+#include <semaphore.h>
+#include <endian.h>
+#include <byteswap.h>
+#include <sys/un.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include "bt_vendor_lib.h"
+
+
+//HCI VENDOR Command opcode
+#define HCI_VSC_READ_REGISTER           0xFFFF
+
+#define RTKBTSERVICE_SOCKETPATH "@/data/misc/bluedroid/rtkbt_service.sock"
+#define MAX_CONNECTION_NUMBER 10
+
+#define RTK_HCICMD          0x01
+#define RTK_CLOSESOCRET     0x02
+#define RTK_INNER           0x03
+#define OTHER               0xff
+
+#define Rtk_Service_Data_SIZE   259
+#define Rtk_Service_Send_Data_SIZE   259
+
+#define HCICMD_REPLY_TIMEOUT_VALUE  8000 //ms
+#define HCI_CMD_PREAMBLE_SIZE   3
+
+typedef void (*tTIMER_HANDLE_CBACK)(union sigval sigval_value);
+
+
+
+typedef struct Rtk_Btservice_Info
+{
+    int socketfd;
+    pthread_t       cmdreadythd;
+    pthread_t       epollthd;
+    int             current_client_sock;
+    int             epoll_fd;
+    int             autopair_fd;
+    sem_t           cmdqueue_sem;
+    sem_t           cmdsend_sem;
+    timer_t         timer_hcicmd_reply;
+    RT_LIST_HEAD    cmdqueue_list;
+    pthread_mutex_t cmdqueue_mutex;
+    volatile uint8_t cmdqueue_thread_running;
+    volatile uint8_t epoll_thread_running;
+    void            (*current_complete_cback)(void *);
+}Rtk_Btservice_Info;
+
+typedef struct Rtk_Service_Data
+{
+    uint16_t        opcode;
+    uint8_t         parameter_len;
+    uint8_t         *parameter;
+    void            (*complete_cback)(void *);
+}Rtk_Service_Data;
+
+/*
+typedef struct Rtk_Socket_Data
+{
+    char            type;      //hci,other,inner
+    uint8_t         opcodeh;
+    uint8_t         opcodel;
+    uint8_t         parameter_len;
+    uint8_t         parameter[0];
+}Rtk_Socket_Data;
+*/
+
+typedef struct Rtk_Queue_Data
+{
+    RT_LIST_ENTRY   list;
+    int             client_sock;
+    uint16_t        opcode;
+    uint8_t         parameter_len;
+    uint8_t         *parameter;
+    void            (*complete_cback)(void *);
+}Rtkqueuedata;
+
+static Rtk_Btservice_Info *rtk_btservice;
+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)
+{
+    struct sigevent sigev;
+    timer_t timerid;
+
+    memset(&sigev, 0, sizeof(struct sigevent));
+    // Create the POSIX timer to generate signo
+    sigev.sigev_notify = SIGEV_THREAD;
+    //sigev.sigev_notify_thread_id = syscall(__NR_gettid);
+    sigev.sigev_notify_function = timer_callback;
+    sigev.sigev_value.sival_ptr = &timerid;
+
+    ALOGD("OsAllocateTimer bt_service sigev.sigev_notify_thread_id = syscall(__NR_gettid)!");
+    //Create the Timer using timer_create signal
+
+    if (timer_create(CLOCK_REALTIME, &sigev, &timerid) == 0)
+    {
+        return timerid;
+    }
+    else
+    {
+        ALOGE("timer_create error!");
+        return (timer_t)-1;
+    }
+}
+
+static int OsFreeTimer(timer_t timerid)
+{
+    int ret = 0;
+    ret = timer_delete(timerid);
+    if(ret != 0)
+        ALOGE("timer_delete fail with errno(%d)", errno);
+
+    return ret;
+}
+
+
+ static int OsStartTimer(timer_t timerid, int msec, int mode)
+ {
+    struct itimerspec itval;
+
+    itval.it_value.tv_sec = msec / 1000;
+    itval.it_value.tv_nsec = (long)(msec % 1000) * (1000000L);
+
+    if (mode == 1)
+
+    {
+        itval.it_interval.tv_sec    = itval.it_value.tv_sec;
+        itval.it_interval.tv_nsec = itval.it_value.tv_nsec;
+    }
+    else
+    {
+        itval.it_interval.tv_sec = 0;
+        itval.it_interval.tv_nsec = 0;
+    }
+
+    //Set the Timer when to expire through timer_settime
+
+    if (timer_settime(timerid, 0, &itval, NULL) != 0)
+    {
+        ALOGE("time_settime error!");
+        return -1;
+    }
+
+    return 0;
+
+}
+
+ static int OsStopTimer(timer_t timerid)
+ {
+    return OsStartTimer(timerid, 0, 0);
+ }
+
+static void init_cmdqueue_hash(Rtk_Btservice_Info* rtk_info)
+{
+    RT_LIST_HEAD* head = &rtk_info->cmdqueue_list;
+    ListInitializeHeader(head);
+}
+
+static void delete_cmdqueue_from_hash(Rtkqueuedata* desc)
+{
+    if (desc)
+    {
+        ListDeleteNode(&desc->list);
+        free(desc);
+        desc = NULL;
+    }
+}
+
+static void flush_cmdqueue_hash(Rtk_Btservice_Info* rtk_info)
+{
+    RT_LIST_HEAD* head = &rtk_info->cmdqueue_list;
+    RT_LIST_ENTRY* iter = NULL, *temp = NULL;
+    Rtkqueuedata* desc = NULL;
+
+    pthread_mutex_lock(&rtk_info->cmdqueue_mutex);
+    LIST_FOR_EACH_SAFELY(iter, temp, head)
+    {
+        desc = LIST_ENTRY(iter, Rtkqueuedata, list);
+        delete_cmdqueue_from_hash(desc);
+    }
+    //ListInitializeHeader(head);
+    pthread_mutex_unlock(&rtk_info->cmdqueue_mutex);
+}
+
+static void hcicmd_reply_timeout_handler()//(union sigval sigev_value)
+{
+    Rtk_Service_Send_Hwerror_Event();
+    //return;
+}
+
+static int hcicmd_alloc_reply_timer()
+ {
+    // Create and set the timer when to expire
+    rtk_btservice->timer_hcicmd_reply = OsAllocateTimer(hcicmd_reply_timeout_handler);
+
+    return 0;
+
+ }
+
+static int hcicmd_free_reply_timer()
+{
+    return OsFreeTimer(rtk_btservice->timer_hcicmd_reply);
+}
+
+
+static int hcicmd_start_reply_timer()
+{
+    return OsStartTimer(rtk_btservice->timer_hcicmd_reply, HCICMD_REPLY_TIMEOUT_VALUE, 1);
+}
+
+static int hcicmd_stop_reply_timer()
+{
+    return OsStopTimer(rtk_btservice->timer_hcicmd_reply);
+}
+
+static void Rtk_Client_Cmd_Cback(void *p_mem)
+{
+    HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
+    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);
+        sendbuf = p_mem;
+        if(rtk_btservice->current_client_sock != -1)
+        {
+            write(rtk_btservice->current_client_sock,sendbuf,len);
+        }
+        else
+        {
+            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;
+    pthread_mutex_lock(&rtk_btservice->cmdqueue_mutex);
+    rtkqueue_data = (Rtkqueuedata *)malloc(sizeof(Rtkqueuedata));
+    if (NULL == rtkqueue_data)
+    {
+        ALOGE("rtkqueue_data: allocate error");
+        return;
+    }
+
+    rtkqueue_data->opcode = RtkData->opcode;
+    rtkqueue_data->parameter = RtkData->parameter;
+    rtkqueue_data->parameter_len = RtkData->parameter_len;
+    rtkqueue_data->client_sock = client_sock;
+    rtkqueue_data->complete_cback = RtkData->complete_cback;
+
+    ListAddToTail(&(rtkqueue_data->list), &(rtk_btservice->cmdqueue_list));
+    sem_post(&rtk_btservice->cmdqueue_sem);
+    pthread_mutex_unlock(&rtk_btservice->cmdqueue_mutex);
+}
+
+static void Rtk_Service_Cmd_Event_Cback(void *p_mem)
+{
+    //int i;
+    //unsigned char *a=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)
+        {
+            rtk_btservice->current_complete_cback(p_mem);
+        }
+        else
+        {
+            ALOGE("%s current_complete_cback is not exist!", __func__);
+        }
+        rtk_btservice->current_complete_cback=NULL;
+        hcicmd_stop_reply_timer();
+        sem_post(&rtk_btservice->cmdsend_sem);
+    }
+}
+
+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
+    userial_recv_rawdata_hook(p_buf,length);
+    free(p_buf);
+}
+
+static void *cmdready_thread()
+{
+    //Rtkqueuedata* rtk_data;
+
+    while(rtk_btservice->cmdqueue_thread_running)
+    {
+       sem_wait(&rtk_btservice->cmdqueue_sem);
+       sem_wait(&rtk_btservice->cmdsend_sem);
+       if(rtk_btservice->cmdqueue_thread_running != 0)
+       {
+        pthread_mutex_lock(&rtk_btservice->cmdqueue_mutex);
+        RT_LIST_ENTRY* iter = ListGetTop(&(rtk_btservice->cmdqueue_list));
+        Rtkqueuedata* desc = NULL;
+        if (iter) {
+            desc = LIST_ENTRY(iter, Rtkqueuedata, list);
+            if (desc)
+            {
+                ListDeleteNode(&desc->list);
+            }
+        }
+
+        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 )
+                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();
+                }
+            if(desc->parameter_len > 0)
+                free(desc->parameter);
+        }
+
+        free(desc);
+       }
+    }
+    pthread_exit(0);
+}
+
+
+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;
+    unsigned char parameter_length=0;
+    unsigned char *parameter = NULL;
+    int recvlen=0;
+    Rtk_Service_Data *p_buf;
+    //int i;
+
+
+    recvlen = read(client_sock,&type,1);
+    ALOGD("%s recvlen=%d,type=%d",__func__,recvlen, type);
+    if(recvlen<=0)
+    {
+        close(client_sock);
+        if(client_sock == rtk_btservice->autopair_fd)
+        {
+            rtk_btservice->autopair_fd = -1;
+        }
+        return;
+    }
+
+    switch (type)
+    {
+        case RTK_HCICMD:
+        {
+            recvlen = read(client_sock,&opcodeh,1);
+            if(recvlen<=0)
+            {
+                ALOGE("read opcode high char error");
+                break;
+            }
+            recvlen = read(client_sock,&opcodel,1);
+            if(recvlen<=0)
+            {
+                ALOGE("read opcode low char error");
+                break;
+            }
+            recvlen = read(client_sock,&parameter_length,1);
+            if(recvlen<=0)
+            {
+                ALOGE("read parameter_length char error");
+                break;
+            }
+
+            if(parameter_length>0)
+            {
+                parameter = (unsigned char *)malloc(sizeof(char)*parameter_length);
+                recvlen = read(client_sock,parameter,parameter_length);
+                ALOGD("%s parameter_length=%d,recvlen=%d",__func__,parameter_length, recvlen);
+                if(recvlen<=0 || recvlen!=parameter_length)
+                {
+                    ALOGE("read parameter_length char error recvlen=%d,parameter_length=%d\n",recvlen,parameter_length);
+                    break;
+                }
+            }
+            p_buf = (Rtk_Service_Data *)malloc(sizeof(Rtk_Service_Data));
+            if (NULL == p_buf)
+            {
+                ALOGE("p_buf: allocate error");
+                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;
+        }
+        case RTK_CLOSESOCRET:
+        {
+            close(client_sock);
+            //pthread_exit(0);
+            break;
+        }
+        default:
+        {
+            ALOGE("%s The RtkSockData type is not found!", __func__);
+            break;
+        }
+    }
+
+}
+
+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++;
+    //uint8_t len = *p++;
+    uint8_t  subcode;
+    HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_full_msg;
+    if(event_code == 0xff)
+        ALOGD("rtk_btservice_internal_event_intercept event_code=0x%x",event_code);
+    switch (event_code)
+    {
+        case HCI_VENDOR_SPECIFIC_EVT:
+        {
+            STREAM_TO_UINT8(subcode, p);
+            switch(subcode)
+            {
+                case HCI_RTKBT_AUTOPAIR_EVT:
+                {
+
+                    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;
+                        memcpy((uint8_t *)(p_bluedroid + 1), p_msg, p_evt_buf->len);
+                        p_bluedroid[1]=0x3e;  //event_code
+                        p_bluedroid[3]=0x02;  //subcode
+                        userial_recv_rawdata_hook(p_bluedroid, p_bluedroid_len);
+                    }
+                }
+
+                default:
+                  break;
+            }
+            break;
+        }
+        //case HCI_COMMAND_COMPLETE_EVT:
+        //{
+            //rtkservice_handle_cmd_complete_evt();
+        //}
+        default:
+            break;
+    }
+}
+
+
+static int socket_accept(socketfd)
+{
+    struct sockaddr_un un;
+    socklen_t len;
+    int client_sock=0;
+    len = sizeof(un);
+    struct epoll_event event;
+
+    client_sock=accept(socketfd, (struct sockaddr *)&un, &len);
+    if(client_sock<0)
+    {
+        printf("accept failed\n");
+        return -1;
+    }
+    //pthread_create(&connectthread,NULL,(void *)accept_request_thread,&client_sock);
+
+    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)
+    {
+        ALOGE("%s unable to register fd %d to epoll set: %s", __func__, client_sock, strerror(errno));
+        close(client_sock);
+        return -1;
+    }
+    return 0;
+}
+
+static void *epoll_thread()
+{
+    struct epoll_event events[64];
+    int nfds=0;
+    int i=0;
+
+    while(rtk_btservice->epoll_thread_running)
+    {
+        nfds=epoll_wait(rtk_btservice->epoll_fd,events,32,500);
+        if(rtk_btservice->epoll_thread_running != 0)
+        {
+        if(nfds>0)
+        {
+            for(i=0;i<nfds;i++)
+            {
+                if(events[i].data.fd == rtk_btservice->socketfd && events[i].events&EPOLLIN)
+                {
+                    if(socket_accept(events[i].data.fd)<0)
+                    {
+                        pthread_exit(0);
+                    }
+                }
+                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);
+                    }
+                }
+            }
+        }
+    }
+    pthread_exit(0);
+}
+
+static int unix_socket_start(const char *servername)
+{
+    int len;
+    struct sockaddr_un un;
+    struct epoll_event event;
+
+    if ((rtk_btservice->socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+    {
+        ALOGE("%s create AF_UNIX socket fail!", __func__);
+        return -1;
+    }
+
+    memset(&un, 0, sizeof(un));
+    un.sun_family = AF_UNIX;
+    strcpy(un.sun_path, servername);
+    un.sun_path[0]=0;
+    len = offsetof(struct sockaddr_un, sun_path) + strlen(servername);
+
+    if (bind(rtk_btservice->socketfd, (struct sockaddr *)&un, len) < 0)
+    {
+        ALOGE("%s bind socket fail!", __func__);
+        return -1;
+    }
+
+    if (listen(rtk_btservice->socketfd, MAX_CONNECTION_NUMBER) < 0)
+    {
+        ALOGE("%s listen socket fail!", __func__);
+        return -1;
+    }
+    /*
+    if(chmod(RTKBTSERVICE_SOCKETPATH,0666) != 0)
+    {
+        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)
+    {
+        ALOGE("%s unable to register fd %d to epoll set: %s", __func__, rtk_btservice->socketfd, strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+int RTK_btservice_thread_start()
+{
+    rtk_btservice->epoll_thread_running=1;
+    if (pthread_create(&rtk_btservice->epollthd, NULL, epoll_thread, NULL)!=0)
+    {
+        ALOGE("pthread_create epoll_thread: %s", strerror(errno));
+        return -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));
+        return -1;
+    }
+
+    return 0;
+}
+
+void RTK_btservice_thread_stop()
+{
+    ALOGD("%s !", __func__);
+    rtk_btservice->epoll_thread_running=0;
+    rtk_btservice->cmdqueue_thread_running=0;
+    sem_post(&rtk_btservice->cmdqueue_sem);
+    sem_post(&rtk_btservice->cmdsend_sem);
+    pthread_join(rtk_btservice->cmdreadythd, NULL);
+    pthread_join(rtk_btservice->epollthd, NULL);
+    close(rtk_btservice->epoll_fd);
+    ALOGD("%s end!", __func__);
+}
+
+int RTK_btservice_init()
+{
+    int ret;
+    rtk_btservice=(Rtk_Btservice_Info *)malloc(sizeof(Rtk_Btservice_Info));
+
+    rtk_btservice->current_client_sock = -1;
+    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);
+    sem_init(&rtk_btservice->cmdsend_sem, 0, 1);
+
+    pthread_mutex_init(&rtk_btservice->cmdqueue_mutex, NULL);
+    init_cmdqueue_hash(rtk_btservice);
+    if(bt_vendor_cbacks == NULL)
+    {
+        ALOGE("%s bt_vendor_cbacks is NULL!", __func__);
+        return -1;
+    }
+
+    rtk_btservice->epoll_fd = epoll_create(64);
+    if (rtk_btservice->epoll_fd == -1) {
+        ALOGE("%s unable to create epoll instance: %s", __func__, strerror(errno));
+        return -1;
+    }
+
+    if(unix_socket_start(RTKBTSERVICE_SOCKETPATH) < 0)
+    {
+        ALOGE("%s unix_socket_start fail!", __func__);
+        return -1;
+    }
+
+    ret = RTK_btservice_thread_start();
+    if(ret<0)
+    {
+        ALOGE("%s RTK_btservice_thread_start fail!", __func__);
+        return -1;
+    }
+    ALOGD("%s init done!", __func__);
+    return 0;
+}
+
+void RTK_btservice_destroyed()
+{
+    ALOGD("%s destroyed start!", __func__);
+    RTK_btservice_thread_stop();
+    close(rtk_btservice->socketfd);
+    sem_destroy(&rtk_btservice->cmdqueue_sem);
+    sem_destroy(&rtk_btservice->cmdsend_sem);
+    flush_cmdqueue_hash(rtk_btservice);
+    hcicmd_free_reply_timer();
+    pthread_mutex_destroy(&rtk_btservice->cmdqueue_mutex);
+    rtk_btservice->autopair_fd = -1;
+    rtk_btservice->current_client_sock = -1;
+    free(rtk_btservice);
+    ALOGD("%s destroyed done!", __func__);
+}
+
+
old mode 100644 (file)
new mode 100755 (executable)
index dcf4636..2de4618
@@ -44,7 +44,7 @@ static pthread_mutex_t btsnoop_log_lock;
 
 
 static void rtk_safe_close_(int *fd);
-static void *rtk_listen_fn_(void *context);
+static void *rtk_listen_fn_();
 
 static const char *RTK_LISTEN_THREAD_NAME_ = "rtk_btsnoop_net";
 static const int RTK_LOCALHOST_ = 0xC0A80AE2;       // 192.168.10.226
@@ -79,14 +79,36 @@ static uint64_t rtk_btsnoop_timestamp(void) {
 void rtk_btsnoop_open()
 {
     pthread_mutex_init(&btsnoop_log_lock, NULL);
+    char last_log_path[PATH_MAX];
+    uint64_t timestamp;
+    uint32_t usec;
+    uint8_t sec,hour, minus,day;
+
     if (hci_btsnoop_fd != -1) {
       ALOGE("%s btsnoop log file is already open.", __func__);
       return;
     }
 
     if(rtk_btsnoop_save_log) {
-        char last_log_path[PATH_MAX];
-        snprintf(last_log_path, PATH_MAX, "%s.%llu", rtk_btsnoop_path, rtk_btsnoop_timestamp());
+        timestamp = rtk_btsnoop_timestamp() - BTSNOOP_EPOCH_DELTA;
+        usec = (uint32_t)(timestamp % 1000000LL);
+        timestamp /= 1000000LL;
+        sec = (uint8_t)(timestamp % 60LL);
+        timestamp /= 60LL;
+        minus = (uint8_t)(timestamp % 60LL);
+        timestamp /= 60LL;
+        hour = (uint8_t)(timestamp % 24LL);
+        timestamp /= 24LL;
+        day = (uint8_t)(timestamp % 30LL);
+        timestamp /= 30LL;
+        //snprintf(last_log_path, PATH_MAX, "%s.%llu", rtk_btsnoop_path, rtk_btsnoop_timestamp());
+        snprintf(last_log_path, PATH_MAX, "%s.%uY-%dD-%dH-%dM-%dS-%dUS", rtk_btsnoop_path,
+          (uint32_t)timestamp, day, hour, minus, sec, usec);
+        if (!rename(rtk_btsnoop_path, last_log_path) && errno != ENOENT)
+            ALOGE("%s unable to rename '%s' to '%s': %s", __func__, rtk_btsnoop_path, last_log_path, strerror(errno));
+    }
+    else {
+        snprintf(last_log_path, PATH_MAX, "%s.last", rtk_btsnoop_path);
         if (!rename(rtk_btsnoop_path, last_log_path) && errno != ENOENT)
             ALOGE("%s unable to rename '%s' to '%s': %s", __func__, rtk_btsnoop_path, last_log_path, strerror(errno));
     }
@@ -327,7 +349,7 @@ void rtk_btsnoop_net_write(serial_data_type_t type, uint8_t *data, bool is_recei
     pthread_mutex_unlock(&rtk_client_socket_lock_);
 }
 
-static void *rtk_listen_fn_(void *context) {
+static void *rtk_listen_fn_() {
     prctl(PR_SET_NAME, (unsigned long)RTK_LISTEN_THREAD_NAME_, 0, 0, 0);
 
     rtk_listen_socket_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
diff --git a/rtkbt/code/libbt-vendor/src/rtk_heartbeat.c b/rtkbt/code/libbt-vendor/src/rtk_heartbeat.c
new file mode 100755 (executable)
index 0000000..4ace262
--- /dev/null
@@ -0,0 +1,245 @@
+#define LOG_TAG "rtk_heartbeat"
+#define RTKBT_RELEASE_NAME     "20180525_BT_ANDROID_8.1"
+
+#include <utils/Log.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <termios.h>
+#include <sys/syscall.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <cutils/properties.h>
+#include <stdlib.h>
+#include "bt_hci_bdroid.h"
+#include "bt_vendor_rtk.h"
+#include "userial.h"
+#include "userial_vendor.h"
+#include "rtk_btservice.h"
+#include "rtk_poll.h"
+#include "upio.h"
+#include <unistd.h>
+#include <sys/eventfd.h>
+#include <semaphore.h>
+#include <endian.h>
+#include <byteswap.h>
+#include <sys/un.h> 
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include "bt_vendor_lib.h"
+
+#define RTKBT_HEARTBEAT_CONF_FILE         "/vendor/etc/bluetooth/rtkbt_heartbeat.conf"
+
+#define HCI_EVT_HEARTBEAT_STATUS_OFFSET          (5)
+#define HCI_EVT_HEARTBEAT_SEQNUM_OFFSET_L          (6)
+#define HCI_EVT_HEARTBEAT_SEQNUM_OFFSET_H          (7)
+
+static const uint32_t DEFALUT_HEARTBEAT_TIMEOUT_MS = 1000; //send a per sercond
+int heartBeatLog = -1;
+static int heartBeatTimeout= -1;
+static bool heartbeatFlag = false;
+static int heartbeatCount= 0;
+static uint16_t nextSeqNum= 1;
+static uint16_t cleanupFlag = 0;
+
+typedef struct Rtk_Service_Data
+{
+    uint16_t        opcode;
+    uint8_t         parameter_len;
+    uint8_t         *parameter;
+    void            (*complete_cback)(void *);
+}Rtk_Service_Data;
+
+#define HCI_CMD_VNDR_HEARTBEAT      0xFC94
+
+extern void Rtk_Service_Vendorcmd_Hook(Rtk_Service_Data *RtkData, int client_sock);
+extern uint8_t get_heartbeat_from_hardware();
+
+static char *rtk_trim(char *str) {
+    while (isspace(*str))
+        ++str;
+
+    if (!*str)
+        return str;
+
+    char *end_str = str + strlen(str) - 1;
+    while (end_str > str && isspace(*end_str))
+        --end_str;
+
+    end_str[1] = '\0';
+    return str;
+}
+
+
+static void load_rtkbt_heartbeat_conf()
+{
+    char *split;
+    FILE *fp = fopen(RTKBT_HEARTBEAT_CONF_FILE, "rt");
+    if (!fp) {
+      ALOGE("%s unable to open file '%s': %s", __func__, RTKBT_HEARTBEAT_CONF_FILE, strerror(errno));
+      return;
+    }
+    int line_num = 0;
+    char line[1024];
+    //char value[1024];
+    while (fgets(line, sizeof(line), fp)) {
+        char *line_ptr = rtk_trim(line);
+        ++line_num;
+
+        // Skip blank and comment lines.
+        if (*line_ptr == '\0' || *line_ptr == '#' || *line_ptr == '[')
+          continue;
+
+        split = strchr(line_ptr, '=');
+        if (!split) {
+            ALOGE("%s no key/value separator found on line %d.", __func__, line_num);
+            continue;
+        }
+
+        *split = '\0';
+        char *endptr;
+        if(!strcmp(rtk_trim(line_ptr), "HeartBeatTimeOut")) {
+            heartBeatTimeout = strtol(rtk_trim(split+1), &endptr, 0);
+        }
+        else if(!strcmp(rtk_trim(line_ptr), "HeartBeatLog")) {
+            heartBeatLog = strtol(rtk_trim(split+1), &endptr, 0);
+        }
+    }
+
+    fclose(fp);
+
+}
+
+static void rtkbt_heartbeat_cmpl_cback (void *p_params)
+{
+    uint8_t  status = 0;
+    uint16_t seqnum;
+    HC_BT_HDR *p_evt_buf = p_params;
+    //uint8_t  *p = NULL;
+    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);
+        heartbeatCount = 0;
+    }
+    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);
+    }
+   
+}
+
+
+static void heartbeat_timed_out()//(union sigval arg)
+{
+    Rtk_Service_Data *p_buf;
+    
+    heartbeatCount++;
+    if(heartbeatCount >= 3)
+    {
+        if(cleanupFlag == 1)
+        {
+            ALOGW("Already cleanup, ignore.");
+            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");
+        usleep(1000);
+        kill(getpid(), SIGKILL);
+        return;
+    }
+    if(heartbeatFlag)
+    {
+        p_buf = (Rtk_Service_Data *)malloc(sizeof(Rtk_Service_Data));
+        if (NULL == p_buf)
+        {
+            ALOGE("p_buf: allocate error");
+            return;
+        }
+        p_buf->opcode = HCI_CMD_VNDR_HEARTBEAT;
+        p_buf->parameter = NULL;
+        p_buf->parameter_len = 0;
+        p_buf->complete_cback = rtkbt_heartbeat_cmpl_cback;
+
+        Rtk_Service_Vendorcmd_Hook(p_buf,-1);
+        free(p_buf);
+        poll_timer_flush();
+    }
+}
+
+
+static void rtkbt_heartbeat_beginTimer_func(void)
+{
+    Rtk_Service_Data *p_buf;
+
+    if((heartBeatTimeout != -1) && (heartBeatLog != -1))
+    {
+        poll_init(heartbeat_timed_out,heartBeatTimeout);
+    }
+    else
+    {
+        heartBeatLog = 0;
+        poll_init(heartbeat_timed_out,DEFALUT_HEARTBEAT_TIMEOUT_MS);
+    }
+    poll_enable(TRUE);
+
+    p_buf = (Rtk_Service_Data *)malloc(sizeof(Rtk_Service_Data));
+    if (NULL == p_buf)
+    {
+        ALOGE("p_buf: allocate error");
+        return;
+    }
+    p_buf->opcode = HCI_CMD_VNDR_HEARTBEAT;
+    p_buf->parameter = NULL;
+    p_buf->parameter_len = 0;
+    p_buf->complete_cback = rtkbt_heartbeat_cmpl_cback;
+    
+    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()
+{
+    heartbeatFlag = false;
+    nextSeqNum = 1;
+    heartbeatCount = 0;
+    cleanupFlag = 1;
+    poll_enable(FALSE);
+    poll_cleanup();
+}
+
+void Heartbeat_init()
+{
+    int res;
+    ALOGD("Heartbeat_init start");
+    Heartbeat_cleanup();
+    load_rtkbt_heartbeat_conf();
+    heartbeatFlag = true;
+    heartbeatCount = 0;
+    cleanupFlag = 0;
+    res = get_heartbeat_from_hardware();
+    ALOGD("Heartbeat_init res = %x",res);
+    if(res == 1)
+      rtkbt_heartbeat_beginTimer_func();
+    else
+      Heartbeat_cleanup();
+    ALOGD("Heartbeat_init end");
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index cc9796f..d170472
@@ -33,7 +33,7 @@
 *
 ******************************************************************************/
 #define LOG_TAG "rtk_parse"
-#define RTKBT_RELEASE_NAME     "Test"
+#define RTKBT_RELEASE_NAME "20180525_BT_ANDROID_8.1"
 
 #include <utils/Log.h>
 #include <stdlib.h>
@@ -191,6 +191,12 @@ enum {
     profile_max = 8
 };
 
+typedef struct RTK_COEX_INFO {
+    RT_LIST_ENTRY   list;
+    HC_BT_HDR  *    p_buf;
+    uint16_t        opcode;
+}tRTK_COEX_INFO;
+
 //profile info data
 typedef struct RTK_PROF_INFO {
     RT_LIST_ENTRY   list;
@@ -214,7 +220,9 @@ typedef struct RTK_CONN_PROF {
 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;
     pthread_mutex_t profile_mutex;
+    pthread_mutex_t coex_mutex;
     pthread_mutex_t udpsocket_mutex;
     pthread_t thread_monitor;
     pthread_t thread_data;
@@ -263,9 +271,12 @@ 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;
+static volatile bool coex_cmd_send = false;
 
 #define BIT(_I)                         (uint16_t)(1<<(_I))
 #define is_profile_connected(profile)   ((rtk_prof.profile_bitmap & BIT(profile)) >0)
@@ -759,17 +770,70 @@ tRTK_PROF_INFO* find_profile_by_handle_dcid_scid(tRTK_PROF* h5, uint16_t handle,
     return NULL;
 }
 
+void init_coex_hash(tRTK_PROF* h5)
+{
+    RT_LIST_HEAD* head = &h5->coex_list;
+    ListInitializeHeader(head);
+}
+
+void delete_coex_from_hash(tRTK_COEX_INFO* desc)
+{
+    if (desc)
+    {
+        ListDeleteNode(&desc->list);
+        free(desc);
+        desc = NULL;
+    }
+}
+
+void flush_coex_hash(tRTK_PROF* h5)
+{
+    RT_LIST_HEAD* head = &h5->coex_list;
+    RT_LIST_ENTRY* iter = NULL, *temp = NULL;
+    tRTK_COEX_INFO* desc = NULL;
+
+    pthread_mutex_lock(&rtk_prof.coex_mutex);
+    LIST_FOR_EACH_SAFELY(iter, temp, head)
+    {
+        desc = LIST_ENTRY(iter, tRTK_COEX_INFO, list);
+        delete_coex_from_hash(desc);
+    }
+    //ListInitializeHeader(head);
+    pthread_mutex_unlock(&rtk_prof.coex_mutex);
+}
+
 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;
+    if (iter) {
+        desc = LIST_ENTRY(iter, tRTK_COEX_INFO, list);
+        if (desc)
+        {
+            ListDeleteNode(&desc->list);
+        }
+    }
+    else {
+        coex_cmd_send = false;
+    }
+    pthread_mutex_unlock(&rtk_prof.coex_mutex);
+
+    if(desc) {
+        ALOGE("%s, transmit_command Opcode:%x",__func__, desc->opcode);
+        bt_vendor_cbacks->xmit_cb(desc->opcode, desc->p_buf, rtk_cmd_complete_cback);
+    }
+
+    free(desc);
     return;
 }
 
 void rtk_vendor_cmd_to_fw(uint16_t opcode, uint8_t parameter_len, uint8_t* parameter)
 {
-    uint8_t temp = 0;
-    HC_BT_HDR  *p_buf=NULL;
+    //uint8_t temp = 0;
+    HC_BT_HDR  *p_buf = NULL;
 
     if(bt_vendor_cbacks)
         p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + parameter_len);
@@ -795,8 +859,29 @@ void rtk_vendor_cmd_to_fw(uint16_t opcode, uint8_t parameter_len, uint8_t* param
     }
     if(bt_vendor_cbacks)
     {
-            ALOGE("transmit_command Opcode:%x",opcode);
+        RtkLogMsg("begin transmit_command Opcode:%x",opcode);
+        pthread_mutex_lock(&rtk_prof.coex_mutex);
+        if(!coex_cmd_send) {
+            coex_cmd_send = true;
+            pthread_mutex_unlock(&rtk_prof.coex_mutex);
             bt_vendor_cbacks->xmit_cb(opcode, p_buf, rtk_cmd_complete_cback);
+        }
+        else {
+            tRTK_COEX_INFO* pcoex_info = NULL;
+            pcoex_info = malloc(sizeof(tRTK_COEX_INFO));
+            if (NULL == pcoex_info)
+            {
+                ALOGE("rtk_vendor_cmd_to_fw: allocate error");
+                return;
+            }
+
+            pcoex_info->p_buf = p_buf;
+            pcoex_info->opcode = opcode;
+
+            ListAddToTail(&(pcoex_info->list), &(rtk_prof.coex_list));
+            pthread_mutex_unlock(&rtk_prof.coex_mutex);
+        }
+
     }
     return ;
 }
@@ -1162,7 +1247,7 @@ uint8_t handle_l2cap_discon_req(uint16_t handle, uint16_t dcid, uint16_t scid, u
 void packets_count(uint16_t handle, uint16_t scid, uint16_t length, uint8_t direction, uint8_t *user_data)
 {
     tRTK_PROF_INFO* prof_info = NULL;
-    uint8_t profile_type;
+    //uint8_t profile_type;
 
     tRTK_CONN_PROF* hci_conn = find_connection_by_handle(&rtk_prof, handle);
     if(NULL == hci_conn)
@@ -1214,6 +1299,14 @@ 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");
+       }
     if (signo == TIMER_POLLING)
     {
         RtkLogMsg("polling timeout");
@@ -1346,9 +1439,9 @@ int udpsocket_send(char *tx_msg, int msg_size)
 
 int udpsocket_recv(uint8_t *recv_msg, uint8_t *msg_size)
 {
-    struct hostent *hostp;  /* client host info */
+    //struct hostent *hostp;  /* client host info */
     char buf[MAX_PAYLOAD];  /* message buf */
-    char *hostaddrp;        /* dotted decimal host addr string */
+    //char *hostaddrp;        /* dotted decimal host addr string */
     int n;                  /* message byte size */
     struct sockaddr_in recv_addr;
     socklen_t clientlen = sizeof(recv_addr);
@@ -1575,6 +1668,7 @@ static void rtk_handle_bt_info_control(uint8_t* p)
 static void rtk_handle_bt_coex_control(uint8_t* p)
 {
     uint8_t opcode = *p++;
+       uint8_t op_len = 0;
     RtkLogMsg("receive bt coex control event from wifi, opration is 0x%x", opcode);
     switch (opcode)
     {
@@ -1589,6 +1683,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             uint8_t opcode_len = *p++;
             uint8_t value = *p++;
             uint8_t temp_cmd[3];
+                       op_len = opcode_len;
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_ENABLE_IGNORE_WLAN_ACT_CMD;
             temp_cmd[1] = 1;
             temp_cmd[2] = value;
@@ -1601,6 +1696,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             uint8_t opcode_len = *p++;
             uint8_t value = *p++;
             uint8_t temp_cmd[3];
+                       op_len = opcode_len;
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_SET_BT_LNA_CONSTRAINT;
             temp_cmd[1] = 1;
             temp_cmd[2] = value;
@@ -1613,6 +1709,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             uint8_t opcode_len = *p++;
             uint8_t power_decrease = *p++;
             uint8_t temp_cmd[3];
+                       op_len = opcode_len;
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_WIFI_FORCE_TX_POWER_CMD;
             temp_cmd[1] = 1;
             temp_cmd[2] = power_decrease;
@@ -1625,6 +1722,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             uint8_t opcode_len = *p++;
             uint8_t psd_mode = *p++;
             uint8_t temp_cmd[3];
+                       op_len = opcode_len;
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_SET_BT_PSD_MODE;
             temp_cmd[1] = 1;
             temp_cmd[2] = psd_mode;
@@ -1636,6 +1734,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
         {
             uint8_t opcode_len = *p++;
             uint8_t temp_cmd[5];
+                       op_len = opcode_len;
             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
@@ -1649,6 +1748,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             rtk_prof.piconet_id = *p++;
             rtk_prof.mode = *p++;
             uint8_t temp_cmd[4];
+                       op_len = opcode_len;
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_GET_AFH_MAP_L;
             temp_cmd[1] = 2;
             temp_cmd[2] = rtk_prof.piconet_id;
@@ -1661,6 +1761,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
         {
             uint8_t opcode_len = *p++;
             uint8_t access_type = *p++;
+                       op_len = opcode_len;
             if(access_type == 0) //read
             {
                 uint8_t temp_cmd[7];
@@ -1691,7 +1792,7 @@ void rtk_handle_event_from_wifi(uint8_t* msg)
 {
     uint8_t *p = msg;
     uint8_t event_code = *p++;
-
+       uint8_t total_length = 0;
     if(memcmp(msg, invite_rsp, sizeof(invite_rsp)) == 0)
     {
 #if 0
@@ -1734,7 +1835,7 @@ void rtk_handle_event_from_wifi(uint8_t* msg)
 
     if(event_code == 0xFE)
     {
-        uint8_t total_length = *p++;
+        total_length = *p++;
         uint8_t extension_event = *p++;
         switch(extension_event)
         {
@@ -1780,7 +1881,7 @@ static void udpsocket_receive_thread_exit_handler(int sig)
     pthread_exit(0);
 }
 
-static void udpsocket_receive_thread(void *arg)
+static void udpsocket_receive_thread()//(void *arg)
 {
     uint8_t msg_recv[MAX_PAYLOAD];
     uint8_t recv_length;
@@ -1791,7 +1892,7 @@ static void udpsocket_receive_thread(void *arg)
     actions.sa_flags = 0;
     actions.sa_handler = udpsocket_receive_thread_exit_handler;
 
-    int rc = sigaction(SIGUSR2,&actions,NULL);
+    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);
@@ -1947,6 +2048,7 @@ void rtk_parse_init(void)
     RtkLogMsg("rtk_profile_init, version: %s", RTK_VERSION);
 
     pthread_mutex_init(&rtk_prof.profile_mutex, NULL);
+    pthread_mutex_init(&rtk_prof.coex_mutex, NULL);
     pthread_mutex_init(&rtk_prof.udpsocket_mutex, NULL);
     alloc_a2dp_packet_count_timer();
     alloc_pan_packet_count_timer();
@@ -1955,6 +2057,7 @@ void rtk_parse_init(void)
 
     init_profile_hash(&rtk_prof);
     init_connection_hash(&rtk_prof);
+    init_coex_hash(&rtk_prof);
 
     create_udpsocket_socket();
 }
@@ -1971,6 +2074,8 @@ void rtk_parse_cleanup()
     flush_connection_hash(&rtk_prof);
     flush_profile_hash(&rtk_prof);
     pthread_mutex_destroy(&rtk_prof.profile_mutex);
+    flush_coex_hash(&rtk_prof);
+    pthread_mutex_destroy(&rtk_prof.coex_mutex);
 
     stop_udpsocket_receive_thread();
     pthread_mutex_destroy(&rtk_prof.udpsocket_mutex);
@@ -2161,6 +2266,10 @@ 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);
@@ -2304,7 +2413,7 @@ static void rtk_handle_disconnect_complete_evt(uint8_t* p)
     }
 }
 
-static void rtk_handle_le_connection_complete_evt(uint8_t* p)
+static void rtk_handle_le_connection_complete_evt(uint8_t* p, bool enhanced)
 {
     uint16_t handle, interval;
     uint8_t status;
@@ -2313,6 +2422,9 @@ static void rtk_handle_le_connection_complete_evt(uint8_t* p)
     status = *p++;
     STREAM_TO_UINT16 (handle, p);
     p += 8; //role, address type, address
+    if(enhanced) {
+        p += 12;
+    }
     STREAM_TO_UINT16 (interval, p);
 
     if(status == 0) {
@@ -2366,9 +2478,11 @@ static void rtk_handle_le_meta_evt(uint8_t* p)
     uint8_t sub_event = *p++;
     switch (sub_event) {
     case HCI_BLE_CONN_COMPLETE_EVT:
-        rtk_handle_le_connection_complete_evt(p);
+        rtk_handle_le_connection_complete_evt(p, false);
+        break;
+    case HCI_BLE_ENHANCED_CONN_COMPLETE_EVT:
+        rtk_handle_le_connection_complete_evt(p, true);
         break;
-
     case HCI_BLE_LL_CONN_PARAM_UPD_EVT:
         rtk_handle_le_connection_update_complete_evt(p);
         break;
@@ -2627,7 +2741,7 @@ 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)
 {
     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)
     {
@@ -2646,7 +2760,7 @@ 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)
 {
     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)
@@ -2689,7 +2803,7 @@ void rtk_add_le_data_count(uint8_t data_type)
     }
 }
 
-static const rtk_parse_manager_t parse_interface = {
+static rtk_parse_manager_t parse_interface = {
   rtk_parse_internal_event_intercept,
   rtk_parse_l2cap_data,
   rtk_parse_init,
@@ -2700,7 +2814,7 @@ static const rtk_parse_manager_t parse_interface = {
   rtk_add_le_data_count,
 };
 
-const rtk_parse_manager_t *rtk_parse_manager_get_interface() {
+rtk_parse_manager_t *rtk_parse_manager_get_interface() {
   return &parse_interface;
 }
 
diff --git a/rtkbt/code/libbt-vendor/src/rtk_poll.c b/rtkbt/code/libbt-vendor/src/rtk_poll.c
new file mode 100755 (executable)
index 0000000..2ed91c9
--- /dev/null
@@ -0,0 +1,248 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014-2016 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Filename:      poll.c
+ *
+ *  Description:   Contains host & controller handshake implementation
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_poll"
+
+#include <utils/Log.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <time.h>
+#include "bt_hci_bdroid.h"
+//#include "bt_utils.h"
+#include "rtk_poll.h"
+
+/******************************************************************************
+**  Constants & Macros
+******************************************************************************/
+#ifndef BTPOLL_DBG
+#define BTPOLL_DBG false
+#endif
+
+#if (BTPOLL_DBG == true)
+#define BTPOLLDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
+#else
+#define BTPOLLDBG(param, ...) {}
+#endif
+
+#ifndef ENABLE_BT_POLL_IN_ACTIVE_MODE
+#define ENABLE_BT_POLL_IN_ACTIVE_MODE false
+#endif
+
+#ifndef DEFAULT_POLL_IDLE_TIMEOUT
+#define DEFAULT_POLL_IDLE_TIMEOUT    2500
+#endif
+
+volatile uint32_t rtkbt_heartbeat_noack_num = 0;
+volatile uint32_t rtkbt_heartbeat_evt_seqno = 0xffffffff;
+
+timed_out poll_idle_timeout;
+
+
+/******************************************************************************
+**  Externs
+******************************************************************************/
+
+/******************************************************************************
+**  Local type definitions
+******************************************************************************/
+
+/* Poll state */
+enum {
+    POLL_DISABLED = 0,      /* initial state */
+    POLL_ENABLED,
+};
+
+/* poll control block */
+typedef struct
+{
+    uint8_t state;       /* poll state */
+    uint8_t timer_created;
+    timer_t timer_id;
+    uint32_t timeout_ms;
+} bt_poll_cb_t;
+
+extern int timer_create(clockid_t clockid, struct sigevent *sevp,
+                                timer_t *timerid);
+extern int timer_delete(timer_t timerid);
+
+int timer_settime(timer_t timerid, int flags,
+                                 const struct itimerspec *new_value,
+                                                          struct itimerspec * old_value);
+/******************************************************************************
+**  Static variables
+******************************************************************************/
+
+static bt_poll_cb_t bt_poll_cb;
+
+/******************************************************************************
+**   Poll Static Functions
+******************************************************************************/
+
+/*******************************************************************************
+**
+** Function         poll_timer_stop
+**
+** Description      stop timer if allowed
+**
+** Returns          None
+**
+*******************************************************************************/
+static void poll_timer_stop(void)
+{
+    int status;
+    struct itimerspec ts;
+
+    ALOGI("poll_timer_stop: timer_created %d", bt_poll_cb.timer_created);
+
+    if (bt_poll_cb.timer_created == true) {
+        ts.it_value.tv_sec = 0;
+        ts.it_value.tv_nsec = 0;
+        ts.it_interval.tv_sec = 0;
+        ts.it_interval.tv_nsec = 0;
+
+        status = timer_settime(bt_poll_cb.timer_id, 0, &ts, 0);
+        if (status == -1)
+            ALOGE("[STOP] Failed to set poll idle timeout");
+    }
+}
+
+/*****************************************************************************
+**   POLL Interface Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function        poll_init
+**
+** Description     Init bt poll
+**
+** Returns         None
+**
+*******************************************************************************/
+void poll_init(timed_out ptr_timeout,uint32_t timeout)
+{
+    memset((void*)&bt_poll_cb, 0, sizeof(bt_poll_cb_t));
+    poll_idle_timeout = ptr_timeout;
+    bt_poll_cb.state = POLL_DISABLED;
+    bt_poll_cb.timeout_ms = timeout;
+
+    ALOGI("poll_init: state %d, timeout %d ms,timeout=%d", bt_poll_cb.state, bt_poll_cb.timeout_ms,timeout);
+}
+
+/*******************************************************************************
+**
+** Function        poll_cleanup
+**
+** Description     Poll clean up
+**
+** Returns         None
+**
+*******************************************************************************/
+void poll_cleanup(void)
+{
+    ALOGI("poll_cleanup: timer_created %d", bt_poll_cb.timer_created);
+
+    if (bt_poll_cb.timer_created == true) {
+        timer_delete(bt_poll_cb.timer_id);
+    }
+}
+
+/*******************************************************************************
+**
+** Function        poll_enable
+**
+** Description     Enalbe/Disable poll
+**
+** Returns         None
+**
+*******************************************************************************/
+void poll_enable(uint8_t turn_on)
+{
+    ALOGI("poll_enable: turn_on %d, state %d", turn_on, bt_poll_cb.state);
+
+    if ((turn_on == true) && (bt_poll_cb.state == POLL_ENABLED)) {
+        ALOGI("poll_enable: poll is already on!!!");
+        return;
+    } else if ((turn_on == false) && (bt_poll_cb.state == POLL_DISABLED)) {
+        ALOGI("poll_enable: poll is already off!!!");
+        return;
+    }
+
+    if (turn_on == false) {
+        poll_timer_stop();
+        bt_poll_cb.state = POLL_DISABLED;
+    } else {
+        /* start poll timer when poll_timer_flush invoked first time */
+        bt_poll_cb.state = POLL_ENABLED;
+    }
+}
+
+/*******************************************************************************
+**
+** Function        poll_timer_flush
+**
+** Description     Called to delay notifying Bluetooth chip.
+**                 Normally this is called when there is data to be sent
+**                 over HCI.
+**
+** Returns         None
+**
+*******************************************************************************/
+void poll_timer_flush(void)
+{
+    int status;
+    struct itimerspec ts;
+    struct sigevent se;
+
+    BTPOLLDBG("poll_timer_flush: state %d", bt_poll_cb.state);
+
+    if (bt_poll_cb.state != POLL_ENABLED)
+        return;
+
+    if (bt_poll_cb.timer_created == false) {
+        se.sigev_notify = SIGEV_THREAD;
+        se.sigev_value.sival_ptr = &bt_poll_cb.timer_id;
+        se.sigev_notify_function = poll_idle_timeout;
+        se.sigev_notify_attributes = NULL;
+
+        status = timer_create(CLOCK_MONOTONIC, &se, &bt_poll_cb.timer_id);
+
+        if (status == 0)
+            bt_poll_cb.timer_created = true;
+    }
+#if (defined(ENABLE_BT_POLL_IN_ACTIVE_MODE) && (ENABLE_BT_POLL_IN_ACTIVE_MODE == false))
+    if (bt_poll_cb.timer_created == true) {
+        ts.it_value.tv_sec = bt_poll_cb.timeout_ms / 1000;
+        ts.it_value.tv_nsec = 1000 * 1000 * (bt_poll_cb.timeout_ms % 1000);
+        ts.it_interval.tv_sec = 0;
+        ts.it_interval.tv_nsec = 0;
+
+        status = timer_settime(bt_poll_cb.timer_id, 0, &ts, 0);
+        if (status == -1)
+            ALOGE("[Flush] Failed to set poll idle timeout");
+    }
+#endif
+}
diff --git a/rtkbt/code/libbt-vendor/src/rtk_socket.c b/rtkbt/code/libbt-vendor/src/rtk_socket.c
new file mode 100755 (executable)
index 0000000..18aa689
--- /dev/null
@@ -0,0 +1,191 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Filename:      userial_vendor.c
+ *
+ *  Description:   Contains vendor-specific userial functions
+ *
+ ******************************************************************************/
+#undef NDEBUG
+#define LOG_TAG "rtk_socket"
+
+#include <utils/Log.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/eventfd.h>
+#include "userial.h"
+#include "userial_vendor.h"
+#include "rtk_socket.h"
+
+/******************************************************************************
+**  Constants & Macros
+******************************************************************************/
+
+/******************************************************************************
+**  Extern functions
+******************************************************************************/
+
+
+/******************************************************************************
+**  Local type definitions
+******************************************************************************/
+
+/******************************************************************************
+**  Static functions
+******************************************************************************/
+
+/******************************************************************************
+**  functions
+******************************************************************************/
+uint32_t Skt_Read(int fd, uint8_t *p_buf, uint32_t len)
+{
+    int n_read = 0;
+    struct pollfd pfd;
+
+    if (fd == -1)
+    {
+        return 0;
+    }
+
+    while (n_read < (int)len)
+    {
+        pfd.fd = fd;
+        pfd.events = POLLIN|POLLHUP;
+
+        /* make sure there is data prior to attempting read to avoid blocking
+           a read for more than poll timeout */
+
+        int poll_ret;
+        RTK_NO_INTR(poll_ret = poll(&pfd, 1, 100));
+        if (poll_ret == 0)
+        {
+            continue;
+        }
+        if (poll_ret < 0) {
+            ALOGE("%s(): poll() failed: return %d errno %d (%s)",
+                           __func__, poll_ret, errno, strerror(errno));
+            break;
+        }
+
+        if (pfd.revents & (POLLHUP|POLLNVAL) )
+        {
+            return 0;
+        }
+
+        ssize_t n;
+        RTK_NO_INTR(n = recv(fd, p_buf + n_read, len - n_read, 0));
+
+        if (n == 0)
+        {
+            ALOGE("Skt_Read : channel detached remotely");
+            return 0;
+        }
+
+        if (n < 0)
+        {
+            ALOGE("Skt_Read : read failed (%s)", strerror(errno));
+            return 0;
+        }
+
+        n_read += n;
+
+    }
+
+    return n_read;
+}
+
+int Skt_Read_noblock(int fd, uint8_t *p_buf, uint32_t len)
+{
+    int n_read = 0;
+    struct pollfd pfd;
+
+    if (fd == -1)
+    {
+        ALOGE("UIPC_Read_noblock closed");
+        return 0;
+    }
+
+    pfd.fd = fd;
+    pfd.events = POLLIN|POLLHUP;
+
+    if (poll(&pfd, 1, 0) == 0)
+    {
+        return 0;
+    }
+
+    if (pfd.revents & (POLLHUP|POLLNVAL) )
+    {
+        return 0;
+    }
+
+    n_read = recv(fd, p_buf, len, MSG_DONTWAIT|MSG_NOSIGNAL);
+
+    return n_read;
+}
+
+bool Skt_Send(int fd, uint8_t *p_buf, uint16_t msglen)
+{
+    ssize_t ret;
+    RTK_NO_INTR(ret = write(fd, p_buf, msglen));
+    if (ret < 0) {
+        ALOGE("failed to write (%s)", strerror(errno));
+    }
+
+    return false;
+}
+
+int Skt_Send_noblock(int fd, uint8_t *p_buf, uint16_t msglen)
+{
+    int res = 0;
+    struct pollfd pfd;
+
+    pfd.fd = fd;
+    pfd.events = POLLOUT|POLLHUP;
+    if (poll(&pfd, 1, 0) == 0)
+    {
+        return 0;
+    }
+
+    if (pfd.revents & (POLLHUP|POLLNVAL) )
+    {
+        ALOGE("poll : channel detached remotely");
+        return 0;
+    }
+
+    res = send(fd, p_buf, msglen, MSG_DONTWAIT);
+    if (res < 0)
+    {
+        ALOGE("failed to write (%s)", strerror(errno));
+    }
+
+    return res;
+}
+
+/******************************************************************************
+**  Static variables
+******************************************************************************/
+
+/*****************************************************************************
+**   Helper Functions
+*****************************************************************************/
+
+
old mode 100644 (file)
new mode 100755 (executable)
index b7a54a9..9291114
@@ -369,9 +369,9 @@ int upio_set_bluetooth_power(int on)
 ** Returns         None
 **
 *******************************************************************************/
-void upio_set(uint8_t pio, uint8_t action, uint8_t polarity)
+void upio_set(uint8_t pio, uint8_t action)//(uint8_t pio, uint8_t action, uint8_t polarity)
 {
-    int rc;
+    //int rc;
 #if (BT_WAKE_VIA_PROC == TRUE)
     int fd = -1;
     char buffer;
old mode 100644 (file)
new mode 100755 (executable)
index 9b62d2f..6283c44
 #include <sys/eventfd.h>
 #include "userial.h"
 #include "userial_vendor.h"
+#include "rtk_socket.h"
 
-#define RTK_SINGLE_CMD_EVENT
+#ifdef CONFIG_SCO_OVER_HCI
+#include "sbc.h"
+#endif
 /******************************************************************************
 **  Constants & Macros
 ******************************************************************************/
@@ -60,6 +63,7 @@
 **  Extern functions
 ******************************************************************************/
 extern char rtkbt_transtype;
+extern void Heartbeat_cleanup();
 
 /******************************************************************************
 **  Local type definitions
@@ -97,19 +101,45 @@ typedef struct
     RTB_QUEUE_HEAD *recv_data;
     RTB_QUEUE_HEAD *send_data;
     RTB_QUEUE_HEAD *data_order;
+    volatile bool  btdriver_state;
 } vnd_userial_cb_t;
 
-#define RTK_NO_INTR(fn)  do {} while ((fn) == -1 && errno == EINTR)
+#ifdef CONFIG_SCO_OVER_HCI
+uint16_t btui_msbc_h2[] = {0x0801,0x3801,0xc801,0xf801};
+typedef struct
+{
+    pthread_mutex_t sco_mutex;
+    pthread_cond_t  sco_cond;
+    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;
+    uint16_t voice_settings;
+    RTB_QUEUE_HEAD *recv_sco_data;
+    RTB_QUEUE_HEAD *send_sco_data;
+    unsigned char enc_data[480];
+    unsigned int current_pos;
+    uint16_t sco_packet_len;
+    bool msbc_used;
+    int ctrl_fd, data_fd;
+    sbc_t sbc_dec, sbc_enc;
+    uint32_t pcm_enc_seq;
+}sco_cb_t;
+#endif
 
 /******************************************************************************
 **  Static functions
 ******************************************************************************/
 static void h5_data_ready_cb(serial_data_type_t type, unsigned int total_length);
 static uint16_t h5_int_transmit_data_cb(serial_data_type_t type, uint8_t *data, uint16_t length) ;
-
+extern void RTK_btservice_destroyed();
 /******************************************************************************
 **  Static variables
 ******************************************************************************/
+#ifdef CONFIG_SCO_OVER_HCI
+static sco_cb_t sco_cb;
+#endif
 static vnd_userial_cb_t vnd_userial;
 static const hci_h5_t* h5_int_interface;
 static int packet_recv_state = RTKBT_PACKET_IDLE;
@@ -126,12 +156,12 @@ static serial_data_type_t coex_current_type = 0;
 static unsigned char coex_resvered_buffer[2048] = {0};
 static int coex_resvered_length = 0;
 
-#ifdef RTK_SINGLE_CMD_EVENT
-static int cmd_packet_recv_state = RTKBT_PACKET_IDLE;
-static int cmd_packet_bytes_need = 0;
-static serial_data_type_t cmd_current_type = 0;
-static unsigned char cmd_resvered_header[10] = {0};
-static int cmd_resvered_length = 0;
+#ifdef RTK_HANDLE_EVENT
+static int received_packet_state = RTKBT_PACKET_IDLE;
+static 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;
 #endif
 
 static rtk_parse_manager_t * rtk_parse_manager = NULL;
@@ -141,6 +171,13 @@ static  hci_h5_callbacks_t h5_int_callbacks = {
     .h5_data_ready_cb = h5_data_ready_cb,
 };
 
+static const uint8_t hci_preamble_sizes[] = {
+    COMMAND_PREAMBLE_SIZE,
+    ACL_PREAMBLE_SIZE,
+    SCO_PREAMBLE_SIZE,
+    EVENT_PREAMBLE_SIZE
+};
+
 /*****************************************************************************
 **   Helper Functions
 *****************************************************************************/
@@ -252,6 +289,16 @@ void userial_vendor_init(char *bt_device_node)
     vnd_userial.data_order = RtbQueueInit();
     vnd_userial.recv_data = RtbQueueInit();
     vnd_userial.send_data = RtbQueueInit();
+#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);
+    memset(&sco_cb.sbc_enc, 0, sizeof(sbc_t));
+    sbc_init(&sco_cb.sbc_enc);//sbc_init(&sco_cb.sbc_enc, 0);
+    memset(&sco_cb.sbc_dec, 0, sizeof(sbc_t));
+    sbc_init(&sco_cb.sbc_dec);//sbc_init(&sco_cb.sbc_enc, 0);
+#endif
 }
 
 
@@ -357,6 +404,7 @@ int userial_vendor_open(tUSERIAL_CFG *p_cfg)
     userial_ioctl_init_bt_wake(vnd_userial.fd);
 #endif
 
+    vnd_userial.btdriver_state = true;
     ALOGI("device fd = %d open", vnd_userial.fd);
 
     return vnd_userial.fd;
@@ -418,34 +466,37 @@ static void userial_coex_close(void)
 *******************************************************************************/
 void userial_vendor_close(void)
 {
-    int result;
-
+    //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();
     userial_uart_close();
     userial_coex_close();
+    Heartbeat_cleanup();
 
     vnd_userial.fd = -1;
+    vnd_userial.btdriver_state = false;
     if(rtk_parse_manager) {
         rtk_parse_manager->rtk_parse_cleanup();
     }
     rtk_parse_manager = NULL;
-
-
-       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);
+#ifdef CONFIG_SCO_OVER_HCI
+    sbc_finish(&sco_cb.sbc_enc);
+    sbc_finish(&sco_cb.sbc_dec);
 #endif
-        h5_int_interface->h5_int_cleanup();
-
-    }
 }
 
 /*******************************************************************************
@@ -486,6 +537,10 @@ 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");
+       }
     switch(op)
     {
 #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
@@ -521,6 +576,10 @@ 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");
+       }
     strcpy(vnd_userial.port_name, p_conf_value);
 
     return 0;
@@ -582,7 +641,7 @@ static uint16_t h4_int_transmit_data(uint8_t *data, uint16_t total_length) {
 
     uint16_t length = total_length;
     uint16_t transmitted_length = 0;
-    while (length > 0) {
+    while (length > 0 && vnd_userial.btdriver_state) {
         ssize_t ret = write(vnd_userial.fd, data + transmitted_length, length);
         switch (ret) {
             case -1:
@@ -591,7 +650,7 @@ static uint16_t h4_int_transmit_data(uint8_t *data, uint16_t total_length) {
         case 0:
             // If we wrote nothing, don't loop more because we
             // can't go to infinity or beyond, ohterwise H5 can resend data
-            ALOGE("%s, ret %d", __func__, ret);
+            ALOGE("%s, ret %zd", __func__, ret);
             goto done;
         default:
             transmitted_length += ret;
@@ -815,12 +874,12 @@ static void userial_coex_send_data_handler(unsigned char * send_buffer, int tota
     free(p_buf);
 }
 
-static void userial_coex_handler(void *context)
+static void userial_coex_handler()//(void *context)
 {
     RTK_BUFFER* skb_data;
     RTK_BUFFER* skb_type;
     eventfd_t value;
-    int read_length = 0;
+    unsigned int read_length = 0;
     eventfd_read(vnd_userial.event_fd, &value);
     if(!value && !vnd_userial.thread_running) {
         return;
@@ -853,13 +912,370 @@ static void userial_coex_handler(void *context)
     }
 }
 
-static void userial_recv_H4_rawdata(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)
+{
+    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;
+    prctl(PR_SET_NAME, (unsigned long)"userial_recv_sco_thread", 0, 0, 0);
+    /*
+    FILE *file;
+    unsigned char enc_data[60];
+    file = fopen("/data/misc/bluedroid/sco_capture.raw", "rb");
+    FILE *file2;
+    file2 = fopen("/data/misc/bluedroid/sco_capture.pcm", "wb");
+    if (!file) {
+        ALOGE("Unable to create file");
+        return NULL;
+    }
+    */
+    RtbEmptyQueue(sco_cb.recv_sco_data);
+    ALOGE("userial_recv_sco_thread start");
+    while(sco_cb.thread_sco_running) {
+        pthread_mutex_lock(&sco_cb.sco_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_mutex_unlock(&sco_cb.sco_mutex);
+        skb_sco_data = RtbDequeueHead(sco_cb.recv_sco_data);
+        if(!skb_sco_data)
+          continue;
+        p_data = skb_sco_data->Data;
+        //if (fwrite(skb_sco_data->Data, 1, 60, file) != 60) {
+            //ALOGE("Error capturing sample");
+        //}
+        /*
+        if(fread(enc_data, 1, 60, file) > 0) {
+            ALOGE("userial_recv_sco_thread, fread data");
+            res = sbc_decode(&sco_cb.sbc_dec, &enc_data[2], 58, dec_data, 240, &writen);
+        }
+        else {
+            fseek(file, 0L, SEEK_SET);
+            if(fread(enc_data, 1, 60, file) > 0) {
+                res = sbc_decode(&sco_cb.sbc_dec, &enc_data[2], 58, dec_data, 240, &writen);
+            }
+        }
+        */
+        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);
+            }
+        }
+        else {
+            ALOGE("msbc decode fail!");
+        }
+        RtbFree(skb_sco_data);
+    }
+    ALOGE("userial_recv_sco_thread exit");
+    RtbEmptyQueue(sco_cb.recv_sco_data);
+    return NULL;
+}
+
+static void* userial_send_sco_thread()//(void *arg)
+{
+    unsigned char enc_data[240];
+    unsigned char pcm_data[960];
+    unsigned char send_data[100];
+    int writen = 0;
+    int num_read;
+    prctl(PR_SET_NAME, (unsigned long)"userial_send_sco_thread", 0, 0, 0);
+    sco_cb.pcm_enc_seq = 0;
+    int i;
+
+    /*
+    FILE *file;
+    file = fopen("/data/misc/bluedroid/sco_playback.raw", "rb");
+    if (!file) {
+        ALOGE("Unable to create file");
+        return NULL;
+    }
+    */
+    ALOGE("userial_send_sco_thread start");
+    while(sco_cb.thread_sco_running) {
+        num_read = Skt_Read(sco_cb.data_fd, pcm_data, 960 * 2);
+        /*
+        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);
+            }
+            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!");
+            }
+            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);
+            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_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);
+}
+
+static void userial_sco_ctrl_skt_handle()
+{
+    uint8_t cmd = 0, ack = 0;;
+    int result = Skt_Read(sco_cb.ctrl_fd, &cmd, 1);
+
+    if(result == 0) {
+        userial_sco_socket_stop();
+        return;
+    }
+
+    ALOGE("%s, cmd = %d, msbc_used = %d", __func__, cmd, sco_cb.msbc_used);
+    switch (cmd) {
+        case SCO_CTRL_CMD_CHECK_READY:
+
+        break;
+
+        case SCO_CTRL_CMD_OUT_START:
+        {
+            pthread_attr_t thread_attr;
+            pthread_attr_init(&thread_attr);
+            pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
+            if(pthread_create(&sco_cb.thread_send_sco_id, &thread_attr, userial_send_sco_thread, NULL)!= 0 )
+            {
+                ALOGE("pthread_create : %s", strerror(errno));
+            }
+        }
+        break;
+
+        case SCO_CTRL_CMD_IN_START:
+        {
+            pthread_attr_t thread_attr;
+            pthread_attr_init(&thread_attr);
+            pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
+            if(pthread_create(&sco_cb.thread_recv_sco_id, &thread_attr, userial_recv_sco_thread, NULL)!= 0 )
+            {
+                ALOGE("pthread_create : %s", strerror(errno));
+            }
+        }
+        break;
+
+        case SCO_CTRL_CMD_OUT_STOP:
+
+        break;
+
+        case SCO_CTRL_CMD_SUSPEND:
+
+        break;
+
+        case SCO_CTRL_GET_AUDIO_CONFIG:
+            if(sco_cb.msbc_used) {
+                ack = 2;
+                Skt_Send(sco_cb.ctrl_fd, &ack, 1);
+            }
+            else {
+                ack = 1;
+                Skt_Send(sco_cb.ctrl_fd, &ack, 1);
+            }
+        break;
+
+        default:
+
+        break;
+    }
+}
+
+static void* userial_socket_sco_thread()//(void *arg)
+{
+    struct sockaddr_un addr, remote;
+    socklen_t alen, len = sizeof(struct sockaddr_un);
+    fd_set read_set, active_set;
+    int result, max_fd;
+    int s_ctrl = socket(AF_LOCAL, SOCK_STREAM, 0);
+    int s_data = socket(AF_LOCAL, SOCK_STREAM, 0);
+    prctl(PR_SET_NAME, (unsigned long)"userial_socket_sco_thread", 0, 0, 0);
+
+    //bind sco ctrl socket
+    unlink(SCO_CTRL_PATH);
+    memset(&addr, 0, sizeof(addr));
+    strcpy(addr.sun_path, SCO_CTRL_PATH);
+    addr.sun_family = AF_LOCAL;
+    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;
+    }
+
+    if(listen(s_ctrl, 5) < 0) {
+        ALOGE("userial_socket_sco_thread, listen ctrl socket error : %s", strerror(errno));
+        return NULL;
+    }
+
+    chmod(SCO_CTRL_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+    //bind sco data socket
+    unlink(SCO_DATA_PATH);
+    memset(&addr, 0, sizeof(addr));
+    strcpy(addr.sun_path, SCO_DATA_PATH);
+    addr.sun_family = AF_LOCAL;
+    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;
+    }
+
+    if(listen(s_data, 5) < 0) {
+        ALOGE("userial_socket_sco_thread, listen data socket error : %s", strerror(errno));
+        return NULL;
+    }
+    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;
+
+    while(sco_cb.thread_sco_running) {
+        read_set = active_set;
+        result = select(max_fd, &read_set, NULL, NULL, NULL);
+        if (result == 0) {
+            ALOGE("select timeout");
+            continue;
+        }
+        if (result < 0) {
+            if (errno != EINTR)
+                ALOGE("select failed %s", strerror(errno));
+            continue;
+        }
+        if(FD_ISSET(s_ctrl, &read_set)) {
+            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;
+            }
+            const int size = (512);
+            setsockopt(sco_cb.ctrl_fd, SOL_SOCKET, SO_RCVBUF, (char*)&size, (int)sizeof(size));
+            FD_SET(sco_cb.ctrl_fd, &active_set);
+            max_fd = (MAX(max_fd, sco_cb.ctrl_fd)) + 1;
+        }
+
+        if(FD_ISSET(s_data, &read_set)) {
+            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;
+            }
+            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)) {
+            userial_sco_ctrl_skt_handle();
+        }
+    }
+    close(s_ctrl);
+    close(s_data);
+    return NULL;
+}
+
+#endif
+
+#ifdef RTK_HANDLE_CMD
+static void userial_handle_cmd(unsigned char * recv_buffer, int 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);
+    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;
+            }
+        break;
+
+
+        case HCI_WRITE_VOICE_SETTINGS :
+            voice_settings = *(uint16_t*)&recv_buffer[3];
+            userial_vendor_usb_ioctl(SET_ISO_CFG, &voice_settings);
+#ifdef CONFIG_SCO_OVER_HCI
+            sco_cb.voice_settings = voice_settings;
+#endif
+        break;
+#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));
+            }
+        break;
+#endif
+        default:
+        break;
+    }
+}
+#endif
+
+
+//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)
 {
     serial_data_type_t type = 0;
     ssize_t bytes_read;
     uint16_t opcode;
     uint16_t transmitted_length = 0;
-    unsigned char *buffer = NULL;
+    //unsigned char *buffer = NULL;
 
     switch (packet_recv_state) {
         case RTKBT_PACKET_IDLE:
@@ -874,9 +1290,10 @@ static void userial_recv_H4_rawdata(void *context)
                     ALOGE("%s, state = %d, bytes_read 0", __func__, packet_recv_state);
                     return;
                 }
-                assert((type >= DATA_TYPE_COMMAND) && (type <= DATA_TYPE_SCO));
+
                 if (type < DATA_TYPE_COMMAND || type > DATA_TYPE_SCO) {
                     ALOGE("%s invalid data type: %d", __func__, type);
+                    assert((type >= DATA_TYPE_COMMAND) && (type <= DATA_TYPE_SCO));
                 }
                 else {
                     packet_bytes_need -= bytes_read;
@@ -888,12 +1305,7 @@ static void userial_recv_H4_rawdata(void *context)
             //fall through
 
         case RTKBT_PACKET_TYPE:
-            if(current_type == DATA_TYPE_ACL) {
-                packet_bytes_need = 4;
-            }
-            else {
-                packet_bytes_need = 3;
-            }
+            packet_bytes_need = hci_preamble_sizes[HCI_PACKET_TYPE_TO_INDEX(current_type)];
             h4_read_length = 0;
             packet_recv_state = RTKBT_PACKET_HEADER;
             //fall through
@@ -906,7 +1318,7 @@ static void userial_recv_H4_rawdata(void *context)
                     return;
                 }
                 if(!bytes_read && packet_bytes_need) {
-                    ALOGE("%s, state = %d, bytes_read 0", __func__, packet_recv_state);
+                    ALOGE("%s, state = %d, bytes_read 0, type : %d", __func__, packet_recv_state, current_type);
                     return;
                 }
                 packet_bytes_need -= bytes_read;
@@ -915,9 +1327,11 @@ static void userial_recv_H4_rawdata(void *context)
             packet_recv_state = RTKBT_PACKET_CONTENT;
 
             if(current_type == DATA_TYPE_ACL) {
-                packet_bytes_need = *(uint16_t *)&h4_read_buffer[3];
+                packet_bytes_need = *(uint16_t *)&h4_read_buffer[COMMON_DATA_LENGTH_INDEX];
+            } else if(current_type == DATA_TYPE_EVENT) {
+                packet_bytes_need = h4_read_buffer[EVENT_DATA_LENGTH_INDEX];
             } else {
-                packet_bytes_need = h4_read_buffer[3];
+                packet_bytes_need = h4_read_buffer[COMMON_DATA_LENGTH_INDEX];
             }
             //fall through
 
@@ -942,10 +1356,13 @@ static void userial_recv_H4_rawdata(void *context)
         case RTKBT_PACKET_END:
             switch (current_type) {
                 case DATA_TYPE_COMMAND:
+#ifdef RTK_HANDLE_CMD
+                    userial_handle_cmd(&h4_read_buffer[1], h4_read_length);
+#endif
                     if(rtkbt_transtype & RTKBT_TRANS_H4) {
                         h4_int_transmit_data(h4_read_buffer, (h4_read_length + 1));
                     }
-                        else {
+                    else {
                         opcode = *(uint16_t *)&h4_read_buffer[1];
                         if(opcode == HCI_VSC_H5_INIT) {
                             h5_int_interface->h5_send_sync_cmd(opcode, NULL, h4_read_length);
@@ -1002,7 +1419,7 @@ static uint16_t h5_int_transmit_data_cb(serial_data_type_t type, uint8_t *data,
     }
 
     uint16_t transmitted_length = 0;
-    while (length > 0) {
+    while (length > 0 && vnd_userial.btdriver_state) {
         ssize_t ret = write(vnd_userial.fd, data + transmitted_length, length);
         switch (ret) {
             case -1:
@@ -1011,7 +1428,7 @@ static uint16_t h5_int_transmit_data_cb(serial_data_type_t type, uint8_t *data,
         case 0:
             // If we wrote nothing, don't loop more because we
             // can't go to infinity or beyond, ohterwise H5 can resend data
-            ALOGE("%s, ret %d", __func__, ret);
+            ALOGE("%s, ret %zd", __func__, ret);
             goto done;
         default:
             transmitted_length += ret;
@@ -1025,53 +1442,148 @@ done:;
 
 }
 
-static void h5_data_ready_cb(serial_data_type_t type, unsigned int total_length)
+#ifdef RTK_HANDLE_EVENT
+static void userial_handle_event(unsigned char * recv_buffer, int total_length)
 {
-    unsigned char buffer[1028] = {0};
-    unsigned length = 0;
-    length = h5_int_interface->h5_int_read_data(&buffer[1], total_length);
-    buffer[0] = type;
-    length++;
-    uint16_t transmitted_length = 0;
-    while (length > 0) {
-        ssize_t ret;
-        RTK_NO_INTR(ret = write(vnd_userial.uart_fd[1], buffer + transmitted_length, 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;
-            length -= ret;
-            break;
+    uint8_t event;
+    uint8_t *p_data = recv_buffer;
+    event = p_data[0];
+    if(total_length == 0)
+    {
+        ALOGD("total_length %d",total_length);
+    }
+#ifdef CONFIG_SCO_OVER_HCI
+    if(event == 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);
         }
+        else {
+          sco_cb.sco_handle = *((uint16_t *)&p_data[3]);
+          if(!(sco_cb.voice_settings & 0x0003)) {
+              sco_cb.sco_packet_len = 240;
+              sco_cb.msbc_used = false;
+          }
+          else {
+              sco_cb.sco_packet_len = 60;
+              sco_cb.msbc_used = true;
+          }
+          sco_cb.current_pos = 0;
+        }
+
+        ALOGE("userial_handle_event sco_handle: %d",sco_cb.sco_handle);
     }
-done:;
-    return;
+    if(event == HCI_DISCONNECTION_COMP_EVT) {
+        if((*((uint16_t *)&p_data[3])) == sco_cb.sco_handle) {
+            sco_cb.sco_handle = 0;
+            sco_cb.msbc_used = false;
+        }
+    }
+#endif
 }
 
+#ifdef CONFIG_SCO_OVER_HCI
+static void userial_enqueue_sco_data(unsigned char * recv_buffer, int total_length)
+{
+    uint16_t sco_handle;
+    uint8_t sco_length;
+    uint8_t *p_data = recv_buffer;
+    RTK_BUFFER* skb_sco_data;
+    int i;
+    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);
+                RtbQueueTail(sco_cb.recv_sco_data, skb_sco_data);
+                pthread_cond_signal(&sco_cb.sco_cond);
+                pthread_mutex_unlock(&sco_cb.sco_mutex);
+
+                sco_cb.current_pos = 0;
+                p_data += (sco_packet_len - current_pos);
+                sco_length -= (sco_packet_len - current_pos);
+            }
+            else {
+                memcpy(&sco_cb.enc_data[current_pos], p_data, sco_length);
+                sco_cb.current_pos += sco_length;
+                return;
+            }
+        }
+
+        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);
+                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);
+            }
+
+            i = (sco_length % sco_packet_len);
+            current_pos = sco_length - i;
+            if(i) {
+                memcpy(sco_cb.enc_data, p_data + current_pos, i);
+                sco_cb.current_pos = i;
+            }
+            return;
+        }
+        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) {
+                  memcpy(sco_cb.enc_data, &p_data[i], (sco_length - i));
+                  sco_cb.current_pos = sco_length - i;
+                  return;
+              }
+              else {
+                  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);
+                  RtbQueueTail(sco_cb.recv_sco_data, skb_sco_data);
+                  pthread_cond_signal(&sco_cb.sco_cond);
+                  pthread_mutex_unlock(&sco_cb.sco_mutex);
+
+                  sco_cb.current_pos = 0;
+                  i += (sco_packet_len - 1);
+              }
+            }
+        }
+    }
+}
+#endif
 
-#ifdef RTK_SINGLE_CMD_EVENT
-static int userial_handle_cmd_event(unsigned char * recv_buffer, int total_length)
+static int userial_handle_recv_data(unsigned char * recv_buffer, int total_length)
 {
     serial_data_type_t type = 0;
     unsigned char * p_data = recv_buffer;
     int length = total_length;
     uint8_t event;
-    switch (cmd_packet_recv_state) {
+
+    switch (received_packet_state) {
         case RTKBT_PACKET_IDLE:
-            cmd_packet_bytes_need = 1;
+            received_packet_bytes_need = 1;
             while(length) {
                 type = p_data[0];
                 length--;
                 p_data++;
-                assert((type > DATA_TYPE_COMMAND) && (type <= DATA_TYPE_EVENT));
                 if (type < DATA_TYPE_ACL || type > DATA_TYPE_EVENT) {
                     ALOGE("%s invalid data type: %d", __func__, type);
+                    assert((type > DATA_TYPE_COMMAND) && (type <= DATA_TYPE_EVENT));
                     if(!length)
                         return total_length;
 
@@ -1079,92 +1591,90 @@ static int userial_handle_cmd_event(unsigned char * recv_buffer, int total_lengt
                 }
                 break;
             }
-            cmd_current_type = type;
-            cmd_packet_recv_state = RTKBT_PACKET_TYPE;
+            recv_packet_current_type = type;
+            received_packet_state = RTKBT_PACKET_TYPE;
             //fall through
 
         case RTKBT_PACKET_TYPE:
-            if(cmd_current_type == DATA_TYPE_ACL) {
-                cmd_packet_bytes_need = 4;
-            }
-            else if(cmd_current_type == DATA_TYPE_EVENT) {
-                cmd_packet_bytes_need = 2;
-            }
-            else {
-                cmd_packet_bytes_need = 3;
-            }
-            cmd_resvered_length = 0;
-            cmd_packet_recv_state = RTKBT_PACKET_HEADER;
+            received_packet_bytes_need = hci_preamble_sizes[HCI_PACKET_TYPE_TO_INDEX(recv_packet_current_type)];
+            received_resvered_length = 0;
+            received_packet_state = RTKBT_PACKET_HEADER;
             //fall through
 
         case RTKBT_PACKET_HEADER:
-            if(length >= cmd_packet_bytes_need) {
-                memcpy(&cmd_resvered_header[cmd_resvered_length], p_data, cmd_packet_bytes_need);
-                cmd_resvered_length += cmd_packet_bytes_need;
-                length -= cmd_packet_bytes_need;
-                p_data += cmd_packet_bytes_need;
+            if(length >= received_packet_bytes_need) {
+                memcpy(&received_resvered_header[received_resvered_length], p_data, received_packet_bytes_need);
+                received_resvered_length += received_packet_bytes_need;
+                length -= received_packet_bytes_need;
+                p_data += received_packet_bytes_need;
             }
             else {
-                memcpy(&cmd_resvered_header[cmd_resvered_length], p_data, length);
-                cmd_resvered_length += length;
-                cmd_packet_bytes_need -= length;
+                memcpy(&received_resvered_header[received_resvered_length], p_data, length);
+                received_resvered_length += length;
+                received_packet_bytes_need -= length;
                 length = 0;
                 return total_length;
             }
-            cmd_packet_recv_state = RTKBT_PACKET_CONTENT;
+            received_packet_state = RTKBT_PACKET_CONTENT;
 
-            if(cmd_current_type == DATA_TYPE_ACL) {
-                cmd_packet_bytes_need = *(uint16_t *)&cmd_resvered_header[2];
+            if(recv_packet_current_type == DATA_TYPE_ACL) {
+                received_packet_bytes_need = *(uint16_t *)&received_resvered_header[2];
             }
-             else if(cmd_current_type == DATA_TYPE_EVENT){
-                cmd_packet_bytes_need = cmd_resvered_header[1];
+             else if(recv_packet_current_type == DATA_TYPE_EVENT){
+                received_packet_bytes_need = received_resvered_header[1];
             }
             else {
-                cmd_packet_bytes_need = cmd_resvered_header[2];
+                received_packet_bytes_need = received_resvered_header[2];
             }
             //fall through
 
         case RTKBT_PACKET_CONTENT:
-            if(cmd_current_type == DATA_TYPE_EVENT) {
-                event = cmd_resvered_header[0];
-                if(cmd_resvered_length == 2) {
-                    if(event == HCI_COMMAND_COMPLETE_EVT) {
-                        if(length > 1) {
-                            *p_data = 1;
-                        }
-                    }
-                    else if(event == HCI_COMMAND_STATUS_EVT) {
-                        if(length > 2) {
-                            *(p_data + 1) = 1;
-                        }
+            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;
                     }
                 }
-                else if(cmd_resvered_length == 3) {
-                    if(event == HCI_COMMAND_STATUS_EVT) {
-                        if(length > 1) {
-                            *p_data = 1;
-                        }
+                else if(event == HCI_COMMAND_STATUS_EVT) {
+                    if(length >= 2) {
+                        *(p_data + 1) = 1;
                     }
-
                 }
             }
-            if(length >= cmd_packet_bytes_need) {
-                length -= cmd_packet_bytes_need;
-                p_data += cmd_packet_bytes_need;
-                cmd_resvered_length += cmd_packet_bytes_need;
-                cmd_packet_bytes_need = 0;
+            if(length >= received_packet_bytes_need) {
+                memcpy(&received_resvered_header[received_resvered_length], p_data, received_packet_bytes_need);
+                length -= received_packet_bytes_need;
+                p_data += received_packet_bytes_need;
+                received_resvered_length += received_packet_bytes_need;
+                received_packet_bytes_need = 0;
             }
             else {
-                cmd_resvered_length += length;
-                cmd_packet_bytes_need -= length;
+                memcpy(&received_resvered_header[received_resvered_length], p_data, length);
+                received_resvered_length += length;
+                received_packet_bytes_need -= length;
                 length = 0;
                 return total_length;
             }
-            cmd_packet_recv_state = RTKBT_PACKET_END;
+            received_packet_state = RTKBT_PACKET_END;
             //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;
+
+                case DATA_TYPE_SCO :
+                    userial_enqueue_sco_data(received_resvered_header, received_resvered_length);
+                break;
+
+                default :
 
+                break;
+            }
+#endif
         break;
 
         default:
@@ -1172,23 +1682,64 @@ static int userial_handle_cmd_event(unsigned char * recv_buffer, int total_lengt
         break;
     }
 
-    cmd_packet_recv_state = RTKBT_PACKET_IDLE;
-    cmd_packet_bytes_need = 0;
-    cmd_current_type = 0;
-    cmd_resvered_length = 0;
+    received_packet_state = RTKBT_PACKET_IDLE;
+    received_packet_bytes_need = 0;
+    recv_packet_current_type = 0;
+    received_resvered_length = 0;
 
     return (total_length - length);
 }
 #endif
 
+static void h5_data_ready_cb(serial_data_type_t type, unsigned int total_length)
+{
+    unsigned char buffer[1028] = {0};
+    unsigned int length = 0;
+    length = h5_int_interface->h5_int_read_data(&buffer[1], total_length);
+    buffer[0] = type;
+    length++;
+    uint16_t transmitted_length = 0;
+    unsigned int real_length = length;
+#ifdef RTK_HANDLE_EVENT
+    unsigned int read_length = 0;
+    do {
+        read_length += userial_handle_recv_data(buffer + read_length, real_length - read_length);
+    }while(read_length < total_length);
+#endif
+
+    while (length > 0) {
+        ssize_t ret;
+        RTK_NO_INTR(ret = write(vnd_userial.uart_fd[1], buffer + transmitted_length, 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;
+            length -= ret;
+            break;
+        }
+    }
+done:;
+    if(real_length)
+        userial_enqueue_coex_rawdata(buffer, real_length, true);
+    return;
+}
+
+//This recv data from driver which is sent or recv by the controller. The data type have ACL/SCO/EVENT
+// direction CONTROLLER -----> BT HOST
 static void userial_recv_uart_rawdata(unsigned char *buffer, unsigned int total_length)
 {
     unsigned int length = total_length;
     uint16_t transmitted_length = 0;
-#ifdef RTK_SINGLE_CMD_EVENT
-    int read_length = 0;
+#ifdef RTK_HANDLE_EVENT
+    unsigned int read_length = 0;
     do {
-        read_length += userial_handle_cmd_event(buffer + read_length, total_length - read_length);
+        read_length += userial_handle_recv_data(buffer + read_length, total_length - read_length);
 
     }while(read_length < total_length);
 #endif
@@ -1215,7 +1766,17 @@ done:;
     return;
 }
 
-static void* userial_recv_socket_thread(void *arg)
+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);
+    }
+}
+
+static void* userial_recv_socket_thread()//(void *arg)
 {
     struct epoll_event events[64];
     int j;
@@ -1243,7 +1804,7 @@ static void* userial_recv_socket_thread(void *arg)
     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;
@@ -1271,7 +1832,9 @@ static void* userial_recv_uart_thread(void *arg)
 
         if (pfd.revents & (POLLERR|POLLHUP)) {
             ALOGE("%s poll error, fd : %d", __func__, vnd_userial.fd);
-            continue;
+            vnd_userial.btdriver_state = false;
+            close(vnd_userial.fd);
+            return NULL;
         }
         if (ret < 0)
         {
@@ -1283,7 +1846,7 @@ static void* userial_recv_uart_thread(void *arg)
     return NULL;
 }
 
-static void* userial_coex_thread(void *arg)
+static void* userial_coex_thread()//(void *arg)
 {
     struct epoll_event events[64];
     int j;
@@ -1361,7 +1924,7 @@ int userial_socket_open()
     vnd_userial.cpoll_fd = epoll_create(64);
     assert (vnd_userial.cpoll_fd != -1);
 
-    vnd_userial.event_fd = eventfd(SIZE_MAX, EFD_NONBLOCK);
+    vnd_userial.event_fd = eventfd(10, EFD_NONBLOCK);
     assert(vnd_userial.event_fd != -1);
     if(vnd_userial.event_fd != -1) {
         rtk_coex_object.fd = vnd_userial.event_fd;
@@ -1384,23 +1947,24 @@ int userial_socket_open()
     return ret;
 }
 
-int userial_vendor_usb_ioctl(int operation)
+int userial_vendor_usb_ioctl(int operation, void* param)
 {
     int retval;
-    retval = ioctl(vnd_userial.fd, operation, NULL);
+    retval = ioctl(vnd_userial.fd, operation, param);
     return retval;
 }
 
 int userial_vendor_usb_open(void)
 {
-       if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1)
-       {
-           ALOGE("%s: unable to open %s: %s", __func__, vnd_userial.port_name, strerror(errno));
-           return -1;
-       }
+    if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1)
+    {
+        ALOGE("%s: unable to open %s: %s", __func__, vnd_userial.port_name, strerror(errno));
+        return -1;
+    }
 
-       ALOGI("device fd = %d open", vnd_userial.fd);
+    vnd_userial.btdriver_state = true;
+    ALOGI("device fd = %d open", vnd_userial.fd);
 
-       return vnd_userial.fd;
+    return vnd_userial.fd;
 }
 
diff --git a/rtkbt/code/rtkcmd/Android.mk b/rtkbt/code/rtkcmd/Android.mk
new file mode 100755 (executable)
index 0000000..d4a3905
--- /dev/null
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES += \
+                    rtkcmd.c
+
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := rtkcmd
+LOCAL_PROPRIETARY_MODULE := true
+include $(BUILD_EXECUTABLE)
+
diff --git a/rtkbt/code/rtkcmd/rtkcmd.c b/rtkbt/code/rtkcmd/rtkcmd.c
new file mode 100755 (executable)
index 0000000..552c5d7
--- /dev/null
@@ -0,0 +1,238 @@
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <syslog.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/un.h>
+#include <stddef.h>
+#include <signal.h>
+#include <unistd.h>
+
+#define UNIX_DOMAIN "@/data/misc/bluedroid/rtkbt_service.sock"
+
+typedef struct Rtk_Socket_Data
+{
+    unsigned char           type;      //hci,other,inner
+    unsigned char           opcodeh;
+    unsigned char           opcodel;
+    unsigned char           parameter_len;
+    unsigned char           parameter[0];
+}Rtk_Socket_Data;
+
+/*typedef struct
+{
+    unsigned short          event;
+    unsigned short          len;
+    unsigned short          offset;
+    unsigned short          layer_specific;
+    unsigned char           data[];
+} HC_BT_HDR;
+*/
+const char shortOptions[] = "f:r:h";
+const struct option longOptions[] = {
+    {"fullhcicmd",  required_argument,      NULL,   'f'},
+    {"read",        required_argument,      NULL,   'r'},
+    {"help",        no_argument,            NULL,   'h'},
+    {0, 0, 0, 0}
+};
+
+static void usage(void)
+{
+    fprintf(stderr, "Usage: rtkcmd [options]\n\n"
+         "Options:\n"
+         "-f | --fullhcicmd [opcode,parameter_len,parameter]    send hci cmd\n"
+         "-r | --read       [address]                           read register address \n"
+         "-h | --help                                           Print this message\n\n");
+}
+
+int Rtkbt_Sendcmd(int socketfd,char *p)
+{
+    char *token = NULL;
+    int i=0;
+    unsigned short OpCode = 0;
+    unsigned char ParamLen = 0;
+    unsigned char ParamLen_1 = 0;
+    int sendlen = 0;
+    int params_count=0;
+    int ret=0;
+    Rtk_Socket_Data *p_buf = NULL;
+
+    token = strtok(p,",");
+    if (token != NULL) {
+        OpCode = strtol(token, NULL, 0);
+        //printf("OpCode = %x\n",OpCode);
+        params_count++;
+    } else {
+        //ret = FUNCTION_PARAMETER_ERROR;
+        printf("parameter error\n");
+        return -1;
+    }
+
+    token = strtok(NULL, ",");
+    if (token != NULL) {
+        ParamLen = strtol(token, NULL, 0);
+        //printf("ParamLen = %d\n",ParamLen);
+        params_count++;
+    } else {
+        printf("parameter error\n");
+        return -1;
+    }
+
+    p_buf=(Rtk_Socket_Data *)malloc(sizeof(Rtk_Socket_Data) + sizeof(char)*ParamLen);
+    p_buf->type = 0x01;
+    p_buf->opcodeh = OpCode>>8;
+    p_buf->opcodel = OpCode&0xff;
+    p_buf->parameter_len = ParamLen;
+
+    ParamLen_1 = ParamLen;
+    while (ParamLen_1--) {
+        token = strtok(NULL, ",");
+        if (token != NULL) {
+            p_buf->parameter[i++] = strtol(token, NULL, 0);
+            params_count++;
+        } else {
+            printf("parameter error\n");
+            return -1;
+        }
+    }
+
+    if (params_count != ParamLen + 2) {
+        printf("parameter error\n");
+        return -1;
+    }
+
+    sendlen=sizeof(Rtk_Socket_Data)+sizeof(char)*p_buf->parameter_len;
+    ret=write(socketfd,p_buf,sendlen);
+    if(ret!=sendlen)
+        return -1;
+
+    free(p_buf);
+    return 0;
+}
+
+int Rtkbt_Getevent(int sock_fd)
+{
+    unsigned short event=0;
+    unsigned short event_len=0;
+    unsigned short offset=0;
+    unsigned short layer_specific=0;
+    unsigned char *recvbuf = NULL;
+    int ret=0;
+    int i;
+
+    ret = read(sock_fd,&event,2);
+    if(ret<=0)
+        return -1;
+    //printf("event = %x\n",event);
+
+    ret = read(sock_fd,&event_len,2);
+    if(ret<=0)
+        return -1;
+    //printf("event_len = %x\n",event_len);
+
+    ret = read(sock_fd,&offset,2);
+    if(ret<=0)
+        return -1;
+    //printf("offset = %x\n",offset);
+
+    ret = read(sock_fd,&layer_specific,2);
+    if(ret<=0)
+        return -1;
+    //printf("layer_specific = %x\n",layer_specific);
+
+    recvbuf=(unsigned char *)malloc(sizeof(char)*event_len);
+    ret = read(sock_fd,recvbuf,event_len);
+    if(ret < event_len)
+        return -1;
+
+    printf("Event: ");
+    for(i=0;i<event_len-1;i++)
+        printf("0x%02x ",recvbuf[i]);
+    printf("0x%02x\n",recvbuf[event_len-1]);
+
+    free(recvbuf);
+    return 0;
+}
+
+int socketinit()
+{
+    int sock_fd;
+    struct sockaddr_un un;
+    int len;
+    memset(&un, 0, sizeof(un));            /* fill socket address structure with our address */
+    un.sun_family = AF_UNIX;
+    strcpy(un.sun_path, UNIX_DOMAIN);
+    un.sun_path[0]=0;
+    len = offsetof(struct sockaddr_un, sun_path) + strlen(UNIX_DOMAIN);
+
+    sock_fd= socket(AF_UNIX, SOCK_STREAM, 0);
+    if(sock_fd<0)
+    {
+        printf("socket failed %s\n",strerror(errno));
+        return -1;
+    }
+    if(connect(sock_fd,(struct sockaddr *)&un, len)<0)
+    {
+        printf("connect failed %s\n",strerror(errno));
+        close(sock_fd);
+        return -1;
+    }
+
+    return sock_fd;
+}
+
+int main(int argc , char* argv[])
+{
+    int index;
+    int c;
+    int ret;
+    int socketfd;
+
+    socketfd = socketinit();
+    if(socketfd<0)
+    {
+        printf("socketinit failed\n");
+        exit(0);
+    }
+
+    c = getopt_long(argc, argv, shortOptions, longOptions, &index);
+
+    if(c==-1)
+    {
+        usage();
+    }
+    else
+    {
+        switch(c)
+        {
+            case 'f':
+            {
+                printf("Hcicmd %s\n",optarg);
+                ret = Rtkbt_Sendcmd(socketfd,optarg);
+                if(ret>=0)
+                {
+                    if(Rtkbt_Getevent(socketfd)<0)
+                        printf("Getevent fail\n");
+                }
+                break;
+            }
+            case 'r':
+            {
+                printf("read register %s\n",optarg);
+                //Rtkbt_Readreg(socketfd,optarg);
+                break;
+            }
+            case 'h':
+            {
+                usage();
+                break;
+            }
+        }
+    }
+
+    close(socketfd);
+
+}
\ No newline at end of file
old mode 100644 (file)
new mode 100755 (executable)
index 41d258c..88c7fe1
@@ -1,84 +1,31 @@
-# RELEASE NAME: 20171107_BT_ANDROID_8.x
+# RELEASE NAME: 20180525_BT_ANDROID_8.1
+# RTKBT_API_VERSION=2.1.1.0
+
+CUR_PATH := hardware/realtek/rtkbt
 
 BOARD_HAVE_BLUETOOTH := true
 BOARD_HAVE_BLUETOOTH_RTK := true
 BOARD_HAVE_BLUETOOTH_RTK_COEX := true
 
+ifeq ($(strip $(TARGET_BOARD_PLATFORM_PRODUCT)), box)
+BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := $(CUR_PATH)/bluetooth
+endif
 
-BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := $(LOCAL_PATH)/bluetooth
-
-
-#PRODUCT_COPY_FILES += \
-       $(LOCAL_PATH)/vendor/etc/bluetooth/rtkbt.conf:vendor/etc/bluetooth/rtkbt.conf \
-       $(LOCAL_PATH)/vendor/firmware/rtl8703as_config:vendor/firmware/rtl8703as_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8703as_fw:vendor/firmware/rtl8703as_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8703bs_config:vendor/firmware/rtl8703bs_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8703bs_fw:vendor/firmware/rtl8703bs_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8703cs_config:vendor/firmware/rtl8703cs_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8703cs_fw:vendor/firmware/rtl8703cs_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723a_config:vendor/firmware/rtl8723a_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723a_config_addr:vendor/firmware/rtl8723a_config_addr \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723a_fw:vendor/firmware/rtl8723a_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723as_config:vendor/firmware/rtl8723as_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723as_fw:vendor/firmware/rtl8723as_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723b_config:vendor/firmware/rtl8723b_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723b_config_2Ant_S0:vendor/firmware/rtl8723b_config_2Ant_S0 \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723b_fw:vendor/firmware/rtl8723b_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723bs_config:vendor/firmware/rtl8723bs_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723bs_fw:vendor/firmware/rtl8723bs_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723bs_VQ0_config:vendor/firmware/rtl8723bs_VQ0_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723bs_VQ0_fw:vendor/firmware/rtl8723bs_VQ0_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723bu_config:vendor/firmware/rtl8723bu_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723c_fw:vendor/firmware/rtl8723c_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723cs_cg_config:vendor/firmware/rtl8723cs_cg_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723cs_cg_fw:vendor/firmware/rtl8723cs_cg_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723cs_vf_config:vendor/firmware/rtl8723cs_vf_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723cs_vf_fw:vendor/firmware/rtl8723cs_vf_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723cs_xx_config:vendor/firmware/rtl8723cs_xx_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723cs_xx_fw:vendor/firmware/rtl8723cs_xx_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723d_config:vendor/firmware/rtl8723d_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723d_fw:vendor/firmware/rtl8723d_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723ds_config:vendor/firmware/rtl8723ds_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8723ds_fw:vendor/firmware/rtl8723ds_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8761a_config:vendor/firmware/rtl8761a_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8761at8192ee_fw:vendor/firmware/rtl8761at8192ee_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8761at_config:vendor/firmware/rtl8761at_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8761at_fw:vendor/firmware/rtl8761at_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8761au8192ee_fw:vendor/firmware/rtl8761au8192ee_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8761au8812ae_fw:vendor/firmware/rtl8761au8812ae_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8761au_fw:vendor/firmware/rtl8761au_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8761aw8192eu_config:vendor/firmware/rtl8761aw8192eu_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8761aw8192eu_fw:vendor/firmware/rtl8761aw8192eu_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8821a_config:vendor/firmware/rtl8821a_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8821a_fw:vendor/firmware/rtl8821a_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8821as_config:vendor/firmware/rtl8821as_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8821as_fw:vendor/firmware/rtl8821as_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8821c_config:vendor/firmware/rtl8821c_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8821c_fw:vendor/firmware/rtl8821c_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8821cs_config:vendor/firmware/rtl8821cs_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8821cs_fw:vendor/firmware/rtl8821cs_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8822b_config:vendor/firmware/rtl8822b_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8822b_fw:vendor/firmware/rtl8822b_fw \
-       $(LOCAL_PATH)/vendor/firmware/rtl8822bs_config:vendor/firmware/rtl8822bs_config \
-       $(LOCAL_PATH)/vendor/firmware/rtl8822bs_fw:vendor/firmware/rtl8822bs_fw \
-
-CUR_PATH := hardware/realtek/rtkbt
 PRODUCT_COPY_FILES += \
        $(CUR_PATH)/vendor/etc/bluetooth/rtkbt.conf:vendor/etc/bluetooth/rtkbt.conf
 
+ifeq ($(strip $(TARGET_BOARD_PLATFORM_PRODUCT)), tablet)
 BT_FIRMWARE_FILES := $(shell ls $(CUR_PATH)/vendor/firmware)
 PRODUCT_COPY_FILES += \
        $(foreach file, $(BT_FIRMWARE_FILES), $(CUR_PATH)/vendor/firmware/$(file):$(TARGET_COPY_OUT_VENDOR)/etc/firmware/$(file))
+else
+BT_FIRMWARE_FILES := $(shell ls $(CUR_PATH)/vendor/firmware_box)
+PRODUCT_COPY_FILES += \
+       $(foreach file, $(BT_FIRMWARE_FILES), $(CUR_PATH)/vendor/firmware_box/$(file):$(TARGET_COPY_OUT_VENDOR)/etc/firmware/$(file))
+endif
 
 PRODUCT_PACKAGES += \
-       Bluetooth \
-       libbt-vendor \
-       android.hardware.bluetooth@1.0-impl \
-       android.hidl.memory@1.0-impl \
-       android.hardware.bluetooth@1.0-service \
-       android.hardware.bluetooth@1.0-service.rc \
-       audio.a2dp.default
-
+       libbt-vendor-realtek
 
 PRODUCT_PROPERTY_OVERRIDES += \
        persist.bluetooth.btsnoopenable=false \
diff --git a/rtkbt/vendor/firmware_box/fw_info.txt b/rtkbt/vendor/firmware_box/fw_info.txt
new file mode 100755 (executable)
index 0000000..6305bae
--- /dev/null
@@ -0,0 +1,18 @@
+          FW           CUT     SVN     Coex
+rtl8761au8192ee_fw      D      13328   3736
+rtl8761a_fw             D      13328   3736
+rtl8761au_fw            D      19884   0006
+rtl8761aw8192eu_fw      D      19884   0006
+rtl8723ds_fw            C      19875   2020
+rtl8822b_fw             C      19903   5656
+rtl8821cs_fw            B      19894   1d1d
+rtl8761at_fw            D      19884   0006
+rtl8761au8812ae_fw      D      19648   0006
+rtl8821as_fw            B      19292   635d
+rtl8821a_fw             B      19292   635d
+rtl8723bs_fw            B      19587   6b4e
+rtl8723b_fw             B      19587   6b4e
+rtl8821c_fw             B      19894   1d1d
+rtl8822bs_fw            C      19903   5656
+rtl8723d_fw             C      19875   2020
+rtl8723bs_VQ0_fw        B      14422   5844
diff --git a/rtkbt/vendor/firmware_box/rtl8723b_config b/rtkbt/vendor/firmware_box/rtl8723b_config
new file mode 100755 (executable)
index 0000000..23fae05
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723b_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8723b_fw b/rtkbt/vendor/firmware_box/rtl8723b_fw
new file mode 100755 (executable)
index 0000000..5a1755d
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723b_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8723bs_VQ0_config b/rtkbt/vendor/firmware_box/rtl8723bs_VQ0_config
new file mode 100755 (executable)
index 0000000..6f3b6a8
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723bs_VQ0_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8723bs_VQ0_fw b/rtkbt/vendor/firmware_box/rtl8723bs_VQ0_fw
new file mode 100755 (executable)
index 0000000..d29f164
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723bs_VQ0_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8723bs_config b/rtkbt/vendor/firmware_box/rtl8723bs_config
new file mode 100755 (executable)
index 0000000..c0f57e7
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723bs_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8723bs_fw b/rtkbt/vendor/firmware_box/rtl8723bs_fw
new file mode 100755 (executable)
index 0000000..580c05c
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723bs_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8723bu_config b/rtkbt/vendor/firmware_box/rtl8723bu_config
new file mode 100755 (executable)
index 0000000..994f6ce
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723bu_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8723d_config b/rtkbt/vendor/firmware_box/rtl8723d_config
new file mode 100755 (executable)
index 0000000..6beca86
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723d_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8723d_fw b/rtkbt/vendor/firmware_box/rtl8723d_fw
new file mode 100755 (executable)
index 0000000..53e9795
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723d_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8723ds_config b/rtkbt/vendor/firmware_box/rtl8723ds_config
new file mode 100755 (executable)
index 0000000..0015d66
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723ds_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8723ds_fw b/rtkbt/vendor/firmware_box/rtl8723ds_fw
new file mode 100755 (executable)
index 0000000..566d674
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8723ds_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8761a_config b/rtkbt/vendor/firmware_box/rtl8761a_config
new file mode 100755 (executable)
index 0000000..8559b4a
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8761a_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8761a_fw b/rtkbt/vendor/firmware_box/rtl8761a_fw
new file mode 100755 (executable)
index 0000000..ac99c0c
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8761a_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8761at_config b/rtkbt/vendor/firmware_box/rtl8761at_config
new file mode 100755 (executable)
index 0000000..f1904fa
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8761at_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8761at_fw b/rtkbt/vendor/firmware_box/rtl8761at_fw
new file mode 100755 (executable)
index 0000000..b34efe5
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8761at_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8761au8192ee_fw b/rtkbt/vendor/firmware_box/rtl8761au8192ee_fw
new file mode 100755 (executable)
index 0000000..a4da0e4
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8761au8192ee_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8761au8812ae_fw b/rtkbt/vendor/firmware_box/rtl8761au8812ae_fw
new file mode 100755 (executable)
index 0000000..4e3bb84
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8761au8812ae_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8761au_fw b/rtkbt/vendor/firmware_box/rtl8761au_fw
new file mode 100755 (executable)
index 0000000..1d79c5e
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8761au_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8761aw8192eu_config b/rtkbt/vendor/firmware_box/rtl8761aw8192eu_config
new file mode 100755 (executable)
index 0000000..ea3e50e
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8761aw8192eu_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8761aw8192eu_fw b/rtkbt/vendor/firmware_box/rtl8761aw8192eu_fw
new file mode 100755 (executable)
index 0000000..e252afc
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8761aw8192eu_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8821a_config b/rtkbt/vendor/firmware_box/rtl8821a_config
new file mode 100755 (executable)
index 0000000..54309f3
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8821a_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8821a_fw b/rtkbt/vendor/firmware_box/rtl8821a_fw
new file mode 100755 (executable)
index 0000000..52c150d
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8821a_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8821as_config b/rtkbt/vendor/firmware_box/rtl8821as_config
new file mode 100755 (executable)
index 0000000..eb784a8
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8821as_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8821as_fw b/rtkbt/vendor/firmware_box/rtl8821as_fw
new file mode 100755 (executable)
index 0000000..09b8560
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8821as_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8821c_config b/rtkbt/vendor/firmware_box/rtl8821c_config
new file mode 100755 (executable)
index 0000000..17f3985
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8821c_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8821c_fw b/rtkbt/vendor/firmware_box/rtl8821c_fw
new file mode 100755 (executable)
index 0000000..92b320d
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8821c_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8821cs_config b/rtkbt/vendor/firmware_box/rtl8821cs_config
new file mode 100755 (executable)
index 0000000..311ee34
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8821cs_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8821cs_fw b/rtkbt/vendor/firmware_box/rtl8821cs_fw
new file mode 100755 (executable)
index 0000000..43cc65e
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8821cs_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8822b_config b/rtkbt/vendor/firmware_box/rtl8822b_config
new file mode 100755 (executable)
index 0000000..17f3985
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8822b_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8822b_fw b/rtkbt/vendor/firmware_box/rtl8822b_fw
new file mode 100755 (executable)
index 0000000..6e3f6ef
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8822b_fw differ
diff --git a/rtkbt/vendor/firmware_box/rtl8822bs_config b/rtkbt/vendor/firmware_box/rtl8822bs_config
new file mode 100755 (executable)
index 0000000..311ee34
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8822bs_config differ
diff --git a/rtkbt/vendor/firmware_box/rtl8822bs_fw b/rtkbt/vendor/firmware_box/rtl8822bs_fw
new file mode 100755 (executable)
index 0000000..bfe37d2
Binary files /dev/null and b/rtkbt/vendor/firmware_box/rtl8822bs_fw differ