summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRockchip2014-12-20 12:54:39 +0800
committerRockchip2014-12-20 12:54:39 +0800
commit96e9a46f7845ffcab64c5c62df20cd82f0c7112a (patch)
treec0a70dbd5babfa73923698b6998bdd859a0c6a72
parentb2de2191d8baf1b759d89cbb62f2520e9721f412 (diff)
bt support libbt_rtk8723bs
-rwxr-xr-xbluetooth/libbt_rtk8723bs/Android.mk32
-rwxr-xr-xbluetooth/libbt_rtk8723bs/bdroid_buildcfg.h29
-rwxr-xr-xbluetooth/libbt_rtk8723bs/include/bt_vendor_rtk.h211
-rwxr-xr-xbluetooth/libbt_rtk8723bs/include/upio.h107
-rwxr-xr-xbluetooth/libbt_rtk8723bs/include/userial_vendor.h182
-rwxr-xr-xbluetooth/libbt_rtk8723bs/include/vnd_cardhu.txt9
-rwxr-xr-xbluetooth/libbt_rtk8723bs/include/vnd_generic.txt8
-rwxr-xr-xbluetooth/libbt_rtk8723bs/src/bt_vendor_rtk.c222
-rwxr-xr-xbluetooth/libbt_rtk8723bs/src/hardware.c1899
-rwxr-xr-xbluetooth/libbt_rtk8723bs/src/upio.c487
-rwxr-xr-xbluetooth/libbt_rtk8723bs/src/userial_vendor.c445
-rwxr-xr-xbluetooth/libbt_rtk8723bs/vnd_buildcfg.mk16
12 files changed, 3647 insertions, 0 deletions
diff --git a/bluetooth/libbt_rtk8723bs/Android.mk b/bluetooth/libbt_rtk8723bs/Android.mk
new file mode 100755
index 0000000..bc879e5
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(strip $(BOARD_CONNECTIVITY_MODULE)), rtl8723bs)
+
+include $(CLEAR_VARS)
+
+BDROID_DIR := $(TOP_DIR)external/bluetooth/bluedroid
+
+LOCAL_SRC_FILES := \
+ src/bt_vendor_rtk.c \
+ src/hardware.c \
+ src/userial_vendor.c \
+ src/upio.c
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/include \
+ $(BDROID_DIR)/hci/include
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils
+
+LOCAL_MODULE := libbt-vendor
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE_OWNER := realtek
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)
+
+include $(LOCAL_PATH)/vnd_buildcfg.mk
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # BOARD_CONNECTIVITY_MODULE
diff --git a/bluetooth/libbt_rtk8723bs/bdroid_buildcfg.h b/bluetooth/libbt_rtk8723bs/bdroid_buildcfg.h
new file mode 100755
index 0000000..ef61b19
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/bdroid_buildcfg.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BDROID_BUILDCFG_H
+#define _BDROID_BUILDCFG_H
+
+#define BTM_DEF_LOCAL_NAME "rk30sdk"
+
+// SERVICE_CLASS:0x5A (Bit17 -Networking,Bit19 - Capturing,Bit20 -Object Transfer,Bit22 -Telephony)
+// MAJOR CLASS: COMPUTER
+// MINOR CLASS: TABLET
+#define BTA_DM_COD {0x1A, 0x01, 0x10}
+
+#define BTIF_HF_SERVICES (BTA_HSP_SERVICE_MASK)
+#define BTIF_HF_SERVICE_NAMES { BTIF_HSAG_SERVICE_NAME }
+#endif
diff --git a/bluetooth/libbt_rtk8723bs/include/bt_vendor_rtk.h b/bluetooth/libbt_rtk8723bs/include/bt_vendor_rtk.h
new file mode 100755
index 0000000..f24e285
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/include/bt_vendor_rtk.h
@@ -0,0 +1,211 @@
+/******************************************************************************
+ *
+ * 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: bt_vendor_rtk.h
+ *
+ * Description: A wrapper header file of bt_vendor_lib.h
+ *
+ * Contains definitions specific for interfacing with Realtek
+ * Bluetooth chipsets
+ *
+ ******************************************************************************/
+
+#ifndef BT_VENDOR_RTK_H
+#define BT_VENDOR_RTK_H
+
+#include "bt_vendor_lib.h"
+#include "vnd_buildcfg.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+
+/* 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/ttyS0" /* rk3x */
+#endif
+
+/* Location of firmware patch files */
+#ifndef FW_PATCHFILE_LOCATION
+#define FW_PATCHFILE_LOCATION "/vendor/firmware/" /* maguro */
+#endif
+
+#ifndef UART_TARGET_BAUD_RATE
+#define UART_TARGET_BAUD_RATE 3000000
+#endif
+
+
+
+/* The Bluetooth Device Aaddress source switch:
+ *
+ * -FALSE- (default value)
+ * Get the factory BDADDR from device's file system. Normally the BDADDR is
+ * stored in the location pointed by the PROPERTY_BT_BDADDR_PATH (defined in
+ * btif_common.h file) property.
+ *
+ * -TRUE-
+ * If the Bluetooth Controller has equipped with a non-volatile memory (such
+ * as BCM4330's OTP memory), the factory BDADDR can be stored in there and
+ * retrieved by the stack while enabling BT.
+ * !!! WARNING !!! Make sure that the OTP feature has been enabled in the
+ * firmware patchram (.hcd) file.
+ */
+#ifndef USE_CONTROLLER_BDADDR
+#define USE_CONTROLLER_BDADDR FALSE
+#endif
+
+/* sleep mode
+
+ 0: disable
+ 1: UART with Host wake/BT wake out of band signals
+*/
+#ifndef LPM_SLEEP_MODE
+#define LPM_SLEEP_MODE 1
+#endif
+
+/* Host Stack Idle Threshold in 300ms or 25ms
+
+ In sleep mode 1, this is the number of firmware loops executed with no
+ activity before the Host wake line is deasserted. Activity includes HCI
+ traffic excluding certain sleep mode commands and the presence of SCO
+ connections if the "Allow Host Sleep During SCO" flag is not set to 1.
+ Each count of this parameter is roughly equivalent to 300ms or 25ms.
+*/
+#ifndef LPM_IDLE_THRESHOLD
+#define LPM_IDLE_THRESHOLD 1
+#endif
+
+/* Host Controller Idle Threshold in 300ms or 25ms
+
+ This is the number of firmware loops executed with no activity before the
+ HC is considered idle. Depending on the mode, HC may then attempt to sleep.
+ Activity includes HCI traffic excluding certain sleep mode commands and
+ the presence of ACL/SCO connections.
+*/
+#ifndef LPM_HC_IDLE_THRESHOLD
+#define LPM_HC_IDLE_THRESHOLD 1
+#endif
+
+/* BT_WAKE Polarity - 0=Active Low, 1= Active High */
+#ifndef LPM_BT_WAKE_POLARITY
+#define LPM_BT_WAKE_POLARITY 1 /* maguro */
+#endif
+
+/* HOST_WAKE Polarity - 0=Active Low, 1= Active High */
+#ifndef LPM_HOST_WAKE_POLARITY
+#define LPM_HOST_WAKE_POLARITY 1 /* maguro */
+#endif
+
+/* LPM_ALLOW_HOST_SLEEP_DURING_SCO
+
+ When this flag is set to 0, the host is not allowed to sleep while
+ an SCO is active. In sleep mode 1, the device will keep the host
+ wake line asserted while an SCO is active.
+ When this flag is set to 1, the host can sleep while an SCO is active.
+ This flag should only be set to 1 if SCO traffic is directed to the PCM
+ interface.
+*/
+#ifndef LPM_ALLOW_HOST_SLEEP_DURING_SCO
+#define LPM_ALLOW_HOST_SLEEP_DURING_SCO 1
+#endif
+
+/* LPM_COMBINE_SLEEP_MODE_AND_LPM
+
+ In Mode 0, always set byte 7 to 0. In sleep mode 1, device always
+ requires permission to sleep between scans / periodic inquiries regardless
+ of the setting of this byte. In sleep mode 1, if byte is set, device must
+ have "permission" to sleep during the low power modes of sniff, hold, and
+ park. If byte is not set, device can sleep without permission during these
+ modes. Permission to sleep in Mode 1 is obtained if the BT_WAKE signal is
+ not asserted.
+*/
+#ifndef LPM_COMBINE_SLEEP_MODE_AND_LPM
+#define LPM_COMBINE_SLEEP_MODE_AND_LPM 1
+#endif
+
+/* LPM_ENABLE_UART_TXD_TRI_STATE
+
+ When set to 0, the device will not tristate its UART TX line before going
+ to sleep.
+ When set to 1, the device will tristate its UART TX line before going to
+ sleep.
+*/
+#ifndef LPM_ENABLE_UART_TXD_TRI_STATE
+#define LPM_ENABLE_UART_TXD_TRI_STATE 0
+#endif
+
+/* LPM_PULSED_HOST_WAKE
+*/
+#ifndef LPM_PULSED_HOST_WAKE
+#define LPM_PULSED_HOST_WAKE 0
+#endif
+
+/* LPM_IDLE_TIMEOUT_MULTIPLE
+
+ The multiple factor of host stack idle threshold in 300ms/25ms
+*/
+#ifndef LPM_IDLE_TIMEOUT_MULTIPLE
+#define LPM_IDLE_TIMEOUT_MULTIPLE 10
+#endif
+
+/* BT_WAKE_VIA_USERIAL_IOCTL
+
+ Use userial ioctl function to control BT_WAKE signal
+*/
+#ifndef BT_WAKE_VIA_USERIAL_IOCTL
+#define BT_WAKE_VIA_USERIAL_IOCTL FALSE
+#endif
+
+/* BT_WAKE_VIA_PROC
+
+ LPM & BT_WAKE control through PROC nodes
+*/
+#ifndef BT_WAKE_VIA_PROC
+#define BT_WAKE_VIA_PROC FALSE
+#endif
+
+/* HW_END_WITH_HCI_RESET
+
+ Sample code implementation of sending a HCI_RESET command during the epilog
+ process. It calls back to the callers after command complete of HCI_RESET
+ is received.
+*/
+#ifndef HW_END_WITH_HCI_RESET
+#define HW_END_WITH_HCI_RESET FALSE
+#endif
+
+/******************************************************************************
+** Extern variables and functions
+******************************************************************************/
+
+extern bt_vendor_callbacks_t *bt_vendor_cbacks;
+
+#endif /* BT_VENDOR_RTK_H */
+
diff --git a/bluetooth/libbt_rtk8723bs/include/upio.h b/bluetooth/libbt_rtk8723bs/include/upio.h
new file mode 100755
index 0000000..512189c
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/include/upio.h
@@ -0,0 +1,107 @@
+/******************************************************************************
+ *
+ * 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: upio.h
+ *
+ * Description: Contains definitions used for I/O controls
+ *
+ ******************************************************************************/
+
+#ifndef UPIO_H
+#define UPIO_H
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+
+#define UPIO_BT_POWER_OFF 0
+#define UPIO_BT_POWER_ON 1
+
+/* UPIO signals */
+enum {
+ UPIO_BT_WAKE = 0,
+ UPIO_HOST_WAKE,
+ UPIO_LPM_MODE,
+ UPIO_MAX_COUNT
+};
+
+/* UPIO assertion/deassertion */
+enum {
+ UPIO_UNKNOWN = 0,
+ UPIO_DEASSERT,
+ UPIO_ASSERT
+};
+
+/******************************************************************************
+** Extern variables and functions
+******************************************************************************/
+
+/******************************************************************************
+** Functions
+******************************************************************************/
+
+/*******************************************************************************
+**
+** Function upio_init
+**
+** Description Initialization
+**
+** Returns None
+**
+*******************************************************************************/
+void upio_init(void);
+
+/*******************************************************************************
+**
+** Function upio_cleanup
+**
+** Description Clean up
+**
+** Returns None
+**
+*******************************************************************************/
+void upio_cleanup(void);
+
+/*******************************************************************************
+**
+** Function upio_set_bluetooth_power
+**
+** Description Interact with low layer driver to set Bluetooth power
+** on/off.
+**
+** Returns 0 : SUCCESS or Not-Applicable
+** <0 : ERROR
+**
+*******************************************************************************/
+int upio_set_bluetooth_power(int on);
+
+/*******************************************************************************
+**
+** Function upio_set
+**
+** Description Set i/o based on polarity
+**
+** Returns None
+**
+*******************************************************************************/
+void upio_set(uint8_t pio, uint8_t action, uint8_t polarity);
+
+#endif /* UPIO_H */
+
diff --git a/bluetooth/libbt_rtk8723bs/include/userial_vendor.h b/bluetooth/libbt_rtk8723bs/include/userial_vendor.h
new file mode 100755
index 0000000..0f1a9bb
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/include/userial_vendor.h
@@ -0,0 +1,182 @@
+/******************************************************************************
+ *
+ * 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 USERIAL_VENDOR_H
+#define USERIAL_VENDOR_H
+
+#include "bt_vendor_rtk.h"
+#include "userial.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+
+/**** baud rates ****/
+#define USERIAL_BAUD_300 0
+#define USERIAL_BAUD_600 1
+#define USERIAL_BAUD_1200 2
+#define USERIAL_BAUD_2400 3
+#define USERIAL_BAUD_9600 4
+#define USERIAL_BAUD_19200 5
+#define USERIAL_BAUD_57600 6
+#define USERIAL_BAUD_115200 7
+#define USERIAL_BAUD_230400 8
+#define USERIAL_BAUD_460800 9
+#define USERIAL_BAUD_921600 10
+#define USERIAL_BAUD_1M 11
+#define USERIAL_BAUD_1_5M 12
+#define USERIAL_BAUD_2M 13
+#define USERIAL_BAUD_3M 14
+#define USERIAL_BAUD_4M 15
+#define USERIAL_BAUD_AUTO 16
+
+/**** Data Format ****/
+/* Stop Bits */
+#define USERIAL_STOPBITS_1 1
+#define USERIAL_STOPBITS_1_5 (1<<1)
+#define USERIAL_STOPBITS_2 (1<<2)
+
+/* Parity Bits */
+#define USERIAL_PARITY_NONE (1<<3)
+#define USERIAL_PARITY_EVEN (1<<4)
+#define USERIAL_PARITY_ODD (1<<5)
+
+/* Data Bits */
+#define USERIAL_DATABITS_5 (1<<6)
+#define USERIAL_DATABITS_6 (1<<7)
+#define USERIAL_DATABITS_7 (1<<8)
+#define USERIAL_DATABITS_8 (1<<9)
+
+
+#define USERIAL_HW_FLOW_CTRL_OFF 0
+#define USERIAL_HW_FLOW_CTRL_ON 1
+
+
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+/* These are the ioctl values used for bt_wake ioctl via UART driver. you may
+ * need to redefine them on you platform!
+ * Logically they need to be unique and not colide with existing uart ioctl's.
+ */
+#ifndef USERIAL_IOCTL_BT_WAKE_ASSERT
+#define USERIAL_IOCTL_BT_WAKE_ASSERT 0x8003
+#endif
+#ifndef USERIAL_IOCTL_BT_WAKE_DEASSERT
+#define USERIAL_IOCTL_BT_WAKE_DEASSERT 0x8004
+#endif
+#ifndef USERIAL_IOCTL_BT_WAKE_GET_ST
+#define USERIAL_IOCTL_BT_WAKE_GET_ST 0x8005
+#endif
+#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+
+/******************************************************************************
+** Type definitions
+******************************************************************************/
+
+/* Structure used to configure serial port during open */
+typedef struct
+{
+ uint16_t fmt; /* Data format */
+ uint8_t baud; /* Baud rate */
+ uint8_t hw_fctrl; /*hardware flowcontrol*/
+} tUSERIAL_CFG;
+
+typedef enum {
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+ USERIAL_OP_ASSERT_BT_WAKE,
+ USERIAL_OP_DEASSERT_BT_WAKE,
+ USERIAL_OP_GET_BT_WAKE_STATE,
+#endif
+ USERIAL_OP_NOP,
+} userial_vendor_ioctl_op_t;
+
+/******************************************************************************
+** Extern variables and functions
+******************************************************************************/
+
+/******************************************************************************
+** Functions
+******************************************************************************/
+
+/*******************************************************************************
+**
+** Function userial_vendor_init
+**
+** Description Initialize userial vendor-specific control block
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_init(void);
+
+/*******************************************************************************
+**
+** Function userial_vendor_open
+**
+** Description Open the serial port with the given configuration
+**
+** Returns device fd
+**
+*******************************************************************************/
+int userial_vendor_open(tUSERIAL_CFG *p_cfg);
+
+/*******************************************************************************
+**
+** Function userial_vendor_close
+**
+** Description Conduct vendor-specific close work
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_close(void);
+
+/*******************************************************************************
+**
+** Function userial_vendor_set_baud
+**
+** Description Set new baud rate
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_set_baud(uint8_t userial_baud);
+
+/*******************************************************************************
+**
+** Function userial_vendor_ioctl
+**
+** Description ioctl inteface
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data);
+
+void userial_vendor_set_hw_fctrl(uint8_t hw_fctrl);
+
+#endif /* USERIAL_VENDOR_H */
+
diff --git a/bluetooth/libbt_rtk8723bs/include/vnd_cardhu.txt b/bluetooth/libbt_rtk8723bs/include/vnd_cardhu.txt
new file mode 100755
index 0000000..4d4261c
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/include/vnd_cardhu.txt
@@ -0,0 +1,9 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2"
+FW_PATCHFILE_LOCATION = "/etc/firmware/"
+BT_WAKE_VIA_PROC = TRUE
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+BTVND_DBG = TRUE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = TRUE
+UPIO_DBG = TRUE
+SCO_PCM_IF_CLOCK_RATE = 2
diff --git a/bluetooth/libbt_rtk8723bs/include/vnd_generic.txt b/bluetooth/libbt_rtk8723bs/include/vnd_generic.txt
new file mode 100755
index 0000000..ebc2807
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/include/vnd_generic.txt
@@ -0,0 +1,8 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyS0"
+FW_PATCHFILE_LOCATION = "/system/etc/firmware/rtlbt/"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = TRUE
+BTVND_DBG = TRUE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = TRUE
+UPIO_DBG = TRUE
diff --git a/bluetooth/libbt_rtk8723bs/src/bt_vendor_rtk.c b/bluetooth/libbt_rtk8723bs/src/bt_vendor_rtk.c
new file mode 100755
index 0000000..7d4c806
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/src/bt_vendor_rtk.c
@@ -0,0 +1,222 @@
+/******************************************************************************
+ *
+ * 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: bt_vendor_rtk.c
+ *
+ * Description: Realtek vendor specific library implementation
+ *
+ ******************************************************************************/
+
+#undef NDEBUG
+#define LOG_TAG "bt_vendor"
+#include <utils/Log.h>
+#include "bt_vendor_rtk.h"
+#include "upio.h"
+#include "userial_vendor.h"
+
+#ifndef BTVND_DBG
+#define BTVND_DBG TRUE
+#endif
+
+#if (BTVND_DBG == TRUE)
+#define BTVNDDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
+#else
+#define BTVNDDBG(param, ...) {}
+#endif
+
+/******************************************************************************
+** Externs
+******************************************************************************/
+
+void hw_config_start(void);
+
+#if (HW_END_WITH_HCI_RESET == TRUE)
+void hw_epilog_process(void);
+#endif
+
+/******************************************************************************
+** Variables
+******************************************************************************/
+
+bt_vendor_callbacks_t *bt_vendor_cbacks = NULL;
+uint8_t vnd_local_bd_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/******************************************************************************
+** Local type definitions
+******************************************************************************/
+
+/******************************************************************************
+** Static Variables
+******************************************************************************/
+
+static const tUSERIAL_CFG userial_init_cfg =
+{
+ (USERIAL_DATABITS_8 | USERIAL_PARITY_EVEN | USERIAL_STOPBITS_1),
+ USERIAL_BAUD_115200,
+ USERIAL_HW_FLOW_CTRL_OFF
+};
+
+/******************************************************************************
+** Functions
+******************************************************************************/
+
+/*****************************************************************************
+**
+** BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
+**
+*****************************************************************************/
+
+static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr)
+{
+ ALOGI("init");
+
+ if (p_cb == NULL)
+ {
+ ALOGE("init failed with no user callbacks!");
+ return -1;
+ }
+
+ userial_vendor_init();
+ upio_init();
+
+ /* store reference to user callbacks */
+ bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb;
+
+ /* This is handed over from the stack */
+ memcpy(vnd_local_bd_addr, local_bdaddr, 6);
+
+ return 0;
+}
+
+
+/** Requested operations */
+static int op(bt_vendor_opcode_t opcode, void *param)
+{
+ int retval = 0;
+
+ BTVNDDBG("op for %d", opcode);
+
+ switch(opcode)
+ {
+ case BT_VND_OP_POWER_CTRL:
+ {
+ int *state = (int *) param;
+ if (*state == BT_VND_PWR_OFF)
+ {
+ upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
+ usleep(200000);
+ BTVNDDBG("set power off and delay 200ms");
+
+ }
+ else if (*state == BT_VND_PWR_ON)
+ {
+ upio_set_bluetooth_power(UPIO_BT_POWER_ON);
+ usleep(500000);
+ BTVNDDBG("set power on and delay 500ms");
+
+ }
+ }
+ break;
+
+ case BT_VND_OP_FW_CFG:
+ {
+ hw_config_start();
+ }
+ break;
+
+ case BT_VND_OP_SCO_CFG:
+ {
+ retval = -1;
+ }
+ break;
+
+ case BT_VND_OP_USERIAL_OPEN:
+ {
+ int (*fd_array)[] = (int (*)[]) param;
+ int fd, idx;
+ fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
+ if (fd != -1)
+ {
+ for (idx=0; idx < CH_MAX; idx++)
+ (*fd_array)[idx] = fd;
+
+ retval = 1;
+ }
+ /* retval contains numbers of open fd of HCI channels */
+ }
+ break;
+
+ case BT_VND_OP_USERIAL_CLOSE:
+ {
+ userial_vendor_close();
+ }
+ break;
+
+ case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
+ {
+
+ }
+ break;
+
+ case BT_VND_OP_LPM_SET_MODE:
+ {
+
+ }
+ break;
+
+ case BT_VND_OP_LPM_WAKE_SET_STATE:
+ {
+
+ }
+ break;
+ case BT_VND_OP_EPILOG:
+ {
+#if (HW_END_WITH_HCI_RESET == FALSE)
+ if (bt_vendor_cbacks)
+ {
+ bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
+ }
+#else
+ hw_epilog_process();
+#endif
+ }
+ break;
+ }
+
+ return retval;
+}
+
+/** Closes the interface */
+static void cleanup( void )
+{
+ BTVNDDBG("cleanup");
+
+ upio_cleanup();
+
+ bt_vendor_cbacks = NULL;
+}
+
+// Entry point of DLib
+const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
+ sizeof(bt_vendor_interface_t),
+ init,
+ op,
+ cleanup
+};
diff --git a/bluetooth/libbt_rtk8723bs/src/hardware.c b/bluetooth/libbt_rtk8723bs/src/hardware.c
new file mode 100755
index 0000000..7b5c385
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/src/hardware.c
@@ -0,0 +1,1899 @@
+/******************************************************************************
+ *
+ * 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: hardware.c
+ *
+ * Description: Contains controller-specific functions, like
+ * firmware patch download
+ * low power mode operations
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_hwcfg"
+
+#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 "bt_vendor_lib.h"
+#include "hci.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+#define RTK_VERSION "3.3-VQ0"
+
+#ifndef BTHW_DBG
+#define BTHW_DBG FALSE
+#endif
+
+#if (BTHW_DBG == TRUE)
+#define BTHWDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
+#else
+#define BTHWDBG(param, ...) {}
+#endif
+
+#ifndef USE_CONTROLLER_BDADDR
+#define USE_CONTROLLER_BDADDR FALSE
+#endif
+
+#define HCI_UART_H4 0
+#define HCI_UART_3WIRE 2
+
+
+#define FIRMWARE_DIRECTORY "/system/etc/firmware/rtlbt/"
+#define BT_CONFIG_DIRECTORY "/system/etc/firmware/rtlbt/"
+#define PATCH_DATA_FIELD_MAX_SIZE 252
+
+#define BT_CAL_DIRECTORY "/data/misc/bluedroid/"
+
+struct patch_struct {
+ int nTxIndex; // current sending pkt number
+ int nTotal; // total pkt number
+ int nRxIndex; // ack index from board
+ int nNeedRetry; // if no response from board
+};
+static struct patch_struct rtk_patch;
+
+
+#define RTK_VENDOR_CONFIG_MAGIC 0x8723ab55
+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));
+
+int gHwFlowControlEnable = 1;
+int gNeedToSetHWFlowControl = 0;
+int gFinalSpeed = 0;
+
+#define FW_PATCHFILE_EXTENSION ".hcd"
+#define FW_PATCHFILE_EXTENSION_LEN 4
+#define FW_PATCHFILE_PATH_MAXLEN 248 /* Local_Name length of return of
+ HCI_Read_Local_Name */
+
+#define HCI_CMD_MAX_LEN 258
+
+#define HCI_RESET 0x0C03
+
+#define HCI_VSC_UPDATE_BAUDRATE 0xFC17
+#define HCI_VSC_DOWNLOAD_FW_PATCH 0xFC20
+#define HCI_VENDOR_READ_RTK_ROM_VERISION 0xFC6D
+#define HCI_READ_LMP 0x1001
+
+#define ROM_LMP_8723a 0x1200
+#define ROM_LMP_8723b 0x8723
+#define ROM_LMP_8821a 0X8821
+#define ROM_LMP_8761a 0X8761
+
+
+#define HCI_VSC_H5_INIT 0xFCEE
+
+
+#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5
+#define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING 6
+#define HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY 6
+#define HCI_EVT_CMD_CMPL_OPCODE 3
+#define LPM_CMD_PARAM_SIZE 12
+#define UPDATE_BAUDRATE_CMD_PARAM_SIZE 6
+#define HCI_CMD_PREAMBLE_SIZE 3
+#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
+
+#define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;}
+#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
+#define UINT32_TO_STREAM(p, u32) {*(p)++ = (uint8_t)(u32); *(p)++ = (uint8_t)((u32) >> 8); *(p)++ = (uint8_t)((u32) >> 16); *(p)++ = (uint8_t)((u32) >> 24);}
+
+/******************************************************************************
+** Local type definitions
+******************************************************************************/
+
+/* Hardware Configuration State */
+enum {
+ HW_CFG_H5_INIT = 1,
+ HW_CFG_START,
+ HW_CFG_SET_UART_BAUD_HOST,//change FW baudrate
+ HW_CFG_SET_UART_BAUD_CONTROLLER,//change Host baudrate
+ HW_CFG_DL_FW_PATCH
+};
+
+/* h/w config control block */
+typedef struct
+{
+ uint8_t state; /* Hardware configuration state */
+ int fw_fd; /* FW patch file fd */
+ uint8_t f_set_baud_2; /* Baud rate switch state */
+ char local_chip_name[LOCAL_NAME_BUFFER_LEN];
+} 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 rtk_get_lmp_cback(void *p_evt_buf);
+
+extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
+
+
+/******************************************************************************
+** Static variables
+******************************************************************************/
+
+static char fw_patchfile_path[256] = FW_PATCHFILE_LOCATION;
+static char fw_patchfile_name[128] = { 0 };
+
+
+static bt_hw_cfg_cb_t hw_cfg_cb;
+
+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
+};
+
+/*********************************add for multi patch start**************************/
+
+//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};
+
+uint16_t project_id[]=
+{
+ ROM_LMP_8723a,
+ ROM_LMP_8723b,
+ ROM_LMP_8821a,
+ ROM_LMP_8761a
+};
+
+
+typedef struct {
+ uint16_t prod_id;
+ char *patch_name;
+ char *config_name;
+} patch_info;
+
+static patch_info patch_table[] = {
+ { ROM_LMP_8723a, "rtl8723a_fw", "rtl8723a_config" }, //Rtl8723AS
+ { ROM_LMP_8723b, "rtl8723b_fw", "rtl8723b_VQ0_config"}, //Rtl8723BS
+ { ROM_LMP_8821a, "rtl8821a_fw", "rtl8821a_config"}, //Rtl8821AS
+ { ROM_LMP_8761a, "rtl8761a_fw", "rtl8761a_config"} //Rtl8761AW
+};
+
+struct rtk_epatch_entry{
+ uint16_t chipID;
+ uint16_t patch_length;
+ uint32_t start_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_total_patch;
+ struct rtk_epatch_entry entry[0];
+} __attribute__ ((packed));
+
+struct rtk_extension_entry{
+ uint8_t opcode;
+ uint8_t length;
+ uint8_t *data;
+} __attribute__ ((packed));
+
+typedef enum _RTK_ROM_VERSION_CMD_STATE
+{
+ cmd_not_send,
+ cmd_has_sent,
+ cmd_sent_event_timeout,
+ event_received
+} RTK_ROM_VERSION_CMD_STATE;
+
+
+uint8_t gEVersion = 0;
+uint8_t need_download_fw = 1;
+uint16_t lmp_version;
+uint8_t gRom_version_cmd_state = cmd_not_send;
+extern tHCI_IF *p_hci_if;
+
+//#define BT_FW_CAL_ENABLE
+
+#ifdef BT_FW_CAL_ENABLE
+
+//add for FW CAL
+uint8_t isFirstBoot = TRUE;
+uint8_t is_first_bt_init = FALSE;
+
+#define CAL_INQUIRY_SUCCESS 0
+#define CAL_INQUIRY_UNKNOWN 1
+#define CAL_INQUIRY_FAIL 2
+
+#define BT_EFUSE_HOST_INFO_DISABLE 0x0001
+#define BT_EFUSE_CAL_STS_EN_DISABLE 0x0002
+#define IS_FIRST_BT_INIT_AFTER_BOOT 0x0004
+#define IS_FIRST_BT_INIT 0x0008
+#define IS_LAST_INQUIRY_SUCCESS 0x0010
+
+
+
+struct _rtk_bt_cal_info_entry{
+ uint16_t offset;
+ uint8_t entry_len;
+ uint16_t bt_cal_efuse_host_info;
+ uint16_t bt_cal_efuse_cal_sts[5];
+} __attribute__ ((packed));
+
+struct _rtk_bt_cal_info_entry *rtk_bt_cal_info_entry = NULL;
+
+
+void rtk_print_host_cal_info(struct _rtk_bt_cal_info_entry *cal_info_entry);
+void rtk_print_host_info(uint16_t bt_cal_efuse_host_info);
+void rtk_print_cal_info(uint16_t *bt_cal_efuse_cal_sts);
+
+
+#endif
+
+
+patch_info* get_patch_entry(uint16_t prod_id)
+{
+ patch_info *patch_entry = NULL;
+ patch_entry = patch_table;
+ while (prod_id != patch_entry->prod_id)
+ {
+ if (0 == patch_entry->prod_id)
+ break;
+
+ patch_entry++;
+ }
+ return patch_entry;
+}
+
+/*********************************add for multi patch end**************************/
+#define BT_PCBA_TEST
+
+#ifdef BT_PCBA_TEST
+void single_bt_pcba_test_results(int result)
+{
+ FILE *fp;
+ char name[64];
+
+ if(result) {
+ strcpy(name, "/data/bt_success.txt"); // 测试成功
+ } else {
+ strcpy(name, "/data/bt_fail.txt"); // 测试失败
+ }
+
+ //printf("name = %s\n", name);
+ fp = fopen (name, "w");
+ if(fp != NULL) {
+ fclose(fp);
+ //printf("create %s success.\n", name);
+ return;
+ }
+ //printf("create %s fail.\n", name);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function ms_delay
+**
+** Description sleep unconditionally for timeout milliseconds
+**
+** Returns None
+**
+*******************************************************************************/
+void ms_delay (uint32_t timeout)
+{
+ struct timespec delay;
+ int err;
+
+ if (timeout == 0)
+ return;
+
+ delay.tv_sec = timeout / 1000;
+ delay.tv_nsec = 1000 * 1000 * (timeout%1000);
+
+ /* [u]sleep can't be used because it uses SIGALRM */
+ do {
+ err = nanosleep(&delay, &delay);
+ } while (err < 0 && errno ==EINTR);
+}
+
+/*******************************************************************************
+**
+** 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
+{
+ int rtk_speed;
+ int 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
+ {0x00007001, 3500000},
+ {0x052A6001, 3500000},//RTL8723BS
+ {0x00005001, 4000000},//same as RTL8723AS
+ {0x0000701d, 115200},
+ {0x0252C002, 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(int uart_speed, int* 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;
+ hw_cfg_cb.state = HW_CFG_SET_UART_BAUD_HOST;
+
+ retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, p_buf, \
+ hw_config_cback);
+
+ return (retval);
+}
+
+static const char *get_firmware_name()
+{
+ static char firmware_file_name[PATH_MAX] = {0};
+ sprintf(firmware_file_name, FIRMWARE_DIRECTORY"rtlbt_fw");
+ return firmware_file_name;
+}
+
+uint32_t rtk_parse_config_file(unsigned char** config_buf, size_t* filelen, char bt_addr[6])
+{
+ struct rtk_bt_vendor_config* config = (struct rtk_bt_vendor_config*) *config_buf;
+ uint16_t config_len = 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;
+
+
+ //bt_addr[0] = 0; //reset bd addr byte 0 to zero
+
+ if (config->signature != RTK_VENDOR_CONFIG_MAGIC)
+ {
+ ALOGE("config signature magic number(%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(%x) is not right(%x)", config_len, *filelen-sizeof(struct rtk_bt_vendor_config));
+ return 0;
+ }
+
+ for (i=0; i<config_len;)
+ {
+
+ switch(entry->offset)
+ {
+ #if (USE_CONTROLLER_BDADDR == FALSE)
+ 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");
+ break;
+ }
+#endif
+ case 0xc:
+ {
+ baudrate = *(uint32_t*)entry->entry_data;
+ if (entry->entry_len >= 12) //0ffset 0x18 - 0xc
+ {
+ gNeedToSetHWFlowControl =1;
+ gHwFlowControlEnable = (entry->entry_data[12] & 0x4) ? 1:0; //0x18 byte bit2
+ }
+ else
+ {
+ gNeedToSetHWFlowControl = 0;
+ }
+ ALOGI("config baud rate to :%08x, hwflowcontrol:%x, %x", baudrate, entry->entry_data[12], gHwFlowControlEnable);
+ break;
+ }
+ default:
+ ALOGI("config offset(%x),length(%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);
+ }
+#if(USE_CONTROLLER_BDADDR == FALSE)
+ if(!config_has_bdaddr){
+ ALOGI("rtk_parse_config_file: DO NOT USE_CONTROLLER_BDADDR, config has no bdaddr");
+ *config_buf = realloc(*config_buf, *filelen+9);
+ ((struct rtk_bt_vendor_config*)*config_buf)->data_len += 9;
+ *((char*)*config_buf + *filelen) = 0x3c;
+ *((char*)*config_buf + *filelen + 1) = 0x00;
+ *((char*)*config_buf + *filelen + 2) = 0x06;
+ *((char*)*config_buf + *filelen + 3) = bt_addr[5];
+ *((char*)*config_buf + *filelen + 4) = bt_addr[4];
+ *((char*)*config_buf + *filelen + 5) = bt_addr[3];
+ *((char*)*config_buf + *filelen + 6) = bt_addr[2];
+ *((char*)*config_buf + *filelen + 7) = bt_addr[1];
+ *((char*)*config_buf + *filelen + 8) = bt_addr[0];
+ *filelen += 9;
+ }
+#endif
+
+
+ return baudrate;
+}
+
+#ifdef BT_FW_CAL_ENABLE
+
+uint32_t rtk_get_bt_cal_info(unsigned char** cal_buf)
+{
+ char bt_cal_file_name[PATH_MAX] = {0};
+
+ struct stat st;
+ size_t filelen;
+ ssize_t ret_len = 0;
+
+ int fd;
+
+
+ sprintf(bt_cal_file_name, BT_CAL_DIRECTORY"rtlbt_cal");
+
+ if (stat(bt_cal_file_name, &st) < 0)
+ {
+ ALOGE("can't access bt cal file:%s, errno:%d\n", bt_cal_file_name, errno);
+ return -1;
+ }
+
+ filelen = st.st_size;
+ ALOGI("CAL File Length = %d", filelen);
+
+ if ((fd = open(bt_cal_file_name, O_RDONLY)) < 0)
+ {
+ ALOGE("Can't open bt cal file, errno = %d", errno);
+ return -1;
+ }
+
+
+ if ((*cal_buf = malloc(filelen)) == NULL)
+ {
+ ALOGE("malloc buffer for cal file fail(%x)\n", filelen);
+ return -1;
+ }
+
+ //
+ //we may need to parse this config file.
+ //for easy debug, only get need data.
+ ret_len = read(fd, *cal_buf, filelen);
+ if ( ret_len < (ssize_t)filelen) {
+ ALOGE("Can't load bt cal file, ret_len(%d), errno = %d", ret_len, errno);
+ free(*cal_buf);
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return filelen;
+}
+
+uint32_t rtk_set_bt_cal_info(unsigned char* cal_buf, uint32_t length)
+{
+ char bt_cal_file_name[PATH_MAX] = {0};
+
+ struct stat st;
+ size_t filelen;
+ int fd;
+
+
+ sprintf(bt_cal_file_name, BT_CAL_DIRECTORY"rtlbt_cal");
+
+ if (stat(bt_cal_file_name, &st) < 0)
+ {
+ ALOGE("can't access bt cal file:%s, errno:%d\n", bt_cal_file_name, errno);
+ filelen = length;
+ }
+ else
+ {
+ filelen = st.st_size;
+ }
+
+
+
+ ALOGI("CAL File Length = %d", filelen);
+
+ if ((fd = open(bt_cal_file_name, O_RDWR | O_CREAT, 0666)) < 0)
+ {
+ ALOGE("Can't open bt cal file, errno = %d", errno);
+ return -1;
+ }
+
+ //
+ //we may need to parse this config file.
+ //for easy debug, only get need data.
+
+ if (write(fd, cal_buf, filelen) < (ssize_t)filelen) {
+ ALOGE("Can't load bt cal file, errno = %d", errno);
+
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return filelen;
+}
+
+#endif
+
+uint32_t rtk_get_bt_config(unsigned char** config_buf,
+ uint32_t* config_baud_rate, char * config_file_short_name)
+{
+ char bt_config_file_name[PATH_MAX] = {0};
+ uint8_t* bt_addr_temp = NULL;
+ char bt_addr[6]={0x00, 0xe0, 0x4c, 0x88, 0x88, 0x88};
+ struct stat st;
+ size_t filelen;
+ int fd;
+ FILE* file = NULL;
+
+ sprintf(bt_config_file_name, BT_CONFIG_DIRECTORY"rtlbt_config");
+ 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 ((fd = open(bt_config_file_name, O_RDONLY)) < 0)
+ {
+ ALOGE("Can't open bt config file");
+ return -1;
+ }
+
+ if ((*config_buf = malloc(filelen)) == NULL)
+ {
+ ALOGE("malloc buffer for config file fail(%x)\n", filelen);
+ return -1;
+ }
+
+ //
+ //we may need to parse this config file.
+ //for easy debug, only get need data.
+
+ 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);
+ ALOGI("Get config baud rate from config file:%x", *config_baud_rate);
+
+ close(fd);
+ return filelen;
+}
+
+int rtk_get_bt_firmware(uint8_t** fw_buf, size_t addi_len, char* fw_short_name)
+{
+ const char *filename = NULL;
+ struct stat st;
+ int fd = -1;
+ size_t fwsize = 0;
+ size_t buf_size = 0;
+
+ filename = get_firmware_name();
+ ALOGI("BT fw file: %s", filename);
+
+ if (stat(filename, &st) < 0) {
+ ALOGE("Can't access firmware, errno:%d", errno);
+ return -1;
+ }
+
+ fwsize = st.st_size;
+ buf_size = fwsize + addi_len;
+
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+ ALOGE("Can't open firmware, errno:%d", errno);
+ return -1;
+ }
+
+ if (!(*fw_buf = malloc(buf_size))) {
+ ALOGE("Can't alloc memory for fw&config, errno:%d", errno);
+ if (fd >= 0)
+ close(fd);
+ return -1;
+ }
+
+ if (read(fd, *fw_buf, fwsize) < (ssize_t) fwsize) {
+ free(*fw_buf);
+ *fw_buf = NULL;
+ if (fd >= 0)
+ close(fd);
+ return -1;
+ }
+
+ if (fd >= 0)
+ close(fd);
+
+ ALOGI("Load FW OK");
+ return buf_size;
+}
+
+
+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;
+}
+
+static void rtk_download_fw_config(HC_BT_HDR *p_buf, uint8_t* buf, size_t filesize, int is_sent_changerate, int proto)
+{
+
+ uint8_t iCurIndex = 0;
+ uint8_t iCurLen = 0;
+ uint8_t iEndIndex = 0;
+ uint8_t iLastPacketLen = 0;
+ uint8_t iAdditionPkt = 0;
+ uint8_t iTotalIndex = 0;
+
+ unsigned char *bufpatch = NULL;
+
+ iEndIndex = (uint8_t)((filesize-1)/PATCH_DATA_FIELD_MAX_SIZE);
+ iLastPacketLen = (filesize)%PATCH_DATA_FIELD_MAX_SIZE;
+
+ if (is_sent_changerate)
+ iAdditionPkt = (iEndIndex+2)%8?(8-(iEndIndex+2)%8):0;
+ else
+ iAdditionPkt = (iEndIndex+1)%8?(8-(iEndIndex+1)%8):0;
+
+ iTotalIndex = iAdditionPkt + iEndIndex;
+ rtk_patch.nTotal = iTotalIndex; //init TotalIndex
+
+ ALOGI("iEndIndex:%d iLastPacketLen:%d iAdditionpkt:%d\n", iEndIndex, iLastPacketLen, iAdditionPkt);
+
+ if (iLastPacketLen == 0)
+ iLastPacketLen = PATCH_DATA_FIELD_MAX_SIZE;
+
+ bufpatch = buf;
+
+ int i;
+ for (i=0; i<=iTotalIndex; i++) {
+ if (iCurIndex < iEndIndex) {
+ iCurIndex = iCurIndex&0x7F;
+ iCurLen = PATCH_DATA_FIELD_MAX_SIZE;
+ }
+ else if (iCurIndex == iEndIndex) {//send last data packet
+ if (iCurIndex == iTotalIndex)
+ iCurIndex = iCurIndex | 0x80;
+ else
+ iCurIndex = iCurIndex&0x7F;
+ iCurLen = iLastPacketLen;
+ }
+ else if (iCurIndex < iTotalIndex) {
+ iCurIndex = iCurIndex&0x7F;
+ bufpatch = NULL;
+ iCurLen = 0;
+ //printf("addtional packet index:%d iCurIndex:%d\n", i, iCurIndex);
+ }
+ else { //send end packet
+ bufpatch = NULL;
+ iCurLen = 0;
+ iCurIndex = iCurIndex|0x80;
+ //printf("end packet index:%d iCurIndex:%d\n", i, iCurIndex);
+ }
+
+ if (iCurIndex & 0x80)
+ ALOGI("Send FW last command");
+
+ if (proto == HCI_UART_H4) {
+ iCurIndex = hci_download_patch_h4(p_buf, iCurIndex, bufpatch, iCurLen);
+ if ((iCurIndex != i) && (i != rtk_patch.nTotal))
+ {
+ // check index but ignore last pkt
+ ALOGE("index mismatch i:%d iCurIndex:%d, patch fail\n", i, iCurIndex);
+ return;
+ }
+ }
+ else if(proto == HCI_UART_3WIRE)
+ //hci_download_patch(fd, iCurIndex, bufpatch, iCurLen);
+ ALOGI("iHCI_UART_3WIRE");
+
+ if (iCurIndex < iEndIndex) {
+ bufpatch += PATCH_DATA_FIELD_MAX_SIZE;
+ }
+ iCurIndex ++;
+ }
+
+ //set last ack packet down
+ if (proto == HCI_UART_3WIRE)
+ {
+ //rtk_send_pure_ack_down(fd);
+ }
+}
+
+
+void rtk_get_eversion_timeout(int sig)
+{
+ ALOGE("RTK get eversion timeout\n");
+ need_download_fw = 0;
+ bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+}
+
+
+/**
+* Send vendor cmd to get eversion: 0xfc6d
+* If Rom code does not support this cmd, use default a.
+*/
+void rtk_get_eversion(void)
+{
+ HC_BT_HDR *p_buf=NULL;
+
+ p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
+ HCI_CMD_MAX_LEN);
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->len = 0;
+ p_buf->layer_specific = 0;
+
+ ALOGI("bt vendor lib: Get eversion");
+ struct sigaction sa;
+ uint8_t *p = (uint8_t *) (p_buf + 1);
+
+ UINT16_TO_STREAM(p, HCI_VENDOR_READ_RTK_ROM_VERISION);
+
+ *p++ = 0; /* parameter length */
+
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+
+ bt_vendor_cbacks->xmit_cb(HCI_VENDOR_READ_RTK_ROM_VERISION, p_buf, \
+ hw_config_cback);
+
+ gRom_version_cmd_state = cmd_has_sent;
+ ALOGI("RTK send HCI_VENDOR_READ_RTK_ROM_VERISION_Command\n");
+
+ alarm(0);
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = rtk_get_eversion_timeout;
+ sigaction(SIGALRM, &sa, NULL);
+ alarm(1);
+
+}
+
+void rtk_get_lmp_timeout(int sig)
+{
+ ALOGE("RTK get lmp timeout\n");
+ need_download_fw = 0;
+ bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+}
+
+void rtk_get_lmp()
+{
+ HC_BT_HDR *p_buf=NULL;
+ struct sigaction sa;
+
+ p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
+ HCI_CMD_MAX_LEN);
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->len = 0;
+ p_buf->layer_specific = 0;
+
+ ALOGI("bt vendor lib: Get lmp");
+ uint8_t *p = (uint8_t *) (p_buf + 1);
+
+ UINT16_TO_STREAM(p, HCI_READ_LMP);
+
+ *p++ = 0; /* parameter length */
+
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+
+ bt_vendor_cbacks->xmit_cb(HCI_READ_LMP, p_buf, rtk_get_lmp_cback);
+
+ gRom_version_cmd_state = cmd_has_sent;
+ ALOGI("RTK send HCI_READ_LMP_Command \n");
+
+ alarm(0);
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = rtk_get_lmp_timeout;
+ sigaction(SIGALRM, &sa, NULL);
+ alarm(1);
+
+}
+
+void rtk_get_lmp_cback(void *p_mem)
+{
+ HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
+ uint8_t *p, status;
+ gRom_version_cmd_state = event_received;
+ alarm(0);
+
+ status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
+
+ if (status == 0)
+ {
+ p = (uint8_t *)(p_evt_buf + 1) + LPM_CMD_PARAM_SIZE;
+ STREAM_TO_UINT16(lmp_version,p);
+ ALOGI("lmp_version = %x", lmp_version);
+ if(lmp_version == ROM_LMP_8723a)
+ {
+ hw_config_cback(NULL);
+ }
+ else
+ {
+ rtk_get_eversion();
+ }
+ }
+
+ if (bt_vendor_cbacks)
+ {
+ bt_vendor_cbacks->lpm_cb(status);
+ bt_vendor_cbacks->dealloc(p_evt_buf);
+ }
+
+}
+
+/*******************************************************************************
+**
+** 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;
+ char *p_name, *p_tmp;
+ uint8_t *p, status;
+ uint16_t opcode;
+ HC_BT_HDR *p_buf=NULL;
+ uint8_t is_proceeding = FALSE;
+ int i;
+
+ static int buf_len = 0;
+ static uint8_t* buf = NULL;
+ static uint32_t baudrate = 0;
+
+ static uint8_t iCurIndex = 0;
+ static uint8_t iCurLen = 0;
+ static uint8_t iEndIndex = 0;
+ static uint8_t iLastPacketLen = 0;
+ static uint8_t iAdditionPkt = 0;
+ static uint8_t iTotalIndex = 0;
+ static unsigned char *bufpatch = NULL;
+
+ static uint8_t iIndexRx = 0;
+
+ uint8_t *ph5_ctrl_pkt = NULL;
+ uint16_t h5_ctrl_pkt = 0;
+
+//add for multi epatch
+ uint8_t is_multi_epatch = 0;
+ uint8_t* epatch_buf = NULL;
+ int epatch_length = -1;
+ struct rtk_epatch* epatch_info = NULL;
+ struct rtk_epatch_entry current_entry;
+ patch_info* prtk_patch_file_info = NULL;
+
+#ifdef BT_FW_CAL_ENABLE
+ int iBtCalLen = 0;
+ uint8_t bt_cal_ext_id = 0;
+ uint8_t bt_cal_ext_length = 0;
+#endif
+
+#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_RET_BYTE);
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode,p);
+ }
+
+
+ /* Ask a new buffer big enough to hold any HCI commands sent in here */
+ //if ((status == 0) && bt_vendor_cbacks)
+ if (bt_vendor_cbacks) //a fc6d status==1
+ {
+ 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;
+
+ p = (uint8_t *) (p_buf + 1);
+
+ //ALOGI("hw_cfg_cb.state = %i", hw_cfg_cb.state);
+ switch (hw_cfg_cb.state)
+ {
+ case HW_CFG_START:
+ {
+ if((lmp_version != ROM_LMP_8723a)&&(p_mem != NULL))
+ {
+ HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
+ status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
+ gRom_version_cmd_state = event_received;
+ alarm(0);
+
+ if(status == 0)
+ {
+ gEVersion = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE + 1);
+ }
+ else if(1 == status)
+ {
+ gEVersion = 0; //default a
+ }
+ else
+ {
+ ALOGE("READ_RTK_ROM_VERISION return status error!");
+ //Need to do more
+ }
+ ALOGI("bt vendor lib: READ_RTK_ROM_VERISION status:%i, gEVersion:%i", status, gEVersion);
+ }
+
+ uint8_t*config_file_buf = NULL;
+ int config_len = -1;
+
+ ALOGI("bt vendor lib:HW_CFG_START");
+ //reset all static variable here
+ buf_len = -1;
+ buf = NULL;
+ baudrate = 0;
+
+ iCurIndex = 0;
+ iCurLen = 0;
+ iEndIndex = 0;
+ iLastPacketLen = 0;
+ iAdditionPkt = 0;
+ iTotalIndex = 0;
+ bufpatch = NULL;
+
+ iIndexRx = 0;
+ gNeedToSetHWFlowControl = 0;
+
+ //download patch
+
+ //get efuse config file and patch code file
+
+ prtk_patch_file_info = get_patch_entry(lmp_version);
+
+ if(prtk_patch_file_info != NULL)
+ {
+ config_len = rtk_get_bt_config(&config_file_buf, &baudrate, prtk_patch_file_info->config_name);
+ }
+ if (config_len < 0)
+ {
+ ALOGE("Get Config file error, just use efuse settings");
+ config_len = 0;
+ }
+#ifdef BT_FW_CAL_ENABLE
+ else
+ {
+ struct rtk_bt_vendor_config* config = (struct rtk_bt_vendor_config*) config_file_buf;
+ config->data_len += 12 + 3;
+ }
+#endif
+ if(prtk_patch_file_info != NULL)
+ {
+ buf_len = rtk_get_bt_firmware(&epatch_buf, config_len, prtk_patch_file_info->patch_name);
+ }
+ if (buf_len < 0)
+ {
+ ALOGE("Get BT firmware error, continue without bt firmware");
+ }
+ else
+ {
+ if(lmp_version == ROM_LMP_8723a)
+ {
+ if(memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) == 0)
+ {
+ ALOGE("8723as Check signature error!");
+ need_download_fw = 0;
+ }
+ else
+ {
+ if (!(buf = malloc(buf_len))) {
+ ALOGE("Can't alloc memory for fw&config, errno:%d", errno);
+ buf_len = -1;
+ }
+ else
+ {
+ ALOGI("8723as, fw copy direct");
+ memcpy(buf,epatch_buf,buf_len);
+ free(epatch_buf);
+ epatch_buf = NULL;
+ if (config_len)
+ {
+ memcpy(&buf[buf_len - config_len], config_file_buf, config_len);
+ }
+ }
+ }
+ }
+ else
+ {
+ struct rtk_extension_entry patch_lmp;
+ //check Extension Section Field
+ if(memcmp(epatch_buf + buf_len-config_len-4 ,Extension_Section_SIGNATURE,4) != 0)
+ {
+ ALOGE("Check Extension_Section_SIGNATURE error! do not download fw");
+ need_download_fw = 0;
+ } else {
+ uint8_t *temp;
+ temp = epatch_buf+buf_len-config_len-5;
+ do{
+ if(*temp == 0x00) {
+ patch_lmp.opcode = *temp;
+ ALOGI("opcode = 0x%x",patch_lmp.opcode);
+ patch_lmp.length = *(temp-1);
+ ALOGI("length = 0x%x",patch_lmp.length);
+ if ((patch_lmp.data = malloc(patch_lmp.length)))
+ {
+ int k;
+ for(k = 0; k < patch_lmp.length; k++){
+ *(patch_lmp.data+k) = *(temp-2-k);
+ ALOGI("data = 0x%x",*(patch_lmp.data+k));
+ }
+ }
+ break;
+ }
+ temp -= *(temp-1)+2;
+ }while(*temp != 0xFF);
+
+ if(lmp_version != project_id[*(patch_lmp.data)]) {
+ ALOGE("lmp_version is %x, project_id is %x, does not match!!!",lmp_version,project_id[*(patch_lmp.data)]);
+ need_download_fw = 0;
+ }
+ else
+ {
+ ALOGI("lmp_version is %x, project_id is %x, match!",lmp_version, project_id[*(patch_lmp.data)]);
+ if(memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) != 0) {
+ ALOGI("Check signature error!");
+ need_download_fw = 0;
+ } else {
+ int i = 0;
+ epatch_info = (struct rtk_epatch*)epatch_buf;
+ ALOGI("fw_version = 0x%x",epatch_info->fw_version);
+ ALOGI("number_of_total_patch = %d",epatch_info->number_of_total_patch);
+
+ //get right epatch entry
+ for(i; i<epatch_info->number_of_total_patch; i++){
+ if(*(uint16_t*)(epatch_buf+14+2*i) == gEVersion + 1)
+ {
+ current_entry.chipID = gEVersion + 1;
+ current_entry.patch_length = *(uint16_t*)(epatch_buf+14+2*epatch_info->number_of_total_patch+2*i);
+ current_entry.start_offset = *(uint32_t*)(epatch_buf+14+4*epatch_info->number_of_total_patch+4*i);
+ break;
+ }
+ }
+ ALOGI("chipID = %d",current_entry.chipID);
+ ALOGI("patch_length = 0x%x",current_entry.patch_length);
+ ALOGI("start_offset = 0x%x",current_entry.start_offset);
+
+ //get right eversion patch: buf, buf_len
+ buf_len = current_entry.patch_length + config_len;
+#ifdef BT_FW_CAL_ENABLE
+ //add for BT CAL
+
+ rtk_get_bt_cal_info((unsigned char**)&rtk_bt_cal_info_entry);
+
+ if(rtk_bt_cal_info_entry == NULL)
+ {
+ is_first_bt_init = TRUE;
+ rtk_bt_cal_info_entry = malloc(sizeof(struct _rtk_bt_cal_info_entry));
+ rtk_bt_cal_info_entry->offset = 0x01E6;
+ rtk_bt_cal_info_entry->entry_len = 0x0C;
+ rtk_bt_cal_info_entry->bt_cal_efuse_host_info= 0xFFEC;
+ rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts[0] = 0xFFFF;
+ rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts[1] = 0xFFFF;
+ rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts[2] = 0xFFFF;
+ rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts[3] = 0xFFFF;
+ rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts[4] = 0xFFFF;
+ }
+ else
+ {
+ is_first_bt_init = FALSE;
+ }
+
+ if(rtk_bt_cal_info_entry != NULL)
+ {
+ rtk_print_host_cal_info(rtk_bt_cal_info_entry);
+ if(isFirstBoot == TRUE)
+ {
+
+ isFirstBoot = FALSE;
+ rtk_bt_cal_info_entry->bt_cal_efuse_host_info |= IS_FIRST_BT_INIT_AFTER_BOOT;
+ //rtk_bt_cal_info_entry->bt_cal_efuse_host_info= 0xECFF;
+ ALOGI("isFirstBoot is TRUE");
+
+ }
+ else
+ {
+ rtk_bt_cal_info_entry->bt_cal_efuse_host_info &= (~IS_FIRST_BT_INIT_AFTER_BOOT);
+ //rtk_bt_cal_info_entry->bt_cal_efuse_host_info= 0xE8FF;
+ ALOGI("isFirstBoot is FALSE");
+ }
+
+ if(is_first_bt_init ==TRUE)
+ {
+ rtk_bt_cal_info_entry->bt_cal_efuse_host_info |= IS_FIRST_BT_INIT;
+ ALOGI("is_first_bt_init is TRUE");
+ }
+ else
+ {
+ rtk_bt_cal_info_entry->bt_cal_efuse_host_info &= (~IS_FIRST_BT_INIT);
+ ALOGI("is_first_bt_init is FALSE");
+ }
+
+ }
+ else
+ {
+
+ ALOGI("rtk_bt_cal_info_entry malloc fail");
+ }
+
+ ALOGE("after update bt_efuse_host_info");
+ rtk_print_host_info(rtk_bt_cal_info_entry->bt_cal_efuse_host_info);
+
+ iBtCalLen = sizeof(struct _rtk_bt_cal_info_entry);
+ buf_len = buf_len + iBtCalLen;
+#endif
+ ALOGI("buf_len = 0x%x",buf_len);
+
+ if (!(buf = malloc(buf_len))) {
+ ALOGE("Can't alloc memory for multi fw&config, errno:%d", errno);
+ buf_len = -1;
+ } else {
+ memcpy(buf,&epatch_buf[current_entry.start_offset],current_entry.patch_length);
+ memcpy(&buf[current_entry.patch_length-4],&epatch_info->fw_version,4);
+ memcpy(&current_entry.svn_version,&buf[current_entry.patch_length-8],4);
+ memcpy(&current_entry.coex_version,&buf[current_entry.patch_length-12],4);
+ ALOGI("fw svn_version = %05d",current_entry.svn_version);
+ ALOGI("BTCOEX20%06d-%04x",
+ ((current_entry.coex_version >> 16) & 0x7ff) + ((current_entry.coex_version >> 27) * 10000),
+ (current_entry.coex_version & 0xffff));
+
+ }
+ free(epatch_buf);
+ epatch_buf = NULL;
+
+ if (config_len)
+ {
+#ifdef BT_FW_CAL_ENABLE
+ memcpy(&buf[buf_len - config_len - iBtCalLen], config_file_buf, config_len);
+#else
+ memcpy(&buf[buf_len - config_len], config_file_buf, config_len);
+#endif
+ }
+#ifdef BT_FW_CAL_ENABLE
+ if(rtk_bt_cal_info_entry != NULL)
+ {
+ memcpy(&buf[buf_len - iBtCalLen], rtk_bt_cal_info_entry, iBtCalLen);
+ }
+
+#endif
+ }
+ }
+ }
+ }
+ }
+
+ if (config_file_buf)
+ free(config_file_buf);
+
+ ALOGI("Fw:%s exists, config file:%s exists", (buf_len > 0) ? "":"not", (config_len>0)?"":"not");
+
+ if((buf_len > 0)&&(need_download_fw))
+ {
+ iEndIndex = (uint8_t)((buf_len-1)/PATCH_DATA_FIELD_MAX_SIZE);
+ iLastPacketLen = (buf_len)%PATCH_DATA_FIELD_MAX_SIZE;
+
+
+ if (baudrate && (lmp_version != ROM_LMP_8723a))
+ iAdditionPkt = (iEndIndex+4)%8?(8-(iEndIndex+4)%8):0;
+ else if((baudrate && (lmp_version == ROM_LMP_8723a))||(!baudrate && (lmp_version != ROM_LMP_8723a)))
+ iAdditionPkt = (iEndIndex+3)%8?(8-(iEndIndex+3)%8):0;
+ else
+ iAdditionPkt = (iEndIndex+2)%8?(8-(iEndIndex+2)%8):0;
+
+ iTotalIndex = iAdditionPkt + iEndIndex;
+ rtk_patch.nTotal = iTotalIndex; //init TotalIndex
+
+ ALOGI("iEndIndex:%d iLastPacketLen:%d iAdditionpkt:%d\n", iEndIndex, iLastPacketLen, iAdditionPkt);
+
+ if (iLastPacketLen == 0)
+ iLastPacketLen = PATCH_DATA_FIELD_MAX_SIZE;
+
+ bufpatch = buf;
+ }
+ else
+ {
+ 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 ((buf_len>0) && (config_len == 0))
+ {
+ goto DOWNLOAD_FW;
+ }
+
+ }
+ /* fall through intentionally */
+
+ case HW_CFG_SET_UART_BAUD_CONTROLLER:
+
+
+ ALOGI("bt vendor lib: set CONTROLLER UART baud %x", baudrate);
+
+
+ is_proceeding = hw_config_set_controller_baudrate(p_buf, baudrate);
+
+
+ break;
+
+ case HW_CFG_SET_UART_BAUD_HOST:
+ {
+ uint32_t HostBaudRate = 0;
+
+ ALOGI("========add delay 100 ms");
+ ms_delay(100);
+
+ /* update baud rate of host's UART port */
+ rtk_speed_to_uart_speed(baudrate, &HostBaudRate);
+ ALOGI("bt vendor lib: set HOST UART baud %i", HostBaudRate);
+ userial_vendor_set_baud( \
+ line_speed_to_userial_baud(HostBaudRate) \
+ );
+ ms_delay(100);
+ }
+ //fall through
+DOWNLOAD_FW:
+ case HW_CFG_DL_FW_PATCH:
+
+ status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
+ //ALOGI("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, opcode:%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_RET_BYTE + 1);
+ //ALOGI("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, iIndexRx:%i", status, iIndexRx);
+ //update buf of patch and index.
+ if (iCurIndex < iEndIndex) {
+ bufpatch += PATCH_DATA_FIELD_MAX_SIZE;
+ }
+ iCurIndex ++;
+ }
+
+ if( (opcode ==HCI_VSC_DOWNLOAD_FW_PATCH)&&( iIndexRx&0x80 || iIndexRx == iTotalIndex) ){
+#ifdef BT_FW_CAL_ENABLE
+ bt_cal_ext_id= *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE + 1 + 1);
+
+ bt_cal_ext_length= *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE + 1 +
+ 1 +1);
+
+ ALOGI("bt_cal_ext_id = %d, bt_cal_ext_length = %d", bt_cal_ext_id, bt_cal_ext_length);
+
+ if(rtk_bt_cal_info_entry != NULL)
+ {
+ if(bt_cal_ext_id == 1 && bt_cal_ext_length == 10)
+ {
+
+ memcpy(rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts, ((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE + 1 +
+ 1 +1 +1), bt_cal_ext_length);
+
+ //cancel cal inquiry result
+ rtk_bt_cal_info_entry->bt_cal_efuse_host_info &= (~IS_LAST_INQUIRY_SUCCESS);
+ rtk_print_cal_info(rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts);
+ /*
+ rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts[0] = 0x1111;
+ rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts[1] = 0x2222;
+ rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts[2] = 0x3333;
+ rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts[3] = 0x4444;
+ rtk_bt_cal_info_entry->bt_cal_efuse_cal_sts[4] = 0x5555;
+ */
+ ALOGI("rtk_set_bt_cal_info");
+ rtk_set_bt_cal_info(rtk_bt_cal_info_entry, sizeof(struct _rtk_bt_cal_info_entry));
+ free(rtk_bt_cal_info_entry);
+ rtk_bt_cal_info_entry = NULL;
+ }
+
+ }
+
+
+#endif
+ ALOGI("vendor lib fwcfg completed");
+ #ifdef BT_PCBA_TEST
+ single_bt_pcba_test_results(1);
+ #endif
+ if(buf) {
+ free(buf);
+ buf = NULL;
+ }
+ bt_vendor_cbacks->dealloc(p_buf);
+ bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+
+ hw_cfg_cb.state = 0;
+
+
+
+ if (hw_cfg_cb.fw_fd != -1)
+ {
+ close(hw_cfg_cb.fw_fd);
+ hw_cfg_cb.fw_fd = -1;
+ }
+ is_proceeding = TRUE;
+
+ break;
+ }
+
+ if (iCurIndex < iEndIndex) {
+ iCurIndex = iCurIndex&0x7F;
+ iCurLen = PATCH_DATA_FIELD_MAX_SIZE;
+ }
+ else if (iCurIndex == iEndIndex) { //send last data packet
+ if (iCurIndex == iTotalIndex)
+ iCurIndex = iCurIndex | 0x80;
+ else
+ iCurIndex = iCurIndex&0x7F;
+ iCurLen = iLastPacketLen;
+ }
+ else if (iCurIndex < iTotalIndex) {
+ iCurIndex = iCurIndex&0x7F;
+ bufpatch = NULL;
+ iCurLen = 0;
+ //printf("addtional packet index:%d iCurIndex:%d\n", i, iCurIndex);
+ }
+ else { //send end packet
+ bufpatch = NULL;
+ iCurLen = 0;
+ iCurIndex = iCurIndex|0x80;
+ //printf("end packet index:%d iCurIndex:%d\n", i, iCurIndex);
+ }
+
+ if (iCurIndex & 0x80)
+ ALOGI("Send FW last command");
+
+ //ALOGI("iCurIndex = %i, iCurLen = %i", iCurIndex, iCurLen);
+
+ is_proceeding = hci_download_patch_h4(p_buf, iCurIndex, bufpatch, iCurLen);
+
+ if (iCurIndex & 0x80)
+ {
+ ALOGI("Change HW flowcontrol setting");
+ if(gNeedToSetHWFlowControl)
+ {
+ if(gHwFlowControlEnable)
+ {
+ userial_vendor_set_hw_fctrl(1);
+ }
+ else
+ {
+ userial_vendor_set_hw_fctrl(0);
+ }
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ } // switch(hw_cfg_cb.state)
+ } // if (p_buf != NULL)
+
+ /* Free the RX event buffer */
+ if ((bt_vendor_cbacks) && (p_mem != 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.fw_fd != -1)
+ {
+ close(hw_cfg_cb.fw_fd);
+ hw_cfg_cb.fw_fd = -1;
+ }
+
+ hw_cfg_cb.state = 0;
+ }
+}
+
+/******************************************************************************
+** LPM Static Functions
+******************************************************************************/
+
+/*******************************************************************************
+**
+** Function hw_lpm_ctrl_cback
+**
+** Description Callback function for lpm enable/disable rquest
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_lpm_ctrl_cback(void *p_mem)
+{
+ HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
+ bt_vendor_op_result_t status = BT_VND_OP_RESULT_FAIL;
+
+ if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0)
+ {
+ status = BT_VND_OP_RESULT_SUCCESS;
+ }
+
+ if (bt_vendor_cbacks)
+ {
+ bt_vendor_cbacks->lpm_cb(status);
+ bt_vendor_cbacks->dealloc(p_evt_buf);
+ }
+}
+
+
+
+
+/*****************************************************************************
+** Hardware Configuration Interface Functions
+*****************************************************************************/
+
+
+/*******************************************************************************
+**
+** Function hw_config_start
+**
+** Description Kick off controller initialization process
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_config_start(void)
+{
+#if 0
+ HC_BT_HDR *p_buf = NULL;
+ uint8_t *p;
+#endif
+
+ hw_cfg_cb.state = 0;
+ hw_cfg_cb.fw_fd = -1;
+ hw_cfg_cb.f_set_baud_2 = FALSE;
+
+
+ /* Start from sending H5 SYNC */
+
+ if (bt_vendor_cbacks)
+ {
+#if 0
+ p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
+ 2);
+ }
+
+ if (p_buf)
+ {
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->layer_specific = 0;
+ p_buf->len = 2;
+
+ p = (uint8_t *) (p_buf + 1);
+ UINT16_TO_STREAM(p, HCI_VSC_H5_INIT);
+
+#endif
+ hw_cfg_cb.state = HW_CFG_START;
+ ALOGI("hw_config_start:Realtek version %s \n",RTK_VERSION);
+ //bt_vendor_cbacks->xmit_cb(HCI_VSC_H5_INIT, p_buf, hw_config_cback);
+ // bt_vendor_cbacks->xmit_cb(HCI_VSC_H5_INIT, p_buf, rtk_get_lmp);
+ bt_vendor_cbacks->xmit_cb(HCI_VSC_H5_INIT, NULL, rtk_get_lmp);
+ ALOGI("hw_config_start:back %s \n",RTK_VERSION);
+ }
+#if 0
+ else
+ {
+ if (bt_vendor_cbacks)
+ {
+ ALOGE("vendor lib fw conf aborted [no buffer]");
+ bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
+ }
+ }
+#endif
+}
+
+
+#ifdef BT_FW_CAL_ENABLE
+
+void rtk_print_host_cal_info(struct _rtk_bt_cal_info_entry *cal_info_entry)
+{
+ if(cal_info_entry)
+ {
+ rtk_print_host_info(cal_info_entry->bt_cal_efuse_host_info);
+ rtk_print_cal_info(cal_info_entry->bt_cal_efuse_cal_sts);
+ }
+}
+
+void rtk_print_host_info(uint16_t bt_cal_efuse_host_info)
+{
+ ALOGI("bt_cal_efuse_host_info = 0x%04x", bt_cal_efuse_host_info);
+ ALOGI("BT_EFUSE_HOST_INFO_DISABLE: %d", bt_cal_efuse_host_info&BT_EFUSE_HOST_INFO_DISABLE);
+ ALOGI("BT_EFUSE_CAL_STS_EN_DISABLE: %d",bt_cal_efuse_host_info&BT_EFUSE_CAL_STS_EN_DISABLE);
+ ALOGI("IS_FIRST_BT_INIT_AFTER_BOOT: %d", bt_cal_efuse_host_info&IS_FIRST_BT_INIT_AFTER_BOOT);
+ ALOGI("IS_FIRST_BT_INIT: %d", bt_cal_efuse_host_info&IS_FIRST_BT_INIT);
+ ALOGI("IS_LAST_INQUIRY_SUCCESS: %d", bt_cal_efuse_host_info&IS_LAST_INQUIRY_SUCCESS);
+}
+
+void rtk_print_cal_info(uint16_t *bt_cal_efuse_cal_sts)
+{
+ if(bt_cal_efuse_cal_sts)
+ {
+ ALOGI("BT_CAL_STS: %04X, %04X, %04X, %04X, %04X",
+ bt_cal_efuse_cal_sts[0],
+ bt_cal_efuse_cal_sts[1],
+ bt_cal_efuse_cal_sts[2],
+ bt_cal_efuse_cal_sts[3],
+ bt_cal_efuse_cal_sts[4]
+ );
+ }
+}
+
+#endif
+
+#if (HW_END_WITH_HCI_RESET == TRUE)
+/******************************************************************************
+*
+**
+** Function hw_epilog_cback
+**
+** Description Callback function for Command Complete Events from HCI
+** commands sent in epilog process.
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_epilog_cback(void *p_mem)
+{
+ HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
+ uint8_t *p, status;
+ uint16_t opcode;
+
+ status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode,p);
+
+ BTHWDBG("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
+
+ if (bt_vendor_cbacks)
+ {
+ /* Must free the RX event buffer */
+ bt_vendor_cbacks->dealloc(p_evt_buf);
+
+ /* Once epilog process is done, must call epilog_cb callback
+ to notify caller */
+ bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
+ }
+}
+
+/******************************************************************************
+*
+**
+** Function hw_epilog_process
+**
+** Description Sample implementation of epilog process
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_epilog_process(void)
+{
+ HC_BT_HDR *p_buf = NULL;
+ uint8_t *p;
+
+ BTHWDBG("hw_epilog_process");
+
+ /* Sending a HCI_RESET */
+ 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);
+ UINT16_TO_STREAM(p, HCI_RESET);
+ *p = 0; /* parameter length */
+
+ /* Send command via HC's xmit_cb API */
+ bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback);
+ }
+ else
+ {
+ if (bt_vendor_cbacks)
+ {
+ ALOGE("vendor lib epilog process aborted [no buffer]");
+ bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_FAIL);
+ }
+ }
+}
+#endif // (HW_END_WITH_HCI_RESET == TRUE)
diff --git a/bluetooth/libbt_rtk8723bs/src/upio.c b/bluetooth/libbt_rtk8723bs/src/upio.c
new file mode 100755
index 0000000..fd2cf0e
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/src/upio.c
@@ -0,0 +1,487 @@
+/******************************************************************************
+ *
+ * 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: upio.c
+ *
+ * Description: Contains I/O functions, like
+ * rfkill control
+ * BT_WAKE/HOST_WAKE control
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_upio"
+
+#include <utils/Log.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <cutils/properties.h>
+#include "bt_vendor_rtk.h"
+#include "upio.h"
+#include "userial_vendor.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+
+#ifndef UPIO_DBG
+#define UPIO_DBG FALSE
+#endif
+
+#if (UPIO_DBG == TRUE)
+#define UPIODBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
+#else
+#define UPIODBG(param, ...) {}
+#endif
+
+/******************************************************************************
+** Local type definitions
+******************************************************************************/
+
+#if (BT_WAKE_VIA_PROC == TRUE)
+
+/* proc fs node for enable/disable lpm mode */
+#ifndef VENDOR_LPM_PROC_NODE
+#define VENDOR_LPM_PROC_NODE "/proc/bluetooth/sleep/lpm"
+#endif
+
+/* proc fs node for notifying write request */
+#ifndef VENDOR_BTWRITE_PROC_NODE
+#define VENDOR_BTWRITE_PROC_NODE "/proc/bluetooth/sleep/btwrite"
+#endif
+
+/*
+ * Maximum btwrite assertion holding time without consecutive btwrite kicking.
+ * This value is correlative(shorter) to the in-activity timeout period set in
+ * the bluesleep LPM code. The current value used in bluesleep is 10sec.
+ */
+#ifndef PROC_BTWRITE_TIMER_TIMEOUT_MS
+#define PROC_BTWRITE_TIMER_TIMEOUT_MS 8000
+#endif
+
+/* lpm proc control block */
+typedef struct
+{
+ uint8_t btwrite_active;
+ uint8_t timer_created;
+ timer_t timer_id;
+ uint32_t timeout_ms;
+} vnd_lpm_proc_cb_t;
+
+static vnd_lpm_proc_cb_t lpm_proc_cb;
+#endif
+
+/******************************************************************************
+** Static variables
+******************************************************************************/
+
+static uint8_t upio_state[UPIO_MAX_COUNT];
+static int rfkill_id = -1;
+static int bt_emul_enable = 0;
+static char *rfkill_state_path = NULL;
+
+/******************************************************************************
+** Static functions
+******************************************************************************/
+
+/* for friendly debugging outpout string */
+static char *lpm_mode[] = {
+ "UNKNOWN",
+ "disabled",
+ "enabled"
+};
+
+static char *lpm_state[] = {
+ "UNKNOWN",
+ "de-asserted",
+ "asserted"
+};
+
+/*****************************************************************************
+** Bluetooth On/Off Static Functions
+*****************************************************************************/
+static int is_emulator_context(void)
+{
+ char value[PROPERTY_VALUE_MAX];
+
+ property_get("ro.kernel.qemu", value, "0");
+ UPIODBG("is_emulator_context : %s", value);
+ if (strcmp(value, "1") == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+static int is_rfkill_disabled(void)
+{
+ char value[PROPERTY_VALUE_MAX];
+
+ property_get("ro.rfkilldisabled", value, "0");
+ UPIODBG("is_rfkill_disabled ? [%s]", value);
+
+ if (strcmp(value, "1") == 0) {
+ return UPIO_BT_POWER_ON;
+ }
+
+ return UPIO_BT_POWER_OFF;
+}
+
+static int init_rfkill()
+{
+ char path[64];
+ char buf[16];
+ int fd, sz, id;
+
+ if (is_rfkill_disabled())
+ return -1;
+
+ for (id = 0; ; id++)
+ {
+ snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id);
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ {
+ ALOGE("init_rfkill : open(%s) failed: %s (%d)\n", \
+ path, strerror(errno), errno);
+ return -1;
+ }
+
+ sz = read(fd, &buf, sizeof(buf));
+ close(fd);
+
+ if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0)
+ {
+ rfkill_id = id;
+ break;
+ }
+ }
+
+ asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id);
+ return 0;
+}
+
+/*****************************************************************************
+** LPM Static Functions
+*****************************************************************************/
+
+#if (BT_WAKE_VIA_PROC == TRUE)
+/*******************************************************************************
+**
+** Function proc_btwrite_timeout
+**
+** Description Timeout thread of proc/.../btwrite assertion holding timer
+**
+** Returns None
+**
+*******************************************************************************/
+static void proc_btwrite_timeout(union sigval arg)
+{
+ UPIODBG("..%s..", __FUNCTION__);
+ lpm_proc_cb.btwrite_active = FALSE;
+}
+#endif
+
+/*****************************************************************************
+** UPIO Interface Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function upio_init
+**
+** Description Initialization
+**
+** Returns None
+**
+*******************************************************************************/
+void upio_init(void)
+{
+ memset(upio_state, UPIO_UNKNOWN, UPIO_MAX_COUNT);
+#if (BT_WAKE_VIA_PROC == TRUE)
+ memset(&lpm_proc_cb, 0, sizeof(vnd_lpm_proc_cb_t));
+#endif
+}
+
+/*******************************************************************************
+**
+** Function upio_cleanup
+**
+** Description Clean up
+**
+** Returns None
+**
+*******************************************************************************/
+void upio_cleanup(void)
+{
+#if (BT_WAKE_VIA_PROC == TRUE)
+ if (lpm_proc_cb.timer_created == TRUE)
+ timer_delete(lpm_proc_cb.timer_id);
+
+ lpm_proc_cb.timer_created = FALSE;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function upio_set_bluetooth_power
+**
+** Description Interact with low layer driver to set Bluetooth power
+** on/off.
+**
+** Returns 0 : SUCCESS or Not-Applicable
+** <0 : ERROR
+**
+*******************************************************************************/
+int upio_set_bluetooth_power(int on)
+{
+ int sz;
+ int fd = -1;
+ int ret = -1;
+ char buffer = '0';
+
+ switch(on)
+ {
+ case UPIO_BT_POWER_OFF:
+ buffer = '0';
+ break;
+
+ case UPIO_BT_POWER_ON:
+ buffer = '1';
+ break;
+ }
+
+ if (is_emulator_context())
+ {
+ /* if new value is same as current, return -1 */
+ if (bt_emul_enable == on)
+ return ret;
+
+ UPIODBG("set_bluetooth_power [emul] %d", on);
+
+ bt_emul_enable = on;
+ return 0;
+ }
+
+ /* check if we have rfkill interface */
+ if (is_rfkill_disabled())
+ return 0;
+
+ if (rfkill_id == -1)
+ {
+ if (init_rfkill())
+ return ret;
+ }
+
+ fd = open(rfkill_state_path, O_WRONLY);
+
+ if (fd < 0)
+ {
+ ALOGE("set_bluetooth_power : open(%s) for write failed: %s (%d)",
+ rfkill_state_path, strerror(errno), errno);
+ return ret;
+ }
+
+ sz = write(fd, &buffer, 1);
+
+ if (sz < 0) {
+ ALOGE("set_bluetooth_power : write(%s) failed: %s (%d)",
+ rfkill_state_path, strerror(errno),errno);
+ }
+ else
+ ret = 0;
+
+ if (fd >= 0)
+ close(fd);
+
+ return ret;
+}
+
+
+/*******************************************************************************
+**
+** Function upio_set
+**
+** Description Set i/o based on polarity
+**
+** Returns None
+**
+*******************************************************************************/
+void upio_set(uint8_t pio, uint8_t action, uint8_t polarity)
+{
+ int rc;
+#if (BT_WAKE_VIA_PROC == TRUE)
+ int fd = -1;
+ char buffer;
+#endif
+
+ switch (pio)
+ {
+ case UPIO_LPM_MODE:
+ if (upio_state[UPIO_LPM_MODE] == action)
+ {
+ UPIODBG("LPM is %s already", lpm_mode[action]);
+ return;
+ }
+
+ upio_state[UPIO_LPM_MODE] = action;
+
+#if (BT_WAKE_VIA_PROC == TRUE)
+ fd = open(VENDOR_LPM_PROC_NODE, O_WRONLY);
+
+ if (fd < 0)
+ {
+ ALOGE("upio_set : open(%s) for write failed: %s (%d)",
+ VENDOR_LPM_PROC_NODE, strerror(errno), errno);
+ return;
+ }
+
+ if (action == UPIO_ASSERT)
+ {
+ buffer = '1';
+ }
+ else
+ {
+ buffer = '0';
+
+ // delete btwrite assertion holding timer
+ if (lpm_proc_cb.timer_created == TRUE)
+ {
+ timer_delete(lpm_proc_cb.timer_id);
+ lpm_proc_cb.timer_created = FALSE;
+ }
+ }
+
+ if (write(fd, &buffer, 1) < 0)
+ {
+ ALOGE("upio_set : write(%s) failed: %s (%d)",
+ VENDOR_LPM_PROC_NODE, strerror(errno),errno);
+ }
+ else
+ {
+ if (action == UPIO_ASSERT)
+ {
+ // create btwrite assertion holding timer
+ if (lpm_proc_cb.timer_created == FALSE)
+ {
+ int status;
+ struct sigevent se;
+
+ se.sigev_notify = SIGEV_THREAD;
+ se.sigev_value.sival_ptr = &lpm_proc_cb.timer_id;
+ se.sigev_notify_function = proc_btwrite_timeout;
+ se.sigev_notify_attributes = NULL;
+
+ status = timer_create(CLOCK_MONOTONIC, &se,
+ &lpm_proc_cb.timer_id);
+
+ if (status == 0)
+ lpm_proc_cb.timer_created = TRUE;
+ }
+ }
+ }
+
+ if (fd >= 0)
+ close(fd);
+#endif
+ break;
+
+ case UPIO_BT_WAKE:
+ if (upio_state[UPIO_BT_WAKE] == action)
+ {
+ UPIODBG("BT_WAKE is %s already", lpm_state[action]);
+
+#if (BT_WAKE_VIA_PROC == TRUE)
+ if (lpm_proc_cb.btwrite_active == TRUE)
+ /*
+ * The proc btwrite node could have not been updated for
+ * certain time already due to heavy downstream path flow.
+ * In this case, we want to explicity touch proc btwrite
+ * node to keep the bt_wake assertion in the LPM kernel
+ * driver. The current kernel bluesleep LPM code starts
+ * a 10sec internal in-activity timeout timer before it
+ * attempts to deassert BT_WAKE line.
+ */
+#endif
+ return;
+ }
+
+ upio_state[UPIO_BT_WAKE] = action;
+
+#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE)
+
+ userial_vendor_ioctl( ( (action==UPIO_ASSERT) ? \
+ USERIAL_OP_ASSERT_BT_WAKE : USERIAL_OP_DEASSERT_BT_WAKE),\
+ NULL);
+
+#elif (BT_WAKE_VIA_PROC == TRUE)
+
+ /*
+ * Kick proc btwrite node only at UPIO_ASSERT
+ */
+ if (action == UPIO_DEASSERT)
+ return;
+
+ fd = open(VENDOR_BTWRITE_PROC_NODE, O_WRONLY);
+
+ if (fd < 0)
+ {
+ ALOGE("upio_set : open(%s) for write failed: %s (%d)",
+ VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno);
+ return;
+ }
+
+ buffer = '1';
+
+ if (write(fd, &buffer, 1) < 0)
+ {
+ ALOGE("upio_set : write(%s) failed: %s (%d)",
+ VENDOR_BTWRITE_PROC_NODE, strerror(errno),errno);
+ }
+ else
+ {
+ lpm_proc_cb.btwrite_active = TRUE;
+
+ if (lpm_proc_cb.timer_created == TRUE)
+ {
+ struct itimerspec ts;
+
+ ts.it_value.tv_sec = PROC_BTWRITE_TIMER_TIMEOUT_MS/1000;
+ ts.it_value.tv_nsec = 1000*(PROC_BTWRITE_TIMER_TIMEOUT_MS%1000);
+ ts.it_interval.tv_sec = 0;
+ ts.it_interval.tv_nsec = 0;
+
+ timer_settime(lpm_proc_cb.timer_id, 0, &ts, 0);
+ }
+ }
+
+ UPIODBG("proc btwrite assertion");
+
+ if (fd >= 0)
+ close(fd);
+#endif
+
+ break;
+
+ case UPIO_HOST_WAKE:
+ UPIODBG("upio_set: UPIO_HOST_WAKE");
+ break;
+ }
+}
+
+
diff --git a/bluetooth/libbt_rtk8723bs/src/userial_vendor.c b/bluetooth/libbt_rtk8723bs/src/userial_vendor.c
new file mode 100755
index 0000000..321206f
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/src/userial_vendor.c
@@ -0,0 +1,445 @@
+/******************************************************************************
+ *
+ * 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 "bt_userial_vendor"
+
+#include <utils/Log.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include "bt_vendor_rtk.h"
+#include "userial.h"
+#include "userial_vendor.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+
+#ifndef VNDUSERIAL_DBG
+#define VNDUSERIAL_DBG TRUE
+#endif
+
+#if (VNDUSERIAL_DBG == TRUE)
+#define VNDUSERIALDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
+#else
+#define VNDUSERIALDBG(param, ...) {}
+#endif
+
+#define VND_PORT_NAME_MAXLEN 256
+
+#ifndef BT_CHIP_HW_FLOW_CTRL_ON
+#define BT_CHIP_HW_FLOW_CTRL_ON TRUE
+#endif
+
+
+
+/******************************************************************************
+** Local type definitions
+******************************************************************************/
+
+/* vendor serial control block */
+typedef struct
+{
+ int fd; /* fd to Bluetooth device */
+ struct termios termios; /* serial terminal of BT port */
+ char port_name[VND_PORT_NAME_MAXLEN];
+} vnd_userial_cb_t;
+
+/******************************************************************************
+** Static variables
+******************************************************************************/
+
+static vnd_userial_cb_t vnd_userial;
+
+/*****************************************************************************
+** Helper Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function userial_to_tcio_baud
+**
+** Description helper function converts USERIAL baud rates into TCIO
+** conforming baud rates
+**
+** Returns TRUE/FALSE
+**
+*******************************************************************************/
+uint8_t userial_to_tcio_baud(uint8_t cfg_baud, uint32_t *baud)
+{
+ if (cfg_baud == USERIAL_BAUD_115200)
+ *baud = B115200;
+ else if (cfg_baud == USERIAL_BAUD_4M)
+ *baud = B4000000;
+ else if (cfg_baud == USERIAL_BAUD_3M)
+ *baud = B3000000;
+ else if (cfg_baud == USERIAL_BAUD_2M)
+ *baud = B2000000;
+ else if (cfg_baud == USERIAL_BAUD_1M)
+ *baud = B1000000;
+ else if (cfg_baud == USERIAL_BAUD_1_5M)
+ *baud = B1500000;
+ else if (cfg_baud == USERIAL_BAUD_921600)
+ *baud = B921600;
+ else if (cfg_baud == USERIAL_BAUD_460800)
+ *baud = B460800;
+ else if (cfg_baud == USERIAL_BAUD_230400)
+ *baud = B230400;
+ else if (cfg_baud == USERIAL_BAUD_57600)
+ *baud = B57600;
+ else if (cfg_baud == USERIAL_BAUD_19200)
+ *baud = B19200;
+ else if (cfg_baud == USERIAL_BAUD_9600)
+ *baud = B9600;
+ else if (cfg_baud == USERIAL_BAUD_1200)
+ *baud = B1200;
+ else if (cfg_baud == USERIAL_BAUD_600)
+ *baud = B600;
+ else
+ {
+ ALOGE( "userial vendor open: unsupported baud idx %i", cfg_baud);
+ *baud = B115200;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+/*******************************************************************************
+**
+** Function userial_ioctl_init_bt_wake
+**
+** Description helper function to set the open state of the bt_wake if ioctl
+** is used. it should not hurt in the rfkill case but it might
+** be better to compile it out.
+**
+** Returns none
+**
+*******************************************************************************/
+void userial_ioctl_init_bt_wake(int fd)
+{
+ uint32_t bt_wake_state;
+
+ /* assert BT_WAKE through ioctl */
+ ioctl(fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL);
+ ioctl(fd, USERIAL_IOCTL_BT_WAKE_GET_ST, &bt_wake_state);
+ VNDUSERIALDBG("userial_ioctl_init_bt_wake read back BT_WAKE state=%i", \
+ bt_wake_state);
+}
+#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+
+
+/*****************************************************************************
+** Userial Vendor API Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function userial_vendor_init
+**
+** Description Initialize userial vendor-specific control block
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_init(void)
+{
+ vnd_userial.fd = -1;
+ snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", \
+ BLUETOOTH_UART_DEVICE_PORT);
+}
+
+/*******************************************************************************
+**
+** Function userial_vendor_open
+**
+** Description Open the serial port with the given configuration
+**
+** Returns device fd
+**
+*******************************************************************************/
+int userial_vendor_open(tUSERIAL_CFG *p_cfg)
+{
+ uint32_t baud;
+ uint8_t data_bits;
+ uint16_t parity;
+ uint8_t stop_bits;
+
+ vnd_userial.fd = -1;
+
+ if (!userial_to_tcio_baud(p_cfg->baud, &baud))
+ {
+ return -1;
+ }
+
+ if(p_cfg->fmt & USERIAL_DATABITS_8)
+ data_bits = CS8;
+ else if(p_cfg->fmt & USERIAL_DATABITS_7)
+ data_bits = CS7;
+ else if(p_cfg->fmt & USERIAL_DATABITS_6)
+ data_bits = CS6;
+ else if(p_cfg->fmt & USERIAL_DATABITS_5)
+ data_bits = CS5;
+ else
+ {
+ ALOGE("userial vendor open: unsupported data bits");
+ return -1;
+ }
+
+ if(p_cfg->fmt & USERIAL_PARITY_NONE)
+ parity = 0;
+ else if(p_cfg->fmt & USERIAL_PARITY_EVEN)
+ parity = PARENB;
+ else if(p_cfg->fmt & USERIAL_PARITY_ODD)
+ parity = (PARENB | PARODD);
+ else
+ {
+ ALOGE("userial vendor open: unsupported parity bit mode");
+ return -1;
+ }
+
+ if(p_cfg->fmt & USERIAL_STOPBITS_1)
+ stop_bits = 0;
+ else if(p_cfg->fmt & USERIAL_STOPBITS_2)
+ stop_bits = CSTOPB;
+ else
+ {
+ ALOGE("userial vendor open: unsupported stop bits");
+ return -1;
+ }
+
+ ALOGI("userial vendor open: opening %s", vnd_userial.port_name);
+
+ if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1)
+ {
+ ALOGE("userial vendor open: unable to open %s", vnd_userial.port_name);
+ return -1;
+ }
+
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+
+ tcgetattr(vnd_userial.fd, &vnd_userial.termios);
+ cfmakeraw(&vnd_userial.termios);
+
+ if(p_cfg->hw_fctrl == USERIAL_HW_FLOW_CTRL_ON)
+ {
+ ALOGI("userial vendor open: with HW flowctrl ON");
+ vnd_userial.termios.c_cflag |= (CRTSCTS | stop_bits| parity);
+ }
+ else
+ {
+ ALOGI("userial vendor open: with HW flowctrl OFF");
+ vnd_userial.termios.c_cflag &= ~CRTSCTS;
+ vnd_userial.termios.c_cflag |= (stop_bits| parity);
+
+ }
+
+ tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+
+ tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+
+ /* set input/output baudrate */
+ cfsetospeed(&vnd_userial.termios, baud);
+ cfsetispeed(&vnd_userial.termios, baud);
+ tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
+
+
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+ userial_ioctl_init_bt_wake(vnd_userial.fd);
+#endif
+
+ ALOGI("device fd = %d open", vnd_userial.fd);
+
+ return vnd_userial.fd;
+}
+
+/*******************************************************************************
+**
+** Function userial_vendor_close
+**
+** Description Conduct vendor-specific close work
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_close(void)
+{
+ int result;
+
+ if (vnd_userial.fd == -1)
+ return;
+
+#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
+
+ ALOGI("device fd = %d close", vnd_userial.fd);
+
+ if ((result = close(vnd_userial.fd)) < 0)
+ ALOGE( "close(fd:%d) FAILED result:%d", vnd_userial.fd, result);
+
+ vnd_userial.fd = -1;
+}
+
+/*******************************************************************************
+**
+** Function userial_vendor_set_baud
+**
+** Description Set new baud rate
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_set_baud(uint8_t userial_baud)
+{
+ uint32_t tcio_baud;
+ ALOGI("userial_vendor_set_baud++");
+ userial_to_tcio_baud(userial_baud, &tcio_baud);
+
+ if(cfsetospeed(&vnd_userial.termios, tcio_baud)<0)
+ ALOGE("cfsetospeed fail");
+
+ if(cfsetispeed(&vnd_userial.termios, tcio_baud)<0)
+ ALOGE("cfsetispeed fail");
+
+ if(tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios)<0)
+ ALOGE("tcsetattr fail ");
+
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+
+ ALOGI("userial_vendor_set_baud--");
+}
+
+/*******************************************************************************
+**
+** Function userial_vendor_ioctl
+**
+** Description ioctl inteface
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data)
+{
+ switch(op)
+ {
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+ case USERIAL_OP_ASSERT_BT_WAKE:
+ VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##");
+ ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL);
+ break;
+
+ case USERIAL_OP_DEASSERT_BT_WAKE:
+ VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##");
+ ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL);
+ break;
+
+ case USERIAL_OP_GET_BT_WAKE_STATE:
+ ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data);
+ break;
+#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+
+ default:
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function userial_set_port
+**
+** Description Configure UART port name
+**
+** Returns 0 : Success
+** Otherwise : Fail
+**
+*******************************************************************************/
+int userial_set_port(char *p_conf_name, char *p_conf_value, int param)
+{
+ strcpy(vnd_userial.port_name, p_conf_value);
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function userial_vendor_set_hw_fctrl
+**
+** Description Conduct vendor-specific close work
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_set_hw_fctrl(uint8_t hw_fctrl)
+{
+ struct termios termios_old;
+
+ if (vnd_userial.fd == -1)
+ {
+ ALOGE("vnd_userial.fd is -1");
+ return;
+ }
+
+ tcgetattr(vnd_userial.fd, &termios_old);
+ if(hw_fctrl)
+ {
+ ALOGI("Set HW FlowControl On");
+ if(termios_old.c_cflag & CRTSCTS)
+ {
+ ALOGI("userial_vendor_set_hw_fctrl already hw flowcontrol on");
+ return;
+ }
+ else
+ {
+ termios_old.c_cflag |= CRTSCTS;
+ tcsetattr(vnd_userial.fd, TCSANOW, &termios_old);
+ ALOGI("userial_vendor_set_hw_fctrl set hw flowcontrol on");
+ }
+ }
+ else
+ {
+ ALOGI("Set HW FlowControl Off");
+ if(termios_old.c_cflag & CRTSCTS)
+ {
+ termios_old.c_cflag &= ~CRTSCTS;
+ tcsetattr(vnd_userial.fd, TCSANOW, &termios_old);
+ return;
+ }
+ else
+ {
+ ALOGI("userial_vendor_set_hw_fctrl set hw flowcontrol off");
+ return;
+ }
+ }
+
+}
+
diff --git a/bluetooth/libbt_rtk8723bs/vnd_buildcfg.mk b/bluetooth/libbt_rtk8723bs/vnd_buildcfg.mk
new file mode 100755
index 0000000..b65033a
--- /dev/null
+++ b/bluetooth/libbt_rtk8723bs/vnd_buildcfg.mk
@@ -0,0 +1,16 @@
+intermediates := $(local-intermediates-dir)
+
+SRC := $(call my-dir)/include/$(addprefix vnd_, $(addsuffix .txt,$(basename $(TARGET_DEVICE))))
+ifeq (,$(wildcard $(SRC)))
+# configuration file does not exist. Use default one
+SRC := $(call my-dir)/include/vnd_generic.txt
+endif
+GEN := $(intermediates)/vnd_buildcfg.h
+TOOL := $(TOP_DIR)external/bluetooth/bluedroid/tools/gen-buildcfg.sh
+
+$(GEN): PRIVATE_PATH := $(call my-dir)
+$(GEN): PRIVATE_CUSTOM_TOOL = $(TOOL) $< $@
+$(GEN): $(SRC) $(TOOL)
+ $(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES += $(GEN)