[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/connectivity/combo_tool/6631_combo_tool/Android.mk b/src/connectivity/combo_tool/6631_combo_tool/Android.mk
new file mode 100644
index 0000000..a4b9e6d
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/Android.mk
@@ -0,0 +1,56 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+#
+# MediaTek Inc. (C) 2010. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+# Copyright (C) 2008 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.
+
+ifeq ($(MTK_COMBO_SUPPORT), yes)
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
+endif
diff --git a/src/connectivity/combo_tool/6631_combo_tool/LICENSE b/src/connectivity/combo_tool/6631_combo_tool/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/connectivity/combo_tool/6631_combo_tool/Makefile.am b/src/connectivity/combo_tool/6631_combo_tool/Makefile.am
new file mode 100644
index 0000000..16d341a
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/Makefile.am
@@ -0,0 +1,16 @@
+bin_PROGRAMS = wmt_loader wmt_launcher wmt_loopback wmt_concurrency stp_dump3
+wmt_loader_SOURCES = combo_loader/yocto_loader.c
+wmt_loopback_SOURCES = src/wmt_loopback.c
+wmt_launcher_SOURCES = src/yocto_stp_uart_launcher.c
+wmt_launcher_LDADD = -lpthread
+
+power_on_wifi_SOURCES = src/power_on_wifi.c
+
+wmt_concurrency_SOURCES = src/yocto_wmt_concurrency.c
+
+stp_dump3_SOURCES = src/stp_dump/os_linux.c \
+ src/stp_dump/eloop.c \
+ src/stp_dump/stp_dump.c \
+ src/stp_dump/bt_fw_logger.c \
+ src/stp_dump/wifi_fw_logger.c
+stp_dump3_LDADD = -lpthread
\ No newline at end of file
diff --git a/src/connectivity/combo_tool/6631_combo_tool/README b/src/connectivity/combo_tool/6631_combo_tool/README
new file mode 100644
index 0000000..d4b3313
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/README
@@ -0,0 +1,22 @@
+This module serves the common part driver of connectivity
+
+WHAT IT DOES?
+=============
+This module creates some executable binary files for loading/configuring/testing
+the common part driver, in addition, it installs the Firmware patch and common part
+cfg files into device.
+
+HOW IT WAS BUILT?
+==================
+It needs the following library from AOSP:
+
+libcutils, libc
+
+HOW TO USE IT?
+==============
+The firmware patch and common part cfg file was installed into device directly when build.
+And the executable binary files will be started in init.rc when boot. they will work together
+to load/configure the common part driver of connectivity
+
+The majority of source code was written by MediaTek. Some code from open source codes are used.
+more detail info, pls ref the NOTICE under the specific sub folder.
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT.cfg
new file mode 100644
index 0000000..71c7ba1
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT.cfg
@@ -0,0 +1,4 @@
+mt6620.defAnt=mt6620_ant_m3.cfg
+mt6628.defAnt=mt6628_ant_m1.cfg
+mt6630.defAnt=mt6630_ant_m1.cfg
+mt6632.defAnt=mt6632_ant_m1.cfg
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_SOC.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_SOC.cfg
new file mode 100644
index 0000000..79cd55f
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_SOC.cfg
@@ -0,0 +1,7 @@
+coex_wmt_ant_mode=1
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+co_clock_flag=0
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_CONNAC.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_CONNAC.cfg
new file mode 100644
index 0000000..f9f6aa6
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_CONNAC.cfg
@@ -0,0 +1,340 @@
+// Action | symbol | Param1 | Param2 | Param3 | Param4 | Param5
+// Read EMI | _EMI | R(0) | Begin offset | End offset
+// Read EMI to temp register | _EMI | R(0) | offset | Temp Reg ID($)
+// Read EMI to temp register | _EMI | R(0) | offset | mask | Temp Reg ID ($)
+// Read CR | _REG | R(0) | Pre-define base-addr ID | offset | times | delay time(ms)
+// Read CR | _REG | R(0) | AP Physical address | offset | times | delay time(ms)
+// Read CR to temp register | _REG | R(0) | Pre-define base-addr ID | offset | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | AP Physical address | offset | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | Pre-define base-addr ID | offset | mask | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | AP Physical address | offset | mask | Temp Reg ID($)
+// Write CR | _REG | W(1) | Pre-define base-addr ID | offset | value
+// Write CR | _REG | W(1) | AP Physical address | offset | value
+// Write CR some bit | _REG | W(1) | Pre-define base-addr ID | offset | value | mask
+// Write CR some bit | _REG | W(1) | AP Physical address | offset | value | mask
+// Read GPIO | GPIO | R(0) | Pin number
+// Disable reset | DRST
+// Chip reset | _RST
+// Keep Wakeup Connsys | WAK+
+// Cancel keep Wakeup | WAK-
+// Show message | SHOW | String(No space)
+// Sleep | _SLP | time(ms)
+// Check condition to result temp register | COND | Result Temp Reg ID($) | Left Temp Reg ID($) | Operator | Right Temp Reg ID($)
+// Check condition to result temp register | COND | Result Temp Reg ID($) | Left Temp Reg ID($) | Operator | Value(Dec or Hex)
+// Save value to temp register | _VAL | Temp Reg ID($) | Value
+//
+// Condition Action | symbol | Param1 | Param2 | Param3 | Param4 | Param5 | Param6
+// Read EMI with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | End offset
+// Read EMI to temp register with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | Temp Reg ID($)
+// Read EMI to temp register with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | mask | Temp Reg ID($)
+// Read CR with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | times | delay time(ms)
+// Read CR with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | times | delay time(ms)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | mask | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | mask | Temp Reg ID($)
+// Write CR with Condition | CREG | Condition Temp Reg ID($) | W(1) | Pre-define base-addr ID | offset | value
+// Write CR with Condition | CREG | Condition Temp Reg ID($) | W(1) | AP Physical address | offset | value
+// Write CR some bit with Condition | CREG | Condition Temp Reg ID($) | W(1) | Pre-define base-addr ID | offset | value | mask
+// Write CR some bit with Condition | CREG | Condition Temp Reg ID($) | W(1) | AP Physical address | offset | value | mask
+//
+// Periodic dump: Add PD in trigger point
+// [TP x] Trigger point
+// [PD+] ms
+// [AT] xxxx
+// [AT] xxxx
+// [PD-]
+//
+// Temp Reg ID: ($0 ~ $9)
+//
+// Operator: ==, !=, >, >=, <, <=, &&, ||
+//
+// Pre-define base-addr ID: (You can find address and size in DTS file)
+// #1 => CONN_MCU_CONFIG_BASE
+// #2 => AP_RGU_BASE
+// #3 => TOPCKGEN_BASE
+// #4 => SPM_BASE
+// #5 => CONN_HIF_ON_BASE
+// #6 => CONN_TOP_MISC_OFF_BASE
+// #7 => CONN_MCU_CFG_ON_BASE
+// #8 => CONN_MCU_CIRQ_BASE
+
+[TP 1] When Command timeout
+ // Host_CSR
+ [AT] _REG 0 #5 0x100 1 0
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 0 #5 0x108 1 0
+ [AT] _REG 0 #5 0x10c 1 0
+ [AT] _REG 0 #5 0x110 1 0
+ [AT] _REG 0 #5 0x114 1 0
+ [AT] _REG 0 #5 0x118 1 0
+ [AT] _REG 0 #5 0x11c 1 0
+ [AT] _REG 0 #5 0x120 1 0
+ [AT] _REG 0 #5 0x124 1 0
+ [AT] _REG 0 #5 0x128 1 0
+ [AT] _REG 0 #5 0x12c 1 0
+ [AT] _REG 0 #5 0x130 1 0
+
+ // PC log from Host_CSR
+ [AT] _REG 1 #5 0x14 0xff000380
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000382
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000384
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000386
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000388
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00038a
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00038c
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00038e
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000390
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000392
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000394
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000396
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000398
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00039a
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00039c
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00039e
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003a0
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003a2
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003a4
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003a6
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003a8
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003aa
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003ac
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003ae
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003b0
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003b2
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003b4
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003b6
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003b8
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003ba
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003bc
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003be
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003c0
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003c2
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003c4
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003c6
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003c8
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003ca
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003cc
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003ce
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003d0
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003fe
+
+ // Bus timeout debug
+ [AT] _REG 0 0x10000000 0x0000 1 0
+ [AT] _REG 0 0x10000000 0x0200 1 0
+ [AT] _REG 0 0x10000000 0x6408 1 0
+ [AT] _REG 0 0x10000000 0x640c 1 0
+ [AT] _REG 0 0x10000000 0x644c 1 0
+ [AT] _REG 0 0x1020e000 0x02c 1 0
+ [AT] _REG 0 0x1020e000 0x180 1 0
+ [AT] _REG 0 0x1020e000 0x184 1 0
+ [AT] _REG 0 0x1020e000 0x188 1 0
+ [AT] _REG 0 0x1020e000 0x18c 1 0
+ [AT] _REG 0 #3 0x220 1 0
+ [AT] _REG 0 #3 0x224 1 0
+ [AT] _REG 0 #3 0x228 1 0
+ [AT] _REG 0 #3 0x250 1 0
+ [AT] _REG 0 #3 0x254 1 0
+ [AT] _REG 0 #3 0x258 1 0
+
+[TP 2] When Firmware trigger assert
+
+[TP 3] Before Chip reset
+ // Host_CSR
+ [AT] _REG 0 #5 0x100 1 0
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 0 #5 0x108 1 0
+ [AT] _REG 0 #5 0x10c 1 0
+ [AT] _REG 0 #5 0x110 1 0
+ [AT] _REG 0 #5 0x114 1 0
+ [AT] _REG 0 #5 0x118 1 0
+ [AT] _REG 0 #5 0x11c 1 0
+ [AT] _REG 0 #5 0x120 1 0
+ [AT] _REG 0 #5 0x124 1 0
+ [AT] _REG 0 #5 0x128 1 0
+ [AT] _REG 0 #5 0x12c 1 0
+ [AT] _REG 0 #5 0x130 1 0
+
+ // PC log from Host_CSR
+ [AT] _REG 1 #5 0x14 0xff000380
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000382
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000384
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000386
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000388
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00038a
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00038c
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00038e
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000390
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000392
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000394
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000396
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff000398
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00039a
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00039c
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff00039e
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003a0
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003a2
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003a4
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003a6
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003a8
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003aa
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003ac
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003ae
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003b0
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003b2
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003b4
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003b6
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003b8
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003ba
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003bc
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003be
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003c0
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003c2
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003c4
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003c6
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003c8
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003ca
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003cc
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003ce
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003d0
+ [AT] _REG 0 #5 0x104 1 0
+ [AT] _REG 1 #5 0x14 0xff0003fe
+
+ // Bus timeout debug
+ [AT] _REG 0 0x10000000 0x0000 1 0
+ [AT] _REG 0 0x10000000 0x0200 1 0
+ [AT] _REG 0 0x10000000 0x6408 1 0
+ [AT] _REG 0 0x10000000 0x640c 1 0
+ [AT] _REG 0 0x10000000 0x644c 1 0
+ [AT] _REG 0 0x1020e000 0x02c 1 0
+ [AT] _REG 0 0x1020e000 0x180 1 0
+ [AT] _REG 0 0x1020e000 0x184 1 0
+ [AT] _REG 0 0x1020e000 0x188 1 0
+ [AT] _REG 0 0x1020e000 0x18c 1 0
+ [AT] _REG 0 #3 0x220 1 0
+ [AT] _REG 0 #3 0x224 1 0
+ [AT] _REG 0 #3 0x228 1 0
+ [AT] _REG 0 #3 0x250 1 0
+ [AT] _REG 0 #3 0x254 1 0
+ [AT] _REG 0 #3 0x258 1 0
+
+[TP 4] After Chip reset
+
+[TP 5] Before Wifi function on
+
+[TP 6] Before Wifi function off
+
+[TP 7] Before BT function on
+
+[TP 8] Before BT function off
+
+[TP 9] Before FM function on
+
+[TP 10] Before FM function off
+
+[TP 11] Before GPS function on
+
+[TP 12] Before GPS function off
+
+[TP 13] Before read consys thermal
+
+[TP 14] Power on sequence(0): Start power on
+
+[TP 15] Power on sequence(1): Before can get connsys id
+
+[TP 16] Power on sequence(2): Before send download patch
+
+[TP 17] Power on sequence(3): Before connsys reset (donwload patch)
+
+[TP 18] Power on sequence(4): Before set wifi and lte coex
+
+[TP 19] Power on sequence(5): Before set BT and Wifi calibration
+
+[TP 20] Power on sequence(6): End power on
+
+[TP 21] Before WMT power off
+
+[TP 22] When AP suspend
+
+[TP 23] When AP resume
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_GEN2.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_GEN2.cfg
new file mode 100644
index 0000000..bd9b47f
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_GEN2.cfg
@@ -0,0 +1,102 @@
+// Action | symbol | Param1 | Param2 | Param3 | Param4 | Param5
+// Read EMI | _EMI | R(0) | Begin offset | End offset
+// Read EMI to temp register | _EMI | R(0) | offset | Temp Reg ID($)
+// Read EMI to temp register | _EMI | R(0) | offset | mask | Temp Reg ID ($)
+// Read CR | _REG | R(0) | Pre-define base-addr ID | offset | times | delay time(ms)
+// Read CR | _REG | R(0) | AP Physical address | offset | times | delay time(ms)
+// Read CR to temp register | _REG | R(0) | Pre-define base-addr ID | offset | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | AP Physical address | offset | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | Pre-define base-addr ID | offset | mask | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | AP Physical address | offset | mask | Temp Reg ID($)
+// Write CR | _REG | W(1) | Pre-define base-addr ID | offset | value
+// Write CR | _REG | W(1) | AP Physical address | offset | value
+// Write CR some bit | _REG | W(1) | Pre-define base-addr ID | offset | value | mask
+// Write CR some bit | _REG | W(1) | AP Physical address | offset | value | mask
+// Read GPIO | GPIO | R(0) | Pin number
+// Disable reset | DRST
+// Chip reset | _RST
+// Keep Wakeup Connsys | WAK+
+// Cancel keep Wakeup | WAK-
+// Show message | SHOW | String(No space)
+// Sleep | _SLP | time(ms)
+// Check condition to result temp register | COND | Result Temp Reg ID($) | Left Temp Reg ID($) | Operator | Right Temp Reg ID($)
+// Check condition to result temp register | COND | Result Temp Reg ID($) | Left Temp Reg ID($) | Operator | Value(Dec or Hex)
+// Save value to temp register | _VAL | Temp Reg ID($) | Value
+//
+// Condition Action | symbol | Param1 | Param2 | Param3 | Param4 | Param5 | Param6
+// Read EMI with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | End offset
+// Read EMI to temp register with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | Temp Reg ID($)
+// Read EMI to temp register with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | mask | Temp Reg ID($)
+// Read CR with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | times | delay time(ms)
+// Read CR with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | times | delay time(ms)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | mask | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | mask | Temp Reg ID($)
+// Write CR with Condition | CREG | Condition Temp Reg ID($) | W(1) | Pre-define base-addr ID | offset | value
+// Write CR with Condition | CREG | Condition Temp Reg ID($) | W(1) | AP Physical address | offset | value
+// Write CR some bit with Condition | CREG | Condition Temp Reg ID($) | W(1) | Pre-define base-addr ID | offset | value | mask
+// Write CR some bit with Condition | CREG | Condition Temp Reg ID($) | W(1) | AP Physical address | offset | value | mask
+//
+// Periodic dump: Add PD in trigger point
+// [TP x] Trigger point
+// [PD+] ms
+// [AT] xxxx
+// [AT] xxxx
+// [PD-]
+//
+// Temp Reg ID: ($0 ~ $9)
+//
+// Operator: ==, !=, >, >=, <, <=, &&, ||
+//
+// Pre-define base-addr ID: (You can find address and size in DTS file)
+// #1 => CONN_MCU_CONFIG_BASE
+// #2 => AP_RGU_BASE
+// #3 => TOPCKGEN_BASE
+// #4 => SPM_BASE
+
+[TP 1] When Command timeout
+
+[TP 2] When Firmware trigger assert
+
+[TP 3] Before Chip reset
+
+[TP 4] After Chip reset
+
+[TP 5] Before Wifi function on
+
+[TP 6] Before Wifi function off
+
+[TP 7] Before BT function on
+
+[TP 8] Before BT function off
+
+[TP 9] Before FM function on
+
+[TP 10] Before FM function off
+
+[TP 11] Before GPS function on
+
+[TP 12] Before GPS function off
+
+[TP 13] Before read consys thermal
+
+[TP 14] Power on sequence(0): Start power on
+
+[TP 15] Power on sequence(1): Before can get connsys id
+
+[TP 16] Power on sequence(2): Before send download patch
+
+[TP 17] Power on sequence(3): Before connsys reset (donwload patch)
+
+[TP 18] Power on sequence(4): Before set wifi and lte coex
+
+[TP 19] Power on sequence(5): Before set BT and Wifi calibration
+
+[TP 20] Power on sequence(6): End power on
+
+[TP 21] Before WMT power off
+
+[TP 22] When AP suspend
+
+[TP 23] When AP resume
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_GEN3.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_GEN3.cfg
new file mode 100644
index 0000000..bd9b47f
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_GEN3.cfg
@@ -0,0 +1,102 @@
+// Action | symbol | Param1 | Param2 | Param3 | Param4 | Param5
+// Read EMI | _EMI | R(0) | Begin offset | End offset
+// Read EMI to temp register | _EMI | R(0) | offset | Temp Reg ID($)
+// Read EMI to temp register | _EMI | R(0) | offset | mask | Temp Reg ID ($)
+// Read CR | _REG | R(0) | Pre-define base-addr ID | offset | times | delay time(ms)
+// Read CR | _REG | R(0) | AP Physical address | offset | times | delay time(ms)
+// Read CR to temp register | _REG | R(0) | Pre-define base-addr ID | offset | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | AP Physical address | offset | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | Pre-define base-addr ID | offset | mask | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | AP Physical address | offset | mask | Temp Reg ID($)
+// Write CR | _REG | W(1) | Pre-define base-addr ID | offset | value
+// Write CR | _REG | W(1) | AP Physical address | offset | value
+// Write CR some bit | _REG | W(1) | Pre-define base-addr ID | offset | value | mask
+// Write CR some bit | _REG | W(1) | AP Physical address | offset | value | mask
+// Read GPIO | GPIO | R(0) | Pin number
+// Disable reset | DRST
+// Chip reset | _RST
+// Keep Wakeup Connsys | WAK+
+// Cancel keep Wakeup | WAK-
+// Show message | SHOW | String(No space)
+// Sleep | _SLP | time(ms)
+// Check condition to result temp register | COND | Result Temp Reg ID($) | Left Temp Reg ID($) | Operator | Right Temp Reg ID($)
+// Check condition to result temp register | COND | Result Temp Reg ID($) | Left Temp Reg ID($) | Operator | Value(Dec or Hex)
+// Save value to temp register | _VAL | Temp Reg ID($) | Value
+//
+// Condition Action | symbol | Param1 | Param2 | Param3 | Param4 | Param5 | Param6
+// Read EMI with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | End offset
+// Read EMI to temp register with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | Temp Reg ID($)
+// Read EMI to temp register with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | mask | Temp Reg ID($)
+// Read CR with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | times | delay time(ms)
+// Read CR with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | times | delay time(ms)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | mask | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | mask | Temp Reg ID($)
+// Write CR with Condition | CREG | Condition Temp Reg ID($) | W(1) | Pre-define base-addr ID | offset | value
+// Write CR with Condition | CREG | Condition Temp Reg ID($) | W(1) | AP Physical address | offset | value
+// Write CR some bit with Condition | CREG | Condition Temp Reg ID($) | W(1) | Pre-define base-addr ID | offset | value | mask
+// Write CR some bit with Condition | CREG | Condition Temp Reg ID($) | W(1) | AP Physical address | offset | value | mask
+//
+// Periodic dump: Add PD in trigger point
+// [TP x] Trigger point
+// [PD+] ms
+// [AT] xxxx
+// [AT] xxxx
+// [PD-]
+//
+// Temp Reg ID: ($0 ~ $9)
+//
+// Operator: ==, !=, >, >=, <, <=, &&, ||
+//
+// Pre-define base-addr ID: (You can find address and size in DTS file)
+// #1 => CONN_MCU_CONFIG_BASE
+// #2 => AP_RGU_BASE
+// #3 => TOPCKGEN_BASE
+// #4 => SPM_BASE
+
+[TP 1] When Command timeout
+
+[TP 2] When Firmware trigger assert
+
+[TP 3] Before Chip reset
+
+[TP 4] After Chip reset
+
+[TP 5] Before Wifi function on
+
+[TP 6] Before Wifi function off
+
+[TP 7] Before BT function on
+
+[TP 8] Before BT function off
+
+[TP 9] Before FM function on
+
+[TP 10] Before FM function off
+
+[TP 11] Before GPS function on
+
+[TP 12] Before GPS function off
+
+[TP 13] Before read consys thermal
+
+[TP 14] Power on sequence(0): Start power on
+
+[TP 15] Power on sequence(1): Before can get connsys id
+
+[TP 16] Power on sequence(2): Before send download patch
+
+[TP 17] Power on sequence(3): Before connsys reset (donwload patch)
+
+[TP 18] Power on sequence(4): Before set wifi and lte coex
+
+[TP 19] Power on sequence(5): Before set BT and Wifi calibration
+
+[TP 20] Power on sequence(6): End power on
+
+[TP 21] Before WMT power off
+
+[TP 22] When AP suspend
+
+[TP 23] When AP resume
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_GEN3_5.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_GEN3_5.cfg
new file mode 100644
index 0000000..bd9b47f
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/WMT_STEP_GEN3_5.cfg
@@ -0,0 +1,102 @@
+// Action | symbol | Param1 | Param2 | Param3 | Param4 | Param5
+// Read EMI | _EMI | R(0) | Begin offset | End offset
+// Read EMI to temp register | _EMI | R(0) | offset | Temp Reg ID($)
+// Read EMI to temp register | _EMI | R(0) | offset | mask | Temp Reg ID ($)
+// Read CR | _REG | R(0) | Pre-define base-addr ID | offset | times | delay time(ms)
+// Read CR | _REG | R(0) | AP Physical address | offset | times | delay time(ms)
+// Read CR to temp register | _REG | R(0) | Pre-define base-addr ID | offset | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | AP Physical address | offset | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | Pre-define base-addr ID | offset | mask | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | AP Physical address | offset | mask | Temp Reg ID($)
+// Write CR | _REG | W(1) | Pre-define base-addr ID | offset | value
+// Write CR | _REG | W(1) | AP Physical address | offset | value
+// Write CR some bit | _REG | W(1) | Pre-define base-addr ID | offset | value | mask
+// Write CR some bit | _REG | W(1) | AP Physical address | offset | value | mask
+// Read GPIO | GPIO | R(0) | Pin number
+// Disable reset | DRST
+// Chip reset | _RST
+// Keep Wakeup Connsys | WAK+
+// Cancel keep Wakeup | WAK-
+// Show message | SHOW | String(No space)
+// Sleep | _SLP | time(ms)
+// Check condition to result temp register | COND | Result Temp Reg ID($) | Left Temp Reg ID($) | Operator | Right Temp Reg ID($)
+// Check condition to result temp register | COND | Result Temp Reg ID($) | Left Temp Reg ID($) | Operator | Value(Dec or Hex)
+// Save value to temp register | _VAL | Temp Reg ID($) | Value
+//
+// Condition Action | symbol | Param1 | Param2 | Param3 | Param4 | Param5 | Param6
+// Read EMI with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | End offset
+// Read EMI to temp register with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | Temp Reg ID($)
+// Read EMI to temp register with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | mask | Temp Reg ID($)
+// Read CR with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | times | delay time(ms)
+// Read CR with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | times | delay time(ms)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | mask | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | mask | Temp Reg ID($)
+// Write CR with Condition | CREG | Condition Temp Reg ID($) | W(1) | Pre-define base-addr ID | offset | value
+// Write CR with Condition | CREG | Condition Temp Reg ID($) | W(1) | AP Physical address | offset | value
+// Write CR some bit with Condition | CREG | Condition Temp Reg ID($) | W(1) | Pre-define base-addr ID | offset | value | mask
+// Write CR some bit with Condition | CREG | Condition Temp Reg ID($) | W(1) | AP Physical address | offset | value | mask
+//
+// Periodic dump: Add PD in trigger point
+// [TP x] Trigger point
+// [PD+] ms
+// [AT] xxxx
+// [AT] xxxx
+// [PD-]
+//
+// Temp Reg ID: ($0 ~ $9)
+//
+// Operator: ==, !=, >, >=, <, <=, &&, ||
+//
+// Pre-define base-addr ID: (You can find address and size in DTS file)
+// #1 => CONN_MCU_CONFIG_BASE
+// #2 => AP_RGU_BASE
+// #3 => TOPCKGEN_BASE
+// #4 => SPM_BASE
+
+[TP 1] When Command timeout
+
+[TP 2] When Firmware trigger assert
+
+[TP 3] Before Chip reset
+
+[TP 4] After Chip reset
+
+[TP 5] Before Wifi function on
+
+[TP 6] Before Wifi function off
+
+[TP 7] Before BT function on
+
+[TP 8] Before BT function off
+
+[TP 9] Before FM function on
+
+[TP 10] Before FM function off
+
+[TP 11] Before GPS function on
+
+[TP 12] Before GPS function off
+
+[TP 13] Before read consys thermal
+
+[TP 14] Power on sequence(0): Start power on
+
+[TP 15] Power on sequence(1): Before can get connsys id
+
+[TP 16] Power on sequence(2): Before send download patch
+
+[TP 17] Power on sequence(3): Before connsys reset (donwload patch)
+
+[TP 18] Power on sequence(4): Before set wifi and lte coex
+
+[TP 19] Power on sequence(5): Before set BT and Wifi calibration
+
+[TP 20] Power on sequence(6): End power on
+
+[TP 21] Before WMT power off
+
+[TP 22] When AP suspend
+
+[TP 23] When AP resume
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m1.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m1.cfg
new file mode 100644
index 0000000..2557394
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m1.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=1
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xCE
+coex_wifi_rssi_mid_limit=0xBB
+coex_wifi_rssi_lower_limit=0xBB
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m2.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m2.cfg
new file mode 100644
index 0000000..1801583
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m2.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=2
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xCE
+coex_wifi_rssi_mid_limit=0xBB
+coex_wifi_rssi_lower_limit=0xBB
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m3.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m3.cfg
new file mode 100644
index 0000000..c019bae
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m3.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=3
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xD2
+coex_wifi_rssi_mid_limit=0xC8
+coex_wifi_rssi_lower_limit=0xBF
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m4.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m4.cfg
new file mode 100644
index 0000000..8788db8
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m4.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=4
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xD2
+coex_wifi_rssi_mid_limit=0xC8
+coex_wifi_rssi_lower_limit=0xBF
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m5.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m5.cfg
new file mode 100644
index 0000000..44eb8c8
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m5.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=5
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xD2
+coex_wifi_rssi_mid_limit=0xC8
+coex_wifi_rssi_lower_limit=0xBF
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m6.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m6.cfg
new file mode 100644
index 0000000..0f9372c
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m6.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=6
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xD2
+coex_wifi_rssi_mid_limit=0xC8
+coex_wifi_rssi_lower_limit=0xBF
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m7.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m7.cfg
new file mode 100644
index 0000000..8b7d601
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6620_ant_m7.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=7
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xD2
+coex_wifi_rssi_mid_limit=0xC8
+coex_wifi_rssi_lower_limit=0xBF
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m1.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m1.cfg
new file mode 100644
index 0000000..346233d
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m1.cfg
@@ -0,0 +1,8 @@
+coex_wmt_ant_mode=1
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m2.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m2.cfg
new file mode 100644
index 0000000..dba5e25
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m2.cfg
@@ -0,0 +1,6 @@
+coex_wmt_ant_mode=2
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m3.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m3.cfg
new file mode 100644
index 0000000..1459ed0
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m3.cfg
@@ -0,0 +1,6 @@
+coex_wmt_ant_mode=3
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m4.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m4.cfg
new file mode 100644
index 0000000..b3011f3
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6628_ant_m4.cfg
@@ -0,0 +1,7 @@
+coex_wmt_ant_mode=4
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m1.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m1.cfg
new file mode 100644
index 0000000..b86c1aa
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m1.cfg
@@ -0,0 +1,9 @@
+coex_wmt_ant_mode=1
+coex_wmt_ext_component=0
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m2.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m2.cfg
new file mode 100644
index 0000000..dba5e25
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m2.cfg
@@ -0,0 +1,6 @@
+coex_wmt_ant_mode=2
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m3.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m3.cfg
new file mode 100644
index 0000000..1459ed0
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m3.cfg
@@ -0,0 +1,6 @@
+coex_wmt_ant_mode=3
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m4.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m4.cfg
new file mode 100644
index 0000000..b3011f3
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6630_ant_m4.cfg
@@ -0,0 +1,7 @@
+coex_wmt_ant_mode=4
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m1.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m1.cfg
new file mode 100644
index 0000000..802bf75
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m1.cfg
@@ -0,0 +1,10 @@
+coex_wmt_ant_mode=44
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+coex_wmt_wifi_path=0x0006
+
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m2.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m2.cfg
new file mode 100644
index 0000000..0f020ef
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m2.cfg
@@ -0,0 +1,10 @@
+coex_wmt_ant_mode=40
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+coex_wmt_wifi_path=0x000f
+
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m3.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m3.cfg
new file mode 100644
index 0000000..c61eea0
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m3.cfg
@@ -0,0 +1,10 @@
+coex_wmt_ant_mode=45
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+coex_wmt_wifi_path=0x000E
+
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m4.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m4.cfg
new file mode 100644
index 0000000..8740e80
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/mt6632_ant_m4.cfg
@@ -0,0 +1,10 @@
+coex_wmt_ant_mode=46
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+coex_wmt_wifi_path=0x0007
+
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/txpowerctrl.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/txpowerctrl.cfg
new file mode 100644
index 0000000..30d74d2
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/txpowerctrl.cfg
@@ -0,0 +1 @@
+test
\ No newline at end of file
diff --git a/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/wifi.cfg b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/wifi.cfg
new file mode 100644
index 0000000..30d74d2
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/cfg_folder/wifi.cfg
@@ -0,0 +1 @@
+test
\ No newline at end of file
diff --git a/src/connectivity/combo_tool/6631_combo_tool/combo_loader/Android.mk b/src/connectivity/combo_tool/6631_combo_tool/combo_loader/Android.mk
new file mode 100644
index 0000000..8a6fe9c
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/combo_loader/Android.mk
@@ -0,0 +1,102 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+#
+# MediaTek Inc. (C) 2010. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+# Copyright (C) 2008 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.
+
+# Configuration
+BUILD_LOADER := false
+BUILD_MT6582_CONSYS := false
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(MTK_COMBO_CHIP), )
+ifneq ($(MTK_COMBO_CHIP),MT7668)
+BUILD_LOADER := true
+endif
+endif
+
+ifneq ($(filter CONSYS_6572,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6582,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6592,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6735,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6755,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6797,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifeq ($(BUILD_LOADER), true)
+$(warning build loader)
+include $(CLEAR_VARS)
+
+ifeq ($(BUILD_MT6582_CONSYS), true)
+LOCAL_CFLAGS := -DMTK_SOC_CONSYS_SUPPORT
+endif
+
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+LOCAL_HEADER_LIBRARIES := libcutils_headers
+LOCAL_SRC_FILES := loader.c
+LOCAL_MODULE := wmt_loader
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+LOCAL_INIT_RC := ../init_connectivity.rc
+include $(MTK_EXECUTABLE)
+endif
diff --git a/src/connectivity/combo_tool/6631_combo_tool/combo_loader/README b/src/connectivity/combo_tool/6631_combo_tool/combo_loader/README
new file mode 100644
index 0000000..053fc8b
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/combo_loader/README
@@ -0,0 +1,19 @@
+This module serves the common part driver of connectivity
+
+WHAT IT DOES?
+=============
+This module creates one executable binary files for loading/initializing the common part driver including
+wifi, fm, gps and BT if needed.
+
+HOW IT WAS BUILT?
+==================
+It needs the following library from AOSP:
+
+libcutils
+
+HOW TO USE IT?
+==============
+the executable binary files, wmt_loader, will be started in init.rc when boot. it will load/initialize
+to load the common part drivers(common part/wifi/fm/gps/BT) of connectivity
+
+The source code was written by MediaTek.
diff --git a/src/connectivity/combo_tool/6631_combo_tool/combo_loader/loader.c b/src/connectivity/combo_tool/6631_combo_tool/combo_loader/loader.c
new file mode 100644
index 0000000..2f90f81
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/combo_loader/loader.c
@@ -0,0 +1,305 @@
+
+#include "loader.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "wmt_loader"
+
+#define WCN_COMBO_LOADER_CHIP_ID_PROP "persist.vendor.connsys.chipid"
+#define WCN_DRIVER_READY_PROP "vendor.connsys.driver.ready"
+#define WCN_COMBO_LOADER_DEV "/dev/wmtdetect"
+#define WMT_MODULES_PRE "/system/lib/modules/"
+#define WMT_MODULES_SUFF ".ko"
+#define WMT_DETECT_IOC_MAGIC 'w'
+
+#define COMBO_IOCTL_GET_CHIP_ID _IOR(WMT_DETECT_IOC_MAGIC, 0, int)
+#define COMBO_IOCTL_SET_CHIP_ID _IOW(WMT_DETECT_IOC_MAGIC, 1, int)
+#define COMBO_IOCTL_EXT_CHIP_DETECT _IOR(WMT_DETECT_IOC_MAGIC, 2, int)
+#define COMBO_IOCTL_GET_SOC_CHIP_ID _IOR(WMT_DETECT_IOC_MAGIC, 3, int)
+#define COMBO_IOCTL_DO_MODULE_INIT _IOR(WMT_DETECT_IOC_MAGIC, 4, int)
+#define COMBO_IOCTL_MODULE_CLEANUP _IOR(WMT_DETECT_IOC_MAGIC, 5, int)
+#define COMBO_IOCTL_EXT_CHIP_PWR_ON _IOR(WMT_DETECT_IOC_MAGIC, 6, int)
+#define COMBO_IOCTL_EXT_CHIP_PWR_OFF _IOR(WMT_DETECT_IOC_MAGIC, 7, int)
+#define COMBO_IOCTL_DO_SDIO_AUDOK _IOR(WMT_DETECT_IOC_MAGIC, 8, int)
+
+
+
+#define STP_WMT_MODULE_PRE_FIX "mtk_stp_wmt"
+#define STP_BT_MODULE_PRE_FIX "mtk_stp_bt"
+#define STP_GPS_MODULE_PRE_FIX "mtk_stp_gps"
+#define HIF_SDIO_MODULE_PRE_FIX "mtk_hif_sdio"
+#define STP_SDIO_MODULE_PRE_FIX "mtk_stp_sdio"
+#define STP_UART_MODULE_PRE_FIX "mtk_stp_uart"
+
+#define WMT_PROC_DBG_PATH "/proc/driver/wmt_dbg"
+#define WMT_PROC_AEE_PATH "/proc/driver/wmt_aee"
+
+static int g_loader_fd = -1;
+
+static int g_chipid_array[] = {
+ 0x6620, 0x6628, 0x6630, 0x6632, 0x6572, 0x6582, 0x6592, 0x8127,
+ 0x6571, 0x6752, 0x6735, 0x0321, 0x0335, 0x0337, 0x8163, 0x6580,
+ 0x6755, 0x0326, 0x6797, 0x0279, 0x6757, 0x0551, 0x8167, 0x6759,
+ 0x0507, 0x6763, 0x0690, 0x6570, 0x0713, 0x6775, 0x0788, 0x6771,
+ 0x6765, 0x3967, 0x6761, 0x8168,
+};
+
+static int loader_do_chipid_vaild_check(int chip_id)
+{
+ int ret = -1;
+ unsigned char i;
+
+ for (i = 0; i < sizeof(g_chipid_array)/sizeof(0x6630); i++) {
+ if (chip_id == g_chipid_array[i]) {
+ ALOGI("chipid vaild check: %d :0x%x!\n", i, chip_id);
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int loader_do_kernel_module_init(int loader_fd, int chip_id) {
+ int ret = 0;
+
+ if (loader_fd < 0) {
+ ALOGE("invalid loaderfd: %d\n", loader_fd);
+ return -1;
+ }
+
+ ret = ioctl(loader_fd, COMBO_IOCTL_MODULE_CLEANUP, chip_id);
+ if (ret) {
+ ALOGE("do WMT-DETECT module cleanup failed: %d\n", ret);
+ return -2;
+ }
+
+ ret = ioctl(loader_fd, COMBO_IOCTL_DO_MODULE_INIT, chip_id);
+ if (ret) {
+ ALOGE("do kernel module init failed: %d\n", ret);
+ return -3;
+ }
+
+ ALOGI("do kernel module init succeed: %d\n", ret);
+
+ return 0;
+}
+
+static void loader_do_combo_sdio_autok(int loader_fd, int chip_id) {
+ int retry_counter = 10;
+ int ret = -1;
+ int no_ext_chip = -1;
+ int chipid_detect = -1;
+ int autok_ret = 0;
+
+ ALOGV("chip id :%x\n", chip_id);
+
+ /*trigger autok process, incase last autok process is interrupted by abnormal power off or battery down*/
+ do {
+ /*power on combo chip*/
+ ret = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_PWR_ON);
+ if (0 != ret) {
+ ALOGE("external combo chip power on failed\n");
+ no_ext_chip = 1;
+ } else {
+ /*detect is there is an external combo chip, this step should not be must*/
+ no_ext_chip = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_DETECT, NULL);
+ }
+
+ ALOGI("external combo chip detected\n");
+ chipid_detect = ioctl(loader_fd, COMBO_IOCTL_GET_CHIP_ID, NULL);
+ ALOGI("chipid (0x%x) detected\n", chipid_detect);
+
+ if (0 == no_ext_chip) {
+ autok_ret = ioctl(loader_fd, COMBO_IOCTL_DO_SDIO_AUDOK, chipid_detect);
+ ALOGE("do SDIO3.0 autok %s\n", autok_ret ? "fail" : "succeed");
+ }
+
+ ret = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_PWR_OFF);
+ ALOGI("external combo chip power off %s\n", ret ? "fail" : "succeed");
+
+ if ((0 == no_ext_chip) && (-1 == chipid_detect)) {
+ /*extenral chip detected, but no valid chipId detected, retry*/
+ retry_counter--;
+ ALOGE("chipId detect failed, retrying, left retryCounter:%d\n", retry_counter);
+ usleep(500000);
+ } else
+ break;
+
+ } while (0 < retry_counter);
+
+}
+
+static void loader_do_first_chip_detect(int loader_fd, int *chip) {
+ int retry_counter = 20;
+ int ret = -1;
+ int no_ext_chip = -1;
+ int chip_id = -1;
+ int autok_ret = 0;
+ char chipid_str[PROPERTY_VALUE_MAX] = {0};
+
+ do {
+ /*power on combo chip*/
+ ret = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_PWR_ON);
+ if (-1 == ret) {
+ ALOGI("SOC chip no need do combo chip power on.\n");
+ no_ext_chip = 1;
+ chip_id = ioctl(loader_fd, COMBO_IOCTL_GET_SOC_CHIP_ID, NULL);
+ } else if (0 == ret) {
+ /*detect is there is an external combo chip*/
+ no_ext_chip = 0;
+ ret = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_DETECT, NULL);
+ if (0 != ret)
+ ALOGE("external combo chip detect failed (%d)\n", ret);
+ else
+ chip_id = ioctl(loader_fd, COMBO_IOCTL_GET_CHIP_ID, NULL);
+ } else
+ ALOGE("external combo power on failed (%d)\n", ret);
+
+ ALOGI("chipid (0x%x) detected\n", chip_id);
+
+ if (chip_id != -1) {
+ sprintf(chipid_str, "0x%04x", chip_id);
+ ret = property_set(WCN_COMBO_LOADER_CHIP_ID_PROP, chipid_str);
+ if (0 != ret) {
+ ALOGE("set property(%s) to %s failed,ret:%d, errno:%d\n",
+ WCN_COMBO_LOADER_CHIP_ID_PROP, chipid_str, ret, errno);
+ } else
+ ALOGI("set property(%s) to %s succeed.\n", WCN_COMBO_LOADER_CHIP_ID_PROP, chipid_str);
+ }
+
+ if (0 == no_ext_chip) {
+ autok_ret = ioctl(loader_fd, COMBO_IOCTL_DO_SDIO_AUDOK, chip_id);
+ ALOGI("do SDIO3.0 autok %s\n", autok_ret ? "fail" : "succeed");
+ ret = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_PWR_OFF);
+ ALOGI("external combo chip power off %s\n", ret ? "fail" : "succeed");
+ }
+
+ if ((0 == no_ext_chip) && (-1 == chip_id)) {
+ /*extenral chip detected, but no valid chipId detected, retry*/
+ retry_counter--;
+#ifdef HAVE_AEE_FEATURE
+ if (0 == retry_counter) {
+ AEE_SYSTEM_EXCEPTION("Connsys Combo chip detect failed");
+ }
+#endif
+ usleep(500000);
+ ALOGE("chipId detect failed, retrying, left retryCounter:%d\n", retry_counter);
+ } else
+ break;
+ } while (0 < retry_counter);
+
+ *chip = chip_id;
+}
+
+static int loader_do_driver_ready_set(void) {
+ int ret = -1;
+ char ready_str[PROPERTY_VALUE_MAX] = {0};
+ ret = property_get(WCN_DRIVER_READY_PROP, ready_str, NULL);
+ if ((0 >= ret) || (0 == strcmp(ready_str, "yes"))) {
+ ALOGE("get property(%s) failed iRet:%d or property is %s\n",
+ WCN_DRIVER_READY_PROP, ret, ready_str);
+ }
+ /*set it to yes anyway*/
+ sprintf(ready_str, "%s", "yes");
+ ret = property_set(WCN_DRIVER_READY_PROP, ready_str);
+ if (0 != ret) {
+ ALOGE("set property(%s) to %s failed ret:%d\n",
+ WCN_DRIVER_READY_PROP, ready_str, ret);
+ } else
+ ALOGI("set property(%s) to %s succeed\n", WCN_DRIVER_READY_PROP, ready_str);
+
+ return ret;
+}
+
+int main(int argc, char *argv[]) {
+ int ret = -1;
+ int chip_id = -1;
+ int count = 0;
+ char chipid_str[PROPERTY_VALUE_MAX] = {0};
+ char ready_str[PROPERTY_VALUE_MAX] = {0};
+
+ ALOGV("argc:%d,argv:%s\n", argc, argv[0]);
+
+ ret = property_get(WCN_DRIVER_READY_PROP, ready_str, NULL);
+ if (0 == strcmp(ready_str, "yes")) {
+ ALOGE("WMT driver has been ready.\n");
+ return ret;
+ }
+
+ do {
+ g_loader_fd = open(WCN_COMBO_LOADER_DEV, O_RDWR | O_NOCTTY);
+ if (g_loader_fd < 0) {
+ count++;
+ ALOGI("Can't open device node(%s) count(%d)\n", WCN_COMBO_LOADER_DEV, count);
+ usleep(300000);
+ }
+ else
+ break;
+ }while(1);
+
+ /*read from system property*/
+ ret = property_get(WCN_COMBO_LOADER_CHIP_ID_PROP, chipid_str, NULL);
+ chip_id = strtoul(chipid_str, NULL, 16);
+ ALOGI("chip id from property:%d\n", chip_id);
+ if ((0 != ret) && (-1 != loader_do_chipid_vaild_check(chip_id))) {
+ /*valid chip_id detected*/
+ ALOGI("key:(%s)-value:(%s),chipId:0x%04x,ret(%d)\n",
+ WCN_COMBO_LOADER_CHIP_ID_PROP, chipid_str, chip_id, ret);
+ if (0x6630 == chip_id || 0x6632 == chip_id)
+ loader_do_combo_sdio_autok(g_loader_fd, chip_id);
+ } else {
+ /*trigger external combo chip detect and chip identification process*/
+ loader_do_first_chip_detect(g_loader_fd, &chip_id);
+ }
+
+ /*set chipid to kernel*/
+ ioctl(g_loader_fd, COMBO_IOCTL_SET_CHIP_ID, chip_id);
+
+ if ((0x0321 == chip_id) || (0x0335 == chip_id) || (0x0337 == chip_id))
+ chip_id = 0x6735;
+
+ if (0x0326 == chip_id)
+ chip_id = 0x6755;
+
+ if (0x0551 == chip_id)
+ chip_id = 0x6757;
+
+ if (0x0690 == chip_id)
+ chip_id = 0x6763;
+
+ if (0x0279 == chip_id)
+ chip_id = 0x6797;
+
+ if (0x0507 == chip_id)
+ chip_id = 0x6759;
+
+ if (0x0713 == chip_id)
+ chip_id = 0x6775;
+
+ if (0x0788 == chip_id)
+ chip_id = 0x6771;
+
+ /*how to handling if not all module init fail?*/
+ if (chip_id == -1) {
+ ALOGE("chip id error !!(0x%x)\n", chip_id);
+ return -1;
+ }
+ loader_do_kernel_module_init(g_loader_fd, chip_id);
+ if (g_loader_fd >= 0) {
+ close(g_loader_fd);
+ g_loader_fd = -1;
+ }
+
+ if ((chown(WMT_PROC_DBG_PATH, AID_SHELL, AID_SYSTEM) == -1) ||
+ (chown(WMT_PROC_AEE_PATH, AID_SHELL, AID_SYSTEM) == -1))
+ ALOGE("chown wmt_dbg or wmt_aee fail:%s\n", strerror(errno));
+
+ ret = loader_do_driver_ready_set();
+
+ return ret;
+}
+
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/combo_loader/loader.h b/src/connectivity/combo_tool/6631_combo_tool/combo_loader/loader.h
new file mode 100644
index 0000000..6c77b03
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/combo_loader/loader.h
@@ -0,0 +1,28 @@
+#ifndef __WMT_LOADER_H_
+#define __WMT_LOADER_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+//#include <cutils/properties.h>
+//#include <cutils/misc.h>
+#include <sys/ioctl.h>
+//#include <cutils/android_filesystem_config.h>
+//#include <log/log.h>
+
+#ifdef HAVE_AEE_FEATURE
+#include <aee.h>
+#define AEE_SYSTEM_EXCEPTION(String) \
+ do { \
+ aee_system_exception( \
+ "wmt_loader", \
+ NULL, \
+ DB_OPT_DEFAULT, \
+ String); \
+ } while(0)
+#endif
+#endif
diff --git a/src/connectivity/combo_tool/6631_combo_tool/combo_loader/yocto_loader.c b/src/connectivity/combo_tool/6631_combo_tool/combo_loader/yocto_loader.c
new file mode 100644
index 0000000..75c51a9
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/combo_loader/yocto_loader.c
@@ -0,0 +1,428 @@
+
+#include "loader.h"
+#include <sys/utsname.h>
+#include <sys/syscall.h>
+
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "wmt_loader"
+#ifndef ALOGI
+#define ALOGI printf
+#endif
+#ifndef ALOGE
+#define ALOGE printf
+#endif
+#ifndef ALOGV
+#define ALOGV printf
+#endif
+#ifndef PROPERTY_VALUE_MAX
+#define PROPERTY_VALUE_MAX (128)
+#endif
+
+
+#define WCN_COMBO_LOADER_CHIP_ID_PROP "persist.vendor.connsys.chipid"
+#define WCN_DRIVER_READY_PROP "vendor.connsys.driver.ready"
+#define WCN_COMBO_LOADER_DEV "/dev/wmtdetect"
+#define WMT_MODULES_PRE "/system/lib/modules/"
+#define WMT_MODULES_SUFF ".ko"
+#define WMT_DETECT_IOC_MAGIC 'w'
+
+/* connectivity modules are built out of kernel tree */
+#define WMT_OUT_KO_PATH_PREFIX "/lib/modules/mt66xx/"
+#define WMT_OUT_WMT_WIFI_MODULE_PATH "wmt_chrdev_wifi.ko"
+#define WMT_OUT_WLAN_MODULE_PATH "wlan_drv_gen4m.ko"
+#define WMT_OUT_WLAN_GEN3_MODULE_PATH "wlan_gen3.ko"
+#define WMT_OUT_BT_MODULE_PATH "wmt_cdev_bt.ko"
+#define WMT_OUT_BT_DRV_MODULE_PATH "bt_drv.ko"
+
+
+
+#define COMBO_IOCTL_GET_CHIP_ID _IOR(WMT_DETECT_IOC_MAGIC, 0, int)
+#define COMBO_IOCTL_SET_CHIP_ID _IOW(WMT_DETECT_IOC_MAGIC, 1, int)
+#define COMBO_IOCTL_EXT_CHIP_DETECT _IOR(WMT_DETECT_IOC_MAGIC, 2, int)
+#define COMBO_IOCTL_GET_SOC_CHIP_ID _IOR(WMT_DETECT_IOC_MAGIC, 3, int)
+#define COMBO_IOCTL_DO_MODULE_INIT _IOR(WMT_DETECT_IOC_MAGIC, 4, int)
+#define COMBO_IOCTL_MODULE_CLEANUP _IOR(WMT_DETECT_IOC_MAGIC, 5, int)
+#define COMBO_IOCTL_EXT_CHIP_PWR_ON _IOR(WMT_DETECT_IOC_MAGIC, 6, int)
+#define COMBO_IOCTL_EXT_CHIP_PWR_OFF _IOR(WMT_DETECT_IOC_MAGIC, 7, int)
+#define COMBO_IOCTL_DO_SDIO_AUDOK _IOR(WMT_DETECT_IOC_MAGIC, 8, int)
+
+
+
+#define STP_WMT_MODULE_PRE_FIX "mtk_stp_wmt"
+#define STP_BT_MODULE_PRE_FIX "mtk_stp_bt"
+#define STP_GPS_MODULE_PRE_FIX "mtk_stp_gps"
+#define HIF_SDIO_MODULE_PRE_FIX "mtk_hif_sdio"
+#define STP_SDIO_MODULE_PRE_FIX "mtk_stp_sdio"
+#define STP_UART_MODULE_PRE_FIX "mtk_stp_uart"
+
+#define WMT_PROC_DBG_PATH "/proc/driver/wmt_dbg"
+#define WMT_PROC_AEE_PATH "/proc/driver/wmt_aee"
+
+static int g_loader_fd = -1;
+
+static char DRIVER_MODULE_PATH[64] = {0};
+static char DRIVER_MODULE_ARG[8] = "";
+
+static int g_chipid_array[] = {
+ 0x6620, 0x6628, 0x6630, 0x6632, 0x6572, 0x6582, 0x6592, 0x8127,
+ 0x6571, 0x6752, 0x6735, 0x0321, 0x0335, 0x0337, 0x8163, 0x6580,
+ 0x6755, 0x0326, 0x6797, 0x0279, 0x6757, 0x0551, 0x8167, 0x6759,
+ 0x0507, 0x6763, 0x0690, 0x6570, 0x0713, 0x6775, 0x0788, 0x6771,
+ 0x6765, 0x3967, 0x6761, 0x8168, 0x8512,
+};
+
+
+/* TBD in platform-specific way */
+static int get_persist_chip_id(char *str, size_t len) { return -1; }
+static int set_persist_chip_id(int id) { return 0; }
+static void set_proc_owner(void) { }
+static void update_driver_ready(void) { }
+
+static int loader_do_chipid_vaild_check(int chip_id)
+{
+ int ret = -1;
+ unsigned char i;
+
+ for (i = 0; i < sizeof(g_chipid_array)/sizeof(0x6630); i++) {
+ if (chip_id == g_chipid_array[i]) {
+ ALOGI("chipid vaild check: %d :0x%x!\n", i, chip_id);
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int loader_do_kernel_module_init(int loader_fd, int chip_id) {
+ int ret = 0;
+
+ if (loader_fd < 0) {
+ ALOGE("invalid loaderfd: %d\n", loader_fd);
+ return -1;
+ }
+
+ ret = ioctl(loader_fd, COMBO_IOCTL_MODULE_CLEANUP, chip_id);
+ if (ret) {
+ ALOGE("do WMT-DETECT module cleanup failed: %d\n", ret);
+ return -2;
+ }
+
+ ret = ioctl(loader_fd, COMBO_IOCTL_DO_MODULE_INIT, chip_id);
+ if (ret) {
+ ALOGE("do kernel module init failed: %d\n", ret);
+ return -3;
+ }
+
+ ALOGI("do kernel module init succeed: %d\n", ret);
+
+ return 0;
+}
+
+static void loader_do_combo_sdio_autok(int loader_fd, int chip_id) {
+ int retry_counter = 10;
+ int ret = -1;
+ int no_ext_chip = -1;
+ int chipid_detect = -1;
+ int autok_ret = 0;
+
+ ALOGV("chip id :%x\n", chip_id);
+
+ /*trigger autok process, incase last autok process is interrupted by abnormal power off or battery down*/
+ do {
+ /*power on combo chip*/
+ ret = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_PWR_ON);
+ if (0 != ret) {
+ ALOGE("external combo chip power on failed\n");
+ no_ext_chip = 1;
+ } else {
+ /*detect is there is an external combo chip, this step should not be must*/
+ no_ext_chip = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_DETECT, NULL);
+ }
+
+ ALOGI("external combo chip detected\n");
+ chipid_detect = ioctl(loader_fd, COMBO_IOCTL_GET_CHIP_ID, NULL);
+ ALOGI("chipid (0x%x) detected\n", chipid_detect);
+
+ if (0 == no_ext_chip) {
+ autok_ret = ioctl(loader_fd, COMBO_IOCTL_DO_SDIO_AUDOK, chipid_detect);
+ ALOGE("do SDIO3.0 autok %s\n", autok_ret ? "fail" : "succeed");
+ }
+
+ ret = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_PWR_OFF);
+ ALOGI("external combo chip power off %s\n", ret ? "fail" : "succeed");
+
+ if ((0 == no_ext_chip) && (-1 == chipid_detect)) {
+ /*extenral chip detected, but no valid chipId detected, retry*/
+ retry_counter--;
+ ALOGE("chipId detect failed, retrying, left retryCounter:%d\n", retry_counter);
+ usleep(500000);
+ } else
+ break;
+
+ } while (0 < retry_counter);
+
+}
+
+static void loader_do_first_chip_detect(int loader_fd, int *chip) {
+ int retry_counter = 20;
+ int ret = -1;
+ int no_ext_chip = -1;
+ int chip_id = -1;
+ int autok_ret = 0;
+ char chipid_str[PROPERTY_VALUE_MAX] = {0};
+
+ do {
+ /*power on combo chip*/
+ ret = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_PWR_ON);
+ if (-1 == ret) {
+ ALOGI("SOC chip no need do combo chip power on.\n");
+ no_ext_chip = 1;
+ chip_id = ioctl(loader_fd, COMBO_IOCTL_GET_SOC_CHIP_ID, NULL);
+ } else if (0 == ret) {
+ /*detect is there is an external combo chip*/
+ no_ext_chip = 0;
+ ret = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_DETECT, NULL);
+ if (0 != ret)
+ ALOGE("external combo chip detect failed (%d)\n", ret);
+ else
+ chip_id = ioctl(loader_fd, COMBO_IOCTL_GET_CHIP_ID, NULL);
+ } else
+ ALOGE("external combo power on failed (%d)\n", ret);
+
+ ALOGI("chipid (0x%x) detected\n", chip_id);
+
+ if (chip_id != -1) {
+ sprintf(chipid_str, "0x%04x", chip_id);
+ ret = set_persist_chip_id(chip_id);
+ if (0 != ret) {
+ ALOGE("set property(%s) to %s failed,ret:%d, errno:%d\n",
+ WCN_COMBO_LOADER_CHIP_ID_PROP, chipid_str, ret, errno);
+ } else
+ ALOGI("set property(%s) to %s succeed.\n", WCN_COMBO_LOADER_CHIP_ID_PROP, chipid_str);
+ }
+
+ if (0 == no_ext_chip) {
+ autok_ret = ioctl(loader_fd, COMBO_IOCTL_DO_SDIO_AUDOK, chip_id);
+ ALOGI("do SDIO3.0 autok %s\n", autok_ret ? "fail" : "succeed");
+ ret = ioctl(loader_fd, COMBO_IOCTL_EXT_CHIP_PWR_OFF);
+ ALOGI("external combo chip power off %s\n", ret ? "fail" : "succeed");
+ }
+
+ if ((0 == no_ext_chip) && (-1 == chip_id)) {
+ /*extenral chip detected, but no valid chipId detected, retry*/
+ retry_counter--;
+#ifdef HAVE_AEE_FEATURE
+ if (0 == retry_counter) {
+ AEE_SYSTEM_EXCEPTION("Connsys Combo chip detect failed");
+ }
+#endif
+ usleep(500000);
+ ALOGE("chipId detect failed, retrying, left retryCounter:%d\n", retry_counter);
+ } else
+ break;
+ } while (0 < retry_counter);
+
+ *chip = chip_id;
+}
+
+#if 0
+static int loader_do_driver_ready_set(void) {
+ int ret = -1;
+ char ready_str[PROPERTY_VALUE_MAX] = {0};
+ ret = property_get(WCN_DRIVER_READY_PROP, ready_str, NULL);
+ if ((0 >= ret) || (0 == strcmp(ready_str, "yes"))) {
+ ALOGE("get property(%s) failed iRet:%d or property is %s\n",
+ WCN_DRIVER_READY_PROP, ret, ready_str);
+ }
+ /*set it to yes anyway*/
+ sprintf(ready_str, "%s", "yes");
+ ret = property_set(WCN_DRIVER_READY_PROP, ready_str);
+ if (0 != ret) {
+ ALOGE("set property(%s) to %s failed ret:%d\n",
+ WCN_DRIVER_READY_PROP, ready_str, ret);
+ } else
+ ALOGI("set property(%s) to %s succeed\n", WCN_DRIVER_READY_PROP, ready_str);
+
+ return ret;
+}
+#endif
+
+static int insmod(const char *filename, const char *args)
+{
+
+ int ret;
+ int fd;
+ fd = open(filename, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+ if (fd < 0) {
+ ALOGI("insmod: open(\"%s\") failed: %s", filename, strerror(errno));
+ return -1;
+ }
+ ret = syscall(__NR_finit_module, fd, args, 0);
+ if (ret < 0) {
+ ALOGI("finit_module for (\"%s\") failed: %s", filename, strerror(errno));
+ }
+ close(fd);
+ return ret;
+}
+
+
+int load_wifi_bt_module(int chip_id)
+{
+ int ret = -1;
+ struct utsname utsname;
+ char wifi_module_path[100] = "";
+ char wlan_module_path[100] = "";
+ char bt_module_path[100] = "";
+
+ /* Use modules built out of kernel tree */
+ ALOGI("Use modules built out of kernel tree chip id %x \n", chip_id);
+ snprintf(wifi_module_path, sizeof(wifi_module_path), "%s%s", WMT_OUT_KO_PATH_PREFIX, WMT_OUT_WMT_WIFI_MODULE_PATH);
+ if (0x6771 == chip_id) snprintf(wlan_module_path, sizeof(wlan_module_path), "%s%s", WMT_OUT_KO_PATH_PREFIX, WMT_OUT_WLAN_GEN3_MODULE_PATH);
+ else snprintf(wlan_module_path, sizeof(wlan_module_path), "%s%s", WMT_OUT_KO_PATH_PREFIX, WMT_OUT_WLAN_MODULE_PATH);
+ if (0x6771 == chip_id) snprintf(bt_module_path, sizeof(bt_module_path), "%s%s", WMT_OUT_KO_PATH_PREFIX, WMT_OUT_BT_DRV_MODULE_PATH);
+ else snprintf(bt_module_path, sizeof(bt_module_path), "%s%s", WMT_OUT_KO_PATH_PREFIX, WMT_OUT_BT_MODULE_PATH);
+
+ if ((0x8512 == chip_id) || (0x8168 == chip_id) || (0x6771 == chip_id)) {
+ //insert 6631 driver
+ if (0 == insmod(wifi_module_path, DRIVER_MODULE_ARG)) {
+ ret = 0;
+ ALOGI("Success to insmod wmt wifi module\n");
+ } else {
+ ALOGI("Fail to insmod wmt wifi module %s\n", wifi_module_path);
+ return -2;
+ }
+
+ if (0 == insmod(wlan_module_path, DRIVER_MODULE_ARG)) {
+ ret = 0;
+ ALOGI("Success to insmod wlan module\n");
+ } else {
+ ALOGI("Fail to insmod wlan module %s\n", wlan_module_path);
+ return -3;
+ }
+
+ if (0 == insmod(bt_module_path, DRIVER_MODULE_ARG)) {
+ ret = 0;
+ ALOGI("Success to insmod bt module\n");
+ } else {
+ ALOGI("Fail to insmod bt module %s\n", bt_module_path);
+ return -4;
+ }
+ }
+
+
+
+ return ret;
+}
+
+
+int main(int argc, char *argv[]) {
+ int ret = -1;
+ int chip_id = -1;
+ int count = 0;
+ int loadWlanResult = 0;
+ char chipid_str[PROPERTY_VALUE_MAX] = {0};
+ char ready_str[PROPERTY_VALUE_MAX] = {0};
+
+ ALOGV("argc:%d,argv:%s\n", argc, argv[0]);
+
+#if 0
+ ret = property_get(WCN_DRIVER_READY_PROP, ready_str, NULL);
+ if (0 == strcmp(ready_str, "yes")) {
+ ALOGE("WMT driver has been ready.\n");
+ return ret;
+ }
+#endif
+
+ do {
+ g_loader_fd = open(WCN_COMBO_LOADER_DEV, O_RDWR | O_NOCTTY);
+ if (g_loader_fd < 0) {
+ count++;
+ ALOGI("Can't open device node(%s) count(%d)\n", WCN_COMBO_LOADER_DEV, count);
+ usleep(300000);
+ }
+ else
+ break;
+ }while(1);
+
+ /*read from system property*/
+ //ret = property_get(WCN_COMBO_LOADER_CHIP_ID_PROP, chipid_str, NULL);
+ //chip_id = strtoul(chipid_str, NULL, 16);
+ chip_id = get_persist_chip_id(chipid_str, sizeof(chipid_str));
+ ALOGI("chip id from property:%d\n", chip_id);
+ if (-1 != loader_do_chipid_vaild_check(chip_id)) {
+ /*valid chip_id detected*/
+ ALOGI("key:(%s)-value:(%s),chipId:0x%04x,ret(%d)\n",
+ WCN_COMBO_LOADER_CHIP_ID_PROP, chipid_str, chip_id, ret);
+ if (0x6630 == chip_id || 0x6632 == chip_id)
+ loader_do_combo_sdio_autok(g_loader_fd, chip_id);
+ } else {
+ /*trigger external combo chip detect and chip identification process*/
+ loader_do_first_chip_detect(g_loader_fd, &chip_id);
+ }
+
+ /*set chipid to kernel*/
+ ioctl(g_loader_fd, COMBO_IOCTL_SET_CHIP_ID, chip_id);
+
+ if ((0x0321 == chip_id) || (0x0335 == chip_id) || (0x0337 == chip_id))
+ chip_id = 0x6735;
+
+ if (0x0326 == chip_id)
+ chip_id = 0x6755;
+
+ if (0x0551 == chip_id)
+ chip_id = 0x6757;
+
+ if (0x0690 == chip_id)
+ chip_id = 0x6763;
+
+ if (0x0279 == chip_id)
+ chip_id = 0x6797;
+
+ if (0x0507 == chip_id)
+ chip_id = 0x6759;
+
+ if (0x0713 == chip_id)
+ chip_id = 0x6775;
+
+ if (0x0788 == chip_id)
+ chip_id = 0x6771;
+
+ /*how to handling if not all module init fail?*/
+ if (chip_id == -1) {
+ ALOGE("chip id error !!(0x%x)\n", chip_id);
+ return -1;
+ }
+ loader_do_kernel_module_init(g_loader_fd, chip_id);
+ if (g_loader_fd >= 0) {
+ close(g_loader_fd);
+ g_loader_fd = -1;
+ }
+
+
+#if 0
+ if ((chown(WMT_PROC_DBG_PATH, AID_SHELL, AID_SYSTEM) == -1) ||
+ (chown(WMT_PROC_AEE_PATH, AID_SHELL, AID_SYSTEM) == -1))
+ ALOGE("chown wmt_dbg or wmt_aee fail:%s\n", strerror(errno));
+
+ ret = loader_do_driver_ready_set();
+#endif
+
+ set_proc_owner();
+ /*insmod wmt_chrdev_wifi.ko & wlan_gen4m.ko & wmt_cdev_bt.ko*/
+ loadWlanResult = load_wifi_bt_module(chip_id);
+ if (loadWlanResult) {
+ ALOGI("load WIFI_BT modules fail(%d):(%d)\n", loadWlanResult, __LINE__);
+ return loadWlanResult;
+ }
+
+ update_driver_ready();
+
+ return ret;
+}
+
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/configure.ac b/src/connectivity/combo_tool/6631_combo_tool/configure.ac
new file mode 100644
index 0000000..dfe0c2c
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/configure.ac
@@ -0,0 +1,5 @@
+AC_INIT([wmt_loader], [1.0])
+AM_INIT_AUTOMAKE([foreign])
+AC_PROG_CC
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/src/connectivity/combo_tool/6631_combo_tool/launcher-service b/src/connectivity/combo_tool/6631_combo_tool/launcher-service
new file mode 100644
index 0000000..3476241
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/launcher-service
@@ -0,0 +1,64 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: launcher
+# Required-Start: $syslog $local_fs $remote_fs
+# Required-Stop: $syslog $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: 66xx launcher Daemon
+### END INIT INFO
+
+. /etc/init.d/init-functions
+prog=launcher
+PIDFILE=/var/run/$prog.pid
+DESC="66xx launcher Daemon"
+start() {
+ log_daemon_msg "Starting $DESC" "$prog"
+ start_daemon_background -p $PIDFILE /usr/bin/wmt_launcher -p /lib/firmware
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+ exit 0
+}
+
+stop() {
+ log_daemon_msg "Stopping $DESC" "$prog"
+ killproc -p $PIDFILE /usr/bin/wmt_launcher
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+}
+
+force_reload() {
+ stop
+ start
+
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ restart)
+ stop
+ start
+ ;;
+
+ *)
+ echo "$Usage: $prog {start|stop|force-reload|restart}"
+ exit 2
+esac
diff --git a/src/connectivity/combo_tool/6631_combo_tool/launcher.service b/src/connectivity/combo_tool/6631_combo_tool/launcher.service
new file mode 100644
index 0000000..61d54ec
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/launcher.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=66xx launcher Daemon
+After=wmtd.service
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/wmt_launcher -p /lib/firmware > ttyS0
+StandardOutput=tty
+StandardError=tty
+
+[Install]
+Alias=launcherd
+WantedBy=multi-user.target
diff --git a/src/connectivity/combo_tool/6631_combo_tool/launcher_6627.service b/src/connectivity/combo_tool/6631_combo_tool/launcher_6627.service
new file mode 100644
index 0000000..61d54ec
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/launcher_6627.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=66xx launcher Daemon
+After=wmtd.service
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/wmt_launcher -p /lib/firmware > ttyS0
+StandardOutput=tty
+StandardError=tty
+
+[Install]
+Alias=launcherd
+WantedBy=multi-user.target
diff --git a/src/connectivity/combo_tool/6631_combo_tool/mt6631_drv_insmod.sh b/src/connectivity/combo_tool/6631_combo_tool/mt6631_drv_insmod.sh
new file mode 100644
index 0000000..2cd2743
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/mt6631_drv_insmod.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+# insmod wmt driver before wmt_loader starts
+echo insmod wmt driver
+insmod /lib/modules/mt66xx/wmt_drv.ko
+#echo insmod wifi cdev driver
+#insmod /lib/modules/mt66xx/wmt_chrdev_wifi.ko
+#echo insmod wifi driver
+#insmod /lib/modules/mt66xx/wlan_drv_gen4m.ko
+#echo insmod bt driver
+#insmod /lib/modules/mt66xx/wmt_cdev_bt.ko
+
+#wpa_supplicant -Dnl80211 -iwlan0 -c/etc/wpa_supplicant.conf
diff --git a/src/connectivity/combo_tool/6631_combo_tool/mt66xx_drv_insmod-service b/src/connectivity/combo_tool/6631_combo_tool/mt66xx_drv_insmod-service
new file mode 100644
index 0000000..27cfc28
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/mt66xx_drv_insmod-service
@@ -0,0 +1,64 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: mt66xx_drv_insmod
+# Required-Start: $syslog $local_fs
+# Required-Stop: $syslog $local_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: mt66xx_drv_insmod
+### END INIT INFO
+
+. /etc/init.d/init-functions
+prog=mt66xx_drv_insmod
+PIDFILE=/var/run/$prog.pid
+DESC="mt66xx_drv_insmod"
+start() {
+ log_daemon_msg "Starting $DESC" "$prog"
+ start_daemon_background -p $PIDFILE /bin/sh /etc/mt66xx_drv_insmod.sh
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+ exit 0
+}
+
+stop() {
+ log_daemon_msg "Stopping $DESC" "$prog"
+ killproc -p $PIDFILE /bin/sh
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+}
+
+force_reload() {
+ stop
+ start
+
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ restart)
+ stop
+ start
+ ;;
+
+ *)
+ echo "$Usage: $prog {start|stop|force-reload|restart}"
+ exit 2
+esac
diff --git a/src/connectivity/combo_tool/6631_combo_tool/mt66xx_drv_insmod.service b/src/connectivity/combo_tool/6631_combo_tool/mt66xx_drv_insmod.service
new file mode 100644
index 0000000..bfcb919
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/mt66xx_drv_insmod.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=mt66xx_drv_insmod
+After=ubi-data-mnt.service
+
+[Service]
+Type=simple
+ExecStart=/bin/sh /etc/mt66xx_drv_insmod.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/LICENSE b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/MNL.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/MNL.bin
new file mode 100644
index 0000000..0b91cf4
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/MNL.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv1_patch_1_0_hdr.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv1_patch_1_0_hdr.bin
new file mode 100644
index 0000000..9fa29dc
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv1_patch_1_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv1_patch_1_1_hdr.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv1_patch_1_1_hdr.bin
new file mode 100644
index 0000000..179a1cd
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv1_patch_1_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_0.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_0.bin
new file mode 100644
index 0000000..39e50ed
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_0.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_0_hdr.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_0_hdr.bin
new file mode 100644
index 0000000..283b355
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_1.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_1.bin
new file mode 100644
index 0000000..95d8ddd
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_1.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_1_hdr.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_1_hdr.bin
new file mode 100644
index 0000000..3e880b8
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_lm_patch_1_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_patch_1_0_hdr.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_patch_1_0_hdr.bin
new file mode 100644
index 0000000..8efc731
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_patch_1_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_patch_1_1_hdr.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_patch_1_1_hdr.bin
new file mode 100644
index 0000000..733a65f
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv2_patch_1_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv3_patch_1_0_hdr.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv3_patch_1_0_hdr.bin
new file mode 100644
index 0000000..e4318e6
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv3_patch_1_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv3_patch_1_1_hdr.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv3_patch_1_1_hdr.bin
new file mode 100644
index 0000000..70b88c8
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/ROMv3_patch_1_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/mt6630_patch_e3_0_hdr.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/mt6630_patch_e3_0_hdr.bin
new file mode 100644
index 0000000..e44a293
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/mt6630_patch_e3_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/patch_folder/mt6630_patch_e3_1_hdr.bin b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/mt6630_patch_e3_1_hdr.bin
new file mode 100644
index 0000000..5021d09
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/patch_folder/mt6630_patch_e3_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/6631_combo_tool/poweronwifi.service b/src/connectivity/combo_tool/6631_combo_tool/poweronwifi.service
new file mode 100644
index 0000000..db06dce
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/poweronwifi.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=power on wifi Daemon
+After=wmtd.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/usr/bin/power_on_wifi
+
+[Install]
+Alias=pwrwifid
+WantedBy=multi-user.target
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/Android.mk b/src/connectivity/combo_tool/6631_combo_tool/src/Android.mk
new file mode 100644
index 0000000..6454cd2
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/Android.mk
@@ -0,0 +1,148 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+#
+# MediaTek Inc. (C) 2010. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+# Copyright (C) 2008 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.
+
+# Configuration
+BUILD_LAUNCHER := false
+BUILD_WMT_LPBK := false
+BUILD_WMT_CONCURRENCY := false
+BUILD_STP_DUMP := false
+BUILD_FDB := false
+LOCAL_PATH := $(call my-dir)
+NDS32_310_V2J := false
+NDS32_321_V3J := false
+NDS32_410_V3 := false
+
+ifneq ($(filter "CONSYS_6765" "CONSYS_6761",$(MTK_COMBO_CHIP)),)
+ NDS32_410_V3 := true
+endif
+
+ifeq ($(NDS32_310_V2J), true)
+ NDS32_PATH := $(LOCAL_PATH)/fdb/nds32_toolchain/bsp310_v2j
+else ifeq ($(NDS32_321_V3J), true)
+ NDS32_PATH := $(LOCAL_PATH)/fdb/nds32_toolchain/bsp321_v3j
+else ifeq ($(NDS32_410_V3), true)
+ NDS32_PATH := $(LOCAL_PATH)/fdb/nds32_toolchain/bsp410_v3
+else
+ NDS32_PATH := $(LOCAL_PATH)/fdb/nds32_toolchain/bsp410_v3
+endif
+
+#ifneq ($(MTK_COMBO_CHIP), )
+#ifneq ($(MTK_COMBO_CHIP),MT7668)
+BUILD_LAUNCHER := true
+BUILD_WMT_LPBK := true
+BUILD_WMT_CONCURRENCY := true
+BUILD_FDB := true
+
+#ifneq ($(filter MT6620E3,$(MTK_COMBO_CHIP)),)
+ BUILD_STP_DUMP := true
+#endif
+#endif
+#endif
+
+ifeq ($(BUILD_LAUNCHER), true)
+include $(CLEAR_VARS)
+
+$(warning after build launcher)
+LOCAL_SRC_FILES := stp_uart_launcher.c
+LOCAL_MODULE := wmt_launcher
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+LOCAL_INIT_RC := ../init_connectivity.rc
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+include $(MTK_EXECUTABLE)
+endif
+
+ifeq ($(BUILD_WMT_LPBK), true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := wmt_loopback.c
+LOCAL_MODULE := wmt_loopback
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := eng
+include $(MTK_EXECUTABLE)
+endif
+
+
+ifeq ($(BUILD_WMT_CONCURRENCY), true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := wmt_concurrency.c
+LOCAL_MODULE := wmt_concurrency
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := eng
+include $(MTK_EXECUTABLE)
+endif
+
+ifeq ($(BUILD_STP_DUMP), true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ stp_dump/stp_dump.c \
+ stp_dump/eloop.c \
+ stp_dump/os_linux.c
+LOCAL_SHARED_LIBRARIES := libc libcutils liblog
+LOCAL_MODULE := stp_dump3
+LOCAL_MODULE_TAGS := optional
+LOCAL_INIT_RC := ../init_connectivity.rc
+include $(MTK_EXECUTABLE)
+endif
+
+ifeq ($(BUILD_FDB), true)
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -I$(NDS32_PATH)
+LOCAL_SRC_FILES := \
+ fdb/fdb.c \
+ fdb/wmt_if.c
+LOCAL_SHARED_LIBRARIES := libc libcutils liblog
+LOCAL_MODULE := wmt_fdb
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+include $(MTK_EXECUTABLE)
+endif
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/NOTICE b/src/connectivity/combo_tool/6631_combo_tool/src/NOTICE
new file mode 100644
index 0000000..1602dea
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/NOTICE
@@ -0,0 +1,30 @@
+This MediaTek software package contains software with the following notices and under the following licenses:
+
+==============================================================================================================
+
+Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/README b/src/connectivity/combo_tool/6631_combo_tool/src/README
new file mode 100644
index 0000000..5c3e03f
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/README
@@ -0,0 +1,20 @@
+This module serves the common part driver of connectivity
+
+WHAT IT DOES?
+=============
+This module creates four executable binary files for configuring/testing
+the common part driver.
+
+HOW IT WAS BUILT?
+==================
+It needs the following library from AOSP:
+
+libcutils, libc
+
+HOW TO USE IT?
+==============
+The executable binary files will be started in init.rc when boot. they will work together
+with wmt_loader to load/configure the common part driver of connectivity, meanwhile some test
+tool was supplied.
+
+The majority of source code was written by MediaTek. Some code from open source codes are used.
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/power_on_wifi.c b/src/connectivity/combo_tool/6631_combo_tool/src/power_on_wifi.c
new file mode 100644
index 0000000..c913982
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/power_on_wifi.c
@@ -0,0 +1,117 @@
+
+/******************************************************************************
+* C O M P I L E R F L A G S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+*******************************************************************************
+*/
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <unistd.h>
+/*#include <syslog.h>*/
+#include <time.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+
+
+/******************************************************************************
+* C O N S T A N T S
+*******************************************************************************
+*/
+/* !defined(ANDROID) */
+#ifndef ALOGI
+#define ALOGI printf
+#endif
+#ifndef ALOGE
+#define ALOGE printf
+#endif
+#ifndef ALOGD
+#define ALOGD printf
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "6620_launcher"
+
+#if TARGET_PLATFORM == mt2635
+#define CUST_COMBO_WIFI_DEV "/dev/wmtWifi"
+#define POWER_ON_WIFI "AP"
+#define POWER_ON_WIFI_LEN 2
+#else
+#define CUST_COMBO_WIFI_DEV "/dev/wmtWifi"
+#define POWER_ON_WIFI "1"
+#define POWER_ON_WIFI_LEN 1
+#endif
+
+/******************************************************************************
+* D A T A T Y P E S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* M A C R O S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* P U B L I C D A T A
+*******************************************************************************
+*/
+
+/******************************************************************************
+* P R I V A T E D A T A
+*******************************************************************************
+*/
+
+static int gWifiFd = -1;
+
+/******************************************************************************
+* F U N C T I O N S
+*******************************************************************************
+*/
+int main(int argc, char *argv[]) {
+ int retryCounter = 0;
+ int i_ret = -1;
+
+ gWifiFd = open(CUST_COMBO_WIFI_DEV, O_RDWR | O_NOCTTY);
+ do {
+ if (gWifiFd < 0) {
+ ALOGI("Can't open device node(%s) error:%d \n", CUST_COMBO_WIFI_DEV, gWifiFd);
+ usleep(300000);
+ } else {
+ break;
+ }
+ retryCounter++;
+ } while (retryCounter < 20);
+
+ if (gWifiFd > 0) {
+ do {
+ i_ret = write(gWifiFd, POWER_ON_WIFI, POWER_ON_WIFI_LEN);
+ if (i_ret == 1) {
+ ALOGI("Power on device node(%s) gWifiFd:%d succeed !!\n", CUST_COMBO_WIFI_DEV, gWifiFd);
+ break;
+ } else {
+ ALOGI("Power on device node(%s) gWifiFd:%d Fail (%d) and retry\n", CUST_COMBO_WIFI_DEV, gWifiFd, i_ret);
+ }
+ retryCounter++;
+ usleep(1000000);
+ } while (retryCounter < 20);
+ }
+ close(gWifiFd);
+
+ return 0;
+}
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/serial.h b/src/connectivity/combo_tool/6631_combo_tool/src/serial.h
new file mode 100644
index 0000000..4e6b745
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/serial.h
@@ -0,0 +1,79 @@
+/* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2014. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* The following software/firmware and/or related documentation ("MediaTek
+* Software") have been modified by MediaTek Inc. All revisions are subject to
+* any receiver's applicable license agreements with MediaTek Inc.
+*/
+
+#ifndef _LINUX_SERIAL_H
+#define _LINUX_SERIAL_H
+
+struct serial_struct {
+ int type;
+ int line;
+ unsigned int port;
+ int irq;
+ int flags;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int baud_base;
+ unsigned short close_delay;
+ char io_type;
+ char reserved_char[1];
+ int hub6;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned char *iomem_base;
+ unsigned short iomem_reg_shift;
+ unsigned int port_high;
+ unsigned long iomap_base;
+};
+
+#define ASYNCB_HUP_NOTIFY 0
+#define ASYNCB_FOURPORT 1
+#define ASYNCB_SAK 2
+#define ASYNCB_SPLIT_TERMIOS 3
+#define ASYNCB_SPD_HI 4
+#define ASYNCB_SPD_VHI 5
+#define ASYNCB_SKIP_TEST 6
+#define ASYNCB_AUTO_IRQ 7
+#define ASYNCB_SESSION_LOCKOUT 8
+#define ASYNCB_PGRP_LOCKOUT 9
+#define ASYNCB_CALLOUT_NOHUP 10
+#define ASYNCB_HARDPPS_CD 11
+#define ASYNCB_SPD_SHI 12
+#define ASYNCB_LOW_LATENCY 13
+#define ASYNCB_BUGGY_UART 14
+#define ASYNCB_AUTOPROBE 15
+
+#endif /* _LINUX_SERIAL_H */
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/bt_fw_logger.c b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/bt_fw_logger.c
new file mode 100644
index 0000000..e8e4384
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/bt_fw_logger.c
@@ -0,0 +1,590 @@
+/**
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <pthread.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+#define BT_FW_LOG_CTRL_FIFO "/tmp/bt_fwlog_ctrl"
+static int fw_log_ctrl_fd = 0;
+#define FIFO_BUF_SIZE (128)
+
+#define BT_FW_LOG_NODE "/dev/fw_log_bt"
+#define BT_FW_LOG_DEFAULT_PATH "/data/misc/stp_dump"
+
+#define LOG_PATH_LENGTH (128)
+static char fw_log_path[LOG_PATH_LENGTH] = {0};
+#define DUMP_PICUS_NAME_EXT ".picus"
+#define DUMP_PICUS_NAME_PREFIX "dump_"
+#define BT_FW_LOG_DEFAULT_SIZE (10 * 1024 * 1024)
+static uint32_t log_file_size = BT_FW_LOG_DEFAULT_SIZE;
+#define BT_FW_LOG_BUF_SIZE (1024*32) //(1944) // Cover old BT driver return size
+#define LOG_VERSION 0x100
+
+#define TRUE (1)
+#define FALSE (0)
+
+static const unsigned long BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL;
+static unsigned long timestamp = 0;
+static unsigned int dump_file_seq_num = 0;
+static int file_size_remain_to_switch = 0;
+static uint8_t buffer[BT_FW_LOG_BUF_SIZE] = {0};
+static int log_file_num = 6;
+static int logger_on = 1;
+
+static pthread_t bt_fw_logger_thread = 0;
+static int fw_log_fd = 0;
+
+#define BT_STACK_CONF_FILE "/data/misc/bluedroid/bt_stack.conf"
+enum
+{
+ FW_LOG_LEVEL_OFF,
+ FW_LOG_LEVEL_LOW_POWER,
+ FW_LOG_LEVEL_SQC,
+ FW_LOG_LEVEL_FULL, //All log
+ FW_LOG_LEVEL_MAX, //invalid
+};
+
+const char *fw_log_cmd[FW_LOG_LEVEL_MAX] = {
+ "echo raw-hex, 01 5d fc 04 02 00 01 00 > /dev/fw_log_bt",
+ "echo raw-hex, 01 5d fc 04 02 00 01 01 > /dev/fw_log_bt",
+ "echo raw-hex, 01 5d fc 04 02 00 01 02 > /dev/fw_log_bt",
+ "echo raw-hex, 01 5d fc 04 02 00 01 03 > /dev/fw_log_bt"
+};
+
+static char *trim(char *str) {
+ while (isspace(*str))
+ ++str;
+
+ if (!*str)
+ return str;
+
+ char *end_str = str + strlen(str) - 1;
+ while (end_str > str && isspace(*end_str))
+ --end_str;
+
+ end_str[1] = '\0';
+ return str;
+}
+
+static void parse_fwlog_config(void)
+{
+ int line_num = 0;
+ char line[1024];
+
+ printf("[bt_fw_logger]%s\n", __func__);
+
+ FILE *fp = fopen(BT_STACK_CONF_FILE, "rt");
+ if (!fp)
+ {
+ printf("[bt_fw_logger]%s unable to open file '%s': %s\n", __func__, BT_STACK_CONF_FILE, strerror(errno));
+ return;
+ }
+
+ while (fgets(line, sizeof(line), fp))
+ {
+ char *line_ptr = trim(line);
+ ++line_num;
+
+ // Skip blank and comment lines.
+ if (*line_ptr == '\0' || *line_ptr == '#')
+ continue;
+
+ if (line_ptr)
+ {
+ char *split = strchr(line_ptr, '=');
+ if (!split)
+ {
+ printf("[bt_fw_logger]%s no key/value separator found on line %d\n", __func__, line_num);
+ continue;
+ }
+ *split = '\0';
+ if (strcmp(trim(line_ptr), "mt66xx_fwlog_level") == 0) //log level
+ {
+ char *level_str = trim(split + 1);
+ if (level_str)
+ {
+ uint32_t level = atoi(&level_str[0]);
+ if (level < FW_LOG_LEVEL_MAX)
+ {
+ printf("[bt_fw_logger]conf file set fwlog level: %d, set fwlog level to driver!!!\n", level);
+ system(fw_log_cmd[level]);
+ }
+ else
+ printf("[bt_fw_logger]log level in conf file is invalid: %d\n", level);
+ }
+ }
+ else if (strcmp(trim(line_ptr), "mt66xx_fwlog_path") == 0)//log location
+ {
+ char *path_str = trim(split + 1);
+ if (path_str)
+ {
+ struct stat st_buf;
+ stat(path_str, &st_buf);
+ if (S_ISDIR(st_buf.st_mode))
+ {
+ snprintf(fw_log_path, LOG_PATH_LENGTH, "%s", path_str);
+ printf("[bt_fw_logger]conf file set fwlog path: %s\n", fw_log_path);
+ }
+ else
+ {
+ printf("[bt_fw_logger]invalid file path %s or permission denied, errno:%d\n", path_str, errno);
+ }
+ }
+ }
+ else if (strcmp(trim(line_ptr), "mt66xx_fwlog_size") == 0)//single log file size
+ {
+ char *size_str = trim(split + 1);
+ if (size_str)
+ {
+ char *ptr = NULL;
+ uint32_t size = (uint32_t)strtoul(size_str, &ptr, 10);
+ if ((size >= 10240) && (size <= (1024*1024*20)))
+ {
+ log_file_size = size;
+ printf("[bt_fw_logger]conf file set fwlog size: %d\n", log_file_size);
+ }
+ }
+ }
+ else if (strcmp(trim(line_ptr), "mt66xx_fwlog_count") == 0)//log file number
+ {
+ char *count_str = trim(split + 1);
+ if (count_str)
+ {
+ char *ptr = NULL;
+ uint32_t num = (uint32_t)strtoul(count_str, &ptr, 10);
+ if ((num > 0) && (num <= 100))
+ {
+ log_file_num = num;
+ printf("[bt_fw_logger]conf file set fwlog count: %d\n", log_file_num);
+ }
+ }
+ }
+ }
+ }
+
+ printf("[bt_fw_logger]%s end\n", __func__);
+}
+
+static void mv_last_log_files(void)
+{
+ char cmd[256] = {0};
+ char old_picus_log_folder[LOG_PATH_LENGTH] = {0};
+
+ snprintf(old_picus_log_folder, LOG_PATH_LENGTH, "%s/%s", fw_log_path, "picus_last");
+
+ if (0 != mkdir(old_picus_log_folder, 0777)) {
+ if (errno != EEXIST) {
+ printf("[bt_fw_logger]create old picus log folder fail errno %d\n", errno);
+ return;
+ }
+ }
+ memset(cmd, 0, sizeof(cmd));
+ snprintf(cmd, sizeof(cmd), "rm -rf %s/*.picus", old_picus_log_folder);
+ if (0 != system(cmd)) {
+ printf("[bt_fw_logger]delete old old files fail errno %d\n", errno);
+ return;
+ }
+ printf("[bt_fw_logger]delete picus files in %s\n", old_picus_log_folder);
+
+ memset(cmd, 0, sizeof(cmd));
+ snprintf(cmd, sizeof(cmd), "mv %s/*.picus %s/", fw_log_path, old_picus_log_folder);
+ if (0 != system(cmd)) {
+ printf("[bt_fw_logger]move old files fail errno %d\n", errno);
+ return;
+ }
+ system("sync");
+ printf("[bt_fw_logger]move last picus files to %s\n", old_picus_log_folder);
+}
+
+static void remove_old_log_files(char *log_path, int all, int index)
+{
+ /* check already exist file under log_path */
+ char temp_picus_filename[36] = {0};
+ char picus_fullname[256] = {0};
+
+ DIR *p_dir = opendir(log_path);
+ if (p_dir != NULL)
+ {
+ struct dirent *p_file;
+ while ((p_file = readdir(p_dir)) != NULL)
+ {
+ /* ignore . and .. directory */
+ if (strncmp(p_file->d_name, "..", 2) == 0
+ || strncmp(p_file->d_name, ".", 1) == 0)
+ {
+ continue;
+ }
+ memset(temp_picus_filename, 0, sizeof(temp_picus_filename));
+ memset(picus_fullname, 0, sizeof(picus_fullname));
+ if (strstr(p_file->d_name, DUMP_PICUS_NAME_EXT) != NULL)
+ {
+ if (all) //remove all old log files
+ {
+ snprintf(picus_fullname, sizeof(picus_fullname), "%s/%s", log_path, p_file->d_name);
+ if (remove(picus_fullname)) {
+ printf("[bt_fw_logger]The old log:%s can't remove, errno: %d\n", p_file->d_name, errno);
+ }
+ else {
+ printf("[bt_fw_logger]The old log: %s is removed\n", p_file->d_name);
+ }
+ }
+ else //remove a specific log file
+ {
+ snprintf(temp_picus_filename, sizeof(temp_picus_filename), "_%d.picus", index);
+ if (strstr(p_file->d_name, temp_picus_filename) != NULL) {
+ snprintf(picus_fullname, sizeof(picus_fullname), "%s/%s", log_path, p_file->d_name);
+ if (remove(picus_fullname)) {
+ printf("[bt_fw_logger]The old log: %s can't remove, errno: %d\n", p_file->d_name, errno);
+ } else {
+ printf("[bt_fw_logger]The old log: %s is removed\n", p_file->d_name);
+ }
+ }
+ }
+ }
+ }
+ closedir(p_dir);
+ }
+ else
+ {
+ printf("[bt_fw_logger]readdir fail, errno: %d\n", errno);
+ }
+}
+
+static unsigned long btsnoop_timestamp(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ // Timestamp is in microseconds.
+ timestamp = tv.tv_sec * 1000000ULL;
+ timestamp += tv.tv_usec;
+ timestamp += BTSNOOP_EPOCH_DELTA;
+ return timestamp;
+}
+
+static void fillheader(unsigned char *header, int headerlen,
+ unsigned short int dump_file_seq_num)
+{
+ int copy_header_len = 0;
+ unsigned int logversion = htobe32(LOG_VERSION);
+ memset(header, 0, headerlen);
+ memcpy(header, &logversion, sizeof(logversion));
+ copy_header_len += 4; /** 4 byte for logversion */
+ copy_header_len += 4; /** 4 byte for chip id, not implement yet */
+ dump_file_seq_num = htobe16(dump_file_seq_num);
+ memcpy(header + copy_header_len, &dump_file_seq_num, sizeof(dump_file_seq_num));
+ copy_header_len += 2; /** 2 byte for sequence number */
+ copy_header_len += 6; /** first hci log length(2), zero(4) */
+ btsnoop_timestamp();
+ timestamp = htobe64(timestamp);
+ memcpy(header + copy_header_len, ×tamp, sizeof(timestamp));
+}
+
+static FILE * create_new_log_file(int index)
+{
+ time_t local_timestamp;
+ char timestamp_buffer[24];
+ char dump_file_name[128] = {0};
+ unsigned char header[24] = {0};
+ unsigned char padding[8] = {0};
+ FILE *fp = NULL;
+
+ /* get current timestamp */
+ time(&local_timestamp);
+ strftime(timestamp_buffer, 24, "%Y%m%d%H%M%S", localtime(&local_timestamp));
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/" DUMP_PICUS_NAME_PREFIX "%s_%d" DUMP_PICUS_NAME_EXT, fw_log_path, timestamp_buffer, index);
+
+ /* dump file for picus log */
+ if ((fp = fopen(dump_file_name, "wb")) == NULL) {
+ printf("[bt_fw_logger]create log file %s fail [%s] errno %d\n", dump_file_name, strerror(errno), errno);
+ return NULL;
+ } else {
+ printf("[bt_fw_logger]log file %s is created, dumping...\n", dump_file_name);
+ }
+
+ fillheader(header, sizeof(header), index);
+ fwrite(header, 1, sizeof(header), fp);
+ fwrite(padding, 1, sizeof(padding), fp);
+ file_size_remain_to_switch = log_file_size;
+
+ return fp;
+}
+
+static void *bt_fw_logger_main(void *arg)
+{
+ int nRead = 0;
+ int nWritten = 0;
+ fd_set rset; /** For select */
+ struct timeval tv;
+ FILE *current_fp = NULL;
+ int current_index = 0;
+ int i_ret = 0;
+
+ printf("[bt_fw_logger]%s, thread_id: 0x%x\n", __func__, pthread_self());
+
+ //create log ctrl fifo
+ i_ret = access(BT_FW_LOG_CTRL_FIFO, F_OK);
+ if (i_ret != 0)
+ {
+ i_ret = mkfifo(BT_FW_LOG_CTRL_FIFO, 0777);
+ if (i_ret < 0)
+ printf("mkfifo %s fail, errno: %d\n", BT_FW_LOG_CTRL_FIFO, errno);
+ else
+ printf("mkfifo %s success\n", BT_FW_LOG_CTRL_FIFO);
+ }
+
+ parse_fwlog_config();
+
+ do
+ {
+ int max_fd = fw_log_fd;
+
+ if ((fw_log_ctrl_fd = open(BT_FW_LOG_CTRL_FIFO, O_RDWR|O_NONBLOCK)) < 0)
+ {
+ printf("open fifo %s fail, errno: %d\n", BT_FW_LOG_CTRL_FIFO, errno);
+ }
+ FD_ZERO(&rset);
+ FD_SET(fw_log_fd, &rset);
+ if (fw_log_ctrl_fd > 0)
+ {
+ FD_SET(fw_log_ctrl_fd, &rset);
+ max_fd = (fw_log_ctrl_fd > fw_log_fd) ? fw_log_ctrl_fd : fw_log_fd;
+ }
+ tv.tv_sec = 10; /* timeout is 10s for select method */
+ tv.tv_usec = 0;
+ if (select(max_fd + 1, &rset, NULL, NULL, NULL) == 0) {
+ printf("[bt_fw_logger]Read data timeout(10s) from fw_log_bt\n");
+ if (fw_log_ctrl_fd > 0) close(fw_log_ctrl_fd);
+ continue;
+ }
+
+ if (fw_log_ctrl_fd > 0)
+ {
+ if (FD_ISSET(fw_log_ctrl_fd, &rset)) //parse log ctrl event
+ {
+ int res = 0;
+ char fifo_buf[FIFO_BUF_SIZE] = {0};
+
+ memset(fifo_buf, 0, FIFO_BUF_SIZE);
+ res = read(fw_log_ctrl_fd, fifo_buf, FIFO_BUF_SIZE);
+ printf("read %d byte from fw_log_ctrl_fd, fifo_buf: %s\n", res, fifo_buf);
+ if (NULL != strstr(fifo_buf, "log_path")) //change log location
+ {
+ struct stat st_buf;
+ fifo_buf[res-1] = '\0'; //replace the \n to \0
+ stat(fifo_buf+9, &st_buf);
+ if (S_ISDIR(st_buf.st_mode))
+ {
+ snprintf(fw_log_path, LOG_PATH_LENGTH, "%s", fifo_buf+9);
+ printf("[bt_fw_logger]change log path to %s\n", fw_log_path);
+ //close current log file in the current location, and create log file with index 0 in new location
+ if (current_fp > 0)
+ {
+ fflush(current_fp);
+ fclose(current_fp);
+ current_fp = 0;
+ }
+ }
+ else
+ {
+ printf("[bt_fw_logger]invalid file path %s or permission denied, errno:%d\n", fifo_buf+9, errno);
+ }
+ }
+ else if (NULL != strstr(fifo_buf, "log_size")) //change single log file size
+ {
+ char *ptr = NULL;
+ uint32_t size = (uint32_t)strtoul(fifo_buf+9, &ptr, 10);
+ if ((size >= 10240) && (size <= (1024*1024*20)))
+ {
+ if (size > log_file_size)
+ file_size_remain_to_switch += (size - log_file_size);
+ else
+ file_size_remain_to_switch = 0;
+ log_file_size = size;
+ printf("[bt_fw_logger]change log_file_size to %d\n", log_file_size);
+ }
+ }
+ else if (NULL != strstr(fifo_buf, "log_count")) //change log file count
+ {
+ char *ptr = NULL;
+ uint32_t num = (uint32_t)strtoul(fifo_buf+10, &ptr, 10);
+ if ((num > 0) && (num <= 100))
+ {
+ log_file_num = num;
+ printf("[bt_fw_logger]change log_file_num to %d\n", log_file_num);
+ }
+ }
+ }
+ }
+
+ if (fw_log_ctrl_fd > 0) close(fw_log_ctrl_fd);
+
+ if (!FD_ISSET(fw_log_fd, &rset))
+ continue;
+
+ if (current_fp == 0)
+ {
+ mv_last_log_files(); // move old log to a folder
+ current_fp = create_new_log_file(0);
+ if (NULL == current_fp)
+ {
+ printf("[bt_fw_logger]fatal error: create new log file fail\n");
+ return NULL;
+ }
+ }
+ /* Read all packet from driver fwlog queue */
+ nRead = read(fw_log_fd, buffer, sizeof(buffer));
+ if (nRead > 0)
+ {
+ nWritten = fwrite(buffer, 1, nRead, current_fp);
+ if (nWritten != nRead)
+ {
+ printf("[bt_fw_logger]write may fail, nRead(%d) != nWritten(%d)\n", nRead, nWritten);
+ }
+ file_size_remain_to_switch -= nWritten;
+ }
+ else if (nRead < 0)
+ {
+ printf("[bt_fw_logger]read fail, errno=%d\n", errno);
+ continue;
+ }
+ /* switch file name if file size is over file_size */
+ if (file_size_remain_to_switch <= 0) {
+ file_size_remain_to_switch = log_file_size;
+ fclose(current_fp);
+ if (log_file_num - 1 > current_index) {
+ current_index++;
+ } else {
+ current_index = 0;
+ }
+ if (current_index == 1) { // if the old picus log is not pulled, it will be lost
+ char old_picus_log_folder[LOG_PATH_LENGTH] = {0};
+ snprintf(old_picus_log_folder, LOG_PATH_LENGTH, "%s/%s", fw_log_path, "picus_last");
+ remove_old_log_files(old_picus_log_folder, TRUE, 0);
+ }
+ /* remove the file before creating */
+ remove_old_log_files(fw_log_path, FALSE, current_index);
+ current_fp = create_new_log_file(current_index);
+ if (NULL == current_fp)
+ {
+ printf("[bt_fw_logger]create new log file fail\n");
+ //TODO
+ return NULL;
+ }
+ }
+ fflush(current_fp);
+ usleep(50000);
+ } while (logger_on);
+
+
+ printf("[bt_fw_logger]%s exit, thread_id: 0x%x\n", __func__, pthread_self());
+
+ return NULL;
+}
+
+
+void bt_fw_logger_start(void)
+{
+ uint16_t index = 0;
+ printf("[bt_fw_logger]%s\n", __func__);
+ if (fw_log_fd > 0)
+ {
+ printf("%s, device is already opened\n", __func__);
+ return;
+ }
+ //1. open device
+ do
+ {
+ fw_log_fd = open(BT_FW_LOG_NODE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ if (fw_log_fd <= 0) {
+ printf("[bt_fw_logger]Can't open device node %s, errno: %d\n", BT_FW_LOG_NODE, errno);
+ sleep(1);
+ } else {
+ printf("[bt_fw_logger]Open device node successfully fw_log_fd = %d, index=%d\n", fw_log_fd, index);
+ break;
+ }
+ if(index == 200)
+ {
+ printf("[bt_fw_logger]Can't open device node with 200 times retry\n");
+ return;
+ }
+ }while (index++ < 200);
+
+ //set default file path
+ snprintf(fw_log_path, LOG_PATH_LENGTH, "%s", BT_FW_LOG_DEFAULT_PATH);
+
+ //2. create logger thread
+ if (bt_fw_logger_thread == 0)
+ {
+ pthread_attr_t thread_attr;
+
+ pthread_attr_init(&thread_attr);
+ pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
+ if (pthread_create(&bt_fw_logger_thread, &thread_attr, bt_fw_logger_main, NULL))
+ {
+ printf("[bt_fw_logger]create logger thread fail\n",__func__);
+ bt_fw_logger_thread = 0;
+ return;
+ }
+ pthread_attr_destroy(&thread_attr);
+ }
+}
+
+void bt_fw_logger_stop(void)
+{
+ //disable fw log first
+ system("echo raw-hex, 01 5d fc 04 02 00 01 00 > /dev/fw_log_bt");
+
+ if (fw_log_fd > 0)
+ {
+ close(fw_log_fd);
+ }
+
+ //thread exit
+ logger_on = 0;
+ bt_fw_logger_thread = 0;
+ printf("[bt_fw_logger]%s\n", __func__);
+
+}
+//---------------------------------------------------------------------------
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/bt_fw_logger.h b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/bt_fw_logger.h
new file mode 100644
index 0000000..8a0e731
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/bt_fw_logger.h
@@ -0,0 +1,40 @@
+/**
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+void bt_fw_logger_start(void);
+void bt_fw_logger_stop(void);
+
+
+//---------------------------------------------------------------------------
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/eloop.c b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/eloop.c
new file mode 100644
index 0000000..c9be496
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/eloop.c
@@ -0,0 +1,653 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ */
+
+/*
+ * Event loop based on select() loop
+ * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include <sys/stat.h>
+#include <grp.h>
+#include <stddef.h>
+//#include <cutils/sockets.h>
+//#include <android/log.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <dirent.h>
+//#include <cutils/properties.h>
+#include <sys/un.h>
+#include <dirent.h>
+#include <linux/limits.h>
+//#include <cutils/sockets.h>
+//#include <cutils/memory.h>
+
+#include "os_linux.h"
+#include "stp_dump.h"
+#include "eloop.h"
+
+struct eloop_sock {
+ int sock;
+ void *eloop_data;
+ void *user_data;
+ eloop_sock_handler handler;
+};
+
+struct eloop_timeout {
+ struct os_time time;
+ void *eloop_data;
+ void *user_data;
+ eloop_timeout_handler handler;
+ struct eloop_timeout *next;
+};
+
+struct eloop_signal {
+ int sig;
+ void *user_data;
+ eloop_signal_handler handler;
+ int signaled;
+};
+
+struct eloop_sock_table {
+ int count;
+ struct eloop_sock *table;
+ int changed;
+};
+
+struct eloop_data {
+ void *user_data;
+
+ int max_sock;
+
+ struct eloop_sock_table readers;
+ struct eloop_sock_table writers;
+ struct eloop_sock_table exceptions;
+
+ struct eloop_timeout *timeout;
+
+ int signal_count;
+ struct eloop_signal *signals;
+ int signaled;
+ int pending_terminate;
+
+ int terminate;
+ int reader_table_changed;
+};
+
+static struct eloop_data eloop;
+
+
+int eloop_init(void *user_data)
+{
+ os_memset(&eloop, 0, sizeof(eloop));
+ eloop.user_data = user_data;
+ return 0;
+}
+
+
+static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
+ int sock, eloop_sock_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_sock *tmp;
+
+ if (table == NULL)
+ {
+ stp_printf(MSG_INFO, "table = NULL\n");
+ return -1;
+ }
+ tmp = (struct eloop_sock *)
+ os_realloc(table->table,
+ (table->count + 1) * sizeof(struct eloop_sock));
+ if (tmp == NULL)
+ {
+ stp_printf(MSG_INFO, "memory allocation for eloop_sock failed\n");
+ return -1;
+ }
+ tmp[table->count].sock = sock;
+ tmp[table->count].eloop_data = eloop_data;
+ tmp[table->count].user_data = user_data;
+ tmp[table->count].handler = handler;
+ table->count++;
+ table->table = tmp;
+ if (sock > eloop.max_sock)
+ {
+ eloop.max_sock = sock;
+ stp_printf(MSG_INFO, "set sock number to %d\n", eloop.max_sock);
+ }
+ table->changed = 1;
+
+ return 0;
+}
+
+
+static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
+ int sock)
+{
+ int i;
+
+ if (table == NULL || table->table == NULL || table->count == 0)
+ return;
+
+ for (i = 0; i < table->count; i++) {
+ if (table->table[i].sock == sock)
+ break;
+ }
+ if (i == table->count)
+ return;
+ if (i != table->count - 1) {
+ os_memmove(&table->table[i], &table->table[i + 1],
+ (table->count - i - 1) *
+ sizeof(struct eloop_sock));
+ }
+ table->count--;
+ table->changed = 1;
+}
+
+
+static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
+ fd_set *fds)
+{
+ int i;
+
+ FD_ZERO(fds);
+
+ if (table->table == NULL)
+ return;
+
+ for (i = 0; i < table->count; i++)
+ FD_SET(table->table[i].sock, fds);
+}
+
+
+static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
+ fd_set *fds)
+{
+ int i;
+
+ if (table == NULL || table->table == NULL)
+ {
+ /*stp_printf(MSG_ERROR, "table == NULL || table->table == NULL\n");*/
+ return;
+ }
+ table->changed = 0;
+ for (i = 0; i < table->count; i++) {
+ if (FD_ISSET(table->table[i].sock, fds)) {
+ table->table[i].handler(table->table[i].sock,
+ table->table[i].eloop_data,
+ table->table[i].user_data);
+ if (table->changed)
+ break;
+ }
+ }
+}
+
+
+static void eloop_sock_table_destroy(struct eloop_sock_table *table)
+{
+ if (table) {
+ int i;
+ for (i = 0; i < table->count && table->table; i++) {
+ printf("ELOOP: remaining socket: sock=%d "
+ "eloop_data=%p user_data=%p handler=%p\n",
+ table->table[i].sock,
+ table->table[i].eloop_data,
+ table->table[i].user_data,
+ table->table[i].handler);
+ }
+ os_free(table->table);
+ }
+}
+
+
+int eloop_register_read_sock(int sock, eloop_sock_handler handler,
+ void *eloop_data, void *user_data)
+{
+ return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
+ eloop_data, user_data);
+}
+
+
+void eloop_unregister_read_sock(int sock)
+{
+ eloop_unregister_sock(sock, EVENT_TYPE_READ);
+}
+
+
+static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
+{
+ switch (type) {
+ case EVENT_TYPE_READ:
+ return &eloop.readers;
+ case EVENT_TYPE_WRITE:
+ return &eloop.writers;
+ case EVENT_TYPE_EXCEPTION:
+ return &eloop.exceptions;
+ }
+ stp_printf(MSG_ERROR, "tyep (%d) error\n", type);
+ return NULL;
+}
+
+
+int eloop_register_sock(int sock, eloop_event_type type,
+ eloop_sock_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_sock_table *table;
+
+ table = eloop_get_sock_table(type);
+ return eloop_sock_table_add_sock(table, sock, handler,
+ eloop_data, user_data);
+}
+
+
+void eloop_unregister_sock(int sock, eloop_event_type type)
+{
+ struct eloop_sock_table *table;
+
+ table = eloop_get_sock_table(type);
+ eloop_sock_table_remove_sock(table, sock);
+}
+
+
+int eloop_register_timeout(unsigned int secs, unsigned int usecs,
+ eloop_timeout_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_timeout *timeout, *tmp, *prev;
+
+ timeout = os_malloc(sizeof(*timeout));
+ if (timeout == NULL)
+ return -1;
+ if (os_get_time(&timeout->time) < 0) {
+ os_free(timeout);
+ return -1;
+ }
+ timeout->time.sec += secs;
+ timeout->time.usec += usecs;
+ while (timeout->time.usec >= 1000000) {
+ timeout->time.sec++;
+ timeout->time.usec -= 1000000;
+ }
+ timeout->eloop_data = eloop_data;
+ timeout->user_data = user_data;
+ timeout->handler = handler;
+ timeout->next = NULL;
+
+ if (eloop.timeout == NULL) {
+ eloop.timeout = timeout;
+ return 0;
+ }
+
+ prev = NULL;
+ tmp = eloop.timeout;
+ while (tmp != NULL) {
+ if (os_time_before(&timeout->time, &tmp->time))
+ break;
+ prev = tmp;
+ tmp = tmp->next;
+ }
+
+ if (prev == NULL) {
+ timeout->next = eloop.timeout;
+ eloop.timeout = timeout;
+ } else {
+ timeout->next = prev->next;
+ prev->next = timeout;
+ }
+
+ return 0;
+}
+
+
+int eloop_cancel_timeout(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_timeout *timeout, *prev, *next;
+ int removed = 0;
+
+ prev = NULL;
+ timeout = eloop.timeout;
+ while (timeout != NULL) {
+ next = timeout->next;
+
+ if (timeout->handler == handler &&
+ (timeout->eloop_data == eloop_data ||
+ eloop_data == ELOOP_ALL_CTX) &&
+ (timeout->user_data == user_data ||
+ user_data == ELOOP_ALL_CTX)) {
+ if (prev == NULL)
+ eloop.timeout = next;
+ else
+ prev->next = next;
+ os_free(timeout);
+ removed++;
+ } else
+ prev = timeout;
+
+ timeout = next;
+ }
+
+ return removed;
+}
+
+
+int eloop_is_timeout_registered(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_timeout *tmp;
+
+ tmp = eloop.timeout;
+ while (tmp != NULL) {
+ if (tmp->handler == handler &&
+ tmp->eloop_data == eloop_data &&
+ tmp->user_data == user_data)
+ return 1;
+
+ tmp = tmp->next;
+ }
+
+ return 0;
+}
+
+
+#ifndef CONFIG_NATIVE_WINDOWS
+static void eloop_handle_alarm(__attribute__((unused))int sig)
+{
+ fprintf(stderr, "eloop: could not process SIGINT or SIGTERM in two "
+ "seconds. Looks like there\n"
+ "is a bug that ends up in a busy loop that "
+ "prevents clean shutdown.\n"
+ "Killing program forcefully.\n");
+ exit(1);
+}
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+
+static void eloop_handle_signal(int sig)
+{
+ int i;
+
+#ifndef CONFIG_NATIVE_WINDOWS
+ if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
+ /* Use SIGALRM to break out from potential busy loops that
+ * would not allow the program to be killed. */
+ eloop.pending_terminate = 1;
+ signal(SIGALRM, eloop_handle_alarm);
+ alarm(2);
+ }
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+ eloop.signaled++;
+ for (i = 0; i < eloop.signal_count; i++) {
+ if (eloop.signals[i].sig == sig) {
+ eloop.signals[i].signaled++;
+ break;
+ }
+ }
+}
+
+
+static void eloop_process_pending_signals(void)
+{
+ int i;
+
+ if (eloop.signaled == 0)
+ return;
+ eloop.signaled = 0;
+
+ if (eloop.pending_terminate) {
+#ifndef CONFIG_NATIVE_WINDOWS
+ alarm(0);
+#endif /* CONFIG_NATIVE_WINDOWS */
+ eloop.pending_terminate = 0;
+ }
+
+ for (i = 0; i < eloop.signal_count; i++) {
+ if (eloop.signals[i].signaled) {
+ eloop.signals[i].signaled = 0;
+ eloop.signals[i].handler(eloop.signals[i].sig,
+ eloop.user_data,
+ eloop.signals[i].user_data);
+ }
+ }
+}
+
+
+int eloop_register_signal(int sig, eloop_signal_handler handler,
+ void *user_data)
+{
+ struct eloop_signal *tmp;
+
+ tmp = (struct eloop_signal *)
+ os_realloc(eloop.signals,
+ (eloop.signal_count + 1) *
+ sizeof(struct eloop_signal));
+ if (tmp == NULL)
+ return -1;
+
+ tmp[eloop.signal_count].sig = sig;
+ tmp[eloop.signal_count].user_data = user_data;
+ tmp[eloop.signal_count].handler = handler;
+ tmp[eloop.signal_count].signaled = 0;
+ eloop.signal_count++;
+ eloop.signals = tmp;
+ signal(sig, eloop_handle_signal);
+
+ return 0;
+}
+
+
+int eloop_register_signal_terminate(eloop_signal_handler handler,
+ void *user_data)
+{
+ int ret = eloop_register_signal(SIGINT, handler, user_data);
+ if (ret == 0)
+ ret = eloop_register_signal(SIGTERM, handler, user_data);
+ if (ret == 0)
+ ret = eloop_register_signal(SIGSEGV, handler, user_data);
+ return ret;
+}
+
+
+int eloop_register_signal_reconfig(eloop_signal_handler handler,
+ void *user_data)
+{
+#ifdef CONFIG_NATIVE_WINDOWS
+ return 0;
+#else /* CONFIG_NATIVE_WINDOWS */
+ return eloop_register_signal(SIGHUP, handler, user_data);
+#endif /* CONFIG_NATIVE_WINDOWS */
+}
+
+
+void eloop_run(void)
+{
+ fd_set *rfds, *wfds, *efds;
+ int res;
+ struct timeval _tv;
+ struct os_time tv, now;
+
+ rfds = os_malloc(sizeof(*rfds));
+ wfds = os_malloc(sizeof(*wfds));
+ efds = os_malloc(sizeof(*efds));
+ if (rfds == NULL || wfds == NULL || efds == NULL) {
+ stp_printf(MSG_ERROR, "eloop_run - malloc failed\n");
+ goto out;
+ }
+
+ while (!eloop.terminate &&
+ (eloop.timeout || eloop.readers.count > 0 ||
+ eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
+ if (eloop.timeout) {
+ os_get_time(&now);
+ if (os_time_before(&now, &eloop.timeout->time))
+ os_time_sub(&eloop.timeout->time, &now, &tv);
+ else
+ tv.sec = tv.usec = 0;
+#if 1
+ printf("next timeout in %lu.%06lu sec\n",
+ tv.sec, tv.usec);
+#endif
+ _tv.tv_sec = tv.sec;
+ _tv.tv_usec = tv.usec;
+ }
+
+ eloop_sock_table_set_fds(&eloop.readers, rfds);
+ eloop_sock_table_set_fds(&eloop.writers, wfds);
+ eloop_sock_table_set_fds(&eloop.exceptions, efds);
+ res = select(eloop.max_sock + 1, rfds, wfds, efds,
+ eloop.timeout ? &_tv : NULL);
+ if (res < 0 && errno != EINTR && errno != 0) {
+ perror("select");
+ stp_printf(MSG_ERROR, "select on socket failed\n");
+ goto out;
+ }
+ eloop_process_pending_signals();
+
+ /* check if some registered timeouts have occurred */
+ if (eloop.timeout) {
+ struct eloop_timeout *tmp;
+
+ os_get_time(&now);
+ if (!os_time_before(&now, &eloop.timeout->time)) {
+ tmp = eloop.timeout;
+ eloop.timeout = eloop.timeout->next;
+ tmp->handler(tmp->eloop_data,
+ tmp->user_data);
+ os_free(tmp);
+ }
+
+ }
+
+ if (res <= 0)
+ continue;
+
+ eloop_sock_table_dispatch(&eloop.readers, rfds);
+ eloop_sock_table_dispatch(&eloop.writers, wfds);
+ eloop_sock_table_dispatch(&eloop.exceptions, efds);
+ }
+
+out:
+ stp_printf(MSG_INFO, "eloop_run exit\n");
+ os_free(rfds);
+ os_free(wfds);
+ os_free(efds);
+}
+
+
+void eloop_terminate(void)
+{
+ eloop.terminate = 1;
+}
+
+
+void eloop_destroy(void)
+{
+ struct eloop_timeout *timeout, *prev;
+ struct os_time now;
+
+ timeout = eloop.timeout;
+ if (timeout)
+ os_get_time(&now);
+ while (timeout != NULL) {
+ int sec, usec;
+ prev = timeout;
+ timeout = timeout->next;
+ sec = prev->time.sec - now.sec;
+ usec = prev->time.usec - now.usec;
+ if (prev->time.usec < now.usec) {
+ sec--;
+ usec += 1000000;
+ }
+ printf("ELOOP: remaining timeout: %d.%06d eloop_data=%p "
+ "user_data=%p handler=%p\n",
+ sec, usec, prev->eloop_data, prev->user_data,
+ prev->handler);
+ os_free(prev);
+ }
+ eloop_sock_table_destroy(&eloop.readers);
+ eloop_sock_table_destroy(&eloop.writers);
+ eloop_sock_table_destroy(&eloop.exceptions);
+ os_free(eloop.signals);
+}
+
+
+int eloop_terminated(void)
+{
+ return eloop.terminate;
+}
+
+
+void eloop_wait_for_read_sock(int sock)
+{
+ fd_set rfds;
+ int res;
+
+ if (sock < 0)
+ return;
+
+ FD_ZERO(&rfds);
+ FD_SET(sock, &rfds);
+ res = select(sock + 1, &rfds, NULL, NULL, NULL);
+ if (res < 0) {
+ stp_printf(MSG_ERROR, "select on socket failed\n");
+ }
+}
+
+
+void * eloop_get_user_data(void)
+{
+ return eloop.user_data;
+}
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/eloop.h b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/eloop.h
new file mode 100644
index 0000000..333ee08
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/eloop.h
@@ -0,0 +1,375 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ */
+
+/*
+ * Event loop
+ * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ *
+ * This file defines an event loop interface that supports processing events
+ * from registered timeouts (i.e., do something after N seconds), sockets
+ * (e.g., a new packet available for reading), and signals. eloop.c is an
+ * implementation of this interface using select() and sockets. This is
+ * suitable for most UNIX/POSIX systems. When porting to other operating
+ * systems, it may be necessary to replace that implementation with OS specific
+ * mechanisms.
+ */
+
+#ifndef ELOOP_H
+#define ELOOP_H
+
+/**
+ * ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts
+ */
+#define ELOOP_ALL_CTX (void *) -1
+
+/**
+ * eloop_event_type - eloop socket event type for eloop_register_sock()
+ * @EVENT_TYPE_READ: Socket has data available for reading
+ * @EVENT_TYPE_WRITE: Socket has room for new data to be written
+ * @EVENT_TYPE_EXCEPTION: An exception has been reported
+ */
+typedef enum {
+ EVENT_TYPE_READ = 0,
+ EVENT_TYPE_WRITE,
+ EVENT_TYPE_EXCEPTION
+} eloop_event_type;
+
+
+
+
+
+/**
+ * eloop_sock_handler - eloop socket event callback type
+ * @sock: File descriptor number for the socket
+ * @eloop_ctx: Registered callback context data (eloop_data)
+ * @sock_ctx: Registered callback context data (user_data)
+ */
+typedef void (*eloop_sock_handler)(int sock, void *eloop_ctx, void *sock_ctx);
+
+/**
+ * eloop_event_handler - eloop generic event callback type
+ * @eloop_ctx: Registered callback context data (eloop_data)
+ * @sock_ctx: Registered callback context data (user_data)
+ */
+typedef void (*eloop_event_handler)(void *eloop_data, void *user_ctx);
+
+/**
+ * eloop_timeout_handler - eloop timeout event callback type
+ * @eloop_ctx: Registered callback context data (eloop_data)
+ * @sock_ctx: Registered callback context data (user_data)
+ */
+typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx);
+
+/**
+ * eloop_signal_handler - eloop signal event callback type
+ * @sig: Signal number
+ * @eloop_ctx: Registered callback context data (global user_data from
+ * eloop_init() call)
+ * @signal_ctx: Registered callback context data (user_data from
+ * eloop_register_signal(), eloop_register_signal_terminate(), or
+ * eloop_register_signal_reconfig() call)
+ */
+typedef void (*eloop_signal_handler)(int sig, void *eloop_ctx,
+ void *signal_ctx);
+
+/**
+ * eloop_init() - Initialize global event loop data
+ * @user_data: Pointer to global data passed as eloop_ctx to signal handlers
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function must be called before any other eloop_* function. user_data
+ * can be used to configure a global (to the process) pointer that will be
+ * passed as eloop_ctx parameter to signal handlers.
+ */
+int eloop_init(void *user_data);
+
+/**
+ * eloop_register_read_sock - Register handler for read events
+ * @sock: File descriptor number for the socket
+ * @handler: Callback function to be called when data is available for reading
+ * @eloop_data: Callback context data (eloop_ctx)
+ * @user_data: Callback context data (sock_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a read socket notifier for the given file descriptor. The handler
+ * function will be called whenever data is available for reading from the
+ * socket. The handler function is responsible for clearing the event after
+ * having processed it in order to avoid eloop from calling the handler again
+ * for the same event.
+ */
+int eloop_register_read_sock(int sock, eloop_sock_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_unregister_read_sock - Unregister handler for read events
+ * @sock: File descriptor number for the socket
+ *
+ * Unregister a read socket notifier that was previously registered with
+ * eloop_register_read_sock().
+ */
+void eloop_unregister_read_sock(int sock);
+
+/**
+ * eloop_register_sock - Register handler for socket events
+ * @sock: File descriptor number for the socket
+ * @type: Type of event to wait for
+ * @handler: Callback function to be called when the event is triggered
+ * @eloop_data: Callback context data (eloop_ctx)
+ * @user_data: Callback context data (sock_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register an event notifier for the given socket's file descriptor. The
+ * handler function will be called whenever the that event is triggered for the
+ * socket. The handler function is responsible for clearing the event after
+ * having processed it in order to avoid eloop from calling the handler again
+ * for the same event.
+ */
+int eloop_register_sock(int sock, eloop_event_type type,
+ eloop_sock_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_unregister_sock - Unregister handler for socket events
+ * @sock: File descriptor number for the socket
+ * @type: Type of event for which sock was registered
+ *
+ * Unregister a socket event notifier that was previously registered with
+ * eloop_register_sock().
+ */
+void eloop_unregister_sock(int sock, eloop_event_type type);
+
+/**
+ * eloop_register_event - Register handler for generic events
+ * @event: Event to wait (eloop implementation specific)
+ * @event_size: Size of event data
+ * @handler: Callback function to be called when event is triggered
+ * @eloop_data: Callback context data (eloop_data)
+ * @user_data: Callback context data (user_data)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register an event handler for the given event. This function is used to
+ * register eloop implementation specific events which are mainly targetted for
+ * operating system specific code (driver interface and l2_packet) since the
+ * portable code will not be able to use such an OS-specific call. The handler
+ * function will be called whenever the event is triggered. The handler
+ * function is responsible for clearing the event after having processed it in
+ * order to avoid eloop from calling the handler again for the same event.
+ *
+ * In case of Windows implementation (eloop_win.c), event pointer is of HANDLE
+ * type, i.e., void*. The callers are likely to have 'HANDLE h' type variable,
+ * and they would call this function with eloop_register_event(h, sizeof(h),
+ * ...).
+ */
+int eloop_register_event(void *event, size_t event_size,
+ eloop_event_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_unregister_event - Unregister handler for a generic event
+ * @event: Event to cancel (eloop implementation specific)
+ * @event_size: Size of event data
+ *
+ * Unregister a generic event notifier that was previously registered with
+ * eloop_register_event().
+ */
+void eloop_unregister_event(void *event, size_t event_size);
+
+/**
+ * eloop_register_timeout - Register timeout
+ * @secs: Number of seconds to the timeout
+ * @usecs: Number of microseconds to the timeout
+ * @handler: Callback function to be called when timeout occurs
+ * @eloop_data: Callback context data (eloop_ctx)
+ * @user_data: Callback context data (sock_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a timeout that will cause the handler function to be called after
+ * given time.
+ */
+int eloop_register_timeout(unsigned int secs, unsigned int usecs,
+ eloop_timeout_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_cancel_timeout - Cancel timeouts
+ * @handler: Matching callback function
+ * @eloop_data: Matching eloop_data or %ELOOP_ALL_CTX to match all
+ * @user_data: Matching user_data or %ELOOP_ALL_CTX to match all
+ * Returns: Number of cancelled timeouts
+ *
+ * Cancel matching <handler,eloop_data,user_data> timeouts registered with
+ * eloop_register_timeout(). ELOOP_ALL_CTX can be used as a wildcard for
+ * cancelling all timeouts regardless of eloop_data/user_data.
+ */
+int eloop_cancel_timeout(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_is_timeout_registered - Check if a timeout is already registered
+ * @handler: Matching callback function
+ * @eloop_data: Matching eloop_data
+ * @user_data: Matching user_data
+ * Returns: 1 if the timeout is registered, 0 if the timeout is not registered
+ *
+ * Determine if a matching <handler,eloop_data,user_data> timeout is registered
+ * with eloop_register_timeout().
+ */
+int eloop_is_timeout_registered(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_register_signal - Register handler for signals
+ * @sig: Signal number (e.g., SIGHUP)
+ * @handler: Callback function to be called when the signal is received
+ * @user_data: Callback context data (signal_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a callback function that will be called when a signal is received.
+ * The callback function is actually called only after the system signal
+ * handler has returned. This means that the normal limits for sighandlers
+ * (i.e., only "safe functions" allowed) do not apply for the registered
+ * callback.
+ *
+ * Signals are 'global' events and there is no local eloop_data pointer like
+ * with other handlers. The global user_data pointer registered with
+ * eloop_init() will be used as eloop_ctx for signal handlers.
+ */
+int eloop_register_signal(int sig, eloop_signal_handler handler,
+ void *user_data);
+
+/**
+ * eloop_register_signal_terminate - Register handler for terminate signals
+ * @handler: Callback function to be called when the signal is received
+ * @user_data: Callback context data (signal_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a callback function that will be called when a process termination
+ * signal is received. The callback function is actually called only after the
+ * system signal handler has returned. This means that the normal limits for
+ * sighandlers (i.e., only "safe functions" allowed) do not apply for the
+ * registered callback.
+ *
+ * Signals are 'global' events and there is no local eloop_data pointer like
+ * with other handlers. The global user_data pointer registered with
+ * eloop_init() will be used as eloop_ctx for signal handlers.
+ *
+ * This function is a more portable version of eloop_register_signal() since
+ * the knowledge of exact details of the signals is hidden in eloop
+ * implementation. In case of operating systems using signal(), this function
+ * registers handlers for SIGINT and SIGTERM.
+ */
+int eloop_register_signal_terminate(eloop_signal_handler handler,
+ void *user_data);
+
+/**
+ * eloop_register_signal_reconfig - Register handler for reconfig signals
+ * @handler: Callback function to be called when the signal is received
+ * @user_data: Callback context data (signal_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a callback function that will be called when a reconfiguration /
+ * hangup signal is received. The callback function is actually called only
+ * after the system signal handler has returned. This means that the normal
+ * limits for sighandlers (i.e., only "safe functions" allowed) do not apply
+ * for the registered callback.
+ *
+ * Signals are 'global' events and there is no local eloop_data pointer like
+ * with other handlers. The global user_data pointer registered with
+ * eloop_init() will be used as eloop_ctx for signal handlers.
+ *
+ * This function is a more portable version of eloop_register_signal() since
+ * the knowledge of exact details of the signals is hidden in eloop
+ * implementation. In case of operating systems using signal(), this function
+ * registers a handler for SIGHUP.
+ */
+int eloop_register_signal_reconfig(eloop_signal_handler handler,
+ void *user_data);
+
+/**
+ * eloop_run - Start the event loop
+ *
+ * Start the event loop and continue running as long as there are any
+ * registered event handlers. This function is run after event loop has been
+ * initialized with event_init() and one or more events have been registered.
+ */
+void eloop_run(void);
+
+/**
+ * eloop_terminate - Terminate event loop
+ *
+ * Terminate event loop even if there are registered events. This can be used
+ * to request the program to be terminated cleanly.
+ */
+void eloop_terminate(void);
+
+/**
+ * eloop_destroy - Free any resources allocated for the event loop
+ *
+ * After calling eloop_destroy(), other eloop_* functions must not be called
+ * before re-running eloop_init().
+ */
+void eloop_destroy(void);
+
+/**
+ * eloop_terminated - Check whether event loop has been terminated
+ * Returns: 1 = event loop terminate, 0 = event loop still running
+ *
+ * This function can be used to check whether eloop_terminate() has been called
+ * to request termination of the event loop. This is normally used to abort
+ * operations that may still be queued to be run when eloop_terminate() was
+ * called.
+ */
+int eloop_terminated(void);
+
+/**
+ * eloop_wait_for_read_sock - Wait for a single reader
+ * @sock: File descriptor number for the socket
+ *
+ * Do a blocking wait for a single read socket.
+ */
+void eloop_wait_for_read_sock(int sock);
+
+/**
+ * eloop_get_user_data - Get global user data
+ * Returns: user_data pointer that was registered with eloop_init()
+ */
+void * eloop_get_user_data(void);
+
+#endif /* ELOOP_H */
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/os_linux.c b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/os_linux.c
new file mode 100644
index 0000000..288b7a2
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/os_linux.c
@@ -0,0 +1,492 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <dirent.h>
+//#include <cutils/properties.h>
+#include <sys/un.h>
+#include <dirent.h>
+#include "os_linux.h"
+
+void os_sleep(os_time_t sec, os_time_t usec)
+{
+ if (sec)
+ sleep(sec);
+ if (usec)
+ usleep(usec);
+}
+
+int os_get_time(struct os_time *t)
+{
+ int res;
+ struct timeval tv;
+ res = gettimeofday(&tv, NULL);
+ t->sec = tv.tv_sec;
+ t->usec = tv.tv_usec;
+ return res;
+}
+
+
+int os_mktime(int year, int month, int day, int hour, int min, int sec,
+ os_time_t *t)
+{
+ struct tm tm;
+
+ if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
+ hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
+ sec > 60)
+ return -1;
+
+ os_memset(&tm, 0, sizeof(tm));
+ tm.tm_year = year - 1900;
+ tm.tm_mon = month - 1;
+ tm.tm_mday = day;
+ tm.tm_hour = hour;
+ tm.tm_min = min;
+ tm.tm_sec = sec;
+
+ *t = (os_time_t) mktime(&tm);
+ return 0;
+}
+
+
+int os_daemonize(const char *pid_file)
+{
+ if (daemon(0, 0)) {
+ perror("daemon");
+ return -1;
+ }
+
+ if (pid_file) {
+ FILE *f = fopen(pid_file, "w");
+ if (f) {
+ fprintf(f, "%u\n", getpid());
+ fclose(f);
+ }
+ }
+
+ return -0;
+}
+
+
+void os_daemonize_terminate(const char *pid_file)
+{
+ if (pid_file)
+ unlink(pid_file);
+}
+
+
+int os_get_random(unsigned char *buf, size_t len)
+{
+ FILE *f;
+ size_t rc;
+
+ f = fopen("/dev/urandom", "rb");
+ if (f == NULL) {
+ printf("Could not open /dev/urandom.\n");
+ return -1;
+ }
+
+ rc = fread(buf, 1, len, f);
+ fclose(f);
+
+ return rc != len ? -1 : 0;
+}
+
+
+unsigned long os_random(void)
+{
+ return random();
+}
+
+
+char * os_rel2abs_path(const char *rel_path)
+{
+ char *buf = NULL, *cwd, *ret;
+ size_t len = 128, cwd_len, rel_len, ret_len;
+
+ if (rel_path[0] == '/')
+ return os_strdup(rel_path);
+
+ for (;;) {
+ buf = os_malloc(len);
+ if (buf == NULL)
+ return NULL;
+ cwd = getcwd(buf, len);
+ if (cwd == NULL) {
+ os_free(buf);
+ if (errno != ERANGE) {
+ return NULL;
+ }
+ len *= 2;
+ } else {
+ break;
+ }
+ }
+
+ cwd_len = strlen(cwd);
+ rel_len = strlen(rel_path);
+ ret_len = cwd_len + 1 + rel_len + 1;
+ ret = os_malloc(ret_len);
+ if (ret) {
+ os_memcpy(ret, cwd, cwd_len);
+ ret[cwd_len] = '/';
+ os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
+ ret[ret_len - 1] = '\0';
+ }
+ os_free(buf);
+ return ret;
+}
+
+
+int os_program_init(void)
+{
+ return 0;
+}
+
+
+void os_program_deinit(void)
+{
+}
+
+
+int os_setenv(const char *name, const char *value, int overwrite)
+{
+ return setenv(name, value, overwrite);
+}
+
+
+int os_unsetenv(const char *name)
+{
+ return unsetenv(name);
+}
+
+
+char * os_readfile(const char *name, size_t *len)
+{
+ FILE *f;
+ char *buf;
+
+ f = fopen(name, "rb");
+ if (f == NULL)
+ return NULL;
+
+ fseek(f, 0, SEEK_END);
+ *len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ buf = os_malloc(*len);
+ if (buf == NULL) {
+ fclose(f);
+ return NULL;
+ }
+
+ fread(buf, 1, *len, f);
+ fclose(f);
+
+ return buf;
+}
+
+
+void * os_zalloc(size_t size)
+{
+ void *n = os_malloc(size);
+ if (n)
+ os_memset(n, 0, size);
+ return n;
+}
+
+
+void * os_malloc(size_t size)
+{
+ return malloc(size);
+}
+
+
+void * os_realloc(void *ptr, size_t size)
+{
+ return realloc(ptr, size);
+}
+
+
+void os_free(void *ptr)
+{
+ free(ptr);
+}
+
+
+void * os_memcpy(void *dest, const void *src, size_t n)
+{
+ char *d = dest;
+ const char *s = src;
+ while (n--)
+ *d++ = *s++;
+ return dest;
+}
+
+
+void * os_memmove(void *dest, const void *src, size_t n)
+{
+ if (dest < src)
+ os_memcpy(dest, src, n);
+ else {
+ /* overlapping areas */
+ char *d = (char *) dest + n;
+ const char *s = (const char *) src + n;
+ while (n--)
+ *--d = *--s;
+ }
+ return dest;
+}
+
+
+void * os_memset(void *s, int c, size_t n)
+{
+ char *p = s;
+ while (n--)
+ *p++ = c;
+ return s;
+}
+
+
+int os_memcmp(const void *s1, const void *s2, size_t n)
+{
+ const unsigned char *p1 = s1, *p2 = s2;
+
+ if (n == 0)
+ return 0;
+
+ while (*p1 == *p2) {
+ p1++;
+ p2++;
+ n--;
+ if (n == 0)
+ return 0;
+ }
+
+ return *p1 - *p2;
+}
+
+
+char * os_strdup(const char *s)
+{
+ char *res;
+ size_t len;
+ if (s == NULL)
+ return NULL;
+ len = os_strlen(s);
+ res = os_malloc(len + 1);
+ if (res)
+ os_memcpy(res, s, len + 1);
+ return res;
+}
+
+
+size_t os_strlen(const char *s)
+{
+ const char *p = s;
+ while (*p)
+ p++;
+ return p - s;
+}
+
+
+int os_strcasecmp(const char *s1, const char *s2)
+{
+ /*
+ * Ignoring case is not required for main functionality, so just use
+ * the case sensitive version of the function.
+ */
+ return os_strcmp(s1, s2);
+}
+
+
+int os_strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ /*
+ * Ignoring case is not required for main functionality, so just use
+ * the case sensitive version of the function.
+ */
+ return os_strncmp(s1, s2, n);
+}
+
+
+char * os_strchr(const char *s, int c)
+{
+ while (*s) {
+ if (*s == c)
+ return (char *) s;
+ s++;
+ //printf("==>s = %p\n", s);
+ }
+ return NULL;
+}
+
+
+char * os_strrchr(const char *s, int c)
+{
+ const char *p = s;
+ while (*p)
+ p++;
+ p--;
+ while (p >= s) {
+ if (*p == c)
+ return (char *) p;
+ p--;
+ }
+ return NULL;
+}
+
+
+int os_strcmp(const char *s1, const char *s2)
+{
+ while (*s1 == *s2) {
+ if (*s1 == '\0')
+ break;
+ s1++;
+ s2++;
+ }
+
+ return *s1 - *s2;
+}
+
+
+int os_strncmp(const char *s1, const char *s2, size_t n)
+{
+ if (n == 0)
+ return 0;
+
+ while (*s1 == *s2) {
+ if (*s1 == '\0')
+ break;
+ s1++;
+ s2++;
+ n--;
+ if (n == 0)
+ return 0;
+ }
+
+ return *s1 - *s2;
+}
+
+
+char * os_strncpy(char *dest, const char *src, size_t n)
+{
+ char *d = dest;
+
+ while (n--) {
+ *d = *src;
+ if (*src == '\0')
+ break;
+ d++;
+ src++;
+ }
+
+ return dest;
+}
+
+
+size_t os_strlcpy(char *dest, const char *src, size_t siz)
+{
+ const char *s = src;
+ size_t left = siz;
+
+ if (left) {
+ /* Copy string up to the maximum size of the dest buffer */
+ while (--left != 0) {
+ if ((*dest++ = *s++) == '\0')
+ break;
+ }
+ }
+
+ if (left == 0) {
+ /* Not enough room for the string; force NUL-termination */
+ if (siz != 0)
+ *dest = '\0';
+ while (*s++)
+ ; /* determine total src string length */
+ }
+
+ return s - src - 1;
+}
+
+
+char * os_strstr(const char *haystack, const char *needle)
+{
+ size_t len = os_strlen(needle);
+ while (*haystack) {
+ if (os_strncmp(haystack, needle, len) == 0)
+ return (char *) haystack;
+ haystack++;
+ }
+
+ return NULL;
+}
+
+
+int os_snprintf(char *str, size_t size, const char *format, ...)
+{
+ va_list ap;
+ int ret;
+
+ /* See http://www.ijs.si/software/snprintf/ for portable
+ * implementation of snprintf.
+ */
+
+ va_start(ap, format);
+ ret = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ if (size > 0)
+ str[size - 1] = '\0';
+ return ret;
+}
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/os_linux.h b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/os_linux.h
new file mode 100644
index 0000000..44a10c4
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/os_linux.h
@@ -0,0 +1,117 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef OS_LINUX_H
+#define OS_LINUX_H
+
+typedef long os_time_t;
+
+void os_sleep(os_time_t sec, os_time_t usec);
+
+struct os_time {
+ os_time_t sec;
+ os_time_t usec;
+};
+
+
+#define os_time_before(a, b) \
+ ((a)->sec < (b)->sec || \
+ ((a)->sec == (b)->sec && (a)->usec < (b)->usec))
+
+#define os_time_sub(a, b, res) do { \
+ (res)->sec = (a)->sec - (b)->sec; \
+ (res)->usec = (a)->usec - (b)->usec; \
+ if ((res)->usec < 0) { \
+ (res)->sec--; \
+ (res)->usec += 1000000; \
+ } \
+} while (0)
+
+int os_get_time(struct os_time *t);
+int os_mktime(int year, int month, int day, int hour, int min, int sec,
+ os_time_t *t);
+int os_daemonize(const char *pid_file);
+void os_daemonize_terminate(const char *pid_file);
+int os_get_random(unsigned char *buf, size_t len);
+unsigned long os_random(void);
+char * os_rel2abs_path(const char *rel_path);
+int os_program_init(void);
+void os_program_deinit(void);
+int os_setenv(const char *name, const char *value, int overwrite);
+int os_unsetenv(const char *name);
+char * os_readfile(const char *name, size_t *len);
+void * os_zalloc(size_t size);
+void * os_malloc(size_t size);
+void * os_realloc(void *ptr, size_t size);
+void os_free(void *ptr);
+void * os_memcpy(void *dest, const void *src, size_t n);
+void * os_memmove(void *dest, const void *src, size_t n);
+void * os_memset(void *s, int c, size_t n);
+int os_memcmp(const void *s1, const void *s2, size_t n);
+char * os_strdup(const char *s);
+size_t os_strlen(const char *s);
+int os_strcasecmp(const char *s1, const char *s2);
+int os_strncasecmp(const char *s1, const char *s2, size_t n);
+char * os_strchr(const char *s, int c);
+char * os_strrchr(const char *s, int c);
+int os_strcmp(const char *s1, const char *s2);
+int os_strncmp(const char *s1, const char *s2, size_t n);
+char * os_strncpy(char *dest, const char *src, size_t n);
+size_t os_strlcpy(char *dest, const char *src, size_t siz);
+
+char * os_strstr(const char *haystack, const char *needle);
+int os_snprintf(char *str, size_t size, const char *format, ...);
+void os_sleep(os_time_t sec, os_time_t usec);
+int os_get_time(struct os_time *t);
+int os_mktime(int year, int month, int day, int hour, int min, int sec,
+ os_time_t *t);
+#define os_daemon daemon
+int os_daemonize(const char *pid_file);
+void os_daemonize_terminate(const char *pid_file);
+int os_get_random(unsigned char *buf, size_t len);
+unsigned long os_random(void);
+char * os_rel2abs_path(const char *rel_path);
+int os_program_init(void);
+void os_program_deinit(void);
+int os_setenv(const char *name, const char *value, int overwrite);
+int os_unsetenv(const char *name);
+char * os_readfile(const char *name, size_t *len);
+void * os_zalloc(size_t size);
+size_t os_strlcpy(char *dest, const char *src, size_t siz);
+
+#endif
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/stp_dump.c b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/stp_dump.c
new file mode 100644
index 0000000..2ae7eee
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/stp_dump.c
@@ -0,0 +1,1452 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <grp.h>
+#include <stddef.h>
+//#include <cutils/sockets.h>
+//#include <android/log.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <dirent.h>
+//#include <cutils/properties.h>
+#include <sys/un.h>
+#include <dirent.h>
+#include <linux/limits.h>
+//#include <cutils/sockets.h>
+//#include <cutils/memory.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+//#include <sys/endian.h>
+#include <linux/serial.h> /* struct serial_struct */
+#include <unistd.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <termios.h>
+#include <sys/poll.h>
+#include <linux/serial.h> /* struct serial_struct */
+#include <sched.h>
+#include <netdb.h>
+#include <pthread.h>
+#include "os_linux.h"
+#include "stp_dump.h"
+#include "bt_fw_logger.h"
+#include "wifi_fw_logger.h"
+#include "eloop.h"
+#include <linux/netlink.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/mman.h>
+#include "../wmt_ioctl.h"
+
+#define LOGE printf
+#define LOGD printf
+
+#define GENL_ID_CTRL NLMSG_MIN_TYPE
+#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
+#define COMBO_T32_DIR "/data/misc/stp_dump/"
+#define COMBO_T32_NAME "combo_t32"
+#define COMBO_T32_ENAME ".cmm"
+#define COMBO_T32_NUM_MAX 50
+#define COM_STR_MAX 100
+#define EMI_ENAME ".emi"
+#define EMI_FILE_NAME "SYS_WCN_EMI_DUMP"
+#define EMICOREDUMP_CMD "emicoredump"
+
+enum {
+ CTRL_CMD_UNSPEC,
+ CTRL_CMD_NEWFAMILY,
+ CTRL_CMD_DELFAMILY,
+ CTRL_CMD_GETFAMILY,
+ CTRL_CMD_NEWOPS,
+ CTRL_CMD_DELOPS,
+ CTRL_CMD_GETOPS,
+ CTRL_CMD_NEWMCAST_GRP,
+ CTRL_CMD_DELMCAST_GRP,
+ CTRL_CMD_GETMCAST_GRP, /* unused */
+ __CTRL_CMD_MAX,
+};
+#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
+
+enum {
+ CTRL_ATTR_UNSPEC,
+ CTRL_ATTR_FAMILY_ID,
+ CTRL_ATTR_FAMILY_NAME,
+ CTRL_ATTR_VERSION,
+ CTRL_ATTR_HDRSIZE,
+ CTRL_ATTR_MAXATTR,
+ CTRL_ATTR_OPS,
+ CTRL_ATTR_MCAST_GROUPS,
+ __CTRL_ATTR_MAX,
+};
+
+#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
+
+struct genlmsghdr {
+ __u8 cmd;
+ __u8 version;
+ __u16 reserved;
+};
+
+#define GENLMSG_DATA(glh) ((void *)((long)NLMSG_DATA(glh) + GENL_HDRLEN))
+#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
+#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
+
+typedef struct _tagGenericNetlinkPacket {
+ struct nlmsghdr n;
+ struct genlmsghdr g;
+ char buf[512*16];
+} GENERIC_NETLINK_PACKET, *P_GENERIC_NETLINK_PACKET;
+
+
+
+////typedef int socklen_t;
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+int stp_debug_level = MSG_MSGDUMP;
+
+struct stp_ctrl_dst {
+ struct stp_ctrl_dst *next;
+ struct sockaddr_un addr;
+ socklen_t addrlen;
+ int debug_level;
+ int errors;
+};
+
+struct ctrl_iface_priv {
+ struct stp_dump *stp_d;
+ int sock;
+ struct stp_ctrl_dst *ctrl_dst;
+};
+
+struct trace_iface_priv {
+ struct stp_dump *stp_d;
+ int sock;
+ struct {
+ FILE *fp_pkt;
+ FILE *fp_drv;
+ FILE *fp_fw;
+ FILE *fp_t32;
+ } log_f;
+};
+
+struct stp_dump {
+ const char *ctrl_interface;
+ const char *ifname;
+ char *ctrl_interface_group;
+ int wmt_fd;
+ int chip_type;
+ struct ctrl_iface_priv *ctrl_iface;
+ struct trace_iface_priv *trace_iface;
+};
+struct list_head {
+ char file_name[100];
+ struct list_head *next, *prev;
+};
+
+struct list_head list_head;
+int combo_t32_num = 0;
+char combo_emi[100];
+
+static inline void INIT_LIST_HEAD(struct list_head *list) {
+ list->next = list;
+ list->prev = list;
+}
+
+static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) {
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+static inline void list_add_tail(struct list_head *new, struct list_head *head) {
+ __list_add(new, head->prev, head);
+}
+
+static inline void __list_del(struct list_head * prev, struct list_head * next) {
+ next->prev = prev;
+ prev->next = next;
+}
+
+static inline void list_del(struct list_head *entry) {
+ __list_del(entry->prev, entry->next);
+ entry->next = NULL;
+ entry->prev = NULL;
+}
+
+void bubble_sort(char *a[], int n)
+{
+ int i, j, len1, len2, len3;
+ char temp[COM_STR_MAX];
+ for (j = 0; j < n - 1; j++)
+ for (i = 0; i < n - 1 - j; i++) {
+ if (atoi(&a[i][10]) > atoi(&a[i+1][10])) {
+ len1 = (strlen(a[i]) <= COM_STR_MAX) ? strlen(a[i]) : COM_STR_MAX;
+ strncpy(temp, a[i], len1);
+ temp[len1-1] = '\0';
+ len2 = (strlen(a[i+1]) <= COM_STR_MAX) ? strlen(a[i+1]) : COM_STR_MAX;
+ strncpy(a[i], a[i+1], len2);
+ a[i][len2-1] = '\0';
+ len3 = (strlen(a[i+1]) <= COM_STR_MAX) ? strlen(a[i+1]) : COM_STR_MAX;
+ strncpy(a[i+1], temp, len3);
+ a[i+1][len3-1] = '\0';
+ }
+ }
+}
+
+/*
+void android_printf(int level, char *format, ...)
+{
+ if (level >= stp_debug_level) {
+ va_list ap;
+ if (level == MSG_ERROR) {
+ level = ANDROID_LOG_ERROR;
+ } else if (level == MSG_WARNING) {
+ level = ANDROID_LOG_WARN;
+ } else if (level == MSG_INFO) {
+ level = ANDROID_LOG_INFO;
+ } else {
+ level = ANDROID_LOG_DEBUG;
+ }
+ va_start(ap, format);
+ __android_log_vprint(level, "stp_dump", format, ap);
+ va_end(ap);
+ }
+}
+*/
+
+int check_log_folder_exit()
+{
+ struct statfs fs_info;
+
+ /* check COMBO_T32_DIR folder */
+ if (statfs(COMBO_T32_DIR,&fs_info) < 0)
+ {
+ if (mkdir(COMBO_T32_DIR, 00777) < 0)
+ {
+ stp_printf(MSG_ERROR, "remake (%s) failed:(%s)\n", COMBO_T32_DIR, strerror(errno));
+ return -1;
+ } else
+ stp_printf(MSG_WARNING, "remake (%s) success\n", COMBO_T32_DIR);
+ }
+ return 0;
+}
+
+/*
+void wait_sdcard_ready()
+{
+ struct statfs fs_status;
+ int count = 0;
+
+ while (1)
+ {
+ if(statfs("/sdcard",&fs_status)==-1)
+ {
+ count++;
+ stp_printf(MSG_WARNING, "fail to get Sdcard stat :%s, count: %d", strerror(errno), count);
+ }
+ else
+ {
+ if(fs_status.f_blocks==0)
+ {
+ stp_printf(MSG_WARNING, "wait sdcard not ready count:%d,:%s", count, strerror(errno));
+ }
+ else if(fs_status.f_blocks>0)
+ {
+ break;
+ }
+ }
+ sleep(2);
+ }
+}
+*/
+
+static void _stp_hexdump(int level, const char *title, const u8 *buf,
+ size_t len, int show)
+{
+ size_t i;
+ if (level < stp_debug_level)
+ return;
+
+ printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
+ if (buf == NULL) {
+ printf(" [NULL]");
+ } else if (show) {
+ for (i = 0; i < len; i++)
+ printf(" %02x", buf[i]);
+ } else {
+ printf(" [REMOVED]");
+ }
+ printf("\n");
+}
+
+void stp_hexdump(int level, const char *title, const u8 *buf, size_t len)
+{
+ _stp_hexdump(level, title, buf, len, 1);
+}
+
+static int stp_dump_ctrl_iface_attach(struct ctrl_iface_priv *priv,
+ struct sockaddr_un *from,
+ socklen_t fromlen)
+{
+ struct stp_ctrl_dst *dst;
+
+ dst = os_zalloc(sizeof(*dst));
+ if (dst == NULL)
+ return -1;
+ os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
+ dst->addrlen = fromlen;
+ dst->debug_level = MSG_INFO;
+ dst->next = priv->ctrl_dst;
+ priv->ctrl_dst = dst;
+ stp_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
+ (u8 *) from->sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path));
+ return 0;
+}
+
+static int stp_dump_ctrl_iface_detach(struct ctrl_iface_priv *priv,
+ struct sockaddr_un *from,
+ socklen_t fromlen)
+{
+ struct stp_ctrl_dst *dst, *prev = NULL;
+
+ dst = priv->ctrl_dst;
+ while (dst) {
+ if (fromlen == dst->addrlen &&
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
+ if (prev == NULL)
+ priv->ctrl_dst = dst->next;
+ else
+ prev->next = dst->next;
+ os_free(dst);
+ stp_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
+ (u8 *) from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
+ return 0;
+ }
+ prev = dst;
+ dst = dst->next;
+ }
+ return -1;
+}
+
+static int stp_dump_ctrl_iface_level(struct ctrl_iface_priv *priv,
+ struct sockaddr_un *from,
+ socklen_t fromlen,
+ char *level)
+{
+ struct stp_ctrl_dst *dst;
+
+ stp_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s\n", level);
+
+ dst = priv->ctrl_dst;
+ while (dst) {
+ if (fromlen == dst->addrlen &&
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
+ stp_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
+ "level", (u8 *) from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
+ dst->debug_level = atoi(level);
+ return 0;
+ }
+ dst = dst->next;
+ }
+
+ return -1;
+}
+
+static void stp_dump_ctrl_iface_receive(int sock, void *eloop_ctx __attribute__((__unused__)),
+ void *sock_ctx)
+{
+ struct ctrl_iface_priv *priv = sock_ctx;
+ char buf[256];
+ int res;
+ struct sockaddr_un from;
+ socklen_t fromlen = sizeof(from);
+ size_t reply_len = 0;
+ int new_attached = 0;
+
+ res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
+ (struct sockaddr *) &from, &fromlen);
+ if (res < 0) {
+ perror("recvfrom(ctrl_iface)");
+ return;
+ }
+ buf[res] = '\0';
+
+ if (os_strcmp(buf, "ATTACH") == 0) {
+ if (stp_dump_ctrl_iface_attach(priv, &from, fromlen))
+ reply_len = 1;
+ else {
+ new_attached = 1;
+ reply_len = 2;
+ }
+ } else if (os_strcmp(buf, "DETACH") == 0) {
+ if (stp_dump_ctrl_iface_detach(priv, &from, fromlen))
+ reply_len = 1;
+ else
+ reply_len = 2;
+ } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
+ if (stp_dump_ctrl_iface_level(priv, &from, fromlen,
+ buf + 6))
+ reply_len = 1;
+ else
+ reply_len = 2;
+ } else {
+ //stp_hexdump(MSG_INFO, "stp_dump_ctrl_iface_process", buf, 4);
+ //reply = stp_dump_ctrl_iface_process(stp_d, buf,
+ // &reply_len);
+ }
+#if 0
+ if (reply) {
+ if ( 0 > sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen))
+ perror("send reply error\n");
+ os_free(reply);
+ } else if (reply_len == 1) {
+#else
+ if (reply_len == 1) {
+#endif
+ if (0 > sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, fromlen))
+ perror("send string 'FAIL' to sock error\n");
+ } else if (reply_len == 2) {
+ if ( 0 > sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, fromlen))
+ perror("send string 'OK' to sock error\n");
+ }
+}
+
+
+static char * stp_dump_ctrl_iface_path(struct stp_dump *stp_d)
+{
+ char *buf;
+ size_t len;
+ char *pbuf, *dir = NULL, *gid_str = NULL;
+ int res;
+
+ if (stp_d->ctrl_interface == NULL)
+ {
+ stp_printf(MSG_ERROR, "stp_d->ctrl_interface = NULL\n");
+ return NULL;
+ }
+ pbuf = os_strdup(stp_d->ctrl_interface);
+
+ if (pbuf == NULL)
+ {
+ stp_printf(MSG_ERROR, "copy string failed\n");
+ return NULL;
+ }
+ if (os_strncmp(pbuf, "DIR=", 4) == 0) {
+ dir = pbuf + 4;
+ gid_str = os_strstr(dir, " GROUP=");
+ if (gid_str) {
+ *gid_str = '\0';
+ gid_str += 7;
+ }
+ } else
+ dir = pbuf;
+
+ len = os_strlen(dir) + os_strlen(stp_d->ifname) + 2;
+ buf = os_malloc(len);
+ if (buf == NULL)
+ {
+ stp_printf(MSG_ERROR, "memory allocation failed\n");
+ os_free(pbuf);
+ return NULL;
+ }
+
+ res = os_snprintf(buf, len, "%s/%s", dir, stp_d->ifname);
+ if (res < 0 || (size_t) res >= len)
+ {
+ stp_printf(MSG_ERROR, "os_snprintf failed\n");
+ os_free(pbuf);
+ os_free(buf);
+ return NULL;
+ }
+ os_free(pbuf);
+ return buf;
+}
+
+int stp_dump_ctrl_iface_trace_logger_init(struct trace_iface_priv *tr_priv) {
+ char str[100] = {""};
+ char *file_name[50] = {NULL};
+ int i = 0;
+ struct dirent *pDirent = NULL;
+ DIR *pDir = NULL;
+ struct list_head *node;
+
+ sprintf(str, "%s%s%s", COMBO_T32_DIR, COMBO_T32_NAME, COMBO_T32_ENAME);
+ tr_priv->log_f.fp_t32 = fopen(str, "a+");
+ if (tr_priv->log_f.fp_t32 == NULL) {
+ stp_printf(MSG_ERROR, "create combo_fw.log fails, exit errno:%d\n", errno);
+ exit(EXIT_FAILURE);
+ }
+ if (0 != remove(str))
+ perror("remove combo_fw fails\n");
+
+ pDir = opendir(COMBO_T32_DIR);
+ if (NULL == pDir) {
+ stp_printf(MSG_ERROR, "coredump patch cannot be opened\n");
+ exit(EXIT_FAILURE);
+ }
+ /* stp_printf(MSG_ERROR, "coreduzmp patch opened\n"); */
+
+ while (NULL != (pDirent = readdir(pDir))) {
+ char *dot = strrchr(pDirent->d_name, '.');
+ /* combo_t32_xxxx.cmm */
+ if (0 == strncmp(pDirent->d_name, COMBO_T32_NAME, sizeof(COMBO_T32_NAME)-1) && dot &&
+ 0 == strncmp(dot, COMBO_T32_ENAME, sizeof(COMBO_T32_ENAME)-1)) {
+ if (combo_t32_num < COMBO_T32_NUM_MAX) {
+ int file_name_len = 0;
+
+ file_name_len = strlen(pDirent->d_name) + 1;
+ if (file_name_len > 100) {
+ stp_printf(MSG_ERROR, "combo_t32 length %d over 100\n", file_name_len);
+ break;
+ }
+ file_name[combo_t32_num] = malloc(100);
+ strncpy(file_name[combo_t32_num], pDirent->d_name, file_name_len);
+ /* stp_printf(MSG_ERROR, "file name:%s\n", file_name[combo_t32_num]); */
+ combo_t32_num++;
+ /* stp_printf(MSG_ERROR, "combo_t32_num:%d\n", combo_t32_num); */
+ } else {
+ /* stp_printf(MSG_ERROR, "file num more than the max\n"); */
+ break;
+ }
+ }
+ }
+ closedir(pDir);
+ bubble_sort(file_name, combo_t32_num);
+
+ INIT_LIST_HEAD(&list_head);
+ for (i = 0; i < combo_t32_num; i++) {
+ node = malloc(sizeof(struct list_head));
+ sprintf(node->file_name, "%s%s", COMBO_T32_DIR, file_name[i]);
+ list_add_tail(node, &list_head);
+ /* stp_printf(MSG_ERROR, "file name:%s\n", node->file_name); */
+ free(file_name[i]);
+ }
+ fclose(tr_priv->log_f.fp_t32);
+ stp_printf(MSG_INFO, "close file combo_t32\n");
+ return 0;
+}
+
+void stp_dump_ctrl_iface_trace_logger_decode(int sock, __attribute__((unused))void *eloop_ctx,
+ void *sock_ctx)
+{
+ struct nlattr *na;
+ char *stpmsghdr = NULL;
+ int size;
+ struct trace_iface_priv *tr_priv = sock_ctx;
+ GENERIC_NETLINK_PACKET mBuffer;
+ GENERIC_NETLINK_PACKET *prBuffer;
+ int i;
+ int len;
+
+ if ((size = recv(sock, &mBuffer, sizeof(mBuffer), 0)) < 0)
+ {
+ LOGE("recv failed (%s)\n", strerror(errno));
+ return ;
+ }
+
+ prBuffer = &mBuffer;
+
+ /* Validate response message */
+ if (!NLMSG_OK(&(prBuffer->n), (unsigned int)size))
+ {
+ LOGE("invalid reply message\n");
+ return ;
+ }
+ else if (prBuffer->n.nlmsg_type == NLMSG_ERROR)
+ { /* error */
+ LOGE("received error\n");
+ return ;
+ }
+ else if (!NLMSG_OK((&prBuffer->n), (unsigned int)size))
+ {
+ LOGE("invalid reply message received via Netlink\n");
+ return ;
+ }
+
+ size = GENLMSG_PAYLOAD(&prBuffer->n);
+ na = (struct nlattr *) GENLMSG_DATA(prBuffer);
+
+ stpmsghdr = (char *)NLA_DATA(na);
+ if ((stpmsghdr[0] == '[') &&
+ (stpmsghdr[1] == 'M') &&
+ (stpmsghdr[2] == ']')) {
+ static char start_dump = 1;
+
+ /* TODO: parsing message to know the action to start dump */
+ if (start_dump) {
+ char combo_t32[100] = {""};
+ char date[64];
+ time_t t = time(0);
+ struct list_head *node;
+ int file_name_len = 0; // combo_t32 length
+
+ strftime(date, sizeof(date), "%Y%m%d%H%M%S", localtime(&t));
+ file_name_len = strlen(COMBO_T32_DIR) + strlen(COMBO_T32_NAME) + strlen(date) +
+ strlen(COMBO_T32_ENAME) + 2;
+ if (file_name_len > 100) {
+ stp_printf(MSG_ERROR, "combo_t32 length %d over 100\n", file_name_len);
+ return ;
+ }
+ /*fclose(tr_priv->log_f.fp_t32);*/
+ /*tr_priv->log_f.fp_t32 = 0;*/
+ if (check_log_folder_exit() != 0)
+ {
+ stp_printf(MSG_ERROR, "####log folder %s not exist####", COMBO_T32_DIR);
+ return;
+ }
+ memset(combo_emi, 0, sizeof(combo_emi));
+ sprintf(combo_emi, "%s%s_%s%s", COMBO_T32_DIR, COMBO_T32_NAME, date, EMI_ENAME);
+ if (1) {
+ sprintf(combo_t32, "%s%s_%s%s", COMBO_T32_DIR, COMBO_T32_NAME, date, COMBO_T32_ENAME);
+
+ tr_priv->log_f.fp_t32 = fopen(combo_t32, "w");
+ if (tr_priv->log_f.fp_t32 == NULL) {
+ stp_printf(MSG_ERROR, "####open %s fail####,%s", combo_t32, strerror(errno));
+ return;
+ }
+ if (0 != chmod(combo_t32, 00664)) {
+ perror("chmod combo_t32 error\n");
+ }
+ /* stp_printf(MSG_DEBUG, "create a new file %s\n", combo_t32); */
+ combo_t32_num++;
+
+ if (combo_t32_num < COMBO_T32_NUM_MAX) {
+ node = malloc(sizeof(struct list_head));
+ /* stp_printf(MSG_ERROR, "create a new node\n"); */
+ } else {
+ char tmp[100] = {0};
+ char *dot;
+
+ node = list_head.next;
+ dot = strrchr(node->file_name, '.');
+ if (dot) {
+ strncpy(tmp, node->file_name, dot - node->file_name);
+ strncpy(tmp + (dot - node->file_name), EMI_ENAME, sizeof(EMI_ENAME));
+ }
+ list_del(list_head.next);
+ stp_printf(MSG_ERROR, "combo_t32_num more than max, delete %s and %s\n", node->file_name, tmp);
+ if (remove(node->file_name))
+ stp_printf(MSG_ERROR, "combo_t32_num more than max, Unable to delete the %s(%d))\n",
+ node->file_name, errno);
+ if (remove(tmp))
+ stp_printf(MSG_ERROR, "combo_t32_num more than max, Unable to delete the %s(%d))\n",
+ tmp, errno);
+ }
+ strncpy(node->file_name, combo_t32, file_name_len);
+ list_add_tail(node, &list_head);
+
+ /* stp_printf(MSG_DEBUG, "rev coredump len:%d\n", len); */
+ /* stp_printf(MSG_DEBUG, "rev coredump date:%s\n", &stpmsghdr[5]); */
+ }
+
+ ioctl(tr_priv->stp_d->wmt_fd, 10, &stpmsghdr[5]);
+ start_dump = 0;
+ }
+
+ if (strstr(&stpmsghdr[5], EMICOREDUMP_CMD)) {
+ void *map_memory;
+ unsigned int emi_size;
+ FILE *fp_emi;
+ char aee_emi[100] = {""};
+
+ /* Get connsys EMI reserve memory size */
+ emi_size = ioctl(tr_priv->stp_d->wmt_fd, WMT_IOCTL_GET_EMI_PHY_SIZE, 0);
+ stp_printf(MSG_INFO, "emi_size: %d\n", emi_size);
+ fp_emi = fopen(combo_emi, "w");
+ if (fp_emi == NULL) {
+ stp_printf(MSG_ERROR, "####open %s fail####,%s", combo_emi, strerror(errno));
+ start_dump = 1;
+ return;
+ }
+ if (0 != chmod(combo_emi, 00664)) {
+ perror("chmod combo_emi error\n");
+ }
+
+ map_memory = mmap(NULL, emi_size, PROT_READ, MAP_SHARED, tr_priv->stp_d->wmt_fd, 0);
+ if (map_memory == MAP_FAILED)
+ stp_printf(MSG_INFO, "mmap failed\n");
+ else {
+ fwrite(map_memory, 1, emi_size, fp_emi);
+ munmap(map_memory, emi_size);
+ }
+
+ fclose(fp_emi);
+ stp_printf(MSG_INFO, "Dump EMI memory Successfully.\n");
+ /* For AEE, rename file name to SYS_WCN_EMI_DUMP */
+ if (0) {
+ sprintf(aee_emi, "%s%s", COMBO_T32_DIR, EMI_FILE_NAME);
+ if (remove(aee_emi) && errno != ENOENT)
+ stp_printf(MSG_ERROR, "Unable to delete the %s(%d))\n", aee_emi, errno);
+
+ if (rename(combo_emi, aee_emi))
+ stp_printf(MSG_ERROR, "Unable to rename the file %s to %s\n", combo_emi, aee_emi);
+ else
+ stp_printf(MSG_ERROR, "Rename the file %s to %s\n", combo_emi, aee_emi);
+ }
+ ioctl(tr_priv->stp_d->wmt_fd, 11, 0);
+ start_dump = 1;
+ return;
+ }
+
+ len = stpmsghdr[4];
+ len <<= 8;
+ len += stpmsghdr[3];
+ for (i = 0; i < len; i++)
+ fprintf(tr_priv->log_f.fp_t32, "%c", stpmsghdr[5+i]);
+ fflush(tr_priv->log_f.fp_t32);
+ /* stp_printf(MSG_DEBUG, "rev coredump len:%d\n", len); */
+ /* stp_printf(MSG_DEBUG, "rev coredump date:%s\n", &stpmsghdr[5]); */
+
+ if (len < 1024) {
+ i = 0;
+ do {
+ i++;
+ }while(('c' != stpmsghdr[len - i]) && (i < 50));
+ }
+ if (strstr(&stpmsghdr[5], "coredump end") || strstr(&stpmsghdr[len - i], "coredump end")) {
+ /* inform user to dump action is done */
+ stp_printf(MSG_DEBUG, "coredump end\n");
+ fclose(tr_priv->log_f.fp_t32);
+ tr_priv->log_f.fp_t32 = 0;
+ if (tr_priv->stp_d->chip_type == WMT_CHIP_TYPE_COMBO) {
+ ioctl(tr_priv->stp_d->wmt_fd, 11, 0);
+ start_dump = 1;
+ }
+ }
+ } else
+ {
+ LOGE("invalid dump data\n");
+ }
+
+}
+
+int stp_dump_ctrl_iface_trace_logger_sendto_fd(int s, const char *buf, int bufLen)
+{
+ struct sockaddr_nl nladdr;
+ int r;
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+
+ while ((r = sendto(s, buf, bufLen, 0, (struct sockaddr *) &nladdr,
+ sizeof(nladdr))) < bufLen)
+ {
+ if (r > 0)
+ {
+ buf += r;
+ bufLen -= r;
+ }
+ else if (errno != EAGAIN)
+ {
+ stp_printf(MSG_ERROR, "%s failed\n", __func__);
+ return -1;
+ }
+ }
+ stp_printf(MSG_INFO, "%s succeed\n", __func__);
+ return 0;
+}
+
+/*
+ * Probe the controller in genetlink to find the family id
+ */
+int stp_dump_ctrl_iface_trace_logger_get_family_id(int sk, const char *family_name)
+{
+ struct nlattr *na;
+ int rep_len;
+ int id = -1;
+ GENERIC_NETLINK_PACKET family_req, ans;
+
+ /* Get family name */
+ family_req.n.nlmsg_type = GENL_ID_CTRL;
+ family_req.n.nlmsg_flags = NLM_F_REQUEST;
+ family_req.n.nlmsg_seq = 0;
+ family_req.n.nlmsg_pid = getpid();
+ family_req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+ family_req.g.cmd = CTRL_CMD_GETFAMILY;
+ family_req.g.version = 0x1;
+
+ na = (struct nlattr *) GENLMSG_DATA(&family_req);
+ na->nla_type = CTRL_ATTR_FAMILY_NAME;
+ na->nla_len = strlen(family_name) + 1 + NLA_HDRLEN;
+ strncpy((char *)NLA_DATA(na), family_name, (strlen(family_name) + 1));
+
+ family_req.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
+
+ if (stp_dump_ctrl_iface_trace_logger_sendto_fd(sk, (char *) &family_req, family_req.n.nlmsg_len) < 0)
+ {
+ stp_printf(MSG_ERROR, "%s failed\n", __func__);
+ return -1;
+ }
+
+ rep_len = recv(sk, &ans, sizeof(ans), 0);
+ if (rep_len < 0)
+ {
+ stp_printf(MSG_ERROR, "no response\n");
+ return -1;
+ }
+ /* Validate response message */
+ else if (!NLMSG_OK((&ans.n), (unsigned int)rep_len))
+ {
+ stp_printf(MSG_ERROR,"invalid reply message\n");
+ return -1;
+ }
+ else if (ans.n.nlmsg_type == NLMSG_ERROR)
+ { /* error */
+ stp_printf(MSG_ERROR, "received error\n");
+ return -1;
+ }
+
+ na = (struct nlattr *) GENLMSG_DATA(&ans);
+ na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len));
+ if (na->nla_type == CTRL_ATTR_FAMILY_ID)
+ {
+ id = *(__u16 *) NLA_DATA(na);
+ }
+
+ return id;
+}
+
+int stp_dump_ctrl_iface_trace_logger_start(struct trace_iface_priv *tr_priv){
+
+ struct sockaddr_nl nladdr;
+ int sz = 64 * 1024;
+ GENERIC_NETLINK_PACKET req;
+ struct nlattr *na;
+ int id;
+ int mlength = 14;
+ const char *message = "HELLO"; //message
+ int rc;
+ int count = 100;
+
+ if (stp_dump_ctrl_iface_trace_logger_init(tr_priv))
+ return -1;
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+ nladdr.nl_pid = getpid();
+
+ if ((tr_priv->sock= socket(AF_NETLINK,
+ SOCK_RAW,NETLINK_GENERIC)) < 0)
+ {
+ stp_printf(MSG_ERROR, "Unable to create uevent socket: %s", strerror(errno));
+ return -1;
+ }
+
+ if (setsockopt(tr_priv->sock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0)
+ {
+ stp_printf(MSG_ERROR,"Unable to set uevent socket options: %s", strerror(errno));
+ return -1;
+ }
+
+ if (bind(tr_priv->sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0)
+ {
+ stp_printf(MSG_ERROR,"Unable to bind uevent socket: %s", strerror(errno));
+ return -1;
+ }
+
+ while(count--)
+ {
+ id = stp_dump_ctrl_iface_trace_logger_get_family_id(tr_priv->sock, "STP_DBG");
+ if (-1 == id)
+ {
+ stp_printf(MSG_ERROR,"Unable to get family id, Retry");
+ sleep(3);
+ }
+ else
+ {
+ stp_printf(MSG_INFO,"[STP_DBG] family id = %d\n", id);
+ printf("[STP_DBG] family id = %d\n", id);
+ break;
+ }
+ }
+
+ req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+ req.n.nlmsg_type = id;
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_seq = 60;
+ req.n.nlmsg_pid = getpid();
+ req.g.cmd = 1;
+
+ na = (struct nlattr *) GENLMSG_DATA(&req);
+ na->nla_type = 1; //MTK_WIFI_ATTR_MSG
+ na->nla_len = mlength + NLA_HDRLEN; //message length
+ memcpy(NLA_DATA(na), message, strlen(message));
+ req.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
+
+ stp_printf(MSG_INFO, "sending dummy command\n");
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+
+ rc = sendto(tr_priv->sock, (char *)&req, req.n.nlmsg_len, 0,
+ (struct sockaddr *) &nladdr, sizeof(nladdr));
+#if 0
+ if (rc > 0)
+ {
+ stp_printf(MSG_INFO, "sending dummy command okay\n");
+ }
+ else if (errno != EAGAIN)
+ {
+ stp_printf(MSG_ERROR, "%s failed\n", __func__);
+ return -1;
+ }
+#endif
+ eloop_register_read_sock(tr_priv->sock, stp_dump_ctrl_iface_trace_logger_decode,
+ tr_priv->stp_d, tr_priv);
+ return 0;
+}
+
+struct ctrl_iface_priv *
+stp_dump_ctrl_iface_init(struct stp_dump *stp_d)
+{
+ struct ctrl_iface_priv *priv;
+ struct trace_iface_priv *tr_priv;
+ struct sockaddr_un addr;
+ char *fname = NULL;
+ gid_t gid = 0;
+ int gid_set = 0;
+ char *buf, *dir = NULL, *gid_str = NULL;
+ struct group *grp;
+ char *endp;
+
+ priv = os_zalloc(sizeof(*priv));
+ if (priv == NULL)
+ {
+ stp_printf(MSG_ERROR, "memory allocation for priv failed\n");
+ return NULL;
+ }
+
+ tr_priv = os_zalloc(sizeof(*tr_priv));
+ if(tr_priv == NULL)
+ {
+ stp_printf(MSG_ERROR, "memory allocation for tr_priv failed\n");
+ os_free(priv);
+ priv = NULL;
+ return NULL;
+ }
+
+ priv->stp_d = stp_d;
+ priv->sock = -1;
+
+ tr_priv->stp_d = stp_d;
+ tr_priv->sock = -1;
+
+ if (stp_d->ctrl_interface == NULL)
+ {
+ stp_printf(MSG_ERROR, "stp_d->ctrl_interface = NULL\n");
+ os_free(priv);
+ priv = NULL;
+ os_free(tr_priv);
+ tr_priv = NULL;
+ return priv;
+ }
+
+ buf = os_strdup(stp_d->ctrl_interface);
+ if (buf == NULL)
+ {
+ stp_printf(MSG_ERROR, "os_strdup\n");
+ goto fail;
+ }
+
+ os_snprintf(addr.sun_path, sizeof(addr.sun_path), "stp_%s",
+ stp_d->ctrl_interface);
+ stp_printf(MSG_INFO, "addr.sun_path:%s\n", addr.sun_path);
+/*
+ priv->sock = android_get_control_socket(addr.sun_path);
+ if (priv->sock >= 0)
+ {
+ stp_printf(MSG_INFO, "priv->sock already exist\n");
+ goto havesock;
+ }
+*/
+ if (os_strncmp(buf, "DIR=", 4) == 0) {
+ dir = buf + 4;
+ gid_str = os_strstr(dir, " GROUP=");
+ if (gid_str) {
+ *gid_str = '\0';
+ gid_str += 7;
+ }
+ } else {
+ dir = buf;
+ gid_str = stp_d->ctrl_interface_group;
+ }
+
+ if (mkdir(dir, 00777) < 0)
+ {
+ if (errno == EEXIST)
+ {
+ stp_printf(MSG_INFO, "Using existing control "
+ "interface directory.\n");
+ }
+ else
+ {
+ stp_printf(MSG_ERROR, "mkdir (%s) failed:(%s)\n", dir, strerror(errno));
+ perror("mkdir[ctrl_interface]");
+ goto fail;
+ }
+ }
+ stp_printf(MSG_INFO, "mkdir (%s) succeed\n", dir);
+ if (gid_str)
+ {
+ //grp = getgrnam("system");
+ grp = getgrnam("sys");
+ if (grp)
+ {
+ gid = grp->gr_gid;
+ gid_set = 1;
+ stp_printf(MSG_INFO, "ctrl_interface_group=%d"
+ " (from group name '%s')\n",
+ (int) gid, gid_str);
+ }
+ else
+ {
+ /* Group name not found - try to parse this as gid */
+ gid = strtol(gid_str, &endp, 10);
+ if (*gid_str == '\0' || *endp != '\0') {
+ stp_printf(MSG_ERROR, "CTRL: Invalid group "
+ "'%s'\n", gid_str);
+ goto fail;
+ }
+ gid_set = 1;
+ stp_printf(MSG_INFO, "ctrl_interface_group=%d\n",
+ (int) gid);
+ }
+ }
+
+ if (gid_set && chown(dir, getuid(), gid) < 0)
+ {
+ perror("chown[ctrl_interface]");
+ stp_printf(MSG_ERROR, "chown (%s) failed\n", dir);
+ goto fail;
+ }
+ stp_printf(MSG_INFO, "chown (%s) succeed\n", dir);
+
+ /* Make sure the group can enter and read the directory */
+ if (gid_set &&
+ chmod(dir, 00775) < 0)
+ {
+ stp_printf(MSG_ERROR, "CTRL: chmod[%s]: %s\n", dir, strerror(errno));
+ goto fail;
+ }
+ stp_printf(MSG_INFO, "CTRL: chmod[%s] succeed\n", dir);
+ if (os_strlen(dir) + 1 + os_strlen(stp_d->ifname) >=
+ sizeof(addr.sun_path))
+ {
+ stp_printf(MSG_ERROR, "ctrl_iface path limit exceeded\n");
+ goto fail;
+ }
+
+ if (stp_dump_ctrl_iface_trace_logger_start(tr_priv))
+ goto fail;
+ priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (priv->sock < 0)
+ {
+ perror("socket(PF_UNIX)");
+ stp_printf(MSG_ERROR, "create socket failed\n");
+ goto fail;
+ }
+
+ os_memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+
+ fname = stp_dump_ctrl_iface_path(stp_d);
+
+ if (fname == NULL)
+ {
+ stp_printf(MSG_ERROR, "stp_dump_ctrl_iface_path failed\n");
+ goto fail;
+ }
+ os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
+ if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ stp_printf(MSG_ERROR, "ctrl_iface bind(PF_UNIX) failed: %s\n",
+ strerror(errno));
+ if (connect(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ stp_printf(MSG_ERROR, "ctrl_iface exists, but does not"
+ " allow connections - assuming it was left"
+ "over from forced program termination\n");
+ if (unlink(fname) < 0) {
+ perror("unlink[ctrl_iface]");
+ stp_printf(MSG_ERROR, "Could not unlink "
+ "existing ctrl_iface socket '%s'\n",
+ fname);
+ goto fail;
+ }
+ if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("bind(PF_UNIX)");
+ goto fail;
+ }
+ stp_printf(MSG_DEBUG, "Successfully replaced leftover " "ctrl_iface socket '%s'\n", fname);
+ } else {
+ stp_printf(MSG_INFO, "ctrl_iface exists and seems to " "be in use - cannot override it\n");
+ stp_printf(MSG_INFO, "Delete '%s' manually if it is "
+ "not used anymore\n", fname);
+ os_free(fname);
+ fname = NULL;
+ goto fail;
+ }
+ }
+ if (gid_set && chown(fname, -1, gid) < 0) {
+ perror("chown[ctrl_interface/ifname]");
+ stp_printf(MSG_ERROR, "chown(%s) failed, ", fname);
+ goto fail;
+ }
+
+ if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
+ perror("chmod[ctrl_interface/ifname]");
+ stp_printf(MSG_ERROR, "chmod(%s) failed, ", fname);
+ goto fail;
+ }
+ os_free(fname);
+ fname = NULL;
+ /* open wmt dev */
+ stp_d->wmt_fd = open("/dev/stpwmt", O_RDWR | O_NOCTTY);
+ if (stp_d->wmt_fd < 0) {
+ stp_printf(MSG_ERROR, "[%s] Can't open stpwmt \n", __FUNCTION__);
+ goto fail;
+ }
+ tr_priv->stp_d->chip_type = ioctl(tr_priv->stp_d->wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 4);
+
+havesock:
+ eloop_register_read_sock(priv->sock, stp_dump_ctrl_iface_receive,
+ stp_d, priv);
+
+ os_free(buf);
+ buf = NULL;
+ return priv;
+
+fail:
+ if (priv->sock >= 0)
+ close(priv->sock);
+ os_free(priv);
+ os_free(tr_priv);
+ priv = NULL;
+ tr_priv = NULL;
+ if (fname) {
+ unlink(fname);
+ os_free(fname);
+ fname = NULL;
+ }
+ os_free(buf);
+ buf = NULL;
+ return NULL;
+}
+
+
+void stp_dump_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
+{
+#if 0
+ struct wpa_ctrl_dst *dst, *prev;
+#endif
+ struct stp_ctrl_dst *dst, *prev;
+ stp_printf(MSG_INFO, "%s\n", __func__);
+ os_sleep(1, 0);
+ /* close wmt dev */
+ if (priv->stp_d->wmt_fd >= 0) {
+ close(priv->stp_d->wmt_fd);
+ }
+
+ if (priv->sock > -1) {
+ char *fname;
+ char *buf, *dir = NULL, *gid_str = NULL;
+ eloop_unregister_read_sock(priv->sock);
+ if (priv->ctrl_dst) {
+ /*
+ * Wait a second before closing the control socket if
+ * there are any attached monitors in order to allow
+ * them to receive any pending messages.
+ */
+ stp_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
+ "monitors to receive messages\n");
+ os_sleep(1, 0);
+ }
+ close(priv->sock);
+ priv->sock = -1;
+#if 0
+ fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s);
+#endif
+ fname = stp_dump_ctrl_iface_path(priv->stp_d);
+ if (fname) {
+ unlink(fname);
+ os_free(fname);
+ fname = NULL;
+ }
+#if 0
+ buf = os_strdup(priv->wpa_s->conf->ctrl_interface);
+#endif
+ buf = os_strdup(priv->stp_d->ctrl_interface);
+ if (buf == NULL)
+ goto free_dst;
+ if (os_strncmp(buf, "DIR=", 4) == 0) {
+ dir = buf + 4;
+ gid_str = os_strstr(dir, " GROUP=");
+ if (gid_str) {
+ *gid_str = '\0';
+ gid_str += 7;
+ }
+ } else
+ dir = buf;
+
+ if (rmdir(dir) < 0) {
+ if (errno == ENOTEMPTY) {
+ stp_printf(MSG_DEBUG, "Control interface "
+ "directory not empty - leaving it "
+ "behind\n");
+ } else {
+ perror("rmdir[ctrl_interface]");
+ }
+ }
+ os_free(buf);
+ }
+
+free_dst:
+ dst = priv->ctrl_dst;
+ while (dst) {
+ prev = dst;
+ dst = dst->next;
+ os_free(prev);
+ }
+ os_free(priv);
+}
+
+void stp_dump_ctrl_iface_wait(struct ctrl_iface_priv *priv)
+{
+ char buf[256];
+ int res;
+ struct sockaddr_un from;
+ socklen_t fromlen = sizeof(from);
+
+ for (;;) {
+ stp_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to "
+ "attach\n", priv->stp_d->ifname);
+ eloop_wait_for_read_sock(priv->sock);
+
+ res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0,
+ (struct sockaddr *) &from, &fromlen);
+ if (res < 0) {
+ perror("recvfrom(ctrl_iface)");
+ continue;
+ }
+ buf[res] = '\0';
+
+ if (os_strcmp(buf, "ATTACH") == 0) {
+ /* handle ATTACH signal of first monitor interface */
+ if (!stp_dump_ctrl_iface_attach(priv, &from,
+ fromlen)) {
+ if (0 > sendto(priv->sock, "OK\n", 3, 0, (struct sockaddr *) &from, fromlen))
+ perror("send string 'OK' to sock error\n");
+ /* OK to continue */
+ return;
+ } else {
+ if (0 > sendto(priv->sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, fromlen))
+ perror("send string 'FAIL' to sock error\n");
+ }
+ } else {
+ /* return FAIL for all other signals */
+ if (0 > sendto(priv->sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, fromlen))
+ perror("send string 'FAIL' to sock error\n");
+ }
+ }
+}
+
+static void stp_dump_terminate(__attribute__((unused))int sig, __attribute__((unused))void *eloop_ctx,
+ __attribute__((unused))void *signal_ctx)
+{
+ eloop_terminate();
+}
+
+int stp_dump_run(void)
+{
+ eloop_register_signal_terminate(stp_dump_terminate, NULL);
+ eloop_run();
+ return 0;
+}
+
+void set_sched_prio(void)
+{
+ struct sched_param sched, test_sched;
+ int policy = 0xff;
+ int err=0xff;
+
+ policy = sched_getscheduler(0);
+ sched_getparam(0, &test_sched);
+ printf("Before %s policy = %d, priority = %d\n", "main" , policy, test_sched.sched_priority);
+
+ sched.sched_priority = sched_get_priority_max(SCHED_FIFO);
+ err = sched_setscheduler(0, SCHED_FIFO, &sched);
+ if(err == 0){
+ printf("pthread_setschedparam SUCCESS \n");
+ policy = sched_getscheduler(0);
+ sched_getparam(0, &test_sched);
+ printf("After %s policy = %d, priority = %d\n", "main" ,policy , test_sched.sched_priority);
+ }
+ else{
+ if(err == EINVAL) printf("policy is not one of SCHED_OTHER, SCHED_RR, SCHED_FIFO\n");
+ if(err == EINVAL) printf("the priority value specified by param is not valid for the specified policy\n");
+ if(err == EPERM) printf("the calling process does not have superuser permissions\n");
+ if(err == ESRCH) printf("the target_thread is invalid or has already terminated\n");
+ if(err == EFAULT) printf("param points outside the process memory space\n");
+ printf("pthread_setschedparam FAIL \n");
+ }
+}
+
+int main(__attribute__((unused))int argc, __attribute__((unused))char *argv[]){
+
+ struct stp_dump *stp_d = NULL;
+ /* This folder is created by init_connectivity.rc*/
+ const char *conf ="DIR=/data/misc/stp_dump GROUP=stp";
+ const char *ifname = "stpd";
+ const char *sname = "data/misc";
+ char value[PROPERTY_VALUE_MAX];
+
+ stp_printf(MSG_INFO, "==>%s \n", __func__ );
+
+/*
+ wait_sdcard_ready();
+
+ property_get("ro.crypto.state", value, "");
+ if (!strcmp(value, "")) {
+ do {
+ stp_printf(MSG_INFO, "ro.crypto.state is NULL, Retry");
+ sleep(1);
+ property_get("ro.crypto.state", value, "");
+ stp_printf(MSG_INFO, "ro.crypto.state: %s!", value);
+ }while(!strcmp(value, ""));
+ }
+ stp_printf(MSG_INFO, "ro.crypto.state: %s!", value);
+ if (0 == strcmp(value, "encrypted")) {
+ property_get("ro.crypto.type", value, "");
+ if (!strcmp(value, "file")) {
+ do {
+ stp_printf(MSG_INFO, "FBE feature is open, waiting for decrypt done");
+ sleep(1);
+ if (access(sname, F_OK|R_OK|W_OK) == 0)
+ break;
+ } while (1);
+ } else {
+ property_get("vold.decrypt", value, "");
+ if (strcmp(value, "trigger_restart_framework")) {
+ do {
+ stp_printf(MSG_INFO, "Waiting for decrypt done");
+ sleep(1);
+ property_get("vold.decrypt", value, "");
+ stp_printf(MSG_INFO, "vold.decrypt: %s!", value);
+ }while(strcmp(value, "trigger_restart_framework"));
+ }
+ stp_printf(MSG_INFO, "vold.decrypt: %s!", value);
+ }
+ stp_printf(MSG_INFO, "Decrypt done!");
+ } else
+ stp_printf(MSG_INFO, "Device is unencrypted!");
+*/
+ stp_d = os_zalloc(sizeof(struct stp_dump));
+ if (stp_d == NULL)
+ {
+ stp_printf(MSG_ERROR, "memory allocation for stp_dump failed\n");
+ return -1;
+ }
+ stp_d->ctrl_interface = conf;
+ stp_d->ifname = ifname;
+ stp_d->ctrl_iface = stp_dump_ctrl_iface_init(stp_d);
+ if (stp_d->ctrl_iface == NULL)
+ {
+ stp_printf(MSG_ERROR,
+ "Failed to initialize control interface '%s'.\n"
+ "You may have another stp_dump process "
+ "already running or the file was\n"
+ "left by an unclean termination of stp_dump "
+ "in which case you will need\n"
+ "to manually remove this file before starting "
+ "wpa_supplicant again.\n",
+ "used by stp_dump\n");
+ return -1;
+ }
+ else
+ {
+ stp_printf(MSG_INFO, "stp_dump_ctrl_iface_init succeed.\n");
+ }
+ stp_printf(MSG_INFO, "==>%s222 \n", __func__ );
+
+ //set_sched_prio();
+
+ bt_fw_logger_start();
+
+ wifi_fw_logger_start();
+
+ stp_dump_run();
+
+ stp_dump_ctrl_iface_deinit(stp_d->ctrl_iface);
+
+ wifi_fw_logger_stop();
+
+ bt_fw_logger_stop();
+ os_free(stp_d);
+
+ return 0;
+}
+
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/stp_dump.h b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/stp_dump.h
new file mode 100644
index 0000000..c5fad81
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/stp_dump.h
@@ -0,0 +1,65 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef STP_DUMP_H
+#define STP_DUMP_H
+extern int stp_debug_level;
+
+#ifndef ALOGI
+#define ALOGI printf
+#endif
+#ifndef ALOGE
+#define ALOGE printf
+#endif
+#ifndef ALOGD
+#define ALOGD printf
+#endif
+
+#ifndef PROPERTY_VALUE_MAX
+#define PROPERTY_VALUE_MAX (128)
+#endif
+
+
+enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR };
+extern void android_printf(int level, char *format, ...);
+#define stp_printf(level, ...) \
+ do { \
+ printf(__VA_ARGS__); \
+ } while (0)
+
+#endif
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/wifi_fw_logger.c b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/wifi_fw_logger.c
new file mode 100644
index 0000000..e4e6e84
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/wifi_fw_logger.c
@@ -0,0 +1,311 @@
+/**
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <pthread.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+#define WIFI_FW_LOG_NODE "/dev/fw_log_wifi"
+#define WIFI_FW_LOG_PATH "/data/misc/stp_dump"
+#define DUMP_WIFI_FW_NAME_EXT ".wifi"
+#define DUMP_WIFI_FW_NAME_PREFIX "dump_"
+#define WIFI_FW_LOG_SIZE (1 * 1024 * 1024)
+#define WIFI_FW_LOG_BUF_SIZE (1944) // Cover old WIFI driver return size
+#define LOG_VERSION 0x100
+
+#define TRUE (1)
+#define FALSE (0)
+
+static const unsigned long BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL;
+static unsigned long timestamp = 0;
+static unsigned int dump_file_seq_num = 0;
+static int file_size_remain_to_switch = 0;
+static uint8_t buffer[WIFI_FW_LOG_BUF_SIZE] = {0};
+static int log_file_num = 6;
+static int logger_on = 1;
+
+static pthread_t wifi_fw_logger_thread = 0;
+static int wifi_fw_log_fd = 0;
+
+static void remove_old_log_files(int all, int index)
+{
+ /* check already exist file under log_path */
+ char temp_wifi_fw_filename[36] = {0};
+ char wifi_fw_fullname[256] = {0};
+
+ DIR *p_dir = opendir(WIFI_FW_LOG_PATH);
+ if (p_dir != NULL)
+ {
+ struct dirent *p_file;
+ while ((p_file = readdir(p_dir)) != NULL)
+ {
+ /* ignore . and .. directory */
+ if (strncmp(p_file->d_name, "..", 2) == 0
+ || strncmp(p_file->d_name, ".", 1) == 0)
+ {
+ continue;
+ }
+ memset(temp_wifi_fw_filename, 0, sizeof(temp_wifi_fw_filename));
+ memset(wifi_fw_fullname, 0, sizeof(wifi_fw_fullname));
+ if (strstr(p_file->d_name, DUMP_WIFI_FW_NAME_EXT) != NULL)
+ {
+ if (all) //remove all old log files
+ {
+ snprintf(wifi_fw_fullname, sizeof(wifi_fw_fullname), "%s/%s", WIFI_FW_LOG_PATH, p_file->d_name);
+ if (remove(wifi_fw_fullname)) {
+ printf("[wifi_fw_logger]The old log:%s can't remove, errno: %d\n", p_file->d_name, errno);
+ }
+ else {
+ printf("[wifi_fw_logger]The old log: %s is removed\n", p_file->d_name);
+ }
+ }
+ else //remove a specific log file
+ {
+ snprintf(temp_wifi_fw_filename, sizeof(temp_wifi_fw_filename), "_%d.wifi", index);
+ if (strstr(p_file->d_name, temp_wifi_fw_filename) != NULL) {
+ snprintf(wifi_fw_fullname, sizeof(wifi_fw_fullname), "%s/%s", WIFI_FW_LOG_PATH, p_file->d_name);
+ if (remove(wifi_fw_fullname)) {
+ printf("[wifi_fw_logger]The old log: %s can't remove, errno: %d\n", p_file->d_name, errno);
+ } else {
+ printf("[wifi_fw_logger]The old log: %s is removed\n", p_file->d_name);
+ }
+ }
+ }
+ }
+ }
+ closedir(p_dir);
+ }
+ else
+ {
+ printf("[wifi_fw_logger]readdir fail, errno: %d\n", errno);
+ }
+}
+
+static unsigned long btsnoop_timestamp(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ // Timestamp is in microseconds.
+ timestamp = tv.tv_sec * 1000000ULL;
+ timestamp += tv.tv_usec;
+ timestamp += BTSNOOP_EPOCH_DELTA;
+ return timestamp;
+}
+
+static void fillheader(unsigned char *header, int headerlen,
+ unsigned short int dump_file_seq_num)
+{
+ int copy_header_len = 0;
+ unsigned int logversion = htobe32(LOG_VERSION);
+ memset(header, 0, headerlen);
+ memcpy(header, &logversion, sizeof(logversion));
+ copy_header_len += 4; /** 4 byte for logversion */
+ copy_header_len += 4; /** 4 byte for chip id, not implement yet */
+ dump_file_seq_num = htobe16(dump_file_seq_num);
+ memcpy(header + copy_header_len, &dump_file_seq_num, sizeof(dump_file_seq_num));
+ copy_header_len += 2; /** 2 byte for sequence number */
+ copy_header_len += 6; /** first hci log length(2), zero(4) */
+ btsnoop_timestamp();
+ timestamp = htobe64(timestamp);
+ memcpy(header + copy_header_len, ×tamp, sizeof(timestamp));
+}
+
+static FILE * create_new_log_file(int index)
+{
+ time_t local_timestamp;
+ char timestamp_buffer[24];
+ char dump_file_name[128] = {0};
+ unsigned char header[24] = {0};
+ unsigned char padding[8] = {0};
+ FILE *fp = NULL;
+
+ /* get current timestamp */
+ time(&local_timestamp);
+ strftime(timestamp_buffer, 24, "%Y%m%d%H%M%S", localtime(&local_timestamp));
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/" DUMP_WIFI_FW_NAME_PREFIX "%s_%d" DUMP_WIFI_FW_NAME_EXT, WIFI_FW_LOG_PATH, timestamp_buffer, index);
+
+ /* dump file for picus log */
+ if ((fp = fopen(dump_file_name, "wb")) == NULL) {
+ printf("[wifi_fw_logger]create log file %s fail [%s] errno %d\n", dump_file_name, strerror(errno), errno);
+ return NULL;
+ } else {
+ printf("[wifi_fw_logger]log file %s is created, dumping...\n", dump_file_name);
+ }
+
+ fillheader(header, sizeof(header), index);
+ fwrite(header, 1, sizeof(header), fp);
+ fwrite(padding, 1, sizeof(padding), fp);
+ file_size_remain_to_switch = WIFI_FW_LOG_SIZE;
+
+ return fp;
+}
+
+static void *wifi_fw_logger_main(void *arg)
+{
+ int nRead = 0;
+ int nWritten = 0;
+ fd_set rset; /** For select */
+ struct timeval tv;
+ FILE *current_fp = NULL;
+ int current_index = 0;
+
+ printf("[wifi_fw_logger]%s, thread_id: 0x%x\n", __func__, pthread_self());
+
+ current_fp = create_new_log_file(0);
+ if (NULL == current_fp)
+ {
+ printf("[wifi_fw_logger]fatal error: create new log file fail\n");
+ return NULL;
+ }
+
+ do
+ {
+ FD_ZERO(&rset);
+ FD_SET(wifi_fw_log_fd, &rset);
+ tv.tv_sec = 10; /* timeout is 10s for select method */
+ tv.tv_usec = 0;
+ if (select(wifi_fw_log_fd + 1, &rset, NULL, NULL, &tv) == 0) {
+ printf("[wifi_fw_logger]Read data timeout(10s) from fw_log_wifi\n");
+ continue;
+ }
+
+ if (!FD_ISSET(wifi_fw_log_fd, &rset))
+ continue;
+ /* Read all packet from driver fwlog queue */
+ nRead = read(wifi_fw_log_fd, buffer, sizeof(buffer));
+ if (nRead > 0)
+ {
+ nWritten = fwrite(buffer, 1, nRead, current_fp);
+ if (nWritten != nRead)
+ {
+ printf("[wifi_fw_logger]write may fail, nRead(%d) != nWritten(%d)\n", nRead, nWritten);
+ }
+ file_size_remain_to_switch -= nWritten;
+ }
+ else if (nRead < 0)
+ {
+ printf("[wifi_fw_logger]read fail, errno=%d\n", errno);
+ continue;
+ }
+ /* switch file name if file size is over file_size */
+ if (file_size_remain_to_switch <= 0) {
+ file_size_remain_to_switch = WIFI_FW_LOG_SIZE;
+ fclose(current_fp);
+ if (log_file_num - 1 > current_index) {
+ current_index++;
+ } else {
+ current_index = 0;
+ }
+ /* remove the file before creating */
+ remove_old_log_files(FALSE, current_index);
+ current_fp = create_new_log_file(current_index);
+ if (NULL == current_fp)
+ {
+ printf("[wifi_fw_logger]create new log file fail\n");
+ //TODO
+ }
+ }
+ fflush(current_fp);
+ } while (logger_on);
+
+
+ printf("[wifi_fw_logger]%s exit, thread_id: 0x%x\n", __func__, pthread_self());
+
+ return NULL;
+}
+
+
+void wifi_fw_logger_start(void)
+{
+ printf("[wifi_fw_logger]%s\n", __func__);
+ if (wifi_fw_log_fd > 0)
+ {
+ printf("%s, device is already opened\n", __func__);
+ return;
+ }
+ //1. open device
+ wifi_fw_log_fd = open(WIFI_FW_LOG_NODE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ if (wifi_fw_log_fd <= 0) {
+ printf("[wifi_fw_logger]Can't open device node %s, errno: %d\n", WIFI_FW_LOG_NODE, errno);
+ return;
+ } else {
+ printf("[wifi_fw_logger]Open device node successfully wifi_fw_log_fd = %d\n", wifi_fw_log_fd);
+ }
+
+ remove_old_log_files(TRUE, 0);
+
+ //2. create logger thread
+ if (wifi_fw_logger_thread == 0)
+ {
+ pthread_attr_t thread_attr;
+
+ pthread_attr_init(&thread_attr);
+ pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
+ if (pthread_create(&wifi_fw_logger_thread, &thread_attr, wifi_fw_logger_main, NULL))
+ {
+ printf("[wifi_fw_logger]create logger thread fail\n",__func__);
+ wifi_fw_logger_thread = 0;
+ return;
+ }
+ pthread_attr_destroy(&thread_attr);
+ }
+}
+
+void wifi_fw_logger_stop(void)
+{
+ //disable fw log first
+ //system("echo raw-hex, 01 5d fc 04 02 00 01 00 > /dev/fw_log_bt");
+
+ if (wifi_fw_log_fd > 0)
+ {
+ close(wifi_fw_log_fd);
+ }
+
+ //thread exit
+ logger_on = 0;
+ wifi_fw_logger_thread = 0;
+ printf("[wifi_fw_logger]%s\n", __func__);
+
+}
+//---------------------------------------------------------------------------
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/wifi_fw_logger.h b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/wifi_fw_logger.h
new file mode 100644
index 0000000..4a6814b
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_dump/wifi_fw_logger.h
@@ -0,0 +1,40 @@
+/**
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+void wifi_fw_logger_start(void);
+void wifi_fw_logger_stop(void);
+
+
+//---------------------------------------------------------------------------
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/stp_uart_launcher.c b/src/connectivity/combo_tool/6631_combo_tool/src/stp_uart_launcher.c
new file mode 100644
index 0000000..cc489a9
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/stp_uart_launcher.c
@@ -0,0 +1,1831 @@
+
+/******************************************************************************
+* C O M P I L E R F L A G S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+*******************************************************************************
+*/
+#include "wmt_ioctl.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <pthread.h>
+/*#include <syslog.h>*/
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/endian.h>
+#include <sys/uio.h>
+#include <linux/serial.h> /* struct serial_struct */
+#include <log/log.h>
+
+#include <dirent.h>
+#include <cutils/properties.h>
+
+
+/******************************************************************************
+* M A C R O S
+*******************************************************************************
+*/
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "wmt_launcher"
+
+#define WCN_COMBO_CHIP_ID_PROP "persist.vendor.connsys.chipid"
+#define WCN_DRIVER_READY_PROP "vendor.connsys.driver.ready"
+#define WCN_FORMETA_READY_PROP "vendor.connsys.formeta.ready"
+#define WCN_FW_DBG_LOG_PROP "persist.vendor.connsys.fwlog.status"
+#define WCN_DYNAMIC_DUMP_PROP "persist.vendor.connsys.dynamic.dump"
+#define WCN_COMBO_PATCH_BUILD_VER_PROP "persist.vendor.connsys.patch.version"
+#define WCN_FW_DEBUG_CLRL_RETRY_LIMIT (5)
+
+//#include "cust_mt6620_test.h" /* project custom header file */
+
+#ifndef N_MTKSTP
+#define N_MTKSTP (15 + 1) /* MediaTek WCN Serial Transport Protocol */
+#endif
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+#define CUST_COMBO_WMT_DEV "/dev/stpwmt"
+#define CUST_COMBO_STP_DEV "/dev/ttyMT2"
+#define CUST_COMBO_PATCH_PATH "/vendor/firmware"
+#define CUST_COMBO_CFG_FILE "/system/vendor/firmware/WMT.cfg"
+
+#define CUST_BAUDRATE_DFT (115200)
+#define CUST_MULTI_PATCH (1)
+#define CUST_PATCH_SEARCH (1)
+#define PATCH_BUILD_VER_LEN (16)
+#define MAX_CMD_LEN (NAME_MAX+1)
+
+#define LAUNCHER_DEBUG (0)
+
+/******************************************************************************
+* D A T A T Y P E S
+*******************************************************************************
+*/
+
+enum stp_modes {
+ STP_MIN = 0x0,
+ STP_UART_FULL = 0x1,
+ STP_UART_MAND = 0x2,
+ STP_BTIF_FULL = 0x3,
+ STP_SDIO = 0x4,
+ STP_MAX = 0x5,
+};
+
+enum stp_uart_fc {
+ UART_DISABLE_FC = 0, /*NO flow control*/
+ UART_MTK_SW_FC = 1, /*MTK SW Flow Control, differs from Linux Flow Control*/
+ UART_LINUX_FC = 2, /*Linux SW Flow Control*/
+ UART_HW_FC = 3, /*HW Flow Control*/
+};
+
+struct sys_property {
+ const char *key;
+ const char *def_value;
+ char value[PROPERTY_VALUE_MAX];
+};
+
+
+struct stp_uart_config {
+ enum stp_uart_fc fc;
+ int parity;
+ int stop_bit;
+ int baud_rate;
+};
+
+struct stp_params_config {
+ enum stp_modes stp_mode;
+ int fm_mode;
+ char patch_path[NAME_MAX + 1];
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ char patch_name[NAME_MAX + 1];
+#endif
+ char stp_dev[NAME_MAX + 1];
+ struct stp_uart_config uart_config;
+};
+
+
+#if CUST_MULTI_PATCH
+struct stp_patch_info {
+ int download_seq;
+ char address[4];
+ char patch_name[NAME_MAX + 1];
+};
+
+struct stp_rom_patch_info {
+ int type;
+ char address[4];
+ char patch_name[NAME_MAX + 1];
+};
+#endif
+
+struct chip_ant_mode_info {
+ const char *cfg_item;
+ char cfg_item_value[NAME_MAX + 1];
+};
+
+struct chip_mode_info {
+ int chip_id;
+ enum stp_modes stp_mode;
+ struct chip_ant_mode_info ant_mode;
+};
+
+#ifndef WMT_PLAT_APEX
+struct chip_mode_info g_chip_mode_info[] = {
+ {0x6620, STP_UART_FULL, {"mt6620.defAnt", "mt6620_ant_m3.cfg"}},
+ {0x6628, STP_UART_FULL, {"mt6628.defAnt", "mt6628_ant_m1.cfg"}},
+ {0x6630, STP_SDIO, {"mt6630.defAnt", "mt6630_ant_m1.cfg"}},
+ {0x6632, STP_SDIO, {"mt6632.defAnt", "mt6632_ant_m1.cfg"}},
+};
+#else
+struct chip_mode_info g_chip_mode_info[] = {
+ {0x6620, STP_UART_FULL, {"mt6620.defAnt", "WMT.cfg"}},
+ {0x6628, STP_UART_FULL, {"mt6628.defAnt", "WMT.cfg"}},
+ {0x6630, STP_SDIO, {"mt6630.defAnt", "WMT.cfg"}},
+ {0x6632, STP_SDIO, {"mt6632.defAnt", "WMT.cfg"}},
+};
+#endif
+
+struct fw_debug_infor {
+ int log_retry; /* for polling log property retry */
+ int dump_retry; /*for polling dump property retry */
+
+ int fw_log_ctrl; /* fw log output by emi ctrl */
+ int fw_dynamic_dump; /*fw coredump dynamic regin dump*/
+
+ /* fw log output by emi state ctrl */
+ char fw_log_state_orig[PROPERTY_VALUE_MAX];
+ char fw_log_state_new[PROPERTY_VALUE_MAX];
+
+ /* fw coredump dynamic regin dump state ctrl */
+ char fw_dump_state_orig[PROPERTY_VALUE_MAX];
+ char fw_dump_state_new[PROPERTY_VALUE_MAX];
+
+ unsigned int bitmap;
+};
+
+struct cmd_hdr{
+ char *cmd;
+ int (*hdr_func)(struct stp_params_config *configs);
+};
+
+struct speed_map {
+ unsigned int baud;
+ speed_t speed;
+};
+
+/******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+*******************************************************************************
+*/
+static int cmd_hdr_baud_115k(struct stp_params_config *configs);
+static int cmd_hdr_baud_921k(struct stp_params_config *configs);
+static int cmd_hdr_baud_2kk(struct stp_params_config *configs);
+static int cmd_hdr_baud_2_5kk(struct stp_params_config *configs);
+static int cmd_hdr_baud_3kk(struct stp_params_config *configs);
+static int cmd_hdr_baud_3_5kk(struct stp_params_config *configs);
+static int cmd_hdr_baud_4kk(struct stp_params_config *configs);
+static int cmd_hdr_stp_open(struct stp_params_config *configs);
+static int cmd_hdr_stp_close(struct stp_params_config *configs);
+static int cmd_hdr_stp_rst(struct stp_params_config *configs);
+static int cmd_hdr_sch_patch(struct stp_params_config *configs);
+static int cmd_hdr_sch_rom_patch(struct stp_params_config *configs);
+
+
+/******************************************************************************
+* P U B L I C D A T A
+*******************************************************************************
+*/
+
+/******************************************************************************
+* P R I V A T E D A T A
+*******************************************************************************
+*/
+static struct speed_map g_speeds[] = {
+ {115200, B115200},
+ {921600, B921600},
+ {1000000, B1000000},
+ {1152000, B1152000},
+ {2000000, B2000000},
+ {2500000, B2500000},
+ {3000000, B3000000},
+ {3500000, B3500000},
+ {4000000, B4000000},
+};
+
+struct cmd_hdr g_cmd_hdr_table[] = {
+ { "baud_115200_0", cmd_hdr_baud_115k},
+ { "baud_921600_0", cmd_hdr_baud_921k},
+ { "baud_2000000_0", cmd_hdr_baud_2kk},
+ { "baud_2500000_0", cmd_hdr_baud_2_5kk},
+ { "baud_3000000_0", cmd_hdr_baud_3kk},
+ { "baud_3500000_0", cmd_hdr_baud_3_5kk},
+ { "baud_4000000_0", cmd_hdr_baud_4kk},
+ { "open_stp", cmd_hdr_stp_open},
+ { "close_stp", cmd_hdr_stp_close},
+ { "rst_stp", cmd_hdr_stp_rst},
+ { "srh_patch", cmd_hdr_sch_patch},
+ { "srh_rom_patch", cmd_hdr_sch_rom_patch},
+};
+
+static volatile sig_atomic_t __io_canceled = 0;
+static char g_wmt_cfg_name[NAME_MAX + 1] = {0};
+static int g_wmt_fd = -1;
+static int g_tty_fd = -1;
+static char g_cmd_str[MAX_CMD_LEN]= {0};
+static char g_resp_str[MAX_CMD_LEN]= {0};
+static struct stp_params_config g_stp_param_config;
+
+pthread_t g_thread_handle = -1;
+static struct fw_debug_infor g_fw_debug_infor;
+
+#if CUST_MULTI_PATCH
+static char g_patch_prefix[16];
+#endif
+/******************************************************************************
+* F U N C T I O N S
+*******************************************************************************
+*/
+
+static speed_t get_speed(int baud_rate) {
+ unsigned int idx;
+ for (idx = 0; idx < sizeof(g_speeds)/sizeof(g_speeds[0]); idx++) {
+ if (baud_rate == (int)g_speeds[idx].baud) {
+ return g_speeds[idx].speed;
+ }
+ }
+ return CBAUDEX;
+}
+
+static int set_speed(int fd, struct termios *ti, int speed) {
+ struct serial_struct ss;
+ int baudenum = get_speed(speed);
+
+ if (speed != CBAUDEX) {
+ /*printf("%s: standard baudrate: %d -> 0x%08x\n", __FUNCTION__, speed, baudenum);*/
+ if ((ioctl(fd, TIOCGSERIAL, &ss)) < 0) {
+ ALOGE("%s: BAUD: error to get the serial_struct info:%s\n", __FUNCTION__, strerror(errno));
+ return -1;
+ }
+ ss.flags &= ~ASYNC_SPD_CUST;
+#if defined(SERIAL_STRUCT_EXT) /*modified in serial_struct.h*/
+ memset(ss.reserved, 0x00, sizeof(ss.reserved));
+#endif
+ ss.flags |= (1 << 13); /*set UPFLOWLATENCY flat to tty, or serial_core will reset tty->low_latency to 0*/
+ /*set standard buadrate setting*/
+ if ((ioctl(fd, TIOCSSERIAL, &ss)) < 0) {
+ ALOGE("%s: BAUD: error to set serial_struct:%s\n", __FUNCTION__, strerror(errno));
+ return -2;
+ }
+ cfsetospeed(ti, baudenum);
+ cfsetispeed(ti, baudenum);
+ return tcsetattr(fd, TCSANOW, ti);
+ }
+ else {
+ ALOGE("%s: unsupported non-standard baudrate: %d -> 0x%08x\n", __FUNCTION__, speed, baudenum);
+ return -3;
+ }
+}
+/* Used as host uart param setup callback */
+static int launcher_setup_uart_param(int com_port, struct stp_uart_config *uart_config)
+{
+ struct termios ti;
+ int fd;
+
+ if (!uart_config) {
+ ALOGE("Invalid stpUartConfig");
+ return -2;
+ }
+
+ ALOGI("setup_uart_param %d %d\n", uart_config->baud_rate, uart_config->fc);
+
+ fd = com_port;
+ if (fd < 0) {
+ ALOGE("Invalid serial port");
+ return -2;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (tcgetattr(fd, &ti) < 0) {
+ ALOGE("Can't get port settings");
+ return -3;
+ }
+
+ cfmakeraw(&ti);
+
+ ALOGI("ti.c_cflag = 0x%08x\n", ti.c_cflag);
+ ti.c_cflag |= CLOCAL;
+ ALOGI("CLOCAL = 0x%x\n", CLOCAL);
+ ALOGI("(ori)ti.c_iflag = 0x%08x\n", ti.c_iflag);
+ ALOGI("(ori)ti.c_cflag = 0x%08x\n", ti.c_cflag);
+ ALOGI("stpuartconfig->fc= %d (0:none,sw,hw,linux)\n", uart_config->fc);
+
+ if (uart_config->fc == UART_DISABLE_FC) {
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ } else if (uart_config->fc == UART_MTK_SW_FC) {
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag |= 0x80000000; /*MTK Software FC*/
+ } else if (uart_config->fc == UART_HW_FC) {
+ ti.c_cflag |= CRTSCTS; /*RTS, CTS Enable*/
+ ti.c_iflag &= ~(0x80000000);
+ } else if (uart_config->fc == UART_LINUX_FC) {
+ ti.c_iflag |= (IXON | IXOFF | IXANY); /*Linux Software FC*/
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ }else {
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ }
+
+ ALOGI("c_c CRTSCTS = 0x%16x\n", CRTSCTS);
+ ALOGI("c_i IXON = 0x%08x\n", IXON);
+ ALOGI("c_i IXOFF = 0x%08x\n", IXOFF);
+ ALOGI("c_i IXANY = 0x%08x\n", IXANY);
+ ALOGI("(aft)ti.c_iflag = 0x%08x\n", ti.c_iflag);
+ ALOGI("(aft)ti.c_cflag = 0x%08x\n\n", ti.c_cflag);
+
+ if (tcsetattr(fd, TCSANOW, &ti) < 0) {
+ ALOGE("Can't set port settings");
+ return -4;
+ }
+
+ /* Set baudrate */
+ if (set_speed(fd, &ti, uart_config->baud_rate) < 0) {
+ ALOGE("Can't set initial baud rate");
+ return -5;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ return 0;
+}
+static int cmd_hdr_baud_115k(struct stp_params_config *config)
+{
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 115200;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_921k(struct stp_params_config *config)
+{
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 921600;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_2kk(struct stp_params_config *config) {
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 2000000;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_2_5kk(struct stp_params_config *config)
+{
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 2500000;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_3kk(struct stp_params_config *config) {
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 3000000;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_3_5kk(struct stp_params_config *config) {
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 3500000;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_4kk(struct stp_params_config *config) {
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 4000000;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_stp_open(struct stp_params_config *config) {
+ int ld;
+
+ ALOGV("%p\n", config);
+ if ((STP_UART_FULL == g_stp_param_config.stp_mode) && (-1 == g_tty_fd)) {
+ g_tty_fd = open(g_stp_param_config.stp_dev, O_RDWR | O_NOCTTY);
+ if (g_tty_fd < 0) {
+ fprintf(stderr, "Can't open serial port %s\n", g_stp_param_config.stp_dev);
+ return -2;
+ }
+ ALOGI("real_tty(%s) opened(%d)\n", g_stp_param_config.stp_dev, g_tty_fd);
+
+ /* Set TTY to N_MTKSTP line discipline */
+ ld = N_MTKSTP;
+ if (ioctl(g_tty_fd, TIOCSETD, &ld) < 0) {
+ fprintf(stderr, "Can't set ldisc to N_MTKSTP\n");
+ return -3;
+ }
+
+ //printf("Set tty->low_latency\n");
+ if (ioctl(g_tty_fd, HCIUARTSETPROTO, 0) < 0) {
+ ALOGE("Can't set HCIUARTSETPROTO\n");
+ return -4;
+ }
+ return 0;
+ }
+ else {
+ fprintf(stderr, "stp_open fail: stp_mode(%d) real_tty_fd(%d) \n",
+ g_stp_param_config.stp_mode, g_tty_fd);
+ return -1;
+ }
+}
+
+static int cmd_hdr_stp_close(struct stp_params_config *config) {
+ int ld;
+
+ ALOGV("%p\n", config);
+ if ((STP_UART_FULL == g_stp_param_config.stp_mode) && (0 <= g_tty_fd)) {
+ /* Restore TTY line discipline */
+ ld = N_TTY;
+ if (ioctl(g_tty_fd, TIOCSETD, &ld) < 0) {
+ ALOGE("Can't restore line discipline");
+ return -2;
+ }
+
+ close(g_tty_fd);
+ g_tty_fd = -1;
+ return 0;
+ } else if (g_tty_fd == -1)
+ return 0;
+ else {
+ fprintf(stderr, "stp_close fail: stp_mode(%d) real_tty_fd(%d) \n", g_stp_param_config.stp_mode, g_tty_fd);
+ return -1;
+ }
+}
+
+static int cmd_hdr_stp_rst(struct stp_params_config *config) {
+ int ret = 0;
+ /*this step fail?*/
+ ret = cmd_hdr_stp_close(config);
+ /*here, launcher is close state*/
+ ret = cmd_hdr_stp_open(config);
+ return ret;
+}
+
+static void launcher_set_patch_version(int fd)
+{
+ int ret = 0;
+ struct sys_property patch_ver_prop;
+ int bytes;
+ char patch_build_ver[PATCH_BUILD_VER_LEN] = {0};
+
+ /*4.2. read patch header and check if metch with MAJOR+MINOR number in fw version */
+ bytes = read(fd, patch_build_ver, PATCH_BUILD_VER_LEN);
+ if (-1 == bytes)
+ ALOGE("read patch_build_ver failed!\n");
+
+ patch_build_ver[PATCH_BUILD_VER_LEN - 1] = '\0';
+
+ patch_ver_prop.key = WCN_COMBO_PATCH_BUILD_VER_PROP;
+ sprintf(patch_ver_prop.value, "%s", patch_build_ver);
+
+ ret = property_set(patch_ver_prop.key, patch_ver_prop.value);
+ if (0 != ret)
+ ALOGE("set property(%s) to %s failed,ret:%d, errno:%d\n",
+ patch_ver_prop.key, patch_ver_prop.value, ret, errno);
+ else
+ ALOGI("set property(%s) to %s succeed.\n",
+ patch_ver_prop.key, patch_ver_prop.value);
+}
+
+
+#if CUST_MULTI_PATCH
+static int launcher_get_patch_prefix(int chip_id, char **patch_prefix) {
+ /* use malloc for alloc memory is better*/
+ int chip = chip_id;
+
+ if (!patch_prefix) {
+ ALOGE("invalid pointer\n");
+ return -1;
+ }
+
+ if ((0x0321 == chip) || (0x0335 == chip) || (0x0337 == chip)) {
+ chip = 0x6735;
+ ALOGI("for denali chipid convert\n");
+ }
+ if (0x0326 == chip) {
+ chip = 0x6755;
+ ALOGI("for jade chipid convert\n");
+ }
+ if (0x0279 == chip) {
+ chip = 0x6797;
+ ALOGI("for everest chipid convert\n");
+ }
+ if (0x0551 == chip) {
+ chip = 0x6757;
+ ALOGI("for olympus chipid convert\n");
+ }
+ if (0x0633 == chip) {
+ chip = 0x6570;
+ ALOGI("for rushmore chipid convert\n");
+ }
+ if (0x0690 == chip) {
+ chip = 0x6763;
+ ALOGI("for bianco chipid convert\n");
+ }
+ if (0x0507 == chip) {
+ chip = 0x6759;
+ ALOGI("for alaska chipid convert\n");
+ }
+ if (0x0699 == chip) {
+ chip = 0x6739;
+ ALOGI("for zion chipid convert\n");
+ }
+ if (0x0713 == chip) {
+ chip = 0x6775;
+ ALOGI("for cannon chipid convert\n");
+ }
+ if (0x0788 == chip) {
+ chip = 0x6771;
+ ALOGI("for sylvia chipid convert\n");
+ }
+
+ memset(g_patch_prefix, '\0', sizeof(g_patch_prefix));
+
+ switch (chip) {
+ case 0x6572:
+ case 0x6582:
+ case 0x6592:
+ strncpy(g_patch_prefix, "ROMv1", strlen("ROMv1"));
+ break;
+ case 0x8127:
+ case 0x6571:
+ strncpy(g_patch_prefix, "ROMv2", strlen("ROMv2"));
+ break;
+ case 0x6755:
+ case 0x6752:
+ case 0x8163:
+ case 0x7623:
+ case 0x6735:
+ case 0x6570:
+ case 0x6580:
+ case 0x6757:
+ case 0x6763:
+ case 0x6739:
+ case 0x8167:
+ strncpy(g_patch_prefix, "ROMv2_lm", strlen("ROMv2_lm"));
+ break;
+ case 0x6797:
+ strncpy(g_patch_prefix, "ROMv3", strlen("ROMv3"));
+ break;
+ case 0x6759:
+ strncpy(g_patch_prefix, "ROMv4", strlen("ROMv4"));
+ break;
+ case 0x6775:
+ case 0x6771:
+ strncpy(g_patch_prefix, "ROMv4_be", strlen("ROMv4_be"));
+ break;
+ case 0x6765:
+ case 0x3967:
+ case 0x6761:
+ case 0x8168:
+ strncpy(g_patch_prefix, "soc1_0", strlen("soc1_0"));
+ break;
+ default:
+ strncpy(g_patch_prefix, "mt", strlen("mt"));
+ sprintf(g_patch_prefix + strlen("mt"), "%04x", chip);
+ break;
+ }
+ strncat(g_patch_prefix, "_patch", strlen("_patch"));
+
+ ALOGI("patch name pre-fix:%s\n", g_patch_prefix);
+
+ *patch_prefix = g_patch_prefix;
+ return 0;
+}
+
+static int launcher_get_patch_version(int patch_fd, unsigned int *patch_ver)
+{
+ int bytes = -1;
+ int ret = 0;
+
+ bytes = read(patch_fd, ((char *)patch_ver) + 1, 1);
+ if (-1 == bytes) {
+ ALOGE("read patch_ver failed!\n");
+ ret = -1;
+ }
+ bytes = read(patch_fd, ((char *)patch_ver), 1);
+ if (-1 == bytes) {
+ ALOGE("read patch_ver failed!\n");
+ ret = -2;
+ }
+
+ return ret;
+}
+
+static int launcher_set_patch_info(int fd, char *patch_info, char *full_name, int is_first) {
+ int patch_num = -1;
+ int patch_seq = -1;
+ struct stp_patch_info pi;
+
+ if (!patch_info) {
+ ALOGE("invalid patch infor!\n");
+ return -1;
+ }
+ if (!full_name) {
+ ALOGE("invalid patch full name!\n");
+ return -2;
+ }
+
+ if (is_first) {
+ patch_num = (patch_info[0] & 0xF0) >> 4;
+ ALOGI("patch num = [%d]\n", patch_num);
+ ioctl(fd, WMT_IOCTL_SET_PATCH_NUM, patch_num);
+ }
+
+ patch_seq = (patch_info[0] & 0x0F);
+ ALOGI("patch seq = [%d]\n", patch_seq);
+ pi.download_seq = patch_seq;
+ memcpy(pi.address, patch_info, sizeof(pi.address));
+ pi.address[0] = 0x00;
+ strncpy(pi.patch_name, full_name, sizeof(pi.patch_name) - 1);
+ pi.patch_name[sizeof(pi.patch_name) - 1] = '\0';
+
+ ioctl(fd, WMT_IOCTL_SET_PATCH_INFO, &pi);
+
+ return 0;
+}
+
+static int cmd_hdr_sch_patch(struct stp_params_config *config) {
+ int chip_id = 0;
+ int fw_version = 0;
+ char *patch_prefix = NULL;
+ char patch_full_name[256] = {0};
+ char patchName[128] = {0};
+ unsigned int patch_ver = 0;
+ DIR *dir = NULL;
+ int patch_fd = -1;
+ int ret = 0;
+ int bytes;
+ char patch_info[8] = {0};
+ unsigned int is_first = 1;
+ struct dirent* dirent = NULL;
+ int flag;
+
+ if (g_wmt_fd <= 0) {
+ ALOGE("file descriptor is not valid\n");
+ return -1;
+ }
+ /*1. ioctl to get CHIP ID*/
+ chip_id = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 0);
+ if (launcher_get_patch_prefix(chip_id, &patch_prefix)) {
+ ALOGE("launcher_get_patch_prefix fail\n");
+ return -2;
+ }
+
+ /*2. ioctl to get FIRMWARE VERSION*/
+ if (chip_id == 0x6765 || chip_id == 0x3967 ||
+ chip_id == 0x6761 || chip_id == 0x8168 ) {
+#if 0
+ ip_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 3);
+ ALOGI("ip_version:0x%08x\n", ip_version);
+#else
+ fw_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI("fw_version:0x%04x\n", fw_version);
+#endif
+ } else {
+ fw_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI("fw_version:0x%04x\n", fw_version);
+ }
+ /*3. open directory patch located*/
+ strncpy(config->patch_path, CUST_COMBO_PATCH_PATH, strlen(CUST_COMBO_PATCH_PATH));
+ config->patch_path[strlen(CUST_COMBO_PATCH_PATH) + 1] = '\0';
+
+ dir = opendir(config->patch_path);
+ if (NULL == dir) {
+ ALOGE("patch path cannot be opened");
+ return -3;
+ }
+ while (NULL != (dirent = readdir(dir))) {
+ patch_ver = 0;
+ if (0 == (strncmp(dirent->d_name, patch_prefix, strlen(patch_prefix)))) {
+ /*4.1. search patch name begined with chip_name*/
+ strncpy(patch_full_name, config->patch_path, strlen(config->patch_path)+1);
+ /*robust, if input patch is /etc/firmwre/ no issue should be happened.*/
+ strncat(patch_full_name, "/", strlen("/"));
+ strncat(patch_full_name, dirent->d_name, strlen(dirent->d_name));
+ ALOGI("%s\n", patch_full_name);
+ strncpy (patchName, dirent->d_name, strlen(dirent->d_name)+1);
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 <= (patch_fd = (open(patch_full_name, O_RDONLY)))) {
+ launcher_set_patch_version(patch_fd);
+
+ if (-1 != lseek(patch_fd, 22, SEEK_SET)) {
+ if (launcher_get_patch_version(patch_fd, &patch_ver)) {
+ ALOGE("read patch_ver failed!\n");
+ ret = -4;
+ goto read_fail;
+ }
+ /*print hardware version information in patch*/
+ ALOGI("fw Ver in patch: 0x%08x\n", patch_ver);
+ if (chip_id == 0x6765 || chip_id == 0x3967 ||
+ chip_id == 0x6761 || chip_id == 0x8168 )
+#if 0
+ flag = patch_ver == ip_version ? 1 : 0;
+#else
+ flag = (0 == ((patch_ver ^ fw_version) & 0x00ff)) ? 1 : 0;
+#endif
+ else
+ flag = (0 == ((patch_ver ^ fw_version) & 0x00ff)) ? 1 : 0;
+ if (flag) {
+ memset(patch_info, 0, sizeof(patch_info));
+ bytes = read(patch_fd, patch_info, 4);
+ if (-1 == bytes) {
+ ret = -5;
+ ALOGE("read patch_info failed!\n");
+ goto read_fail;
+ }
+ patch_info[4] = '\0';
+ ALOGI("read patch info:0x%02x,0x%02x,0x%02x,0x%02x\n",
+ patch_info[0], patch_info[1], patch_info[2], patch_info[3]);
+ if (launcher_set_patch_info(g_wmt_fd, patch_info, patchName, is_first)) {
+ ALOGE("launcher_set_patch_info fail\n");
+ ret = -6;
+ goto read_fail;
+ }
+ is_first = 0;
+ }
+ } else
+ ALOGE("seek failed\n");
+read_fail:
+ close(patch_fd);
+ patch_fd = -1;
+ } else
+ ALOGE("open patch file(%s) failed\n", patchName);
+ }
+ }
+ /*5. return value*/
+ closedir(dir);
+ dir = NULL;
+
+ return ret;
+}
+
+static int launcher_get_rom_patch_prefix(int chip_id, char **patch_prefix) {
+ /* use malloc for alloc memory is better*/
+ int chip = chip_id;
+
+ if (!patch_prefix) {
+ ALOGE("invalid pointer\n");
+ return -1;
+ }
+
+ memset(g_patch_prefix, '\0', sizeof(g_patch_prefix));
+
+ switch (chip) {
+ case 0x6765:
+ case 0x3967:
+ case 0x6761:
+ case 0x8168:
+ strncpy(g_patch_prefix, "soc1_0", strlen("soc1_0"));
+ break;
+ case 0x6779:
+ strncpy(g_patch_prefix, "soc2_0", strlen("soc2_0"));
+ break;
+ default:
+ strncpy(g_patch_prefix, "soc1_0", strlen("soc1_0"));
+ break;
+
+ }
+ strncat(g_patch_prefix, "_ram", strlen("_ram"));
+
+ ALOGI("patch name pre-fix:%s\n", g_patch_prefix);
+
+ *patch_prefix = g_patch_prefix;
+
+ return 0;
+}
+
+static int launcher_set_rom_patch_info(int fd, char *patch_info, char *full_name) {
+ struct stp_rom_patch_info pi;
+ int iRet = 0;
+
+ if (!patch_info) {
+ ALOGE("invalid patch infor!\n");
+ return -1;
+ }
+ if (!full_name) {
+ ALOGE("invalid patch full name!\n");
+ return -2;
+ }
+
+ pi.type = patch_info[7];
+ ALOGI("rom patch type = [%d]\n", pi.type);
+ memcpy(pi.address, patch_info, sizeof(pi.address));
+ pi.address[0] = 0x00;
+ strncpy(pi.patch_name, full_name, sizeof(pi.patch_name) - 1);
+ pi.patch_name[sizeof(pi.patch_name) - 1] = '\0';
+
+ iRet = ioctl(fd, WMT_IOCTL_SET_ROM_PATCH_INFO, &pi);
+ if (iRet != 0) {
+ ALOGE("ioctl WMT_IOCTL_SET_ROM_PATCH_INFO error (0x%x)\n", iRet);
+ return -3;
+ }
+
+ return 0;
+}
+
+static int cmd_hdr_sch_rom_patch(struct stp_params_config *config) {
+ int chip_id = 0;
+#if 0
+ unsigned int ip_version = 0;
+#else
+ unsigned int fw_version = 0;
+#endif
+ char *patch_prefix = NULL;
+ char patch_full_name[256] = {0};
+ char patchName[128] = {0};
+ unsigned int patch_ver = 0;
+ DIR *dir = NULL;
+ int patch_fd = -1;
+ int ret = 0;
+ int bytes;
+ char patch_info[8] = {0};
+ struct dirent* dirent = NULL;
+
+ if (g_wmt_fd <= 0) {
+ ALOGE("file descriptor is not valid\n");
+ return -1;
+ }
+ /*1. ioctl to get CHIP ID*/
+ chip_id = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 0);
+ if (launcher_get_rom_patch_prefix(chip_id, &patch_prefix)) {
+ ALOGE("launcher_get_rom_patch_prefix fail\n");
+ return -2;
+ }
+
+ /*2. ioctl to get FIRMWARE VERSION*/
+#if 0
+ ip_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 3);
+ ALOGI("ip_version:0x%04x\n", ip_version);
+#else
+ fw_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI("fw_version:0x%04x\n", fw_version);
+#endif
+ /*3. open directory patch located*/
+ strncpy(config->patch_path, CUST_COMBO_PATCH_PATH, strlen(CUST_COMBO_PATCH_PATH));
+ config->patch_path[strlen(CUST_COMBO_PATCH_PATH) + 1] = '\0';
+
+ dir = opendir(config->patch_path);
+ if (NULL == dir) {
+ ALOGE("patch path cannot be opened");
+ return -3;
+ }
+ while (NULL != (dirent = readdir(dir))) {
+ patch_ver = 0;
+ if (0 == (strncmp(dirent->d_name, patch_prefix, strlen(patch_prefix)))) {
+ /*4.1. search patch name begined with chip_name*/
+ strncpy(patch_full_name, config->patch_path, strlen(config->patch_path)+1);
+ /*robust, if input patch is /etc/firmwre/ no issue should be happened.*/
+ strncat(patch_full_name, "/", strlen("/"));
+ strncat(patch_full_name, dirent->d_name, strlen(dirent->d_name));
+ ALOGI("%s\n", patch_full_name);
+ strncpy(patchName, dirent->d_name, strlen(dirent->d_name)+1);
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 <= (patch_fd = (open(patch_full_name, O_RDONLY)))) {
+ if (-1 != lseek(patch_fd, 22, SEEK_SET)) {
+ if (launcher_get_patch_version(patch_fd, &patch_ver)) {
+ ALOGE("read patch_ver failed!\n");
+ ret = -4;
+ goto read_fail;
+ }
+ /*print hardware version information in patch*/
+ ALOGI("fw Ver in patch: 0x%04x\n", patch_ver);
+#if 0
+ if (0 == ((patch_ver ^ ip_version) & 0xffffffff)) {
+#else
+ if (0 == ((patch_ver ^ fw_version) & 0x00ff)) {
+#endif
+ memset(patch_info, 0, sizeof(patch_info));
+ bytes = read(patch_fd, patch_info, 8);
+ if (-1 == bytes) {
+ ret = -5;
+ ALOGE("read patch_info failed!\n");
+ goto read_fail;
+ }
+ if ((patch_info[3] & 0xF0) && (patch_info[7] >= 0 && patch_info[7] <= 5)) {
+ ALOGI("patch info:0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n",
+ patch_info[0], patch_info[1], patch_info[2], patch_info[3],
+ patch_info[4], patch_info[5], patch_info[6], patch_info[7]);
+ if (launcher_set_rom_patch_info(g_wmt_fd, patch_info, patchName)) {
+ ALOGE("launcher_set_rom_patch_info fail\n");
+ ret = -6;
+ goto read_fail;
+ }
+ }
+ }
+ } else
+ ALOGE("seek failed\n");
+read_fail:
+ close(patch_fd);
+ patch_fd = -1;
+ } else
+ ALOGE("open patch file(%s) failed\n", patchName);
+ }
+ }
+ /*5. return value*/
+ closedir(dir);
+ dir = NULL;
+
+ return ret;
+}
+#else
+static int cmd_hdr_sch_patch(struct stp_params_config *config) {
+ int chip_id = 0;
+ int fw_version = 0;
+ char chip_name[16] = {0};
+ char patch_full_name[256] = {0};
+ unsigned int patch_ver = 0;
+ DIR *dir = NULL;
+ int patch_fd = -1;
+ struct dirent* dirent = NULL;
+ int ret = -1;
+
+ if (g_wmt_fd <= 0) {
+ ALOGE("file descriptor is not valid\n");
+ return -1;
+ }
+
+ /*1. ioctl to get CHIP ID*/
+ chip_id = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 0);
+ strncpy(chip_name, "mt", strlen("mt")+1);
+ sprintf(chip_name + strlen(chip_name), "%04x", chip_id);
+ strncat(chip_name, "_patch", strlen("_patch"));
+ ALOGI("patch name pre-fix:%s\n", chip_name);
+
+ /*2. ioctl to get FIRMWARE VERSION*/
+ fw_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI("fwVersion:0x%04x\n", fw_version);
+
+ /*3. open directory patch located*/
+ strncpy(config->patch_path, CUST_COMBO_PATCH_PATH, strlen(CUST_COMBO_PATCH_PATH));
+ config->patch_path[strlen(CUST_COMBO_PATCH_PATH) + 1] = '\0';
+
+ dir = opendir(config->patch_path);
+ if (NULL == dir) {
+ ALOGE("patch path cannot be opened");
+ ret = -2;
+ return ret;
+ }
+ while (NULL != (dirent = readdir(dir))) {
+ patch_ver = 0;
+ if (0 == (strncmp(dirent->d_name, chip_name, strlen(chip_name)))) {
+ /*4.1. search patch name begined with chipName*/
+ strncpy(patch_full_name, config->patch_path, strlen(config->patch_path)+1);
+ /*robust, if input patch is /etc/firmwre/ no issue should be happened.*/
+ strncat(patch_full_name, "/", strlen("/"));
+ strncat(patch_full_name, dirent->d_name, strlen(dirent->d_name));
+ ALOGI("%s\n", patch_full_name);
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 < (patch_fd = (open(patch_full_name, O_RDONLY)))) {
+ /*4.2. read patch header and check if metch with MAJOR+MINOR number in fw version */
+ if (-1 != lseek(patch_fd, 22, SEEK_SET)) {
+ read(patch_fd, ((char *)&patch_ver) + 1, 1);
+ read(patch_fd, ((char *)&patch_ver), 1);
+ /*print firmware version information in patch*/
+ ALOGI("fw Ver in patch: 0x%04x\n", patch_ver);
+ if (0 == ((patch_ver ^ fw_version) & 0x00ff)) {
+ ioctl(g_wmt_fd, WMT_IOCTL_SET_PATCH_NAME, patch_full_name);
+ ALOGI("fw Ver in patch matches with firmware version\n");
+ ret = 0;
+ close(patch_fd);
+ break;
+ }
+ } else
+ ALOGE("seek failed\n");
+
+ close(patch_fd);
+ patch_fd = -1;
+ } else
+ ALOGE("open patch file(%s) failed\n", patch_full_name);
+ }
+ }
+ /*5. return value*/
+ closedir(dir);
+ dir = NULL;
+
+ return ret;
+}
+#endif
+/*
+ret 0: success
+ret 1: cmd not found
+ret -x: handler return value
+*/
+static int launcher_handle_cmd(struct stp_params_config *stp_param_config, char *cmd, int len) {
+ int ret = 1;
+ int i;
+ int cmd_len;
+
+ for (i = 0; i < (int)(sizeof(g_cmd_hdr_table)/sizeof(g_cmd_hdr_table[0])); ++i) {
+ cmd_len = (int)strlen(g_cmd_hdr_table[i].cmd);
+ if (!strncmp(g_cmd_hdr_table[i].cmd, cmd, (len < cmd_len) ? len : cmd_len)) {
+ ret = (*g_cmd_hdr_table[i].hdr_func)(stp_param_config);
+ }
+ }
+
+ return ret;
+}
+
+static void launcher_display_usage(void)
+{
+ unsigned int index = 0;
+
+ char * usage[] = {
+ "MTK WCN combo tool set, version 1.0-release",
+ "Usage: wmt_launcher [-m mode] -p patchfolderpath [-d uartdevicenode] [-b baudrate] [-c uartflowcontrol]",
+ " -m (BT/GPS/FM common interface mode selection, optional)",
+ " -1: UART mode (common interface: UART)",
+ " -3: BTIF mode (common interface: BTIF)",
+ " -4: SDIO mode (common interface: SDIO)",
+ " -p (MTK WCN chip firmware patch location, must)",
+ " -e.g. /system/etc/firmware",
+ " -n (MTK WCN chip firmware patch name, option)",
+ " -e.g. /system/etc/firmware/firmware/mt6628_patch_hdr.bin",
+ " if UART mode is set, you need config baud rate and tty device:",
+ " -b (Baudrate set when BT/GPS/FM runs under UART mode, no needed under SDIO mode)",
+ " -115200/921600/2000000/2500000/3000000/3500000/4000000",
+ " -d (UART device node, when under UART mode, no needed under SDIO mode)",
+ " -e.g. /dev/ttyMT1, /dev/ttyMT2, /dev/ttyHS2, etc.",
+ " -c (UART flowcontrol set)",
+ " -0, no flowcontrol default value, please donot modify this parameter",
+ "e.g. wmt_launcher -m 3 -p /system/etc/firmware/",
+ "e.g. wmt_launcher -m 1 -n /system/etc/firmware/mt6628_patch_hdr.bin",
+ "e.g. wmt_launcher -m 4 -d /dev/ttyMT2 -b 4000000 -n /system/etc/firmware/mt6628_patch_hdr.bin",
+ };
+
+ for (index = 0; index < sizeof(usage) / sizeof(usage[0]); index++ )
+ ALOGI("%s\n", usage[index]);
+
+ exit(EXIT_FAILURE);
+}
+
+
+static int launcher_stp_param_valid_check(struct stp_params_config *stp_param_configs, enum wmt_chip_type chip_type)
+{
+ int ret = 0;
+
+ /*fix me, check condition should be more reasonable*/
+ if ('\0' == stp_param_configs->patch_path[0]) {
+ ALOGE("MCU patch path not config,use /system/etc/firmware\n");
+ strncpy(stp_param_configs->patch_path, "/system/etc/firmware", strlen("/system/etc/firmware"));
+ stp_param_configs->patch_path[strlen("/system/etc/firmware") + 1] = '\0';
+ ret = -1;
+ }
+
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ if ('\0' == stp_param_configs->patch_name[0]) {
+ ALOGE("MCU patch path not config,you need config it yourself\n");
+ ret = -2;
+ }
+#endif
+ if (stp_param_configs->stp_mode != STP_SDIO &&
+ stp_param_configs->stp_mode != STP_UART_MAND &&
+ stp_param_configs->stp_mode != STP_UART_FULL &&
+ stp_param_configs->stp_mode != STP_BTIF_FULL) {
+ if (WMT_CHIP_TYPE_COMBO == chip_type) {
+ ALOGE("Stp Mode is not set, common interface use default: SDIO Mode");
+ stp_param_configs->stp_mode = STP_SDIO;
+ } else {
+ ALOGE("Stp Mode is not set, common interface use default: BTIF Mode");
+ stp_param_configs->stp_mode = STP_BTIF_FULL;
+ }
+ ret = -3;
+ }
+
+ if (stp_param_configs->stp_mode == STP_UART_MAND || stp_param_configs->stp_mode == STP_UART_FULL) {
+ ALOGI ("Common Interface: UART mode\n");
+ if ('\0' == stp_param_configs->stp_dev[0]) {
+ strncpy(stp_param_configs->stp_dev, CUST_COMBO_STP_DEV, strlen(CUST_COMBO_STP_DEV)+1);
+ ALOGI("no uart device input, use default: %s\n", stp_param_configs->stp_dev);
+ ret = -4;
+ }
+ if (stp_param_configs->uart_config.baud_rate < 0) {
+ /* FixMe:Chaozhong, add baudrate validation check */
+ stp_param_configs->uart_config.baud_rate = 4000000;
+ ALOGI("no baudrate input, use default: %d\n", stp_param_configs->uart_config.baud_rate);
+ ret = -5;
+ }
+ }
+ return ret;
+}
+
+static int launcher_parser_wmt_cfg(char *item)
+{
+ int index = 0;
+ int length = 0;
+ char *str = NULL;
+ char *key = NULL;
+ char *value = NULL;
+ int max_index = sizeof (g_chip_mode_info) / sizeof (g_chip_mode_info[0]);
+
+ if (NULL == item) {
+ ALOGE("Warning:item is NULL\n");
+ return -1;
+ }
+ /*all item must be start with mt66xx*/
+ str = strstr(item, "m");
+ if (NULL == str) {
+ ALOGE("Warning:no string start with 'm' found in %s\n", item);
+ return -2;
+ }
+
+ for (index = 0; index < max_index; index++) {
+ key = (char*)g_chip_mode_info[index].ant_mode.cfg_item;
+
+ if (0 == strncasecmp(str, key, strlen(key))) {
+ str = strstr(str, "=");
+ if (NULL == str) {
+ ALOGE("Warning:no '=' found in %s\n", str);
+ return -3;
+ }
+ str = strstr(str, "m");
+ if (NULL == str) {
+ ALOGE("Warning:no 'm' found in %s\n", str);
+ return -4;
+ }
+
+ while (((*str) == ' ') || ((*str) == '\t') || ((*str) == '\n')) {
+ if (str >= item + strlen(item))
+ break;
+ str++;
+ }
+ value = str;
+
+ while (((*str) != ' ') && ((*str) != '\t') && ((*str) != '\0') && ((*str) != '\n') && ((*str) != '\r')) {
+ if (str >= item + strlen(item))
+ break;
+ str++;
+ }
+ *str = '\0';
+ length = sizeof(g_chip_mode_info[index].ant_mode.cfg_item_value);
+ strncpy(g_chip_mode_info[index].ant_mode.cfg_item_value, value, length - 1);
+ g_chip_mode_info[index].ant_mode.cfg_item_value[length - 1] = '\0';
+ ALOGI("Info:key:%s value:%s\n", key, g_chip_mode_info[index].ant_mode.cfg_item_value);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int launcher_get_wmt_cfg_infor(void)
+{
+ FILE * file = NULL;
+ int ret = -1;
+ char *str = NULL;
+ char line[NAME_MAX];
+
+ file = fopen(CUST_COMBO_CFG_FILE, "r");
+ if (NULL == file) {
+ ALOGE("%s cannot be opened, errno:%d\n", CUST_COMBO_CFG_FILE, errno);
+ return -2;
+ }
+ ret = 0;
+ do {
+ str = fgets(line, NAME_MAX, file);
+ if (NULL == str) {
+ ALOGI("NULL is returned, eighter EOF or error maybe found\n");
+ break;
+ }
+ launcher_parser_wmt_cfg(line);
+ memset(line, 0, NAME_MAX);
+
+ } while (str != NULL);
+
+ if (NULL != file) {
+ if (0 == fclose(file))
+ ALOGI("close %s succeed\n", CUST_COMBO_CFG_FILE);
+ else
+ ALOGI("close %s failed, errno:%d\n", CUST_COMBO_CFG_FILE, errno);
+ }
+ return ret;
+}
+
+
+static int launcher_get_chip_info_index(int chip_id)
+{
+ int index = -1;
+ int left = 0;
+ int middle = 0;
+ int right = sizeof (g_chip_mode_info) / sizeof (g_chip_mode_info[0]) - 1;
+
+ if ((chip_id < g_chip_mode_info[left].chip_id) || (chip_id > g_chip_mode_info[right].chip_id))
+ return index;
+
+ middle = (left + right) / 2;
+
+ while (left <= right) {
+ if (chip_id > g_chip_mode_info[middle].chip_id)
+ left = middle + 1;
+ else if (chip_id < g_chip_mode_info[middle].chip_id)
+ right = middle - 1;
+ else {
+ index = middle;
+ break;
+ }
+ middle = (left + right) / 2;
+ }
+
+ if (0 > index)
+ ALOGE("no supported chip_id found\n");
+ else
+ ALOGI("index:%d, chip_id:0x%x\n", index, g_chip_mode_info[index].chip_id);
+
+ return index;
+}
+
+static void launcher_combine_cfg_name(int chip_id, char *cfg_file_path)
+{
+ int index = -1;
+ int stp_mode = g_stp_param_config.stp_mode;
+
+ index = launcher_get_chip_info_index(chip_id);
+ if ((stp_mode <= STP_MIN) || (STP_SDIO < stp_mode)) {
+ ALOGI("STP Mode is not set, fetching default mode...\n");
+ if (0 <= index)
+ g_stp_param_config.stp_mode = g_chip_mode_info[index].stp_mode;
+ else
+ g_stp_param_config.stp_mode = -1;
+ }
+
+ if ((0 <= index) && (NULL != cfg_file_path)) {
+ memset(g_wmt_cfg_name, 0, sizeof(g_wmt_cfg_name));
+ strncpy(g_wmt_cfg_name, g_chip_mode_info[index].ant_mode.cfg_item_value, sizeof(g_wmt_cfg_name) - 1);
+ g_wmt_cfg_name[strlen(g_chip_mode_info[index].ant_mode.cfg_item_value)] = '\0';
+ } else
+ memset(g_wmt_cfg_name, 0, sizeof(g_wmt_cfg_name));
+
+ ALOGI("chip_id(0x%04x), default Mode(%d), strlen(g_wmt_cfg_name)(%zd), g_wmt_cfg_name(%s)\n",
+ chip_id, g_stp_param_config.stp_mode, strlen(g_wmt_cfg_name), g_wmt_cfg_name);
+
+}
+
+static void launcher_set_wmt_cfg_infor(int chip_id, char *cfg_file_path) {
+ if (!launcher_get_wmt_cfg_infor()) {
+ launcher_combine_cfg_name(chip_id, cfg_file_path);
+ /* send WMT config name configuration to driver */
+ ioctl(g_wmt_fd, WMT_IOCTL_WMT_CFG_NAME, g_wmt_cfg_name);
+ } else
+ ALOGE("launcher_get_wmt_cfg_infor fail\n");
+}
+
+static void launcher_set_uart_port_name(char *stp_dev) {
+ char *uart_name = NULL;
+
+ /* send uart name to driver*/
+ if (stp_dev) {
+ uart_name = strstr(stp_dev, "tty");
+ if (!uart_name)
+ ALOGE("no uart name found in %s\n", stp_dev);
+ else
+ ALOGI("uart name %s\n", uart_name);
+ }
+
+ if (!uart_name) {
+ uart_name = "ttyMT2";
+ ALOGI("use default uart %s\n", uart_name);
+ }
+
+ ioctl(g_wmt_fd, WMT_IOCTL_PORT_NAME, uart_name);
+}
+
+static void* launcher_pwr_on_thread(void * arg)
+{
+ int retry_counter = 0;
+ int ret = -1;
+ int chip_id = *(int*)arg;
+
+ pthread_setname_np(pthread_self(), "pwr_on_conn");
+
+ ALOGI("enter power on connsys flow");
+ do {
+ ret = ioctl(g_wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, 1);
+ if (0 == ret)
+ break;
+ ioctl(g_wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, 0);
+ ALOGI("power on %x failed, retrying, retry counter:%d\n", chip_id, retry_counter);
+ usleep(1000000);
+ retry_counter++;
+ } while (retry_counter < 20);
+
+ pthread_detach(g_thread_handle);
+ g_thread_handle = -1;
+
+ return NULL;
+}
+
+static void launcher_pwr_on_chip(int *chip_id) {
+ if (pthread_create(&g_thread_handle, NULL, launcher_pwr_on_thread, chip_id)) {
+ ALOGE("create pwr on thread fail\n");
+ } else
+ ALOGI("create pwr on thread ok\n");
+}
+static void* launcher_set_fwdbg_thread(void * arg) {
+ int i_ret = -1;
+ int flag = *(int*)arg;
+
+ pthread_setname_np(pthread_self(), "dump_fwemi_log");
+ ALOGI("dump firmware dbg log from emi buffer ");
+ i_ret = ioctl(g_wmt_fd, WMT_IOCTL_FW_DBGLOG_CTRL, flag);
+ if (i_ret < 0) {
+ ALOGI("ioctl error: err msg: %s\n", strerror(errno));
+ pthread_detach(g_thread_handle);
+ g_thread_handle = -1;
+ }
+ return NULL;
+}
+
+static void sig_hup(int sig) {
+ fprintf(stderr, "sig_hup...(%d)\n", sig);
+}
+
+static void sig_term(int sig)
+{
+ fprintf(stderr, "sig_term...(%d)\n", sig);
+ __io_canceled = 1;
+ ioctl(g_wmt_fd, WMT_IOCTL_SET_LAUNCHER_KILL, 1);
+}
+
+static void launcher_set_signal_handler(void) {
+ struct sigaction sa;
+
+ /*set signal handler*/
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGCHLD, &sa, NULL);
+ sigaction(SIGPIPE, &sa, NULL);
+
+ sa.sa_handler = sig_term;
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+
+ sa.sa_handler = sig_hup;
+ sigaction(SIGHUP, &sa, NULL);
+}
+
+static void launcher_check_driver_ready(void) {
+ int ret = -1;
+ struct sys_property sp;
+
+ sp.key = WCN_DRIVER_READY_PROP;
+ sp.def_value = NULL;
+
+ do {
+ ret = property_get(sp.key, sp.value, sp.def_value);
+ if (0 >= ret)
+ ALOGE("get property(%s) failed i_ret:%d\n", sp.key, ret);
+ else {
+ ALOGI("get property(%s) is %s\n", sp.key, sp.value);
+ if (!strcmp(sp.value, "yes"))
+ break;
+ }
+ usleep(300000);
+ } while (1);
+}
+
+static void launcher_open_wmt_device(void) {
+ do {
+ g_wmt_fd = open(CUST_COMBO_WMT_DEV, O_RDWR | O_NOCTTY);
+ if (g_wmt_fd < 0) {
+ ALOGE("Can't open device node(%s) error:%d \n", CUST_COMBO_WMT_DEV, g_wmt_fd);
+ usleep(300000);
+ } else
+ break;
+ }while(1);
+
+ ALOGI("open device node succeed.(Node:%s, fd:%d) \n", CUST_COMBO_WMT_DEV, g_wmt_fd);
+}
+
+static int launcher_query_chip_id(void) {
+ int chip_id = -1;
+ int ret = -1;
+ struct sys_property chipid_prop;
+
+ chipid_prop.key = WCN_COMBO_CHIP_ID_PROP;
+ chipid_prop.def_value = NULL;
+
+ do {
+ /*read from system property*/
+ ret = property_get(chipid_prop.key, chipid_prop.value, chipid_prop.def_value);
+ if (0 != ret) {
+ chip_id = strtoul(chipid_prop.value, NULL, 16);
+ ALOGI("key:(%s)-value:(%s),chip_id:0x%04x\n",
+ chipid_prop.key, chipid_prop.value, chip_id);
+ } else {
+ ALOGE("get chip_id property(%s) failed\n", chipid_prop.key);
+ /* we do not return here, use another way to get chip id*/
+ }
+
+ if (-1 != chip_id)
+ break;
+
+ chip_id = ioctl(g_wmt_fd, WMT_IOCTL_WMT_QUERY_CHIPID, NULL);
+ ALOGI("chip_id from kernel by ioctl:0x%04x\n", chip_id);
+ if (-1 != chip_id)
+ break;
+ usleep(300000);
+ }while(1);
+
+ ALOGI("chip_id:0x%04x\n", chip_id);
+
+ return chip_id;
+}
+
+static enum wmt_chip_type launcher_check_chip_type(int chip_id)
+{
+ enum wmt_chip_type chip_type = WMT_CHIP_TYPE_INVALID;
+
+ if (chip_id <= 0) {
+ ALOGE("invalid chip id(%d)\n", chip_id);
+ goto done;
+ }
+ if ((0x6620 == chip_id) || (0x6628 == chip_id) ||
+ (0x6630 == chip_id) || (0x6632 == chip_id))
+ chip_type = WMT_CHIP_TYPE_COMBO;
+ else
+ chip_type = WMT_CHIP_TYPE_SOC;
+done:
+ return chip_type;
+}
+static void launcher_init_stp_parameter(struct stp_params_config *stp_param_config, enum wmt_chip_type chip_type) {
+ stp_param_config->fm_mode = 2;
+
+ if (WMT_CHIP_TYPE_SOC == chip_type)
+ stp_param_config->stp_mode = STP_BTIF_FULL;
+ if (WMT_CHIP_TYPE_COMBO == chip_type) {
+ stp_param_config->stp_mode = STP_SDIO;
+ stp_param_config->uart_config.baud_rate = 4000000;
+ stp_param_config->uart_config.fc = UART_DISABLE_FC;
+ stp_param_config->uart_config.parity = 0;
+ stp_param_config->uart_config.stop_bit = 0;
+ memset(stp_param_config->stp_dev, '\0', sizeof(stp_param_config->stp_dev));
+ }
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ memset(stp_param_config->patch_name, '\0', sizeof(stp_param_config->patch_name));
+#endif
+ memset(stp_param_config->patch_path, '\0', sizeof(stp_param_config->patch_path));
+}
+
+static void launcher_print_stp_parameter(struct stp_params_config *stp_param_config) {
+ ALOGI("fm mode:%d\n", stp_param_config->fm_mode);
+ ALOGI("stp mode:%d\n", stp_param_config->stp_mode);
+ ALOGI("patch path:%s\n", stp_param_config->patch_path);
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ ALOGI("patch name:%d\n", stp_param_config->patch_name);
+#endif
+ if ((stp_param_config->stp_mode == STP_UART_FULL) ||
+ (stp_param_config->stp_mode == STP_UART_MAND)) {
+ ALOGI("stp uart dev:%s\n", stp_param_config->stp_dev);
+ ALOGI("stp uart baud rate:%d\n", stp_param_config->uart_config.baud_rate);
+ ALOGI("stp uart fc:%d\n", stp_param_config->uart_config.fc);
+ ALOGI("stp uart parity:%d\n", stp_param_config->uart_config.parity);
+ ALOGI("stp uart stop bit:%d\n", stp_param_config->uart_config.stop_bit);
+ }
+}
+/*
+ * -m: mode (SDIO/UART)
+ * -d: uart device node
+ * -b: baudrate
+ * -c: enable SW FC or not
+ * -p: patch folder path
+ * -n: patch file name (fullpath)
+ *
+ */
+static void launcher_set_parameter_to_driver(int argc, char *argv[], int chip_id)
+{
+ int opt;
+ static const char *op_string = "m:d:b:c:p:n:?";
+ enum wmt_chip_type chip_type;
+
+ chip_type = launcher_check_chip_type(chip_id);
+ if (chip_type == WMT_CHIP_TYPE_INVALID) {
+ ALOGE("unknow chip type, may be chid id is invalid\n");
+ chip_type = WMT_CHIP_TYPE_SOC;
+ }
+ launcher_init_stp_parameter(&g_stp_param_config, chip_type);
+
+ opt = getopt(argc, argv, op_string);
+ while (opt != -1) {
+ switch (opt) {
+ case 'm':
+ g_stp_param_config.stp_mode = atoi(optarg);
+ break;
+ case 'd':
+ strncpy(g_stp_param_config.stp_dev, optarg, strlen(optarg)+1);
+ break;
+ case 'b':
+ g_stp_param_config.uart_config.baud_rate = atoi(optarg);
+ break;
+ case 'c':
+ g_stp_param_config.uart_config.fc = atoi(optarg);
+ break;
+ case 'p':
+ strncpy(g_stp_param_config.patch_path, optarg, strlen(optarg)+1);
+ ALOGI("patch path:%s\n", g_stp_param_config.patch_path);
+ break;
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ case 'n':
+ strncpy(g_stp_param_config.patch_name, optarg, strlen(optarg)+1);
+ break;
+#endif
+ case '?':
+ default:
+ launcher_display_usage();
+ break;
+ }
+ opt = getopt(argc, argv, op_string);
+ }
+
+#if LAUNCHER_DEBUG
+ ALOGI("argc = %d, optind= %d\n", argc, optind);
+ {
+ int i = 0;
+ for (i = 0; i < argc; i++)
+ ALOGI("arg[%d] = %s\n", i, argv[i]);
+ }
+#endif
+
+ if (0 != launcher_stp_param_valid_check(&g_stp_param_config, chip_type)) {
+ ALOGE("stp param is invalid, use default:\n");
+ launcher_print_stp_parameter(&g_stp_param_config);
+ ALOGE("if this default param is not correct,please see usage help:\n");
+ launcher_display_usage();
+ }
+ if (WMT_CHIP_TYPE_COMBO == chip_type) {
+ ioctl(g_wmt_fd, WMT_IOCTL_WMT_TELL_CHIPID, chip_id);
+ ALOGI("set chip_id(0x%x) to driver\n", chip_id);
+ launcher_set_wmt_cfg_infor(chip_id, &g_stp_param_config.patch_path[0]);
+ if ((g_stp_param_config.stp_mode == STP_UART_FULL) ||
+ (g_stp_param_config.stp_mode == STP_UART_MAND))
+ launcher_set_uart_port_name(&g_stp_param_config.stp_dev[0]);
+ }
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ /* send default patch file name path to driver */
+ ioctl(g_wmt_fd, WMT_IOCTL_SET_PATCH_NAME, g_stp_param_config.patch_name);
+#endif
+ /* send hardware interface configuration to driver */
+ ioctl(g_wmt_fd, WMT_IOCTL_SET_STP_MODE,
+ ((g_stp_param_config.uart_config.baud_rate & 0xFFFFFF) << 8) |
+ ((g_stp_param_config.fm_mode & 0x0F) << 4) |
+ (g_stp_param_config.stp_mode & 0x0F));
+
+ ioctl(g_wmt_fd, WMT_IOCTL_SET_LAUNCHER_KILL, 0);
+
+}
+
+static int launcher_get_fw_debug_orign_infor(int chip_id) {
+ int ret = -1;
+ enum wmt_chip_type chip_type;
+ char readyStr[PROPERTY_VALUE_MAX] = {0};
+
+ chip_type = launcher_check_chip_type(chip_id);
+
+ if (chip_type == WMT_CHIP_TYPE_SOC) {
+ g_fw_debug_infor.log_retry = 0;
+ g_fw_debug_infor.dump_retry = 0;
+ g_fw_debug_infor.fw_log_ctrl = 0;
+ g_fw_debug_infor.fw_dynamic_dump = 0;
+ g_fw_debug_infor.bitmap = 0;
+ memset(g_fw_debug_infor.fw_log_state_orig, '\0', sizeof(g_fw_debug_infor.fw_log_state_orig));
+ memset(g_fw_debug_infor.fw_log_state_new, '\0', sizeof(g_fw_debug_infor.fw_log_state_new));
+ memset(g_fw_debug_infor.fw_dump_state_orig, '\0', sizeof(g_fw_debug_infor.fw_dump_state_orig));
+ memset(g_fw_debug_infor.fw_dump_state_new, '\0', sizeof(g_fw_debug_infor.fw_dump_state_new));
+
+ ret = property_get(WCN_FW_DBG_LOG_PROP, g_fw_debug_infor.fw_log_state_orig, NULL);
+ if (0 > ret)
+ ALOGE("get property(%s) failed ret:%d\n", WCN_FW_DBG_LOG_PROP, ret);
+ else if (0 == ret)
+ ALOGI("(%s) is not supported\n", WCN_FW_DBG_LOG_PROP);
+ else
+ ALOGI("get property (%s) is %s\n", WCN_FW_DBG_LOG_PROP, g_fw_debug_infor.fw_log_state_orig);
+
+ ret = property_get(WCN_DYNAMIC_DUMP_PROP, g_fw_debug_infor.fw_dump_state_orig, NULL);
+ if (0 > ret)
+ ALOGE("get property(%s) failed ret:%d\n", WCN_DYNAMIC_DUMP_PROP, ret);
+ else if (0 == ret)
+ ALOGI("(%s) is not supported\n", WCN_DYNAMIC_DUMP_PROP);
+ else
+ ALOGI("get property (%s) is %s\n", WCN_DYNAMIC_DUMP_PROP, g_fw_debug_infor.fw_dump_state_orig);
+ }
+
+ /*meta tool may turn on wifi very early, this property is used to protect turn on wifi.*/
+ ret= property_get(WCN_FORMETA_READY_PROP, readyStr, NULL);
+ if ((0 >= ret) || (0 == strcmp(readyStr, "yes"))) {
+ ALOGI("get property(%s) failed iRet:%d or property is %s\n", WCN_FORMETA_READY_PROP, ret, readyStr);
+ }
+
+ sprintf(readyStr, "%s", "yes");
+ ret = property_set(WCN_FORMETA_READY_PROP, readyStr);
+ if (0 != ret) {
+ ALOGI("set property(%s) to %s failed iRet:%d\n", WCN_FORMETA_READY_PROP, readyStr, ret);
+ } else {
+ ALOGI("set property(%s) to %s succeed\n", WCN_FORMETA_READY_PROP, readyStr);
+ }
+
+ return 0;
+}
+
+static int launcher_set_fw_log_ctrl(void) {
+ int ret = -1;
+ int fw_debug_enable = 0;
+
+ if (g_fw_debug_infor.bitmap & 0x1) {
+ ALOGV("fw log ctrl flag has been set\n");
+ return 0;
+ }
+
+ if ((g_fw_debug_infor.fw_log_ctrl == 1) ||
+ (g_fw_debug_infor.log_retry > WCN_FW_DEBUG_CLRL_RETRY_LIMIT)) {
+ ALOGV("retry: %d\n", g_fw_debug_infor.log_retry);
+
+ if (!strcmp(g_fw_debug_infor.fw_log_state_new, "yes")) {
+ fw_debug_enable = 1;
+ if (pthread_create(&g_thread_handle, NULL, launcher_set_fwdbg_thread, &fw_debug_enable))
+ ALOGE("create enable firmware dbglog thread fail\n");
+ } else {
+ ret = ioctl(g_wmt_fd, WMT_IOCTL_FW_DBGLOG_CTRL, fw_debug_enable);
+ /* if do this jude,it will confuse user beacuse kernel return -1 */
+ /* if (ret < 0)*/
+ /* ALOGE("ioctl error: err msg: %s\n", strerror(errno));*/
+ }
+ g_fw_debug_infor.bitmap |= (0x1 << 0);
+ } else if (g_fw_debug_infor.log_retry++ <= WCN_FW_DEBUG_CLRL_RETRY_LIMIT) {
+ ret = property_get(WCN_FW_DBG_LOG_PROP, g_fw_debug_infor.fw_log_state_new, NULL);
+ if (0 > ret)
+ ALOGE("get property(%s) failed ret:%d\n", WCN_FW_DBG_LOG_PROP, ret);
+ else if (0 == ret)
+ ALOGI("(%s) is not supported\n", WCN_FW_DBG_LOG_PROP);
+ else {
+ ALOGV("get property(%s) is %s\n", WCN_FW_DBG_LOG_PROP, g_fw_debug_infor.fw_log_state_new);
+ if (strcmp(g_fw_debug_infor.fw_log_state_new, g_fw_debug_infor.fw_log_state_orig))
+ g_fw_debug_infor.fw_log_ctrl = 1;
+ }
+ } else
+ ALOGV("retry finish\n");
+ return 0;
+}
+
+static int launcher_set_fw_dynamic_dump(void) {
+ int ret = -1;
+
+ if (g_fw_debug_infor.bitmap & (0x1 << 1)) {
+ ALOGV("fw dynamic ctrl flag has been set\n");
+ return 0;
+ }
+
+ if ((g_fw_debug_infor.fw_dynamic_dump == 1) ||
+ (g_fw_debug_infor.dump_retry > WCN_FW_DEBUG_CLRL_RETRY_LIMIT)) {
+ ALOGV("dump_retry: %d\n", g_fw_debug_infor.dump_retry);
+
+ if (g_fw_debug_infor.fw_dynamic_dump == 1) {
+ /* it is only meaningfull to do ioctl in this case*/
+ ret = ioctl(g_wmt_fd, WMT_IOCTL_DYNAMIC_DUMP_CTRL, g_fw_debug_infor.fw_dump_state_new);
+ ALOGV("%d, %zd,\n", PROPERTY_VALUE_MAX, strlen(g_fw_debug_infor.fw_dump_state_new));
+ if (ret < 0)
+ ALOGE("ioctl error: err msg: %s\n", strerror(errno));
+ }
+ g_fw_debug_infor.bitmap |= (0x1 << 1);
+ } else if (g_fw_debug_infor.dump_retry++ <= WCN_FW_DEBUG_CLRL_RETRY_LIMIT) {
+ ret = property_get(WCN_DYNAMIC_DUMP_PROP, g_fw_debug_infor.fw_dump_state_new, NULL);
+ if (0 > ret)
+ ALOGE("get property(%s) failed ret:%d\n", WCN_DYNAMIC_DUMP_PROP, ret);
+ else if (0 == ret)
+ ALOGI("(%s) is not supported\n", WCN_DYNAMIC_DUMP_PROP);
+ else {
+ ALOGV("get property(%s) is %s\n", WCN_DYNAMIC_DUMP_PROP, g_fw_debug_infor.fw_dump_state_new);
+ if (strcmp(g_fw_debug_infor.fw_dump_state_new, g_fw_debug_infor.fw_dump_state_orig))
+ g_fw_debug_infor.fw_dynamic_dump = 1;
+ }
+ } else
+ ALOGV("retry finish\n");
+
+ return 0;
+}
+
+static void launcher_set_fw_debug_infor(int chip_id) {
+ enum wmt_chip_type chip_type = WMT_CHIP_TYPE_INVALID;
+
+ chip_type = launcher_check_chip_type(chip_id);
+ if (chip_type == WMT_CHIP_TYPE_SOC) {
+ launcher_set_fw_log_ctrl();
+ launcher_set_fw_dynamic_dump();
+ }
+}
+
+int main(int argc, char *argv[]) {
+ int ld, err;
+ struct pollfd fds[2];
+ int fd_num = 0;
+ int len = 0;
+ int chip_id = -1;
+
+ launcher_check_driver_ready();
+ launcher_open_wmt_device();
+ chip_id = launcher_query_chip_id();
+
+ launcher_set_parameter_to_driver(argc, argv, chip_id);
+
+ launcher_set_signal_handler();
+
+ launcher_get_fw_debug_orign_infor(chip_id);
+
+ fds[0].fd = g_wmt_fd; /* stp_wmt fd */
+ fds[0].events = POLLIN | POLLRDNORM; /* wait read events */
+ ++fd_num;
+
+ launcher_pwr_on_chip(&chip_id);
+
+ while (!__io_canceled) {
+ launcher_set_fw_debug_infor(chip_id);
+ fds[0].revents = 0;
+ err = poll(fds, fd_num, 2000); /* 2 seconds */
+ if (err < 0) {
+ if (errno == EINTR)
+ continue;
+ else {
+ ALOGE("poll error:%d errno:%d, %s\n", err, errno, strerror(errno));
+ break;
+ }
+ } else if (!err)
+ continue;
+
+
+ if (fds[0].revents & POLLIN) {
+ if (g_wmt_fd < 0)
+ break;
+ memset(g_cmd_str, 0, sizeof(g_cmd_str));
+ len = read(g_wmt_fd, g_cmd_str, sizeof(g_cmd_str)-1);
+ if (len <= 0 || len >= (int)sizeof(g_cmd_str)) {
+ ALOGE("POLLIN(%d) but read fail:%d\n", g_wmt_fd, len);
+ continue;
+ }
+ g_cmd_str[len] = '\0';
+ /*ALOGI("rx_cmd_str:%s\n", g_cmd_str);*/
+ err = launcher_handle_cmd(&g_stp_param_config, g_cmd_str, len);
+ if (!err) {
+ /* ALOGI("handle_cmd(%s), respond ok \n", g_cmd_str); */
+ snprintf(g_resp_str, sizeof(g_resp_str), "ok");
+ } else {
+ if (err == 1)
+ snprintf(g_resp_str, sizeof(g_resp_str), "cmd not found");
+ else
+ snprintf(g_resp_str, sizeof(g_resp_str), "resp_%d", err);
+ }
+ ALOGI("cmd(%s) resp(%s)\n", g_cmd_str, g_resp_str);
+ len = write(g_wmt_fd, g_resp_str, strlen(g_resp_str));
+ if (len != (int)strlen(g_resp_str))
+ fprintf(stderr, "write resp(%d) fail: len(%d), errno(%d, %s)\n",
+ g_wmt_fd, len, errno, (len == -1) ? strerror(errno) : "");
+ }
+ }
+
+ if (g_wmt_fd >= 0) {
+ close(g_wmt_fd);
+ g_wmt_fd = -1;
+ }
+
+ if (((g_stp_param_config.stp_mode == STP_UART_MAND) ||
+ (g_stp_param_config.stp_mode == STP_UART_FULL)) && g_tty_fd >= 0) {
+ /* Restore TTY line discipline */
+ ld = N_TTY;
+ if (ioctl(g_tty_fd, TIOCSETD, &ld) < 0) {
+ ALOGE("Can't restore line discipline");
+ exit(1);
+ }
+
+ close(g_tty_fd);
+ g_tty_fd = -1;
+ }
+
+ if (g_thread_handle != -1) {
+ pthread_detach(g_thread_handle);
+ g_thread_handle = -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/wmt_concurrency.c b/src/connectivity/combo_tool/6631_combo_tool/src/wmt_concurrency.c
new file mode 100644
index 0000000..22e0f9b
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/wmt_concurrency.c
@@ -0,0 +1,381 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#define _GNU_SOURCE
+#include "wmt_ioctl.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/endian.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <linux/serial.h> /* struct serial_struct */
+#include <pthread.h>
+#include <sched.h>
+#define FIBER_STACK 8192
+
+pthread_mutex_t mutex;
+
+typedef enum DRV_INDEX
+{
+ DRV_BT = 0,
+ DRV_FM,
+ DRV_GPS,
+ DRV_WIFI,
+ DRV_MAX,
+}ENUM_DRV_INDEX;
+
+typedef enum ARG_DRV_INDEX
+{
+ ARG_DRV_BT = 1 << DRV_BT,
+ ARG_DRV_FM = 1 << DRV_FM,
+ ARG_DRV_GPS = 1 << DRV_GPS,
+ ARG_DRV_WIFI = 1 << DRV_WIFI,
+ ARG_DRV_ALL = ARG_DRV_BT + ARG_DRV_FM + ARG_DRV_GPS + ARG_DRV_WIFI,
+}ENUM_ARG_DRV_INDEX;
+
+#define is_bt_mask_on(a) ((a) & ARG_DRV_BT)
+#define is_fm_mask_on(a) ((a) & ARG_DRV_FM)
+#define is_gps_mask_on(a) ((a) & ARG_DRV_GPS)
+#define is_wifi_mask_on(a) ((a) & ARG_DRV_WIFI)
+
+#define QUICK_FUNC_ON_OFF_SUPPORT
+#ifdef QUICK_FUNC_ON_OFF_SUPPORT
+ #define MIN_INTERVAL 1
+#else
+ #define MIN_FUNC_ON_TIME 4
+ #define MIN_FUNC_OFF_TIME 1
+ #define MIN_INTERVAL MIN_FUNC_ON_TIME + MIN_FUNC_OFF_TIME
+#endif
+
+#define MAX_FUNC_ON_TIME 9
+#define MAX_FUNC_OFF_TIME 3
+#define MAX_INTERVAL MAX_FUNC_ON_TIME + MAX_FUNC_OFF_TIME
+//enum bool {false = 0, true = !false};
+
+char *src_name[]={
+ "BT",
+ "FM",
+ "GPS",
+ "WIFI",
+ "UNKNOWN DEVICE",
+ };
+
+static int g_wmt_fd = -1;
+static int g_reference = 0;
+static int g_count = 2;
+int g_on2off_interval = MAX_INTERVAL;
+int g_off2on_interval = MAX_INTERVAL;
+volatile int g_state[5] = {0};
+
+void dump_state(void)
+{
+ //printf("%s:++, pid =%d\n", __FUNCTION__, getpid());
+ printf("%d: %s:g_state:[BT]%d, [FM]:%d, [GPS]:%d, [WIFI]:%d\n", getpid(), __FUNCTION__, g_state[0], g_state[1], g_state[2], g_state[3]);
+ //printf("%s:--, pid =%d\n", __FUNCTION__, getpid());
+}
+
+int read_reference(ENUM_DRV_INDEX index)
+{
+ volatile int flag = 0;
+ pthread_mutex_lock(&mutex);
+ if(index >= 4)
+ {
+ if(g_state[0] || g_state[1] || g_state[2] || g_state[3])
+ {
+ flag = 1;
+ }
+ else
+ {
+ flag = 0;
+ }
+ }
+ else
+ {
+ flag = g_state[index];
+ }
+ pthread_mutex_unlock(&mutex);
+ return flag;
+}
+
+void get_reference(ENUM_DRV_INDEX index)
+{
+ pthread_mutex_lock(&mutex);
+ g_reference++;
+ g_state[index] = 1;
+ dump_state();
+ pthread_mutex_unlock(&mutex);
+}
+
+
+void put_reference(ENUM_DRV_INDEX index)
+{
+ pthread_mutex_lock(&mutex);
+ g_reference--;
+ g_state[index] = 0;
+ dump_state();
+ pthread_mutex_unlock(&mutex);
+}
+
+int func_on_off(void * drv_index)
+{
+ ENUM_DRV_INDEX index = (ENUM_DRV_INDEX) drv_index;
+ int count = g_count;
+// printf("%s:++, index =%d\n", __FUNCTION__, index);
+ if(DRV_MAX > index && g_wmt_fd > 0)
+ {
+ while(count--)
+ {
+ //turn on src_name[index] function
+ if (0 == ioctl(g_wmt_fd, WMT_IOCTL_FUNC_ONOFF_CTRL, 0xBEEF0000 | index))
+ {
+ printf("pid:%d, turn on %s success.\n", getpid(), src_name[index]);
+ //exit(0);
+ }
+ else
+ {
+ printf("pid:%d, turn on %s fail.\n", getpid(), src_name[index]);
+ exit(-1);
+ }
+
+ //printf("%s:-- pid: %d, finish turn on %s\n", __FUNCTION__, getpid(), src_name[index]);
+ /*
+ //turn off src_name[index] function
+ */
+ sleep(g_on2off_interval);
+ if ( 0 == ioctl(g_wmt_fd, WMT_IOCTL_FUNC_ONOFF_CTRL, 0xDEAD0000 | index))
+ {
+ printf("pid:%d, turn off %s success.\n", getpid(), src_name[index]);
+ //exit(0);
+ }
+ else
+ {
+ printf("pid:%d, turn off %s fail.\n", getpid(), src_name[index]);
+ exit(-1);
+ }
+ printf("%d:%s test:left count = %d.\n", getpid(), src_name[index], count);
+ sleep(g_off2on_interval);
+
+ }
+ }
+ else
+ {
+ printf("pid:%d, undnown device with index:%d.\n", getpid(), index);
+ }
+ // printf("%s:--, index =%d\n", __FUNCTION__, index);
+ //exit(-2);
+ //return;
+ exit(0);
+}
+
+
+static void sig_child_term(__attribute__((unused))int sig)
+{
+ printf("%s ++.\n", __FUNCTION__);
+ int pid = -1;
+ int stat;
+ while((pid = waitpid(0, &stat, WNOHANG)) != 0)
+ {
+ printf("%s:pid = %d, exit event.\n", __FUNCTION__, pid);
+ }
+ printf("%s:pid = %d.\n", __FUNCTION__, pid);
+ printf("%s --.\n", __FUNCTION__);
+}
+
+int main(int argc, char *argv[])
+{
+
+ int bitmask = ARG_DRV_ALL;
+
+ int i = 0;
+ void *stack[8];
+ struct sigaction sa;
+ if(argc != 5)
+ {
+ printf("wmt_concurrency usage:\n\
+ wmt_concurrency looptimes bitmask on2offtime off2ontime\n\
+ -looptimes on<->off switch times (<1000000)\n\
+ -bitmask\n\
+ -1:BT on<->off test\n\
+ -2:FM on<->off test\n\
+ -4:GPS on<->off test\n\
+ -8:WIFI on<->off test\n\
+ -x: can be combination of the upper 4 bitmasks\n\
+ -on2offtime (0~12s)\n\
+ -function on hold time before turn off\n\
+ -off2ontime (0~12s)\n\
+ -function off hold time before turn on\n\
+ ");
+ return -1;
+ }
+ if ((argc > 1) && (argv[1] != NULL)) {
+
+ g_count = atoi(argv[1]);
+ printf("%s:argv[1] g_count param = %d\n", __FUNCTION__, g_count);
+ if(g_count < 0)
+ {
+ g_count = 2;
+ }
+ g_count = g_count > 1000000 ? 1000000 : g_count;
+ printf("%s:g_count = %d\n", __FUNCTION__, g_count);
+ }
+ if ((argc > 2) && (argv[2] != NULL)) {
+
+ bitmask = atoi(argv[2]);
+ printf("%s:argv[2] bitmask param = %d\n", __FUNCTION__, bitmask);
+ if(bitmask <= 0 || bitmask > ARG_DRV_ALL)
+ {
+ bitmask = ARG_DRV_ALL;
+ }
+ printf("%s:bitmask = %d\n", __FUNCTION__, bitmask);
+ }
+
+ if ((argc > 3) && (argv[3] != NULL)) {
+
+ g_on2off_interval = atoi(argv[3]);
+ printf("%s:argv[3] g_on2off_interval param = %d\n", __FUNCTION__, g_on2off_interval);
+ if(g_on2off_interval < MIN_INTERVAL)
+ {
+ g_on2off_interval = MIN_INTERVAL;
+ }
+ if(g_on2off_interval > MAX_INTERVAL)
+ {
+ g_on2off_interval = MAX_INTERVAL;
+ }
+ printf("%s:g_on2off_interval = %d\n", __FUNCTION__, g_on2off_interval);
+ }
+ if ((argc > 4) && (argv[4] != NULL)) {
+
+ g_off2on_interval = atoi(argv[4]);
+ printf("%s:argv[4] g_off2on_interval param = %d\n", __FUNCTION__, g_off2on_interval);
+ if(g_off2on_interval < MIN_INTERVAL)
+ {
+ g_off2on_interval = MIN_INTERVAL;
+ }
+ if(g_off2on_interval > MAX_INTERVAL)
+ {
+ g_off2on_interval = MAX_INTERVAL;
+ }
+ printf("%s:g_off2on_interval = %d\n", __FUNCTION__, g_off2on_interval);
+ }
+
+ for (i = sizeof(g_state)/sizeof(g_state[0]); i > 0; )
+ {
+ g_state[--i] = 0;
+ }
+
+ printf("pid = %d\n", getpid());
+ for(i = sizeof(stack)/sizeof(void *); i > 0; )
+ {
+ stack[--i] = malloc(FIBER_STACK);
+ if(stack[i] == NULL)
+ {
+ printf("pid = %d, malloc error\n", getpid());
+ goto out;
+ }
+ }
+
+ g_wmt_fd = open("/dev/stpwmt", O_RDWR | O_NOCTTY);
+ printf("%s:argc = %d\n", __FUNCTION__, argc);
+
+ if(pthread_mutex_init(&mutex, NULL) != 0)
+ {
+ printf("%s:pthread_mutex_init fail\n", __FUNCTION__);
+ goto out;
+ }
+ if(g_wmt_fd > 0)
+ {
+ memset(&sa, 0, sizeof(sa));
+ //signal(SIGCHLD, sig_child_term);
+ sa.sa_handler = sig_child_term;
+ sa.sa_flags = SA_NOCLDSTOP;
+ sigaction(SIGCHLD, &sa, 0);
+ int sleepCOunter = g_count;
+
+ if(is_bt_mask_on(bitmask) && read_reference(DRV_BT) == 0)
+ {
+ clone(&func_on_off, (char *)stack[0] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_BT);
+ //clone(&func_off, (char *)stack[4] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_BT);
+ }
+
+ if(is_wifi_mask_on(bitmask) && read_reference(DRV_WIFI) == 0)
+ {
+ clone(&func_on_off, (char *)stack[1] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_WIFI);
+ //clone(&func_off, (char *)stack[5] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_WIFI);
+ }
+ if(is_fm_mask_on(bitmask) && read_reference(DRV_FM) == 0)
+ {
+ clone(&func_on_off, (char *)stack[2] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_FM);
+ //clone(&func_off, (char *)stack[6] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_FM);
+ }
+ if(is_gps_mask_on(bitmask) && read_reference(DRV_GPS) == 0)
+ {
+ clone(&func_on_off, (char *)stack[3] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_GPS);
+ //clone(&func_off, (char *)stack[7] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_GPS);
+ }
+ //printf("%s:left g_count = %d.\n", __FUNCTION__, g_count);
+ sleep(sleepCOunter * (g_on2off_interval + g_off2on_interval));
+ }
+out:
+
+ for(i = sizeof(stack)/sizeof(void *); i > 0; )
+ {
+ printf("%s:pid = %d, free stack information.\n", __FUNCTION__, getpid());
+ if (NULL != stack[--i])
+ {
+ free(stack[i]);
+ }
+ stack[i] = NULL;
+ }
+ if(g_wmt_fd > 0)
+ {
+ close(g_wmt_fd);
+ g_wmt_fd = -1;
+ }
+ printf("%s:pid = %d, exit.\n", __FUNCTION__, getpid());
+ return 0;
+}
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/wmt_ioctl.h b/src/connectivity/combo_tool/6631_combo_tool/src/wmt_ioctl.h
new file mode 100644
index 0000000..54731bc
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/wmt_ioctl.h
@@ -0,0 +1,52 @@
+#ifndef _WMT_IOCTL_H_
+#define _WMT_IOCTL_H_
+
+#include <sys/ioctl.h>
+
+#define WMT_IOC_MAGIC 0xa0
+#define WMT_IOCTL_SET_PATCH_NAME _IOW(WMT_IOC_MAGIC,4,char*)
+#define WMT_IOCTL_SET_STP_MODE _IOW(WMT_IOC_MAGIC,5,int)
+#define WMT_IOCTL_FUNC_ONOFF_CTRL _IOW(WMT_IOC_MAGIC,6,int)
+#define WMT_IOCTL_LPBK_POWER_CTRL _IOW(WMT_IOC_MAGIC,7,int)
+#define WMT_IOCTL_LPBK_TEST _IOWR(WMT_IOC_MAGIC,8,char*)
+#define WMT_IOCTL_GET_CHIP_INFO _IOR(WMT_IOC_MAGIC,12,int)
+#define WMT_IOCTL_SET_LAUNCHER_KILL _IOW(WMT_IOC_MAGIC,13,int)
+#define WMT_IOCTL_SET_PATCH_NUM _IOW(WMT_IOC_MAGIC,14,int)
+#define WMT_IOCTL_SET_PATCH_INFO _IOW(WMT_IOC_MAGIC,15,char*)
+#define WMT_IOCTL_PORT_NAME _IOWR(WMT_IOC_MAGIC, 20, char*)
+#define WMT_IOCTL_WMT_CFG_NAME _IOWR(WMT_IOC_MAGIC, 21, char*)
+#define WMT_IOCTL_WMT_QUERY_CHIPID _IOR(WMT_IOC_MAGIC, 22, int)
+#define WMT_IOCTL_WMT_TELL_CHIPID _IOW(WMT_IOC_MAGIC, 23, int)
+#define WMT_IOCTL_WMT_COREDUMP_CTRL _IOW(WMT_IOC_MAGIC, 24, int)
+#define WMT_IOCTL_SEND_BGW_DS_CMD _IOW(WMT_IOC_MAGIC,25,char*)
+#define WMT_IOCTL_ADIE_LPBK_TEST _IOWR(WMT_IOC_MAGIC,26,char*)
+#define WMT_IOCTL_GET_APO_FLAG _IOR(WMT_IOC_MAGIC, 28, int)
+#define WMT_IOCTL_FW_DBGLOG_CTRL _IOR(WMT_IOC_MAGIC, 29, int)
+#define WMT_IOCTL_DYNAMIC_DUMP_CTRL _IOR(WMT_IOC_MAGIC, 30, char*)
+#define WMT_IOCTL_SET_ROM_PATCH_INFO _IOW(WMT_IOC_MAGIC,31,char*)
+#define WMT_IOCTL_FDB_CTRL _IOW(WMT_IOC_MAGIC,32,char*)
+#define WMT_IOCTL_GET_EMI_PHY_SIZE _IOR(WMT_IOC_MAGIC, 33, unsigned int)
+
+typedef enum _CONSYS_BASE_ADDRESS_INDEX_ {
+ MCU_BASE_INDEX = 0,
+ TOP_RGU_BASE_INDEX,
+ INFRACFG_AO_BASE_INDEX,
+ SPM_BASE_INDEX,
+ MCU_CFG_ON_BASE_INDEX,
+ MCU_CIRQ_BASE_INDEX,
+} ENUM_CONSYS_BASE_ADDRESS_INDEX, *P_ENUM_CONSYS_BASE_ADDRESS_INDEX;
+
+typedef struct {
+ unsigned int is_write;
+ ENUM_CONSYS_BASE_ADDRESS_INDEX base_index;
+ unsigned int offset;
+ unsigned int value;
+} WMT_FDB_CTRL, *P_WMT_FDB_CTRL;
+
+enum wmt_chip_type {
+ WMT_CHIP_TYPE_COMBO,
+ WMT_CHIP_TYPE_SOC,
+ WMT_CHIP_TYPE_INVALID
+};
+
+#endif
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/wmt_loopback.c b/src/connectivity/combo_tool/6631_combo_tool/src/wmt_loopback.c
new file mode 100644
index 0000000..b79fd50
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/wmt_loopback.c
@@ -0,0 +1,333 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include "wmt_ioctl.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+//#include <sys/endian.h>
+#include <linux/serial.h> /* struct serial_struct */
+
+#define LEN_MAX 1024
+
+typedef enum {
+ LEN_FIXED = 0,
+ LEN_INC = 1,
+ LEN_DEC = 2,
+ LEN_RAND = 3,
+ COMBO_POWER_ON = 4,
+ COMBO_POWER_OFF = 5,
+ ADIE_LPK = 6,
+ LPBK_OP_MAX
+} LPBK_OP_ENUM;
+
+unsigned char WMT_TEST_LPBK_CMD[] = {0x1, 0x2, 0x0, 0x0, 0x7};
+unsigned char WMT_TEST_LPBK_EVT[] = {0x2, 0x2, 0x0, 0x0, 0x0};
+/*
+unsigned char out_buf[2048] = {0};
+unsigned char in_buf[2048] = {0};
+*/
+struct lpbk_package{
+ long payload_length;
+ unsigned char out_payload[2048];
+ unsigned char in_payload[2048];
+};
+
+static int wmt_loopback(int type, int count, int max, int delay) {
+ int wmt_fd;
+ int ret = -1;
+ int loop = 0;
+ int offset;
+ unsigned short buf_length = 0;
+ struct lpbk_package lpbk_buffer;
+ printf("*type(%d) count(%d) max(%d) \n", type, count, max);
+
+ if(type >= LPBK_OP_MAX){
+ printf("[%s] cannot support %d opeartion\n", __FUNCTION__, type);
+ return -1;
+ }
+
+ /* open wmt dev */
+ wmt_fd = open("/dev/stpwmt", O_RDWR | O_NOCTTY);
+ if (wmt_fd < 0) {
+ printf("[%s] Can't open stpwmt \n", __FUNCTION__);
+ return -1;
+ }
+
+ if(type == COMBO_POWER_ON){
+ printf("[power on combo chip]\n");
+ if(ioctl(wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, 2) != 0)
+ {
+ printf("[%s] power on combo chip failed\n", __FUNCTION__);
+ close(wmt_fd);
+ wmt_fd = -1;
+ return -1;
+ } else {
+ close(wmt_fd);
+ printf("[power on combo chip ok!]\n");
+ }
+ return 0;
+ }
+
+ if(type == COMBO_POWER_OFF){
+ printf("[power off combo chip]\n");
+ if(ioctl(wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, 3) != 0)
+ {
+ printf("[%s] power off combo chip failed\n", __FUNCTION__);
+ close(wmt_fd);
+ ret = -1;
+ } else {
+ close(wmt_fd);
+ printf("[power off combo chip ok!]\n");
+ }
+ return 0;
+ }
+
+ /*turn LPBK function on*/
+ printf("[power on combo chip]\n");
+ if(ioctl(wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, 2) != 0)
+ {
+ printf("[%s] Can't power on combo chip ok! failed\n", __FUNCTION__);
+ close(wmt_fd);
+ wmt_fd = -1;
+ return -1;
+ } else {
+ printf("[power on combo chip ok!]\n");
+ }
+
+ /* init length */
+ switch (type) {
+ case LEN_FIXED:
+ buf_length = (unsigned short)max;
+ break;
+ case LEN_INC:
+ buf_length = 1;
+ break;
+ case LEN_DEC:
+ buf_length = max;
+ break;
+ default:
+ /* random */
+ break;
+ }
+
+ if( (type >= LEN_FIXED) && (type <= LEN_RAND) )
+ {
+ for (loop = 0; loop < count; loop++) {
+ //<1> init buffer
+ memset((void *)&lpbk_buffer, 0, sizeof(struct lpbk_package));
+ lpbk_buffer.payload_length = buf_length;
+ for (offset = 0; offset < buf_length; offset++) {
+ lpbk_buffer.out_payload[offset] = (offset + 1)/*for test use: begin from 1*/ & 0xFF;
+ }
+
+ /*<2> do LPBK*/
+ usleep(delay * 1000);
+
+ if(( ret = ioctl(wmt_fd, WMT_IOCTL_LPBK_TEST, &lpbk_buffer)) != lpbk_buffer.payload_length){
+ printf("[%s] LPBK operation failed, return length = %d\n", __FUNCTION__, ret);
+ break;
+ }
+
+ if(lpbk_buffer.payload_length < 0) {
+ printf("[%s] LPBK operation failed, return length = %ld\n",
+ __FUNCTION__, lpbk_buffer.payload_length);
+ break;
+ }
+
+ /*<3> compare result*/
+ if (memcmp(lpbk_buffer.in_payload, lpbk_buffer.out_payload, lpbk_buffer.payload_length)) {
+ printf("[%s] WMT_TEST_LPBK_CMD payload compare error\n", __FUNCTION__);
+ break;
+ }
+ printf("[%s] exec WMT_TEST_LPBK_CMD succeed(loop = %d, size = %ld) \n", __FUNCTION__, loop, lpbk_buffer.payload_length);
+
+ /*<4> update buffer length */
+ switch (type) {
+ case LEN_INC:
+ buf_length = (buf_length == max) ? 1 : buf_length + 1;
+ break;
+ case LEN_DEC:
+ buf_length = (buf_length == 1) ? max : buf_length - 1;
+ break;
+ case LEN_RAND:
+ buf_length = rand() % max + 1;
+ break;
+ default:
+ /* no change */
+ break;
+ }
+ }
+ }
+ else if( type == ADIE_LPK )
+ {
+ int adie_chipID = 0;
+ for (loop = 0; loop < count; loop++) {
+ //<1> init buffer
+ memset((void *)&lpbk_buffer, 0, sizeof(struct lpbk_package));
+ adie_chipID = 0;
+
+ /*<2> do LPBK*/
+ usleep(delay * 1000);
+
+ if(( ret = ioctl(wmt_fd, WMT_IOCTL_ADIE_LPBK_TEST, &lpbk_buffer)) != 2){
+ printf("[%s] ADIE_LPK operation failed, return length = %d\n", __FUNCTION__, ret);
+ break;
+ }
+ adie_chipID = ((lpbk_buffer.out_payload[1] >> 4) & 0xf)*1000 +
+ (lpbk_buffer.out_payload[1] & 0xf)*100 +
+ ((lpbk_buffer.out_payload[0] >> 4) & 0xf)*10 +
+ (lpbk_buffer.out_payload[0] & 0xf);
+
+ /*<3> compare result*/
+ if ( adie_chipID != max ) {
+ printf("[%s] ADIE_LPK payload compare error\n", __FUNCTION__);
+ break;
+ }
+ printf("[%s] exec ADIE_LPK succeed(loop = %d, ChipID = %d) \n", __FUNCTION__,
+ loop, adie_chipID);
+ }
+ }
+
+ /*Not to power off chip on default, please manually to do this*/
+#if 0
+ /*turn off LPBK function*/
+ if(ioctl(wmt_fd, 7, 0) != 0)
+ {
+ printf("[%s] turn lpbk function off failed\n", __FUNCTION__);
+ ret = -1;
+ }
+ else
+ {
+ ret = 0;
+ }
+#endif
+ ret = 0;
+
+ if (loop != count) {
+ printf("fail at loop(%d) buf_length(%d)\n", loop, buf_length);
+ }
+
+ /* close wmt dev */
+ if (wmt_fd >= 0) {
+ close(wmt_fd);
+ }
+
+ return ret;
+}
+static void print_usage(void)
+{
+ unsigned int usage_lines = 0;
+ static char *(usage[]) = {
+ "wmt_loopback type count length delay",
+ " --type: essential",
+ " -0: loopback test with fixed packet length",
+ " -1: loopback test with packet length increase 1 per packet based on 1",
+ " -2: loopback test packet length decrease 1 per packet based on 1024",
+ " -3: loopback test with random packet length",
+ " -4: only turn loopback function on without test",
+ " -5: only turn loopback function off without test",
+ " -6: loopback test spi bus by get Adie chpid in SOC chip",
+ " --count: optional, total packet count, 1000 by default",
+ " --length: optional, 1 ~ 1024, 1024 by default",
+ " --delay: optional, interval between packets (ms), 0 by default",
+
+ };
+
+ for (usage_lines = 0 ; usage_lines < sizeof (usage)/sizeof(usage[0]); usage_lines++)
+ {
+ printf("%s\n", usage[usage_lines]);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int type = LEN_FIXED;
+ int count = 1000;
+ int length = 1024;
+ int delay = 0;
+ if(argc <= 1)
+ {
+ printf ("Error lack of arguments\n");
+ print_usage();
+ return -1;
+ }
+
+ if ((argc > 1) && (argv[1] != NULL)) {
+ printf("type: argv[1] %s %d\n", argv[1], atoi(argv[1]));
+ type = atoi(argv[1]);
+ }
+ if ((type < LEN_FIXED) || (type >= LPBK_OP_MAX))
+ type = LEN_FIXED;
+
+ if ((argc > 2) && (argv[2] != NULL)) {
+ printf("count: argv[2] %s %d\n", argv[2], atoi(argv[2]));
+ count = atoi(argv[2]);
+ }
+ if ((count <= 0) || (count > 10000))
+ count = 1000;
+
+ if ((argc > 3) && (argv[3] != NULL)) {
+ printf("count: argv[3] %s %d\n", argv[3], atoi(argv[3]));
+ length = atoi(argv[3]);
+ if (0 == length) {
+ printf("length is zero, reset default value 1024\n");
+ length = 1024;
+ }
+ }
+ if ((length <= 0) || (length > 2048))
+ length = 1024;
+
+ if ((argc > 4) && (argv[4] != NULL)) {
+ printf("count: argv[4] %s %d\n", argv[4], atoi(argv[4]));
+ delay = atoi(argv[4]);
+ }
+ if ((delay < 0) || (delay > 1000))
+ delay = 0;
+
+ return wmt_loopback(type, count, length, delay);
+}
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/yocto_stp_uart_launcher.c b/src/connectivity/combo_tool/6631_combo_tool/src/yocto_stp_uart_launcher.c
new file mode 100644
index 0000000..4b42bc2
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/yocto_stp_uart_launcher.c
@@ -0,0 +1,1911 @@
+
+/******************************************************************************
+* C O M P I L E R F L A G S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+*******************************************************************************
+*/
+#include "wmt_ioctl.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <pthread.h>
+/*#include <syslog.h>*/
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+//#include <sys/endian.h>
+#include <sys/uio.h>
+#include <linux/serial.h> /* struct serial_struct */
+//#include <log/log.h>
+
+#include <dirent.h>
+//#include <cutils/properties.h>
+
+
+/******************************************************************************
+* M A C R O S
+*******************************************************************************
+*/
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "wmt_launcher"
+#ifndef ALOGI
+#define ALOGI printf
+#endif
+#ifndef ALOGE
+#define ALOGE printf
+#endif
+#ifndef ALOGV
+#define ALOGV printf
+#endif
+#ifndef PROPERTY_VALUE_MAX
+#define PROPERTY_VALUE_MAX (128)
+#endif
+
+
+#define WCN_COMBO_CHIP_ID_PROP "persist.vendor.connsys.chipid"
+#define WCN_DRIVER_READY_PROP "vendor.connsys.driver.ready"
+#define WCN_FORMETA_READY_PROP "vendor.connsys.formeta.ready"
+#define WCN_FW_DBG_LOG_PROP "persist.vendor.connsys.fwlog.status"
+#define WCN_DYNAMIC_DUMP_PROP "persist.vendor.connsys.dynamic.dump"
+#define WCN_COMBO_PATCH_BUILD_VER_PROP "persist.vendor.connsys.patch.version"
+#define WCN_FW_DEBUG_CLRL_RETRY_LIMIT (5)
+
+//#include "cust_mt6620_test.h" /* project custom header file */
+
+#ifndef N_MTKSTP
+#define N_MTKSTP (15 + 1) /* MediaTek WCN Serial Transport Protocol */
+#endif
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+#define CUST_COMBO_WMT_DEV "/dev/stpwmt"
+#define CUST_COMBO_STP_DEV "/dev/ttyMT2"
+#define CUST_COMBO_PATCH_PATH "/lib/firmware"
+#define CUST_COMBO_CFG_FILE "/lib/firmware/WMT.cfg"
+
+#define CUST_BAUDRATE_DFT (115200)
+#define CUST_MULTI_PATCH (1)
+#define CUST_PATCH_SEARCH (1)
+#define PATCH_BUILD_VER_LEN (16)
+#define MAX_CMD_LEN (NAME_MAX+1)
+
+#define LAUNCHER_DEBUG (0)
+
+/******************************************************************************
+* D A T A T Y P E S
+*******************************************************************************
+*/
+
+enum stp_modes {
+ STP_MIN = 0x0,
+ STP_UART_FULL = 0x1,
+ STP_UART_MAND = 0x2,
+ STP_BTIF_FULL = 0x3,
+ STP_SDIO = 0x4,
+ STP_MAX = 0x5,
+};
+
+enum stp_uart_fc {
+ UART_DISABLE_FC = 0, /*NO flow control*/
+ UART_MTK_SW_FC = 1, /*MTK SW Flow Control, differs from Linux Flow Control*/
+ UART_LINUX_FC = 2, /*Linux SW Flow Control*/
+ UART_HW_FC = 3, /*HW Flow Control*/
+};
+
+struct sys_property {
+ const char *key;
+ const char *def_value;
+ char value[PROPERTY_VALUE_MAX];
+};
+
+
+struct stp_uart_config {
+ enum stp_uart_fc fc;
+ int parity;
+ int stop_bit;
+ int baud_rate;
+};
+
+struct stp_params_config {
+ enum stp_modes stp_mode;
+ int fm_mode;
+ char patch_path[NAME_MAX + 1];
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ char patch_name[NAME_MAX + 1];
+#endif
+ char stp_dev[NAME_MAX + 1];
+ struct stp_uart_config uart_config;
+};
+
+
+#if CUST_MULTI_PATCH
+struct stp_patch_info {
+ int download_seq;
+ char address[4];
+ char patch_name[NAME_MAX + 1];
+};
+
+struct stp_rom_patch_info {
+ int type;
+ char address[4];
+ char patch_name[NAME_MAX + 1];
+};
+#endif
+
+struct chip_ant_mode_info {
+ const char *cfg_item;
+ char cfg_item_value[NAME_MAX + 1];
+};
+
+struct chip_mode_info {
+ int chip_id;
+ enum stp_modes stp_mode;
+ struct chip_ant_mode_info ant_mode;
+};
+
+#ifndef WMT_PLAT_APEX
+struct chip_mode_info g_chip_mode_info[] = {
+ {0x6620, STP_UART_FULL, {"mt6620.defAnt", "mt6620_ant_m3.cfg"}},
+ {0x6628, STP_UART_FULL, {"mt6628.defAnt", "mt6628_ant_m1.cfg"}},
+ {0x6630, STP_SDIO, {"mt6630.defAnt", "mt6630_ant_m1.cfg"}},
+ {0x6632, STP_SDIO, {"mt6632.defAnt", "mt6632_ant_m1.cfg"}},
+};
+#else
+struct chip_mode_info g_chip_mode_info[] = {
+ {0x6620, STP_UART_FULL, {"mt6620.defAnt", "WMT.cfg"}},
+ {0x6628, STP_UART_FULL, {"mt6628.defAnt", "WMT.cfg"}},
+ {0x6630, STP_SDIO, {"mt6630.defAnt", "WMT.cfg"}},
+ {0x6632, STP_SDIO, {"mt6632.defAnt", "WMT.cfg"}},
+};
+#endif
+
+struct fw_debug_infor {
+ int log_retry; /* for polling log property retry */
+ int dump_retry; /*for polling dump property retry */
+
+ int fw_log_ctrl; /* fw log output by emi ctrl */
+ int fw_dynamic_dump; /*fw coredump dynamic regin dump*/
+
+ /* fw log output by emi state ctrl */
+ char fw_log_state_orig[PROPERTY_VALUE_MAX];
+ char fw_log_state_new[PROPERTY_VALUE_MAX];
+
+ /* fw coredump dynamic regin dump state ctrl */
+ char fw_dump_state_orig[PROPERTY_VALUE_MAX];
+ char fw_dump_state_new[PROPERTY_VALUE_MAX];
+
+ unsigned int bitmap;
+};
+
+struct cmd_hdr{
+ char *cmd;
+ int (*hdr_func)(struct stp_params_config *configs);
+};
+
+struct speed_map {
+ unsigned int baud;
+ speed_t speed;
+};
+
+/******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+*******************************************************************************
+*/
+static int cmd_hdr_baud_115k(struct stp_params_config *configs);
+static int cmd_hdr_baud_921k(struct stp_params_config *configs);
+static int cmd_hdr_baud_2kk(struct stp_params_config *configs);
+static int cmd_hdr_baud_2_5kk(struct stp_params_config *configs);
+static int cmd_hdr_baud_3kk(struct stp_params_config *configs);
+static int cmd_hdr_baud_3_5kk(struct stp_params_config *configs);
+static int cmd_hdr_baud_4kk(struct stp_params_config *configs);
+static int cmd_hdr_stp_open(struct stp_params_config *configs);
+static int cmd_hdr_stp_close(struct stp_params_config *configs);
+static int cmd_hdr_stp_rst(struct stp_params_config *configs);
+static int cmd_hdr_sch_patch(struct stp_params_config *configs);
+static int cmd_hdr_sch_rom_patch(struct stp_params_config *configs);
+
+
+/******************************************************************************
+* P U B L I C D A T A
+*******************************************************************************
+*/
+
+/******************************************************************************
+* P R I V A T E D A T A
+*******************************************************************************
+*/
+static struct speed_map g_speeds[] = {
+ {115200, B115200},
+ {921600, B921600},
+ {1000000, B1000000},
+ {1152000, B1152000},
+ {2000000, B2000000},
+ {2500000, B2500000},
+ {3000000, B3000000},
+ {3500000, B3500000},
+ {4000000, B4000000},
+};
+
+struct cmd_hdr g_cmd_hdr_table[] = {
+ { "baud_115200_0", cmd_hdr_baud_115k},
+ { "baud_921600_0", cmd_hdr_baud_921k},
+ { "baud_2000000_0", cmd_hdr_baud_2kk},
+ { "baud_2500000_0", cmd_hdr_baud_2_5kk},
+ { "baud_3000000_0", cmd_hdr_baud_3kk},
+ { "baud_3500000_0", cmd_hdr_baud_3_5kk},
+ { "baud_4000000_0", cmd_hdr_baud_4kk},
+ { "open_stp", cmd_hdr_stp_open},
+ { "close_stp", cmd_hdr_stp_close},
+ { "rst_stp", cmd_hdr_stp_rst},
+ { "srh_patch", cmd_hdr_sch_patch},
+ { "srh_rom_patch", cmd_hdr_sch_rom_patch},
+};
+
+static volatile sig_atomic_t __io_canceled = 0;
+static char g_wmt_cfg_name[NAME_MAX + 1] = {0};
+static int g_wmt_fd = -1;
+static int g_tty_fd = -1;
+static char g_cmd_str[MAX_CMD_LEN]= {0};
+static char g_resp_str[MAX_CMD_LEN]= {0};
+static struct stp_params_config g_stp_param_config;
+
+pthread_t g_thread_handle = -1;
+static struct fw_debug_infor g_fw_debug_infor;
+
+#if CUST_MULTI_PATCH
+static char g_patch_prefix[16];
+#endif
+/******************************************************************************
+* F U N C T I O N S
+*******************************************************************************
+*/
+
+/* TBD in platform-specific way */
+static int get_persist_chip_id(void) { return -1; }
+static int set_persist_chip_id(const int id) { return 0; }
+
+/* return 0 for not ready, otherwise ready */
+static int get_drv_rdy(void) {
+ /* GeK: no property to communicate with wmt_loader, and we need another way
+ * to check driver ready. Maybe query ioctl(COMBO_IOCTL_DO_MODULE_INIT) to
+ * WCN_COMBO_LOADER_DEV is a possible way for both android and non-android.
+ */
+ ALOGI("WARNING!!! Need a correct way to check driver ready!!!");
+ return 1;
+}
+
+static speed_t get_speed(int baud_rate) {
+ unsigned int idx;
+ for (idx = 0; idx < sizeof(g_speeds)/sizeof(g_speeds[0]); idx++) {
+ if (baud_rate == (int)g_speeds[idx].baud) {
+ return g_speeds[idx].speed;
+ }
+ }
+ return CBAUDEX;
+}
+
+static int set_speed(int fd, struct termios *ti, int speed) {
+ struct serial_struct ss;
+ int baudenum = get_speed(speed);
+
+ if (speed != CBAUDEX) {
+ /*printf("%s: standard baudrate: %d -> 0x%08x\n", __FUNCTION__, speed, baudenum);*/
+ if ((ioctl(fd, TIOCGSERIAL, &ss)) < 0) {
+ ALOGE("%s: BAUD: error to get the serial_struct info:%s\n", __FUNCTION__, strerror(errno));
+ return -1;
+ }
+ ss.flags &= ~ASYNC_SPD_CUST;
+#if defined(SERIAL_STRUCT_EXT) /*modified in serial_struct.h*/
+ memset(ss.reserved, 0x00, sizeof(ss.reserved));
+#endif
+ ss.flags |= (1 << 13); /*set UPFLOWLATENCY flat to tty, or serial_core will reset tty->low_latency to 0*/
+ /*set standard buadrate setting*/
+ if ((ioctl(fd, TIOCSSERIAL, &ss)) < 0) {
+ ALOGE("%s: BAUD: error to set serial_struct:%s\n", __FUNCTION__, strerror(errno));
+ return -2;
+ }
+ cfsetospeed(ti, baudenum);
+ cfsetispeed(ti, baudenum);
+ return tcsetattr(fd, TCSANOW, ti);
+ }
+ else {
+ ALOGE("%s: unsupported non-standard baudrate: %d -> 0x%08x\n", __FUNCTION__, speed, baudenum);
+ return -3;
+ }
+}
+/* Used as host uart param setup callback */
+static int launcher_setup_uart_param(int com_port, struct stp_uart_config *uart_config)
+{
+ struct termios ti;
+ int fd;
+
+ if (!uart_config) {
+ ALOGE("Invalid stpUartConfig");
+ return -2;
+ }
+
+ ALOGI("setup_uart_param %d %d\n", uart_config->baud_rate, uart_config->fc);
+
+ fd = com_port;
+ if (fd < 0) {
+ ALOGE("Invalid serial port");
+ return -2;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (tcgetattr(fd, &ti) < 0) {
+ ALOGE("Can't get port settings");
+ return -3;
+ }
+
+ cfmakeraw(&ti);
+
+ ALOGI("ti.c_cflag = 0x%08x\n", ti.c_cflag);
+ ti.c_cflag |= CLOCAL;
+ ALOGI("CLOCAL = 0x%x\n", CLOCAL);
+ ALOGI("(ori)ti.c_iflag = 0x%08x\n", ti.c_iflag);
+ ALOGI("(ori)ti.c_cflag = 0x%08x\n", ti.c_cflag);
+ ALOGI("stpuartconfig->fc= %d (0:none,sw,hw,linux)\n", uart_config->fc);
+
+ if (uart_config->fc == UART_DISABLE_FC) {
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ } else if (uart_config->fc == UART_MTK_SW_FC) {
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag |= 0x80000000; /*MTK Software FC*/
+ } else if (uart_config->fc == UART_HW_FC) {
+ ti.c_cflag |= CRTSCTS; /*RTS, CTS Enable*/
+ ti.c_iflag &= ~(0x80000000);
+ } else if (uart_config->fc == UART_LINUX_FC) {
+ ti.c_iflag |= (IXON | IXOFF | IXANY); /*Linux Software FC*/
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ }else {
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ }
+
+ ALOGI("c_c CRTSCTS = 0x%16x\n", CRTSCTS);
+ ALOGI("c_i IXON = 0x%08x\n", IXON);
+ ALOGI("c_i IXOFF = 0x%08x\n", IXOFF);
+ ALOGI("c_i IXANY = 0x%08x\n", IXANY);
+ ALOGI("(aft)ti.c_iflag = 0x%08x\n", ti.c_iflag);
+ ALOGI("(aft)ti.c_cflag = 0x%08x\n\n", ti.c_cflag);
+
+ if (tcsetattr(fd, TCSANOW, &ti) < 0) {
+ ALOGE("Can't set port settings");
+ return -4;
+ }
+
+ /* Set baudrate */
+ if (set_speed(fd, &ti, uart_config->baud_rate) < 0) {
+ ALOGE("Can't set initial baud rate");
+ return -5;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ return 0;
+}
+static int cmd_hdr_baud_115k(struct stp_params_config *config)
+{
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 115200;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_921k(struct stp_params_config *config)
+{
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 921600;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_2kk(struct stp_params_config *config) {
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 2000000;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_2_5kk(struct stp_params_config *config)
+{
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 2500000;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_3kk(struct stp_params_config *config) {
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 3000000;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_3_5kk(struct stp_params_config *config) {
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 3500000;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_baud_4kk(struct stp_params_config *config) {
+ struct stp_uart_config *uart_configs = &config->uart_config;
+ uart_configs->baud_rate = 4000000;
+ return (g_tty_fd != -1) ? launcher_setup_uart_param(g_tty_fd, uart_configs) : -1;
+}
+
+static int cmd_hdr_stp_open(struct stp_params_config *config) {
+ int ld;
+
+ ALOGV("%p\n", config);
+ if ((STP_UART_FULL == g_stp_param_config.stp_mode) && (-1 == g_tty_fd)) {
+ g_tty_fd = open(g_stp_param_config.stp_dev, O_RDWR | O_NOCTTY);
+ if (g_tty_fd < 0) {
+ fprintf(stderr, "Can't open serial port %s\n", g_stp_param_config.stp_dev);
+ return -2;
+ }
+ ALOGI("real_tty(%s) opened(%d)\n", g_stp_param_config.stp_dev, g_tty_fd);
+
+ /* Set TTY to N_MTKSTP line discipline */
+ ld = N_MTKSTP;
+ if (ioctl(g_tty_fd, TIOCSETD, &ld) < 0) {
+ fprintf(stderr, "Can't set ldisc to N_MTKSTP\n");
+ return -3;
+ }
+
+ //printf("Set tty->low_latency\n");
+ if (ioctl(g_tty_fd, HCIUARTSETPROTO, 0) < 0) {
+ ALOGE("Can't set HCIUARTSETPROTO\n");
+ return -4;
+ }
+ return 0;
+ }
+ else {
+ fprintf(stderr, "stp_open fail: stp_mode(%d) real_tty_fd(%d) \n",
+ g_stp_param_config.stp_mode, g_tty_fd);
+ return -1;
+ }
+}
+
+static int cmd_hdr_stp_close(struct stp_params_config *config) {
+ int ld;
+
+ ALOGV("%p\n", config);
+ if ((STP_UART_FULL == g_stp_param_config.stp_mode) && (0 <= g_tty_fd)) {
+ /* Restore TTY line discipline */
+ ld = N_TTY;
+ if (ioctl(g_tty_fd, TIOCSETD, &ld) < 0) {
+ ALOGE("Can't restore line discipline");
+ return -2;
+ }
+
+ close(g_tty_fd);
+ g_tty_fd = -1;
+ return 0;
+ } else if (g_tty_fd == -1)
+ return 0;
+ else {
+ fprintf(stderr, "stp_close fail: stp_mode(%d) real_tty_fd(%d) \n", g_stp_param_config.stp_mode, g_tty_fd);
+ return -1;
+ }
+}
+
+static int cmd_hdr_stp_rst(struct stp_params_config *config) {
+ int ret = 0;
+ /*this step fail?*/
+ ret = cmd_hdr_stp_close(config);
+ /*here, launcher is close state*/
+ ret = cmd_hdr_stp_open(config);
+ return ret;
+}
+#if 0
+static void launcher_set_patch_version(int fd)
+{
+ int ret = 0;
+ struct sys_property patch_ver_prop;
+ int bytes;
+ char patch_build_ver[PATCH_BUILD_VER_LEN] = {0};
+
+ /*4.2. read patch header and check if metch with MAJOR+MINOR number in fw version */
+ bytes = read(fd, patch_build_ver, PATCH_BUILD_VER_LEN);
+ if (-1 == bytes)
+ ALOGE("read patch_build_ver failed!\n");
+
+ patch_build_ver[PATCH_BUILD_VER_LEN - 1] = '\0';
+
+ patch_ver_prop.key = WCN_COMBO_PATCH_BUILD_VER_PROP;
+ sprintf(patch_ver_prop.value, "%s", patch_build_ver);
+
+ ret = property_set(patch_ver_prop.key, patch_ver_prop.value);
+ if (0 != ret)
+ ALOGE("set property(%s) to %s failed,ret:%d, errno:%d\n",
+ patch_ver_prop.key, patch_ver_prop.value, ret, errno);
+ else
+ ALOGI("set property(%s) to %s succeed.\n",
+ patch_ver_prop.key, patch_ver_prop.value);
+}
+#endif
+
+#if CUST_MULTI_PATCH
+static int launcher_get_patch_prefix(int chip_id, char **patch_prefix) {
+ /* use malloc for alloc memory is better*/
+ int chip = chip_id;
+
+ if (!patch_prefix) {
+ ALOGE("invalid pointer\n");
+ return -1;
+ }
+
+ if ((0x0321 == chip) || (0x0335 == chip) || (0x0337 == chip)) {
+ chip = 0x6735;
+ ALOGI("for denali chipid convert\n");
+ }
+ if (0x0326 == chip) {
+ chip = 0x6755;
+ ALOGI("for jade chipid convert\n");
+ }
+ if (0x0279 == chip) {
+ chip = 0x6797;
+ ALOGI("for everest chipid convert\n");
+ }
+ if (0x0551 == chip) {
+ chip = 0x6757;
+ ALOGI("for olympus chipid convert\n");
+ }
+ if (0x0633 == chip) {
+ chip = 0x6570;
+ ALOGI("for rushmore chipid convert\n");
+ }
+ if (0x0690 == chip) {
+ chip = 0x6763;
+ ALOGI("for bianco chipid convert\n");
+ }
+ if (0x0507 == chip) {
+ chip = 0x6759;
+ ALOGI("for alaska chipid convert\n");
+ }
+ if (0x0699 == chip) {
+ chip = 0x6739;
+ ALOGI("for zion chipid convert\n");
+ }
+ if (0x0713 == chip) {
+ chip = 0x6775;
+ ALOGI("for cannon chipid convert\n");
+ }
+ if (0x0788 == chip) {
+ chip = 0x6771;
+ ALOGI("for sylvia chipid convert\n");
+ }
+
+ memset(g_patch_prefix, '\0', sizeof(g_patch_prefix));
+
+ switch (chip) {
+ case 0x6572:
+ case 0x6582:
+ case 0x6592:
+ strncpy(g_patch_prefix, "ROMv1", strlen("ROMv1"));
+ break;
+ case 0x8127:
+ case 0x6571:
+ strncpy(g_patch_prefix, "ROMv2", strlen("ROMv2"));
+ break;
+ case 0x6755:
+ case 0x6752:
+ case 0x8163:
+ case 0x7623:
+ case 0x6735:
+ case 0x6570:
+ case 0x6580:
+ case 0x6757:
+ case 0x6763:
+ case 0x6739:
+ case 0x8167:
+ strncpy(g_patch_prefix, "ROMv2_lm", strlen("ROMv2_lm"));
+ break;
+ case 0x6797:
+ strncpy(g_patch_prefix, "ROMv3", strlen("ROMv3"));
+ break;
+ case 0x6759:
+ strncpy(g_patch_prefix, "ROMv4", strlen("ROMv4"));
+ break;
+ case 0x6775:
+ case 0x6771:
+ strncpy(g_patch_prefix, "ROMv4_be", strlen("ROMv4_be"));
+ break;
+ case 0x6765:
+ case 0x3967:
+ case 0x6761:
+ case 0x8168:
+ strncpy(g_patch_prefix, "soc1_0", strlen("soc1_0"));
+ break;
+ case 0x8512:
+ strncpy(g_patch_prefix, "soc2_1", strlen("soc2_1"));
+ break;
+ default:
+ strncpy(g_patch_prefix, "mt", strlen("mt"));
+ sprintf(g_patch_prefix + strlen("mt"), "%04x", chip);
+ break;
+ }
+ strncat(g_patch_prefix, "_patch", strlen("_patch"));
+
+ ALOGI("patch name pre-fix:%s\n", g_patch_prefix);
+
+ *patch_prefix = g_patch_prefix;
+ return 0;
+}
+
+static int launcher_get_patch_version(int patch_fd, unsigned int *patch_ver)
+{
+ int bytes = -1;
+ int ret = 0;
+
+ bytes = read(patch_fd, ((char *)patch_ver) + 1, 1);
+ if (-1 == bytes) {
+ ALOGE("read patch_ver failed!\n");
+ ret = -1;
+ }
+ bytes = read(patch_fd, ((char *)patch_ver), 1);
+ if (-1 == bytes) {
+ ALOGE("read patch_ver failed!\n");
+ ret = -2;
+ }
+
+ return ret;
+}
+
+static int launcher_set_patch_info(int fd, char *patch_info, char *full_name, int is_first) {
+ int patch_num = -1;
+ int patch_seq = -1;
+ struct stp_patch_info pi;
+
+ if (!patch_info) {
+ ALOGE("invalid patch infor!\n");
+ return -1;
+ }
+ if (!full_name) {
+ ALOGE("invalid patch full name!\n");
+ return -2;
+ }
+
+ if (is_first) {
+ patch_num = (patch_info[0] & 0xF0) >> 4;
+ ALOGI("patch num = [%d]\n", patch_num);
+ ioctl(fd, WMT_IOCTL_SET_PATCH_NUM, patch_num);
+ }
+
+ patch_seq = (patch_info[0] & 0x0F);
+ ALOGI("patch seq = [%d]\n", patch_seq);
+ pi.download_seq = patch_seq;
+ memcpy(pi.address, patch_info, sizeof(pi.address));
+ pi.address[0] = 0x00;
+ strncpy(pi.patch_name, full_name, sizeof(pi.patch_name) - 1);
+ pi.patch_name[sizeof(pi.patch_name) - 1] = '\0';
+
+ ioctl(fd, WMT_IOCTL_SET_PATCH_INFO, &pi);
+
+ return 0;
+}
+
+static int cmd_hdr_sch_patch(struct stp_params_config *config) {
+ int chip_id = 0;
+ int fw_version = 0;
+ char *patch_prefix = NULL;
+ char patch_full_name[256] = {0};
+ char patchName[128] = {0};
+ unsigned int patch_ver = 0;
+ DIR *dir = NULL;
+ int patch_fd = -1;
+ int ret = 0;
+ int bytes;
+ char patch_info[8] = {0};
+ unsigned int is_first = 1;
+ struct dirent* dirent = NULL;
+ int flag;
+
+ if (g_wmt_fd <= 0) {
+ ALOGE("file descriptor is not valid\n");
+ return -1;
+ }
+ /*1. ioctl to get CHIP ID*/
+ chip_id = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 0);
+ if (launcher_get_patch_prefix(chip_id, &patch_prefix)) {
+ ALOGE("launcher_get_patch_prefix fail\n");
+ return -2;
+ }
+
+ /*2. ioctl to get FIRMWARE VERSION*/
+ if (chip_id == 0x6765 || chip_id == 0x3967 ||
+ chip_id == 0x6761 || chip_id == 0x8168 ||
+ chip_id == 0x8512) {
+#if 0
+ ip_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 3);
+ ALOGI("ip_version:0x%08x\n", ip_version);
+#else
+ fw_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI("fw_version:0x%04x\n", fw_version);
+#endif
+ } else {
+ fw_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI("fw_version:0x%04x\n", fw_version);
+ }
+ /*3. open directory patch located*/
+ strncpy(config->patch_path, CUST_COMBO_PATCH_PATH, strlen(CUST_COMBO_PATCH_PATH));
+ config->patch_path[strlen(CUST_COMBO_PATCH_PATH) + 1] = '\0';
+
+ dir = opendir(config->patch_path);
+ if (NULL == dir) {
+ ALOGE("patch path cannot be opened");
+ return -3;
+ }
+ while (NULL != (dirent = readdir(dir))) {
+ patch_ver = 0;
+ if (0 == (strncmp(dirent->d_name, patch_prefix, strlen(patch_prefix)))) {
+ /*4.1. search patch name begined with chip_name*/
+ strncpy(patch_full_name, config->patch_path, strlen(config->patch_path)+1);
+ /*robust, if input patch is /etc/firmwre/ no issue should be happened.*/
+ strncat(patch_full_name, "/", strlen("/"));
+ strncat(patch_full_name, dirent->d_name,
+ sizeof(patch_full_name) - strlen(patch_full_name) - 1);
+ patch_full_name[sizeof(patch_full_name) - 1] = '\0';
+ ALOGI("%s\n", patch_full_name);
+ strncpy (patchName, dirent->d_name, strlen(dirent->d_name)+1);
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 <= (patch_fd = (open(patch_full_name, O_RDONLY)))) {
+#if 0
+ launcher_set_patch_version(patch_fd);
+#endif
+
+ if (-1 != lseek(patch_fd, 22, SEEK_SET)) {
+ if (launcher_get_patch_version(patch_fd, &patch_ver)) {
+ ALOGE("read patch_ver failed!\n");
+ ret = -4;
+ goto read_fail;
+ }
+ /*print hardware version information in patch*/
+ ALOGI("fw Ver in patch: 0x%08x\n", patch_ver);
+ if (chip_id == 0x6765 || chip_id == 0x3967 ||
+ chip_id == 0x6761 || chip_id == 0x8168 ||
+ chip_id == 0x8512)
+#if 0
+ flag = patch_ver == ip_version ? 1 : 0;
+#else
+ flag = (0 == ((patch_ver ^ fw_version) & 0x00ff)) ? 1 : 0;
+#endif
+ else
+ flag = (0 == ((patch_ver ^ fw_version) & 0x00ff)) ? 1 : 0;
+ if (flag) {
+ memset(patch_info, 0, sizeof(patch_info));
+ bytes = read(patch_fd, patch_info, 4);
+ if (-1 == bytes) {
+ ret = -5;
+ ALOGE("read patch_info failed!\n");
+ goto read_fail;
+ }
+ patch_info[4] = '\0';
+ ALOGI("read patch info:0x%02x,0x%02x,0x%02x,0x%02x\n",
+ patch_info[0], patch_info[1], patch_info[2], patch_info[3]);
+ if (launcher_set_patch_info(g_wmt_fd, patch_info, patchName, is_first)) {
+ ALOGE("launcher_set_patch_info fail\n");
+ ret = -6;
+ goto read_fail;
+ }
+ is_first = 0;
+ }
+ } else
+ ALOGE("seek failed\n");
+read_fail:
+ close(patch_fd);
+ patch_fd = -1;
+ } else
+ ALOGE("open patch file(%s) failed\n", patchName);
+ }
+ }
+ /*5. return value*/
+ closedir(dir);
+ dir = NULL;
+
+ return ret;
+}
+
+static int launcher_get_rom_patch_prefix(int chip_id, char **patch_prefix) {
+ /* use malloc for alloc memory is better*/
+ int chip = chip_id;
+
+ if (!patch_prefix) {
+ ALOGE("invalid pointer\n");
+ return -1;
+ }
+
+ memset(g_patch_prefix, '\0', sizeof(g_patch_prefix));
+
+ switch (chip) {
+ case 0x6765:
+ case 0x3967:
+ case 0x6761:
+ case 0x8168:
+ strncpy(g_patch_prefix, "soc1_0", strlen("soc1_0"));
+ break;
+ case 0x8512:
+ strncpy(g_patch_prefix, "soc2_1", strlen("soc2_1"));
+ break;
+ case 0x6779:
+ strncpy(g_patch_prefix, "soc2_0", strlen("soc2_0"));
+ break;
+ default:
+ strncpy(g_patch_prefix, "soc1_0", strlen("soc1_0"));
+ break;
+
+ }
+ strncat(g_patch_prefix, "_ram", strlen("_ram"));
+
+ ALOGI("patch name pre-fix:%s\n", g_patch_prefix);
+
+ *patch_prefix = g_patch_prefix;
+
+ return 0;
+}
+
+static int launcher_set_rom_patch_info(int fd, char *patch_info, char *full_name) {
+ struct stp_rom_patch_info pi;
+ int iRet = 0;
+
+ if (!patch_info) {
+ ALOGE("invalid patch infor!\n");
+ return -1;
+ }
+ if (!full_name) {
+ ALOGE("invalid patch full name!\n");
+ return -2;
+ }
+
+ pi.type = patch_info[7];
+ ALOGI("rom patch type = [%d]\n", pi.type);
+ memcpy(pi.address, patch_info, sizeof(pi.address));
+ pi.address[0] = 0x00;
+ strncpy(pi.patch_name, full_name, sizeof(pi.patch_name) - 1);
+ pi.patch_name[sizeof(pi.patch_name) - 1] = '\0';
+
+ iRet = ioctl(fd, WMT_IOCTL_SET_ROM_PATCH_INFO, &pi);
+ if (iRet != 0) {
+ ALOGE("ioctl WMT_IOCTL_SET_ROM_PATCH_INFO error (0x%x)\n", iRet);
+ return -3;
+ }
+
+ return 0;
+}
+
+static int cmd_hdr_sch_rom_patch(struct stp_params_config *config) {
+ int chip_id = 0;
+#if 0
+ unsigned int ip_version = 0;
+#else
+ unsigned int fw_version = 0;
+#endif
+ char *patch_prefix = NULL;
+ char patch_full_name[256] = {0};
+ char patchName[128] = {0};
+ unsigned int patch_ver = 0;
+ DIR *dir = NULL;
+ int patch_fd = -1;
+ int ret = 0;
+ int bytes;
+ char patch_info[8] = {0};
+ struct dirent* dirent = NULL;
+
+ if (g_wmt_fd <= 0) {
+ ALOGE("file descriptor is not valid\n");
+ return -1;
+ }
+ /*1. ioctl to get CHIP ID*/
+ chip_id = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 0);
+ if (launcher_get_rom_patch_prefix(chip_id, &patch_prefix)) {
+ ALOGE("launcher_get_rom_patch_prefix fail\n");
+ return -2;
+ }
+
+ /*2. ioctl to get FIRMWARE VERSION*/
+#if 0
+ ip_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 3);
+ ALOGI("ip_version:0x%04x\n", ip_version);
+#else
+ fw_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI("fw_version:0x%04x\n", fw_version);
+#endif
+ /*3. open directory patch located*/
+ strncpy(config->patch_path, CUST_COMBO_PATCH_PATH, strlen(CUST_COMBO_PATCH_PATH));
+ config->patch_path[strlen(CUST_COMBO_PATCH_PATH) + 1] = '\0';
+
+ dir = opendir(config->patch_path);
+ if (NULL == dir) {
+ ALOGE("patch path cannot be opened");
+ return -3;
+ }
+ while (NULL != (dirent = readdir(dir))) {
+ patch_ver = 0;
+ if (0 == (strncmp(dirent->d_name, patch_prefix, strlen(patch_prefix)))) {
+ /*4.1. search patch name begined with chip_name*/
+ strncpy(patch_full_name, config->patch_path, strlen(config->patch_path)+1);
+ /*robust, if input patch is /etc/firmwre/ no issue should be happened.*/
+ strncat(patch_full_name, "/", strlen("/"));
+ strncat(patch_full_name, dirent->d_name,
+ sizeof(patch_full_name) - strlen(patch_full_name) - 1);
+ ALOGI("%s\n", patch_full_name);
+ strncpy(patchName, dirent->d_name, strlen(dirent->d_name)+1);
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 <= (patch_fd = (open(patch_full_name, O_RDONLY)))) {
+ if (-1 != lseek(patch_fd, 22, SEEK_SET)) {
+ if (launcher_get_patch_version(patch_fd, &patch_ver)) {
+ ALOGE("read patch_ver failed!\n");
+ ret = -4;
+ goto read_fail;
+ }
+ /*print hardware version information in patch*/
+ ALOGI("fw Ver in patch: 0x%04x\n", patch_ver);
+#if 0
+ if (0 == ((patch_ver ^ ip_version) & 0xffffffff)) {
+#else
+ if (0 == ((patch_ver ^ fw_version) & 0x00ff)) {
+#endif
+ memset(patch_info, 0, sizeof(patch_info));
+ bytes = read(patch_fd, patch_info, 8);
+ if (-1 == bytes) {
+ ret = -5;
+ ALOGE("read patch_info failed!\n");
+ goto read_fail;
+ }
+ if ((patch_info[3] & 0xF0) && (patch_info[7] >= 0 && patch_info[7] <= 5)) {
+ ALOGI("patch info:0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n",
+ patch_info[0], patch_info[1], patch_info[2], patch_info[3],
+ patch_info[4], patch_info[5], patch_info[6], patch_info[7]);
+ if (launcher_set_rom_patch_info(g_wmt_fd, patch_info, patchName)) {
+ ALOGE("launcher_set_rom_patch_info fail\n");
+ ret = -6;
+ goto read_fail;
+ }
+ }
+ }
+ } else
+ ALOGE("seek failed\n");
+read_fail:
+ close(patch_fd);
+ patch_fd = -1;
+ } else
+ ALOGE("open patch file(%s) failed\n", patchName);
+ }
+ }
+ /*5. return value*/
+ closedir(dir);
+ dir = NULL;
+
+ return ret;
+}
+#else
+static int cmd_hdr_sch_patch(struct stp_params_config *config) {
+ int chip_id = 0;
+ int fw_version = 0;
+ char chip_name[16] = {0};
+ char patch_full_name[256] = {0};
+ unsigned int patch_ver = 0;
+ DIR *dir = NULL;
+ int patch_fd = -1;
+ struct dirent* dirent = NULL;
+ int ret = -1;
+
+ if (g_wmt_fd <= 0) {
+ ALOGE("file descriptor is not valid\n");
+ return -1;
+ }
+
+ /*1. ioctl to get CHIP ID*/
+ chip_id = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 0);
+ strncpy(chip_name, "mt", strlen("mt")+1);
+ sprintf(chip_name + strlen(chip_name), "%04x", chip_id);
+ strncat(chip_name, "_patch", strlen("_patch"));
+ ALOGI("patch name pre-fix:%s\n", chip_name);
+
+ /*2. ioctl to get FIRMWARE VERSION*/
+ fw_version = ioctl(g_wmt_fd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI("fwVersion:0x%04x\n", fw_version);
+
+ /*3. open directory patch located*/
+ strncpy(config->patch_path, CUST_COMBO_PATCH_PATH, strlen(CUST_COMBO_PATCH_PATH));
+ config->patch_path[strlen(CUST_COMBO_PATCH_PATH) + 1] = '\0';
+
+ dir = opendir(config->patch_path);
+ if (NULL == dir) {
+ ALOGE("patch path cannot be opened");
+ ret = -2;
+ return ret;
+ }
+ while (NULL != (dirent = readdir(dir))) {
+ patch_ver = 0;
+ if (0 == (strncmp(dirent->d_name, chip_name, strlen(chip_name)))) {
+ /*4.1. search patch name begined with chipName*/
+ strncpy(patch_full_name, config->patch_path, strlen(config->patch_path)+1);
+ /*robust, if input patch is /etc/firmwre/ no issue should be happened.*/
+ strncat(patch_full_name, "/", strlen("/"));
+ strncat(patch_full_name, dirent->d_name, strlen(dirent->d_name));
+ ALOGI("%s\n", patch_full_name);
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 < (patch_fd = (open(patch_full_name, O_RDONLY)))) {
+ /*4.2. read patch header and check if metch with MAJOR+MINOR number in fw version */
+ if (-1 != lseek(patch_fd, 22, SEEK_SET)) {
+ read(patch_fd, ((char *)&patch_ver) + 1, 1);
+ read(patch_fd, ((char *)&patch_ver), 1);
+ /*print firmware version information in patch*/
+ ALOGI("fw Ver in patch: 0x%04x\n", patch_ver);
+ if (0 == ((patch_ver ^ fw_version) & 0x00ff)) {
+ ioctl(g_wmt_fd, WMT_IOCTL_SET_PATCH_NAME, patch_full_name);
+ ALOGI("fw Ver in patch matches with firmware version\n");
+ ret = 0;
+ close(patch_fd);
+ break;
+ }
+ } else
+ ALOGE("seek failed\n");
+
+ close(patch_fd);
+ patch_fd = -1;
+ } else
+ ALOGE("open patch file(%s) failed\n", patch_full_name);
+ }
+ }
+ /*5. return value*/
+ closedir(dir);
+ dir = NULL;
+
+ return ret;
+}
+#endif
+/*
+ret 0: success
+ret 1: cmd not found
+ret -x: handler return value
+*/
+static int launcher_handle_cmd(struct stp_params_config *stp_param_config, char *cmd, int len) {
+ int ret = 1;
+ int i;
+ int cmd_len;
+
+ for (i = 0; i < (int)(sizeof(g_cmd_hdr_table)/sizeof(g_cmd_hdr_table[0])); ++i) {
+ cmd_len = (int)strlen(g_cmd_hdr_table[i].cmd);
+ if (!strncmp(g_cmd_hdr_table[i].cmd, cmd, (len < cmd_len) ? len : cmd_len)) {
+ ret = (*g_cmd_hdr_table[i].hdr_func)(stp_param_config);
+ }
+ }
+
+ return ret;
+}
+
+static void launcher_display_usage(void)
+{
+ unsigned int index = 0;
+
+ char * usage[] = {
+ "MTK WCN combo tool set, version 1.0-release",
+ "Usage: wmt_launcher [-m mode] -p patchfolderpath [-d uartdevicenode] [-b baudrate] [-c uartflowcontrol]",
+ " -m (BT/GPS/FM common interface mode selection, optional)",
+ " -1: UART mode (common interface: UART)",
+ " -3: BTIF mode (common interface: BTIF)",
+ " -4: SDIO mode (common interface: SDIO)",
+ " -p (MTK WCN chip firmware patch location, must)",
+ " -e.g. /system/etc/firmware",
+ " -n (MTK WCN chip firmware patch name, option)",
+ " -e.g. /system/etc/firmware/firmware/mt6628_patch_hdr.bin",
+ " if UART mode is set, you need config baud rate and tty device:",
+ " -b (Baudrate set when BT/GPS/FM runs under UART mode, no needed under SDIO mode)",
+ " -115200/921600/2000000/2500000/3000000/3500000/4000000",
+ " -d (UART device node, when under UART mode, no needed under SDIO mode)",
+ " -e.g. /dev/ttyMT1, /dev/ttyMT2, /dev/ttyHS2, etc.",
+ " -c (UART flowcontrol set)",
+ " -0, no flowcontrol default value, please donot modify this parameter",
+ "e.g. wmt_launcher -m 3 -p /system/etc/firmware/",
+ "e.g. wmt_launcher -m 1 -n /system/etc/firmware/mt6628_patch_hdr.bin",
+ "e.g. wmt_launcher -m 4 -d /dev/ttyMT2 -b 4000000 -n /system/etc/firmware/mt6628_patch_hdr.bin",
+ };
+
+ for (index = 0; index < sizeof(usage) / sizeof(usage[0]); index++ )
+ ALOGI("%s\n", usage[index]);
+
+ exit(EXIT_FAILURE);
+}
+
+
+static int launcher_stp_param_valid_check(struct stp_params_config *stp_param_configs, enum wmt_chip_type chip_type)
+{
+ int ret = 0;
+
+ /*fix me, check condition should be more reasonable*/
+ if ('\0' == stp_param_configs->patch_path[0]) {
+ ALOGE("MCU patch path not config,use /system/etc/firmware\n");
+ strncpy(stp_param_configs->patch_path, "/system/etc/firmware", strlen("/system/etc/firmware"));
+ stp_param_configs->patch_path[strlen("/system/etc/firmware") + 1] = '\0';
+ ret = -1;
+ }
+
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ if ('\0' == stp_param_configs->patch_name[0]) {
+ ALOGE("MCU patch path not config,you need config it yourself\n");
+ ret = -2;
+ }
+#endif
+ if (stp_param_configs->stp_mode != STP_SDIO &&
+ stp_param_configs->stp_mode != STP_UART_MAND &&
+ stp_param_configs->stp_mode != STP_UART_FULL &&
+ stp_param_configs->stp_mode != STP_BTIF_FULL) {
+ if (WMT_CHIP_TYPE_COMBO == chip_type) {
+ ALOGE("Stp Mode is not set, common interface use default: SDIO Mode");
+ stp_param_configs->stp_mode = STP_SDIO;
+ } else {
+ ALOGE("Stp Mode is not set, common interface use default: BTIF Mode");
+ stp_param_configs->stp_mode = STP_BTIF_FULL;
+ }
+ ret = -3;
+ }
+
+ if (stp_param_configs->stp_mode == STP_UART_MAND || stp_param_configs->stp_mode == STP_UART_FULL) {
+ ALOGI ("Common Interface: UART mode\n");
+ if ('\0' == stp_param_configs->stp_dev[0]) {
+ strncpy(stp_param_configs->stp_dev, CUST_COMBO_STP_DEV, strlen(CUST_COMBO_STP_DEV)+1);
+ ALOGI("no uart device input, use default: %s\n", stp_param_configs->stp_dev);
+ ret = -4;
+ }
+ if (stp_param_configs->uart_config.baud_rate < 0) {
+ /* FixMe:Chaozhong, add baudrate validation check */
+ stp_param_configs->uart_config.baud_rate = 4000000;
+ ALOGI("no baudrate input, use default: %d\n", stp_param_configs->uart_config.baud_rate);
+ ret = -5;
+ }
+ }
+ return ret;
+}
+
+static int launcher_parser_wmt_cfg(char *item)
+{
+ int index = 0;
+ int length = 0;
+ char *str = NULL;
+ char *key = NULL;
+ char *value = NULL;
+ int max_index = sizeof (g_chip_mode_info) / sizeof (g_chip_mode_info[0]);
+
+ if (NULL == item) {
+ ALOGE("Warning:item is NULL\n");
+ return -1;
+ }
+ /*all item must be start with mt66xx*/
+ str = strstr(item, "m");
+ if (NULL == str) {
+ ALOGE("Warning:no string start with 'm' found in %s\n", item);
+ return -2;
+ }
+
+ for (index = 0; index < max_index; index++) {
+ key = (char*)g_chip_mode_info[index].ant_mode.cfg_item;
+
+ if (0 == strncasecmp(str, key, strlen(key))) {
+ str = strstr(str, "=");
+ if (NULL == str) {
+ ALOGE("Warning:no '=' found in %s\n", str);
+ return -3;
+ }
+ str = strstr(str, "m");
+ if (NULL == str) {
+ ALOGE("Warning:no 'm' found in %s\n", str);
+ return -4;
+ }
+
+ while (((*str) == ' ') || ((*str) == '\t') || ((*str) == '\n')) {
+ if (str >= item + strlen(item))
+ break;
+ str++;
+ }
+ value = str;
+
+ while (((*str) != ' ') && ((*str) != '\t') && ((*str) != '\0') && ((*str) != '\n') && ((*str) != '\r')) {
+ if (str >= item + strlen(item))
+ break;
+ str++;
+ }
+ *str = '\0';
+ length = sizeof(g_chip_mode_info[index].ant_mode.cfg_item_value);
+ strncpy(g_chip_mode_info[index].ant_mode.cfg_item_value, value, length - 1);
+ g_chip_mode_info[index].ant_mode.cfg_item_value[length - 1] = '\0';
+ ALOGI("Info:key:%s value:%s\n", key, g_chip_mode_info[index].ant_mode.cfg_item_value);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int launcher_get_wmt_cfg_infor(void)
+{
+ FILE * file = NULL;
+ int ret = -1;
+ char *str = NULL;
+ char line[NAME_MAX];
+
+ file = fopen(CUST_COMBO_CFG_FILE, "r");
+ if (NULL == file) {
+ ALOGE("%s cannot be opened, errno:%d\n", CUST_COMBO_CFG_FILE, errno);
+ return -2;
+ }
+ ret = 0;
+ do {
+ str = fgets(line, NAME_MAX, file);
+ if (NULL == str) {
+ ALOGI("NULL is returned, eighter EOF or error maybe found\n");
+ break;
+ }
+ launcher_parser_wmt_cfg(line);
+ memset(line, 0, NAME_MAX);
+
+ } while (str != NULL);
+
+ if (NULL != file) {
+ if (0 == fclose(file))
+ ALOGI("close %s succeed\n", CUST_COMBO_CFG_FILE);
+ else
+ ALOGI("close %s failed, errno:%d\n", CUST_COMBO_CFG_FILE, errno);
+ }
+ return ret;
+}
+
+
+static int launcher_get_chip_info_index(int chip_id)
+{
+ int index = -1;
+ int left = 0;
+ int middle = 0;
+ int right = sizeof (g_chip_mode_info) / sizeof (g_chip_mode_info[0]) - 1;
+
+ if ((chip_id < g_chip_mode_info[left].chip_id) || (chip_id > g_chip_mode_info[right].chip_id))
+ return index;
+
+ middle = (left + right) / 2;
+
+ while (left <= right) {
+ if (chip_id > g_chip_mode_info[middle].chip_id)
+ left = middle + 1;
+ else if (chip_id < g_chip_mode_info[middle].chip_id)
+ right = middle - 1;
+ else {
+ index = middle;
+ break;
+ }
+ middle = (left + right) / 2;
+ }
+
+ if (0 > index)
+ ALOGE("no supported chip_id found\n");
+ else
+ ALOGI("index:%d, chip_id:0x%x\n", index, g_chip_mode_info[index].chip_id);
+
+ return index;
+}
+
+static void launcher_combine_cfg_name(int chip_id, char *cfg_file_path)
+{
+ int index = -1;
+ int stp_mode = g_stp_param_config.stp_mode;
+
+ index = launcher_get_chip_info_index(chip_id);
+ if ((stp_mode <= STP_MIN) || (STP_SDIO < stp_mode)) {
+ ALOGI("STP Mode is not set, fetching default mode...\n");
+ if (0 <= index)
+ g_stp_param_config.stp_mode = g_chip_mode_info[index].stp_mode;
+ else
+ g_stp_param_config.stp_mode = -1;
+ }
+
+ if ((0 <= index) && (NULL != cfg_file_path)) {
+ memset(g_wmt_cfg_name, 0, sizeof(g_wmt_cfg_name));
+ strncpy(g_wmt_cfg_name, g_chip_mode_info[index].ant_mode.cfg_item_value, sizeof(g_wmt_cfg_name) - 1);
+ g_wmt_cfg_name[strlen(g_chip_mode_info[index].ant_mode.cfg_item_value)] = '\0';
+ } else
+ memset(g_wmt_cfg_name, 0, sizeof(g_wmt_cfg_name));
+
+ ALOGI("chip_id(0x%04x), default Mode(%d), strlen(g_wmt_cfg_name)(%zd), g_wmt_cfg_name(%s)\n",
+ chip_id, g_stp_param_config.stp_mode, strlen(g_wmt_cfg_name), g_wmt_cfg_name);
+
+}
+
+static void launcher_set_wmt_cfg_infor(int chip_id, char *cfg_file_path) {
+ if (!launcher_get_wmt_cfg_infor()) {
+ launcher_combine_cfg_name(chip_id, cfg_file_path);
+ /* send WMT config name configuration to driver */
+ ioctl(g_wmt_fd, WMT_IOCTL_WMT_CFG_NAME, g_wmt_cfg_name);
+ } else
+ ALOGE("launcher_get_wmt_cfg_infor fail\n");
+}
+
+static void launcher_set_uart_port_name(char *stp_dev) {
+ char *uart_name = NULL;
+
+ /* send uart name to driver*/
+ if (stp_dev) {
+ uart_name = strstr(stp_dev, "tty");
+ if (!uart_name)
+ ALOGE("no uart name found in %s\n", stp_dev);
+ else
+ ALOGI("uart name %s\n", uart_name);
+ }
+
+ if (!uart_name) {
+ uart_name = "ttyMT2";
+ ALOGI("use default uart %s\n", uart_name);
+ }
+
+ ioctl(g_wmt_fd, WMT_IOCTL_PORT_NAME, uart_name);
+}
+
+#if (MTK_COMBO_ENABLE_WIFI_IN_LAUNCHER==1)
+#define CUST_COMBO_WIFI_DEV "/dev/wmtWifi"
+#define POWER_ON_WIFI "1"
+#define POWER_ON_WIFI_LEN 1
+static int gWifiFd = -1;
+
+static int enable_wifi(void) {
+ int retryCounter = 0;
+ int i_ret = -1;
+
+ gWifiFd = open(CUST_COMBO_WIFI_DEV, O_RDWR | O_NOCTTY);
+ do {
+ if (gWifiFd < 0) {
+ ALOGI("Can't open device node(%s) error:%d \n", CUST_COMBO_WIFI_DEV, gWifiFd);
+ usleep(300000);
+ gWifiFd = open(CUST_COMBO_WIFI_DEV, O_RDWR | O_NOCTTY);
+ } else {
+ break;
+ }
+ retryCounter++;
+ } while (retryCounter < 20);
+
+ if (gWifiFd > 0) {
+ do {
+ i_ret = write(gWifiFd, POWER_ON_WIFI, POWER_ON_WIFI_LEN);
+ if (i_ret == 1) {
+ ALOGI("Power on device node(%s) gWifiFd:%d succeed !!\n", CUST_COMBO_WIFI_DEV, gWifiFd);
+ break;
+ } else {
+ ALOGI("Power on device node(%s) gWifiFd:%d Fail (%d) and retry\n", CUST_COMBO_WIFI_DEV, gWifiFd, i_ret);
+ }
+ retryCounter++;
+ usleep(300000);
+ } while (retryCounter < 20);
+ }
+ close(gWifiFd);
+
+ return 0;
+}
+#endif /* MTK_COMBO_ENABLE_WIFI_IN_LAUNCHER */
+
+static void* launcher_pwr_on_thread(void * arg)
+{
+ int retry_counter = 0;
+ int ret = -1;
+ int chip_id = *(int*)arg;
+
+ pthread_setname_np(pthread_self(), "pwr_on_conn");
+
+ ALOGI("enter power on connsys flow\n");
+ do {
+ ret = ioctl(g_wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, 1);
+ if (0 == ret)
+ break;
+ ioctl(g_wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, 0);
+ ALOGI("power on %x failed, retrying, retry counter:%d\n", chip_id, retry_counter);
+ usleep(1000000);
+ retry_counter++;
+ } while (retry_counter < 20);
+
+#if (MTK_COMBO_ENABLE_WIFI_IN_LAUNCHER==1)
+ ALOGI("enter enable wifi");
+ enable_wifi();
+#endif /* MTK_COMBO_ENABLE_WIFI_IN_LAUNCHER */
+
+ pthread_detach(g_thread_handle);
+ g_thread_handle = -1;
+
+ return NULL;
+}
+
+static void launcher_pwr_on_chip(int *chip_id) {
+ if (pthread_create(&g_thread_handle, NULL, launcher_pwr_on_thread, chip_id)) {
+ ALOGE("create pwr on thread fail\n");
+ } else
+ ALOGI("create pwr on thread ok\n");
+}
+static void* launcher_set_fwdbg_thread(void * arg) {
+ int i_ret = -1;
+ int flag = *(int*)arg;
+
+ pthread_setname_np(pthread_self(), "dump_fwemi_log");
+ ALOGI("dump firmware dbg log from emi buffer ");
+ i_ret = ioctl(g_wmt_fd, WMT_IOCTL_FW_DBGLOG_CTRL, flag);
+ if (i_ret < 0) {
+ ALOGI("ioctl error: err msg: %s\n", strerror(errno));
+ pthread_detach(g_thread_handle);
+ g_thread_handle = -1;
+ }
+ return NULL;
+}
+
+static void sig_hup(int sig) {
+ fprintf(stderr, "sig_hup...(%d)\n", sig);
+}
+
+static void sig_term(int sig)
+{
+ fprintf(stderr, "sig_term...(%d)\n", sig);
+ __io_canceled = 1;
+ ioctl(g_wmt_fd, WMT_IOCTL_SET_LAUNCHER_KILL, 1);
+}
+
+static void launcher_set_signal_handler(void) {
+ struct sigaction sa;
+
+ /*set signal handler*/
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGCHLD, &sa, NULL);
+ sigaction(SIGPIPE, &sa, NULL);
+
+ sa.sa_handler = sig_term;
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+
+ sa.sa_handler = sig_hup;
+ sigaction(SIGHUP, &sa, NULL);
+}
+
+static void launcher_check_driver_ready(void) {
+ int ret = -1;
+
+#if 0
+ struct sys_property sp;
+
+ sp.key = WCN_DRIVER_READY_PROP;
+ sp.def_value = NULL;
+
+ do {
+ ret = property_get(sp.key, sp.value, sp.def_value);
+ if (0 >= ret)
+ ALOGE("get property(%s) failed i_ret:%d\n", sp.key, ret);
+ else {
+ ALOGI("get property(%s) is %s\n", sp.key, sp.value);
+ if (!strcmp(sp.value, "yes"))
+ break;
+ }
+ usleep(300000);
+ } while (1);
+#endif
+
+ do {
+ ret = get_drv_rdy();
+ if (ret)
+ break;
+ usleep(300000);
+ } while (1);
+}
+
+static void launcher_open_wmt_device(void) {
+ do {
+ g_wmt_fd = open(CUST_COMBO_WMT_DEV, O_RDWR | O_NOCTTY);
+ if (g_wmt_fd < 0) {
+ ALOGE("Can't open device node(%s) error:%d \n", CUST_COMBO_WMT_DEV, g_wmt_fd);
+ usleep(300000);
+ } else
+ break;
+ }while(1);
+
+ ALOGI("open device node succeed.(Node:%s, fd:%d) \n", CUST_COMBO_WMT_DEV, g_wmt_fd);
+}
+
+static int launcher_query_chip_id(void) {
+ int chip_id = -1;
+ int ret = -1;
+
+ do {
+ chip_id = ioctl(g_wmt_fd, WMT_IOCTL_WMT_QUERY_CHIPID, NULL);
+ ALOGI("chip_id from kernel by ioctl:0x%04x\n", chip_id);
+ if (-1 != chip_id)
+ break;
+ usleep(300000);
+ }while(1);
+
+ ALOGI("chip_id:0x%04x\n", chip_id);
+
+ return chip_id;
+}
+
+static enum wmt_chip_type launcher_check_chip_type(int chip_id)
+{
+ enum wmt_chip_type chip_type = WMT_CHIP_TYPE_INVALID;
+
+ if (chip_id <= 0) {
+ ALOGE("invalid chip id(%d)\n", chip_id);
+ goto done;
+ }
+ if ((0x6620 == chip_id) || (0x6628 == chip_id) ||
+ (0x6630 == chip_id) || (0x6632 == chip_id))
+ chip_type = WMT_CHIP_TYPE_COMBO;
+ else
+ chip_type = WMT_CHIP_TYPE_SOC;
+done:
+ return chip_type;
+}
+static void launcher_init_stp_parameter(struct stp_params_config *stp_param_config, enum wmt_chip_type chip_type) {
+ stp_param_config->fm_mode = 2;
+
+ if (WMT_CHIP_TYPE_SOC == chip_type)
+ stp_param_config->stp_mode = STP_BTIF_FULL;
+ if (WMT_CHIP_TYPE_COMBO == chip_type) {
+ stp_param_config->stp_mode = STP_SDIO;
+ stp_param_config->uart_config.baud_rate = 4000000;
+ stp_param_config->uart_config.fc = UART_DISABLE_FC;
+ stp_param_config->uart_config.parity = 0;
+ stp_param_config->uart_config.stop_bit = 0;
+ memset(stp_param_config->stp_dev, '\0', sizeof(stp_param_config->stp_dev));
+ }
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ memset(stp_param_config->patch_name, '\0', sizeof(stp_param_config->patch_name));
+#endif
+ memset(stp_param_config->patch_path, '\0', sizeof(stp_param_config->patch_path));
+}
+
+static void launcher_print_stp_parameter(struct stp_params_config *stp_param_config) {
+ ALOGI("fm mode:%d\n", stp_param_config->fm_mode);
+ ALOGI("stp mode:%d\n", stp_param_config->stp_mode);
+ ALOGI("patch path:%s\n", stp_param_config->patch_path);
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ ALOGI("patch name:%d\n", stp_param_config->patch_name);
+#endif
+ if ((stp_param_config->stp_mode == STP_UART_FULL) ||
+ (stp_param_config->stp_mode == STP_UART_MAND)) {
+ ALOGI("stp uart dev:%s\n", stp_param_config->stp_dev);
+ ALOGI("stp uart baud rate:%d\n", stp_param_config->uart_config.baud_rate);
+ ALOGI("stp uart fc:%d\n", stp_param_config->uart_config.fc);
+ ALOGI("stp uart parity:%d\n", stp_param_config->uart_config.parity);
+ ALOGI("stp uart stop bit:%d\n", stp_param_config->uart_config.stop_bit);
+ }
+}
+/*
+ * -m: mode (SDIO/UART)
+ * -d: uart device node
+ * -b: baudrate
+ * -c: enable SW FC or not
+ * -p: patch folder path
+ * -n: patch file name (fullpath)
+ *
+ */
+static void launcher_set_parameter_to_driver(int argc, char *argv[], int chip_id)
+{
+ int opt;
+ static const char *op_string = "m:d:b:c:p:n:?";
+ enum wmt_chip_type chip_type;
+
+ chip_type = launcher_check_chip_type(chip_id);
+ if (chip_type == WMT_CHIP_TYPE_INVALID) {
+ ALOGE("unknow chip type, may be chid id is invalid\n");
+ chip_type = WMT_CHIP_TYPE_SOC;
+ }
+ launcher_init_stp_parameter(&g_stp_param_config, chip_type);
+
+ opt = getopt(argc, argv, op_string);
+ while (opt != -1) {
+ switch (opt) {
+ case 'm':
+ g_stp_param_config.stp_mode = atoi(optarg);
+ break;
+ case 'd':
+ strncpy(g_stp_param_config.stp_dev, optarg, strlen(optarg)+1);
+ break;
+ case 'b':
+ g_stp_param_config.uart_config.baud_rate = atoi(optarg);
+ break;
+ case 'c':
+ g_stp_param_config.uart_config.fc = atoi(optarg);
+ break;
+ case 'p':
+ strncpy(g_stp_param_config.patch_path, optarg, strlen(optarg)+1);
+ ALOGI("patch path:%s\n", g_stp_param_config.patch_path);
+ break;
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ case 'n':
+ strncpy(g_stp_param_config.patch_name, optarg, strlen(optarg)+1);
+ break;
+#endif
+ case '?':
+ default:
+ launcher_display_usage();
+ break;
+ }
+ opt = getopt(argc, argv, op_string);
+ }
+
+#if LAUNCHER_DEBUG
+ ALOGI("argc = %d, optind= %d\n", argc, optind);
+ {
+ int i = 0;
+ for (i = 0; i < argc; i++)
+ ALOGI("arg[%d] = %s\n", i, argv[i]);
+ }
+#endif
+
+ if (0 != launcher_stp_param_valid_check(&g_stp_param_config, chip_type)) {
+ ALOGE("stp param is invalid, use default:\n");
+ launcher_print_stp_parameter(&g_stp_param_config);
+ ALOGE("if this default param is not correct,please see usage help:\n");
+ launcher_display_usage();
+ }
+ if (WMT_CHIP_TYPE_COMBO == chip_type) {
+ ioctl(g_wmt_fd, WMT_IOCTL_WMT_TELL_CHIPID, chip_id);
+ ALOGI("set chip_id(0x%x) to driver\n", chip_id);
+ launcher_set_wmt_cfg_infor(chip_id, &g_stp_param_config.patch_path[0]);
+ if ((g_stp_param_config.stp_mode == STP_UART_FULL) ||
+ (g_stp_param_config.stp_mode == STP_UART_MAND))
+ launcher_set_uart_port_name(&g_stp_param_config.stp_dev[0]);
+ }
+#if (!CUST_MULTI_PATCH && !CUST_PATCH_SEARCH)
+ /* send default patch file name path to driver */
+ ioctl(g_wmt_fd, WMT_IOCTL_SET_PATCH_NAME, g_stp_param_config.patch_name);
+#endif
+ /* send hardware interface configuration to driver */
+ ioctl(g_wmt_fd, WMT_IOCTL_SET_STP_MODE,
+ ((g_stp_param_config.uart_config.baud_rate & 0xFFFFFF) << 8) |
+ ((g_stp_param_config.fm_mode & 0x0F) << 4) |
+ (g_stp_param_config.stp_mode & 0x0F));
+
+ ioctl(g_wmt_fd, WMT_IOCTL_SET_LAUNCHER_KILL, 0);
+
+}
+
+#if 0
+static int launcher_get_fw_debug_orign_infor(int chip_id) {
+ int ret = -1;
+ enum wmt_chip_type chip_type;
+ char readyStr[PROPERTY_VALUE_MAX] = {0};
+
+ chip_type = launcher_check_chip_type(chip_id);
+
+ if (chip_type == WMT_CHIP_TYPE_SOC) {
+ g_fw_debug_infor.log_retry = 0;
+ g_fw_debug_infor.dump_retry = 0;
+ g_fw_debug_infor.fw_log_ctrl = 0;
+ g_fw_debug_infor.fw_dynamic_dump = 0;
+ g_fw_debug_infor.bitmap = 0;
+ memset(g_fw_debug_infor.fw_log_state_orig, '\0', sizeof(g_fw_debug_infor.fw_log_state_orig));
+ memset(g_fw_debug_infor.fw_log_state_new, '\0', sizeof(g_fw_debug_infor.fw_log_state_new));
+ memset(g_fw_debug_infor.fw_dump_state_orig, '\0', sizeof(g_fw_debug_infor.fw_dump_state_orig));
+ memset(g_fw_debug_infor.fw_dump_state_new, '\0', sizeof(g_fw_debug_infor.fw_dump_state_new));
+
+ ret = property_get(WCN_FW_DBG_LOG_PROP, g_fw_debug_infor.fw_log_state_orig, NULL);
+ if (0 > ret)
+ ALOGE("get property(%s) failed ret:%d\n", WCN_FW_DBG_LOG_PROP, ret);
+ else if (0 == ret)
+ ALOGI("(%s) is not supported\n", WCN_FW_DBG_LOG_PROP);
+ else
+ ALOGI("get property (%s) is %s\n", WCN_FW_DBG_LOG_PROP, g_fw_debug_infor.fw_log_state_orig);
+
+ ret = property_get(WCN_DYNAMIC_DUMP_PROP, g_fw_debug_infor.fw_dump_state_orig, NULL);
+ if (0 > ret)
+ ALOGE("get property(%s) failed ret:%d\n", WCN_DYNAMIC_DUMP_PROP, ret);
+ else if (0 == ret)
+ ALOGI("(%s) is not supported\n", WCN_DYNAMIC_DUMP_PROP);
+ else
+ ALOGI("get property (%s) is %s\n", WCN_DYNAMIC_DUMP_PROP, g_fw_debug_infor.fw_dump_state_orig);
+ }
+
+ /*meta tool may turn on wifi very early, this property is used to protect turn on wifi.*/
+ ret= property_get(WCN_FORMETA_READY_PROP, readyStr, NULL);
+ if ((0 >= ret) || (0 == strcmp(readyStr, "yes"))) {
+ ALOGI("get property(%s) failed iRet:%d or property is %s\n", WCN_FORMETA_READY_PROP, ret, readyStr);
+ }
+
+ sprintf(readyStr, "%s", "yes");
+ ret = property_set(WCN_FORMETA_READY_PROP, readyStr);
+ if (0 != ret) {
+ ALOGI("set property(%s) to %s failed iRet:%d\n", WCN_FORMETA_READY_PROP, readyStr, ret);
+ } else {
+ ALOGI("set property(%s) to %s succeed\n", WCN_FORMETA_READY_PROP, readyStr);
+ }
+
+ return 0;
+}
+
+static int launcher_set_fw_log_ctrl(void) {
+ int ret = -1;
+ int fw_debug_enable = 0;
+
+ if (g_fw_debug_infor.bitmap & 0x1) {
+ ALOGV("fw log ctrl flag has been set\n");
+ return 0;
+ }
+
+ if ((g_fw_debug_infor.fw_log_ctrl == 1) ||
+ (g_fw_debug_infor.log_retry > WCN_FW_DEBUG_CLRL_RETRY_LIMIT)) {
+ ALOGV("retry: %d\n", g_fw_debug_infor.log_retry);
+
+ if (!strcmp(g_fw_debug_infor.fw_log_state_new, "yes")) {
+ fw_debug_enable = 1;
+ if (pthread_create(&g_thread_handle, NULL, launcher_set_fwdbg_thread, &fw_debug_enable))
+ ALOGE("create enable firmware dbglog thread fail\n");
+ } else {
+ ret = ioctl(g_wmt_fd, WMT_IOCTL_FW_DBGLOG_CTRL, fw_debug_enable);
+ /* if do this jude,it will confuse user beacuse kernel return -1 */
+ /* if (ret < 0)*/
+ /* ALOGE("ioctl error: err msg: %s\n", strerror(errno));*/
+ }
+ g_fw_debug_infor.bitmap |= (0x1 << 0);
+ } else if (g_fw_debug_infor.log_retry++ <= WCN_FW_DEBUG_CLRL_RETRY_LIMIT) {
+ ret = property_get(WCN_FW_DBG_LOG_PROP, g_fw_debug_infor.fw_log_state_new, NULL);
+ if (0 > ret)
+ ALOGE("get property(%s) failed ret:%d\n", WCN_FW_DBG_LOG_PROP, ret);
+ else if (0 == ret)
+ ALOGI("(%s) is not supported\n", WCN_FW_DBG_LOG_PROP);
+ else {
+ ALOGV("get property(%s) is %s\n", WCN_FW_DBG_LOG_PROP, g_fw_debug_infor.fw_log_state_new);
+ if (strcmp(g_fw_debug_infor.fw_log_state_new, g_fw_debug_infor.fw_log_state_orig))
+ g_fw_debug_infor.fw_log_ctrl = 1;
+ }
+ } else
+ ALOGV("retry finish\n");
+ return 0;
+}
+
+static int launcher_set_fw_dynamic_dump(void) {
+ int ret = -1;
+
+ if (g_fw_debug_infor.bitmap & (0x1 << 1)) {
+ ALOGV("fw dynamic ctrl flag has been set\n");
+ return 0;
+ }
+
+ if ((g_fw_debug_infor.fw_dynamic_dump == 1) ||
+ (g_fw_debug_infor.dump_retry > WCN_FW_DEBUG_CLRL_RETRY_LIMIT)) {
+ ALOGV("dump_retry: %d\n", g_fw_debug_infor.dump_retry);
+
+ if (g_fw_debug_infor.fw_dynamic_dump == 1) {
+ /* it is only meaningfull to do ioctl in this case*/
+ ret = ioctl(g_wmt_fd, WMT_IOCTL_DYNAMIC_DUMP_CTRL, g_fw_debug_infor.fw_dump_state_new);
+ ALOGV("%d, %zd,\n", PROPERTY_VALUE_MAX, strlen(g_fw_debug_infor.fw_dump_state_new));
+ if (ret < 0)
+ ALOGE("ioctl error: err msg: %s\n", strerror(errno));
+ }
+ g_fw_debug_infor.bitmap |= (0x1 << 1);
+ } else if (g_fw_debug_infor.dump_retry++ <= WCN_FW_DEBUG_CLRL_RETRY_LIMIT) {
+ ret = property_get(WCN_DYNAMIC_DUMP_PROP, g_fw_debug_infor.fw_dump_state_new, NULL);
+ if (0 > ret)
+ ALOGE("get property(%s) failed ret:%d\n", WCN_DYNAMIC_DUMP_PROP, ret);
+ else if (0 == ret)
+ ALOGI("(%s) is not supported\n", WCN_DYNAMIC_DUMP_PROP);
+ else {
+ ALOGV("get property(%s) is %s\n", WCN_DYNAMIC_DUMP_PROP, g_fw_debug_infor.fw_dump_state_new);
+ if (strcmp(g_fw_debug_infor.fw_dump_state_new, g_fw_debug_infor.fw_dump_state_orig))
+ g_fw_debug_infor.fw_dynamic_dump = 1;
+ }
+ } else
+ ALOGV("retry finish\n");
+
+ return 0;
+}
+
+static void launcher_set_fw_debug_infor(int chip_id) {
+ enum wmt_chip_type chip_type = WMT_CHIP_TYPE_INVALID;
+
+ chip_type = launcher_check_chip_type(chip_id);
+ if (chip_type == WMT_CHIP_TYPE_SOC) {
+ launcher_set_fw_log_ctrl();
+ launcher_set_fw_dynamic_dump();
+ }
+}
+#endif
+
+int main(int argc, char *argv[]) {
+ int ld, err;
+ struct pollfd fds[2];
+ int fd_num = 0;
+ int len = 0;
+ int chip_id = -1;
+
+ launcher_check_driver_ready();
+ launcher_open_wmt_device();
+ chip_id = launcher_query_chip_id();
+
+ launcher_set_parameter_to_driver(argc, argv, chip_id);
+
+ launcher_set_signal_handler();
+
+ //launcher_get_fw_debug_orign_infor(chip_id);
+
+ fds[0].fd = g_wmt_fd; /* stp_wmt fd */
+ fds[0].events = POLLIN | POLLRDNORM; /* wait read events */
+ ++fd_num;
+
+ launcher_pwr_on_chip(&chip_id);
+
+ while (!__io_canceled) {
+ //launcher_set_fw_debug_infor(chip_id);
+ fds[0].revents = 0;
+ err = poll(fds, fd_num, 2000); /* 2 seconds */
+ if (err < 0) {
+ if (errno == EINTR)
+ continue;
+ else {
+ ALOGE("poll error:%d errno:%d, %s\n", err, errno, strerror(errno));
+ break;
+ }
+ } else if (!err)
+ continue;
+
+
+ if (fds[0].revents & POLLIN) {
+ if (g_wmt_fd < 0)
+ break;
+ memset(g_cmd_str, 0, sizeof(g_cmd_str));
+ len = read(g_wmt_fd, g_cmd_str, sizeof(g_cmd_str)-1);
+ if (len <= 0 || len >= (int)sizeof(g_cmd_str)) {
+ ALOGE("POLLIN(%d) but read fail:%d\n", g_wmt_fd, len);
+ continue;
+ }
+ g_cmd_str[len] = '\0';
+ /*ALOGI("rx_cmd_str:%s\n", g_cmd_str);*/
+ err = launcher_handle_cmd(&g_stp_param_config, g_cmd_str, len);
+ if (!err) {
+ /* ALOGI("handle_cmd(%s), respond ok \n", g_cmd_str); */
+ snprintf(g_resp_str, sizeof(g_resp_str), "ok");
+ } else {
+ if (err == 1)
+ snprintf(g_resp_str, sizeof(g_resp_str), "cmd not found");
+ else
+ snprintf(g_resp_str, sizeof(g_resp_str), "resp_%d", err);
+ }
+ ALOGI("cmd(%s) resp(%s)\n", g_cmd_str, g_resp_str);
+ len = write(g_wmt_fd, g_resp_str, strlen(g_resp_str));
+ if (len != (int)strlen(g_resp_str))
+ fprintf(stderr, "write resp(%d) fail: len(%d), errno(%d, %s)\n",
+ g_wmt_fd, len, errno, (len == -1) ? strerror(errno) : "");
+ }
+ }
+
+ if (g_wmt_fd >= 0) {
+ close(g_wmt_fd);
+ g_wmt_fd = -1;
+ }
+
+ if (((g_stp_param_config.stp_mode == STP_UART_MAND) ||
+ (g_stp_param_config.stp_mode == STP_UART_FULL)) && g_tty_fd >= 0) {
+ /* Restore TTY line discipline */
+ ld = N_TTY;
+ if (ioctl(g_tty_fd, TIOCSETD, &ld) < 0) {
+ ALOGE("Can't restore line discipline");
+ exit(1);
+ }
+
+ close(g_tty_fd);
+ g_tty_fd = -1;
+ }
+
+ if (g_thread_handle != -1) {
+ pthread_detach(g_thread_handle);
+ g_thread_handle = -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/connectivity/combo_tool/6631_combo_tool/src/yocto_wmt_concurrency.c b/src/connectivity/combo_tool/6631_combo_tool/src/yocto_wmt_concurrency.c
new file mode 100644
index 0000000..ac10520
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/src/yocto_wmt_concurrency.c
@@ -0,0 +1,381 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#define _GNU_SOURCE
+#include "wmt_ioctl.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+//#include <sys/endian.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <linux/serial.h> /* struct serial_struct */
+#include <pthread.h>
+#include <sched.h>
+#define FIBER_STACK 8192
+
+pthread_mutex_t mutex;
+
+typedef enum DRV_INDEX
+{
+ DRV_BT = 0,
+ DRV_FM,
+ DRV_GPS,
+ DRV_WIFI,
+ DRV_MAX,
+}ENUM_DRV_INDEX;
+
+typedef enum ARG_DRV_INDEX
+{
+ ARG_DRV_BT = 1 << DRV_BT,
+ ARG_DRV_FM = 1 << DRV_FM,
+ ARG_DRV_GPS = 1 << DRV_GPS,
+ ARG_DRV_WIFI = 1 << DRV_WIFI,
+ ARG_DRV_ALL = ARG_DRV_BT + ARG_DRV_FM + ARG_DRV_GPS + ARG_DRV_WIFI,
+}ENUM_ARG_DRV_INDEX;
+
+#define is_bt_mask_on(a) ((a) & ARG_DRV_BT)
+#define is_fm_mask_on(a) ((a) & ARG_DRV_FM)
+#define is_gps_mask_on(a) ((a) & ARG_DRV_GPS)
+#define is_wifi_mask_on(a) ((a) & ARG_DRV_WIFI)
+
+#define QUICK_FUNC_ON_OFF_SUPPORT
+#ifdef QUICK_FUNC_ON_OFF_SUPPORT
+ #define MIN_INTERVAL 1
+#else
+ #define MIN_FUNC_ON_TIME 4
+ #define MIN_FUNC_OFF_TIME 1
+ #define MIN_INTERVAL MIN_FUNC_ON_TIME + MIN_FUNC_OFF_TIME
+#endif
+
+#define MAX_FUNC_ON_TIME 9
+#define MAX_FUNC_OFF_TIME 3
+#define MAX_INTERVAL MAX_FUNC_ON_TIME + MAX_FUNC_OFF_TIME
+//enum bool {false = 0, true = !false};
+
+char *src_name[]={
+ "BT",
+ "FM",
+ "GPS",
+ "WIFI",
+ "UNKNOWN DEVICE",
+ };
+
+static int g_wmt_fd = -1;
+static int g_reference = 0;
+static int g_count = 2;
+int g_on2off_interval = MAX_INTERVAL;
+int g_off2on_interval = MAX_INTERVAL;
+volatile int g_state[5] = {0};
+
+void dump_state(void)
+{
+ //printf("%s:++, pid =%d\n", __FUNCTION__, getpid());
+ printf("%d: %s:g_state:[BT]%d, [FM]:%d, [GPS]:%d, [WIFI]:%d\n", getpid(), __FUNCTION__, g_state[0], g_state[1], g_state[2], g_state[3]);
+ //printf("%s:--, pid =%d\n", __FUNCTION__, getpid());
+}
+
+int read_reference(ENUM_DRV_INDEX index)
+{
+ volatile int flag = 0;
+ pthread_mutex_lock(&mutex);
+ if(index >= 4)
+ {
+ if(g_state[0] || g_state[1] || g_state[2] || g_state[3])
+ {
+ flag = 1;
+ }
+ else
+ {
+ flag = 0;
+ }
+ }
+ else
+ {
+ flag = g_state[index];
+ }
+ pthread_mutex_unlock(&mutex);
+ return flag;
+}
+
+void get_reference(ENUM_DRV_INDEX index)
+{
+ pthread_mutex_lock(&mutex);
+ g_reference++;
+ g_state[index] = 1;
+ dump_state();
+ pthread_mutex_unlock(&mutex);
+}
+
+
+void put_reference(ENUM_DRV_INDEX index)
+{
+ pthread_mutex_lock(&mutex);
+ g_reference--;
+ g_state[index] = 0;
+ dump_state();
+ pthread_mutex_unlock(&mutex);
+}
+
+int func_on_off(void * drv_index)
+{
+ ENUM_DRV_INDEX index = (ENUM_DRV_INDEX) drv_index;
+ int count = g_count;
+// printf("%s:++, index =%d\n", __FUNCTION__, index);
+ if(DRV_MAX > index && g_wmt_fd > 0)
+ {
+ while(count--)
+ {
+ //turn on src_name[index] function
+ if (0 == ioctl(g_wmt_fd, WMT_IOCTL_FUNC_ONOFF_CTRL, 0xBEEF0000 | index))
+ {
+ printf("pid:%d, turn on %s success.\n", getpid(), src_name[index]);
+ //exit(0);
+ }
+ else
+ {
+ printf("pid:%d, turn on %s fail.\n", getpid(), src_name[index]);
+ exit(-1);
+ }
+
+ //printf("%s:-- pid: %d, finish turn on %s\n", __FUNCTION__, getpid(), src_name[index]);
+ /*
+ //turn off src_name[index] function
+ */
+ sleep(g_on2off_interval);
+ if ( 0 == ioctl(g_wmt_fd, WMT_IOCTL_FUNC_ONOFF_CTRL, 0xDEAD0000 | index))
+ {
+ printf("pid:%d, turn off %s success.\n", getpid(), src_name[index]);
+ //exit(0);
+ }
+ else
+ {
+ printf("pid:%d, turn off %s fail.\n", getpid(), src_name[index]);
+ exit(-1);
+ }
+ printf("%d:%s test:left count = %d.\n", getpid(), src_name[index], count);
+ sleep(g_off2on_interval);
+
+ }
+ }
+ else
+ {
+ printf("pid:%d, undnown device with index:%d.\n", getpid(), index);
+ }
+ // printf("%s:--, index =%d\n", __FUNCTION__, index);
+ //exit(-2);
+ //return;
+ exit(0);
+}
+
+
+static void sig_child_term(__attribute__((unused))int sig)
+{
+ printf("%s ++.\n", __FUNCTION__);
+ int pid = -1;
+ int stat;
+ while((pid = waitpid(0, &stat, WNOHANG)) != 0)
+ {
+ printf("%s:pid = %d, exit event.\n", __FUNCTION__, pid);
+ }
+ printf("%s:pid = %d.\n", __FUNCTION__, pid);
+ printf("%s --.\n", __FUNCTION__);
+}
+
+int main(int argc, char *argv[])
+{
+
+ int bitmask = ARG_DRV_ALL;
+
+ int i = 0;
+ void *stack[8];
+ struct sigaction sa;
+ if(argc != 5)
+ {
+ printf("wmt_concurrency usage:\n\
+ wmt_concurrency looptimes bitmask on2offtime off2ontime\n\
+ -looptimes on<->off switch times (<1000000)\n\
+ -bitmask\n\
+ -1:BT on<->off test\n\
+ -2:FM on<->off test\n\
+ -4:GPS on<->off test\n\
+ -8:WIFI on<->off test\n\
+ -x: can be combination of the upper 4 bitmasks\n\
+ -on2offtime (0~12s)\n\
+ -function on hold time before turn off\n\
+ -off2ontime (0~12s)\n\
+ -function off hold time before turn on\n\
+ ");
+ return -1;
+ }
+ if ((argc > 1) && (argv[1] != NULL)) {
+
+ g_count = atoi(argv[1]);
+ printf("%s:argv[1] g_count param = %d\n", __FUNCTION__, g_count);
+ if(g_count < 0)
+ {
+ g_count = 2;
+ }
+ g_count = g_count > 1000000 ? 1000000 : g_count;
+ printf("%s:g_count = %d\n", __FUNCTION__, g_count);
+ }
+ if ((argc > 2) && (argv[2] != NULL)) {
+
+ bitmask = atoi(argv[2]);
+ printf("%s:argv[2] bitmask param = %d\n", __FUNCTION__, bitmask);
+ if(bitmask <= 0 || bitmask > ARG_DRV_ALL)
+ {
+ bitmask = ARG_DRV_ALL;
+ }
+ printf("%s:bitmask = %d\n", __FUNCTION__, bitmask);
+ }
+
+ if ((argc > 3) && (argv[3] != NULL)) {
+
+ g_on2off_interval = atoi(argv[3]);
+ printf("%s:argv[3] g_on2off_interval param = %d\n", __FUNCTION__, g_on2off_interval);
+ if(g_on2off_interval < MIN_INTERVAL)
+ {
+ g_on2off_interval = MIN_INTERVAL;
+ }
+ if(g_on2off_interval > MAX_INTERVAL)
+ {
+ g_on2off_interval = MAX_INTERVAL;
+ }
+ printf("%s:g_on2off_interval = %d\n", __FUNCTION__, g_on2off_interval);
+ }
+ if ((argc > 4) && (argv[4] != NULL)) {
+
+ g_off2on_interval = atoi(argv[4]);
+ printf("%s:argv[4] g_off2on_interval param = %d\n", __FUNCTION__, g_off2on_interval);
+ if(g_off2on_interval < MIN_INTERVAL)
+ {
+ g_off2on_interval = MIN_INTERVAL;
+ }
+ if(g_off2on_interval > MAX_INTERVAL)
+ {
+ g_off2on_interval = MAX_INTERVAL;
+ }
+ printf("%s:g_off2on_interval = %d\n", __FUNCTION__, g_off2on_interval);
+ }
+
+ for (i = sizeof(g_state)/sizeof(g_state[0]); i > 0; )
+ {
+ g_state[--i] = 0;
+ }
+
+ printf("pid = %d\n", getpid());
+ for(i = sizeof(stack)/sizeof(void *); i > 0; )
+ {
+ stack[--i] = malloc(FIBER_STACK);
+ if(stack[i] == NULL)
+ {
+ printf("pid = %d, malloc error\n", getpid());
+ goto out;
+ }
+ }
+
+ g_wmt_fd = open("/dev/stpwmt", O_RDWR | O_NOCTTY);
+ printf("%s:argc = %d\n", __FUNCTION__, argc);
+
+ if(pthread_mutex_init(&mutex, NULL) != 0)
+ {
+ printf("%s:pthread_mutex_init fail\n", __FUNCTION__);
+ goto out;
+ }
+ if(g_wmt_fd > 0)
+ {
+ memset(&sa, 0, sizeof(sa));
+ //signal(SIGCHLD, sig_child_term);
+ sa.sa_handler = sig_child_term;
+ sa.sa_flags = SA_NOCLDSTOP;
+ sigaction(SIGCHLD, &sa, 0);
+ int sleepCOunter = g_count;
+
+ if(is_bt_mask_on(bitmask) && read_reference(DRV_BT) == 0)
+ {
+ clone(&func_on_off, (char *)stack[0] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_BT);
+ //clone(&func_off, (char *)stack[4] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_BT);
+ }
+
+ if(is_wifi_mask_on(bitmask) && read_reference(DRV_WIFI) == 0)
+ {
+ clone(&func_on_off, (char *)stack[1] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_WIFI);
+ //clone(&func_off, (char *)stack[5] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_WIFI);
+ }
+ if(is_fm_mask_on(bitmask) && read_reference(DRV_FM) == 0)
+ {
+ clone(&func_on_off, (char *)stack[2] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_FM);
+ //clone(&func_off, (char *)stack[6] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_FM);
+ }
+ if(is_gps_mask_on(bitmask) && read_reference(DRV_GPS) == 0)
+ {
+ clone(&func_on_off, (char *)stack[3] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_GPS);
+ //clone(&func_off, (char *)stack[7] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_GPS);
+ }
+ //printf("%s:left g_count = %d.\n", __FUNCTION__, g_count);
+ sleep(sleepCOunter * (g_on2off_interval + g_off2on_interval));
+ }
+out:
+
+ for(i = sizeof(stack)/sizeof(void *); i > 0; )
+ {
+ printf("%s:pid = %d, free stack information.\n", __FUNCTION__, getpid());
+ if (NULL != stack[--i])
+ {
+ free(stack[i]);
+ }
+ stack[i] = NULL;
+ }
+ if(g_wmt_fd > 0)
+ {
+ close(g_wmt_fd);
+ g_wmt_fd = -1;
+ }
+ printf("%s:pid = %d, exit.\n", __FUNCTION__, getpid());
+ return 0;
+}
diff --git a/src/connectivity/combo_tool/6631_combo_tool/stp_dump-service b/src/connectivity/combo_tool/6631_combo_tool/stp_dump-service
new file mode 100644
index 0000000..95352b1
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/stp_dump-service
@@ -0,0 +1,64 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: stp_dump
+# Required-Start: $syslog $local_fs $remote_fs
+# Required-Stop: $syslog $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: stp dump Daemon
+### END INIT INFO
+
+. /etc/init.d/init-functions
+prog=stp_dump
+PIDFILE=/var/run/$prog.pid
+DESC="stp dump Daemon"
+start() {
+ log_daemon_msg "Starting $DESC" "$prog"
+ start_daemon_background -p $PIDFILE /usr/bin/stp_dump3
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+ exit 0
+}
+
+stop() {
+ log_daemon_msg "Stopping $DESC" "$prog"
+ killproc -p $PIDFILE /usr/bin/stp_dump3
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+}
+
+force_reload() {
+ stop
+ start
+
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ restart)
+ stop
+ start
+ ;;
+
+ *)
+ echo "$Usage: $prog {start|stop|force-reload|restart}"
+ exit 2
+esac
diff --git a/src/connectivity/combo_tool/6631_combo_tool/stp_dump.service b/src/connectivity/combo_tool/6631_combo_tool/stp_dump.service
new file mode 100644
index 0000000..815bc2f
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/stp_dump.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=stp dump Daemon
+After=launcher.service
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/stp_dump3
+
+[Install]
+Alias=stp_dump
+WantedBy=multi-user.target
diff --git a/src/connectivity/combo_tool/6631_combo_tool/wmtd-service b/src/connectivity/combo_tool/6631_combo_tool/wmtd-service
new file mode 100644
index 0000000..c369f41
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/wmtd-service
@@ -0,0 +1,64 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: wmtd
+# Required-Start: $syslog $local_fs $remote_fs $network
+# Required-Stop: $syslog $local_fs $remote_fs $network
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: WMT Daemon
+### END INIT INFO
+
+. /etc/init.d/init-functions
+prog=wmtd
+PIDFILE=/var/run/$prog.pid
+DESC="WMT Daemon"
+start() {
+ log_daemon_msg "Starting $DESC" "$prog"
+ start_daemon_background -p $PIDFILE /usr/bin/wmt_loader
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+ exit 0
+}
+
+stop() {
+ log_daemon_msg "Stopping $DESC" "$prog"
+ killproc -p $PIDFILE /usr/bin/wmt_loader
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+}
+
+force_reload() {
+ stop
+ start
+
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ restart)
+ stop
+ start
+ ;;
+
+ *)
+ echo "$Usage: $prog {start|stop|force-reload|restart}"
+ exit 2
+esac
diff --git a/src/connectivity/combo_tool/6631_combo_tool/wmtd.service b/src/connectivity/combo_tool/6631_combo_tool/wmtd.service
new file mode 100644
index 0000000..c801191
--- /dev/null
+++ b/src/connectivity/combo_tool/6631_combo_tool/wmtd.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=WMT Daemon
+After=network.target
+Requires=nvram_daemon.service
+After=nvram_daemon.service
+
+[Service]
+ExecStart=/usr/bin/wmt_loader > ttyS0
+Type=oneshot
+StandardOutput=tty
+StandardError=tty
+
+[Install]
+Alias=wmtd
+WantedBy=multi-user.target
diff --git a/src/connectivity/combo_tool/LICENSE b/src/connectivity/combo_tool/LICENSE
new file mode 100755
index 0000000..77f59ed
--- /dev/null
+++ b/src/connectivity/combo_tool/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/connectivity/combo_tool/Makefile.am b/src/connectivity/combo_tool/Makefile.am
new file mode 100755
index 0000000..e25d3b8
--- /dev/null
+++ b/src/connectivity/combo_tool/Makefile.am
@@ -0,0 +1,10 @@
+bin_PROGRAMS = wmt_loader 6620_launcher power_on_wifi wmt_loopback stp_dump
+wmt_loader_SOURCES = combo_loader/yocto_loader.c
+wmt_loopback_SOURCES = src/wmt_loopback.c
+6620_launcher_SOURCES = src/yocto_stp_uart_launcher.c
+6620_launcher_LDADD = -lpthread
+
+power_on_wifi_SOURCES = src/power_on_wifi.c
+stp_dump_SOURCES = src/stp_dump/os_linux.c \
+ src/stp_dump/eloop.c \
+ src/stp_dump/stp_dump.c
diff --git a/src/connectivity/combo_tool/README b/src/connectivity/combo_tool/README
new file mode 100755
index 0000000..d4b3313
--- /dev/null
+++ b/src/connectivity/combo_tool/README
@@ -0,0 +1,22 @@
+This module serves the common part driver of connectivity
+
+WHAT IT DOES?
+=============
+This module creates some executable binary files for loading/configuring/testing
+the common part driver, in addition, it installs the Firmware patch and common part
+cfg files into device.
+
+HOW IT WAS BUILT?
+==================
+It needs the following library from AOSP:
+
+libcutils, libc
+
+HOW TO USE IT?
+==============
+The firmware patch and common part cfg file was installed into device directly when build.
+And the executable binary files will be started in init.rc when boot. they will work together
+to load/configure the common part driver of connectivity
+
+The majority of source code was written by MediaTek. Some code from open source codes are used.
+more detail info, pls ref the NOTICE under the specific sub folder.
diff --git a/src/connectivity/combo_tool/cfg_folder/WMT.cfg b/src/connectivity/combo_tool/cfg_folder/WMT.cfg
new file mode 100755
index 0000000..cd214d8
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/WMT.cfg
@@ -0,0 +1,3 @@
+mt6620.defAnt=mt6620_ant_m3.cfg
+mt6628.defAnt=mt6628_ant_m1.cfg
+mt6630.defAnt=mt6630_ant_m1.cfg
\ No newline at end of file
diff --git a/src/connectivity/combo_tool/cfg_folder/WMT_SOC.cfg b/src/connectivity/combo_tool/cfg_folder/WMT_SOC.cfg
new file mode 100755
index 0000000..3a155ab
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/WMT_SOC.cfg
@@ -0,0 +1,9 @@
+coex_wmt_ant_mode=1
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+co_clock_flag=0
+
+
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m1.cfg b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m1.cfg
new file mode 100755
index 0000000..2557394
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m1.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=1
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xCE
+coex_wifi_rssi_mid_limit=0xBB
+coex_wifi_rssi_lower_limit=0xBB
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m2.cfg b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m2.cfg
new file mode 100755
index 0000000..1801583
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m2.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=2
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xCE
+coex_wifi_rssi_mid_limit=0xBB
+coex_wifi_rssi_lower_limit=0xBB
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m3.cfg b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m3.cfg
new file mode 100755
index 0000000..c019bae
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m3.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=3
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xD2
+coex_wifi_rssi_mid_limit=0xC8
+coex_wifi_rssi_lower_limit=0xBF
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m4.cfg b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m4.cfg
new file mode 100755
index 0000000..8788db8
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m4.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=4
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xD2
+coex_wifi_rssi_mid_limit=0xC8
+coex_wifi_rssi_lower_limit=0xBF
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m5.cfg b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m5.cfg
new file mode 100755
index 0000000..44eb8c8
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m5.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=5
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xD2
+coex_wifi_rssi_mid_limit=0xC8
+coex_wifi_rssi_lower_limit=0xBF
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m6.cfg b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m6.cfg
new file mode 100755
index 0000000..0f9372c
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m6.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=6
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xD2
+coex_wifi_rssi_mid_limit=0xC8
+coex_wifi_rssi_lower_limit=0xBF
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m7.cfg b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m7.cfg
new file mode 100755
index 0000000..8b7d601
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6620_ant_m7.cfg
@@ -0,0 +1,33 @@
+coex_wmt_ant_mode=7
+coex_wmt_wifi_time_ctl=0
+coex_wmt_ext_pta_dev_on=0
+
+coex_bt_rssi_upper_limit=0xD2
+coex_bt_rssi_mid_limit=0xC8
+coex_bt_rssi_lower_limit=0xBA
+coex_bt_pwr_high=0x5
+coex_bt_pwr_mid=0x5
+coex_bt_pwr_low=0x5
+
+coex_wifi_rssi_upper_limit=0xD2
+coex_wifi_rssi_mid_limit=0xC8
+coex_wifi_rssi_lower_limit=0xBF
+coex_wifi_pwr_high=0xA
+coex_wifi_pwr_mid=0xA
+coex_wifi_pwr_low=0xA
+
+coex_ext_pta_hi_tx_tag=6
+coex_ext_pta_hi_rx_tag=6
+coex_ext_pta_lo_tx_tag=12
+coex_ext_pta_lo_rx_tag=12
+coex_ext_pta_sample_t1=10
+coex_ext_pta_sample_t2=4
+coex_ext_pta_wifi_bt_con_trx=0x0
+
+coex_misc_ext_pta_on=0
+coex_misc_ext_feature_set=0xFFFFFFFF
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m1.cfg b/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m1.cfg
new file mode 100755
index 0000000..346233d
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m1.cfg
@@ -0,0 +1,8 @@
+coex_wmt_ant_mode=1
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m2.cfg b/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m2.cfg
new file mode 100755
index 0000000..dba5e25
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m2.cfg
@@ -0,0 +1,6 @@
+coex_wmt_ant_mode=2
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m3.cfg b/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m3.cfg
new file mode 100755
index 0000000..1459ed0
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m3.cfg
@@ -0,0 +1,6 @@
+coex_wmt_ant_mode=3
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m4.cfg b/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m4.cfg
new file mode 100755
index 0000000..b3011f3
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6628_ant_m4.cfg
@@ -0,0 +1,7 @@
+coex_wmt_ant_mode=4
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m1.cfg b/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m1.cfg
new file mode 100755
index 0000000..346233d
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m1.cfg
@@ -0,0 +1,8 @@
+coex_wmt_ant_mode=1
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+
+
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m2.cfg b/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m2.cfg
new file mode 100755
index 0000000..dba5e25
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m2.cfg
@@ -0,0 +1,6 @@
+coex_wmt_ant_mode=2
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m3.cfg b/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m3.cfg
new file mode 100755
index 0000000..1459ed0
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m3.cfg
@@ -0,0 +1,6 @@
+coex_wmt_ant_mode=3
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
diff --git a/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m4.cfg b/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m4.cfg
new file mode 100755
index 0000000..b3011f3
--- /dev/null
+++ b/src/connectivity/combo_tool/cfg_folder/mt6630_ant_m4.cfg
@@ -0,0 +1,7 @@
+coex_wmt_ant_mode=4
+
+wmt_gps_lna_pin=0
+wmt_gps_lna_enable=0
+
+sdio_driving_cfg=0x00077777
+
diff --git a/src/connectivity/combo_tool/combo_loader/Android.mk b/src/connectivity/combo_tool/combo_loader/Android.mk
new file mode 100755
index 0000000..d0f51a2
--- /dev/null
+++ b/src/connectivity/combo_tool/combo_loader/Android.mk
@@ -0,0 +1,101 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+#
+# MediaTek Inc. (C) 2010. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+# Copyright (C) 2008 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.
+
+# Configuration
+BUILD_LOADER := false
+BUILD_MT6582_CONSYS := false
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(MTK_COMBO_CHIP), )
+BUILD_LOADER := true
+endif
+
+ifneq ($(filter CONSYS_6572,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6582,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6592,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6735,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6755,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6797,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifeq ($(BUILD_LOADER), true)
+$(warning build loader)
+include $(CLEAR_VARS)
+
+ifeq ($(BUILD_MT6582_CONSYS), true)
+LOCAL_CFLAGS := -DMTK_SOC_CONSYS_SUPPORT
+endif
+
+
+LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_SRC_FILES := loader.c \
+ load_fm.c \
+ load_wifi.c \
+ load_ant.c \
+ loader_pwr.c
+LOCAL_MODULE := wmt_loader
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+endif
diff --git a/src/connectivity/combo_tool/combo_loader/README b/src/connectivity/combo_tool/combo_loader/README
new file mode 100755
index 0000000..053fc8b
--- /dev/null
+++ b/src/connectivity/combo_tool/combo_loader/README
@@ -0,0 +1,19 @@
+This module serves the common part driver of connectivity
+
+WHAT IT DOES?
+=============
+This module creates one executable binary files for loading/initializing the common part driver including
+wifi, fm, gps and BT if needed.
+
+HOW IT WAS BUILT?
+==================
+It needs the following library from AOSP:
+
+libcutils
+
+HOW TO USE IT?
+==============
+the executable binary files, wmt_loader, will be started in init.rc when boot. it will load/initialize
+to load the common part drivers(common part/wifi/fm/gps/BT) of connectivity
+
+The source code was written by MediaTek.
diff --git a/src/connectivity/combo_tool/combo_loader/load_ant.c b/src/connectivity/combo_tool/combo_loader/load_ant.c
new file mode 100755
index 0000000..53438be
--- /dev/null
+++ b/src/connectivity/combo_tool/combo_loader/load_ant.c
@@ -0,0 +1,105 @@
+/* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2014. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* The following software/firmware and/or related documentation ("MediaTek
+* Software") have been modified by MediaTek Inc. All revisions are subject to
+* any receiver's applicable license agreements with MediaTek Inc.
+*/
+
+/*
+*ANT radio driver kernel module insmod file for wmt dynamic loader
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <cutils/misc.h>
+
+//For directory operation
+#include <dirent.h>
+
+#define ANT_MODULES_PATH "/system/lib/modules/mtk_stp_ant.ko"
+extern int load_ant_module(int chip_id);
+extern int init_module(void *, unsigned long, const char *);
+
+//insmod
+static int insmod(const char *filename, const char *args)
+{
+ void *module;
+ unsigned int size;
+ int ret = -1;
+ int retry = 10;
+
+ printf("filename(%s)\n",filename);
+
+ module = load_file(filename, &size);
+ if (!module)
+ {
+ printf("load file fail\n");
+ return -1;
+ }
+
+ while(retry-- > 0){
+ ret = init_module(module, size, args);
+
+ if(ret < 0)
+ {
+ printf("insmod module fail(%d)\n",ret);
+ usleep(10000);
+ }
+ else
+ break;
+
+ }
+
+ free(module);
+
+ return ret;
+}
+
+
+int load_ant_module(int chip_id)
+{
+ int ret = -1;
+ ret = insmod(ANT_MODULES_PATH, "");
+ if(ret)
+ {
+ printf("insert mtk_ant_drv.ko fail(%d)\n",ret);
+ }
+ else
+ {
+ printf("insert mtk_ant_drv.ko ok\n");
+ }
+ return ret;
+}
+
diff --git a/src/connectivity/combo_tool/combo_loader/load_fm.c b/src/connectivity/combo_tool/combo_loader/load_fm.c
new file mode 100755
index 0000000..cf5411b
--- /dev/null
+++ b/src/connectivity/combo_tool/combo_loader/load_fm.c
@@ -0,0 +1,67 @@
+/*
+*FM radio driver kernel module insmod file for wmt dynamic loader
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <cutils/misc.h>
+
+//For directory operation
+#include <dirent.h>
+
+#define FMR_MODULES_PATH "/system/lib/modules/mtk_fm_drv.ko"
+extern int load_fm_module(int chip_id);
+extern int init_module(void *, unsigned long, const char *);
+
+//insmod
+static int insmod(const char *filename, const char *args)
+{
+ void *module;
+ unsigned int size;
+ int ret = -1;
+ int retry = 10;
+
+ printf("filename(%s)\n",filename);
+
+ module = load_file(filename, &size);
+ if (!module)
+ {
+ printf("load file fail\n");
+ return -1;
+ }
+
+ while(retry-- > 0){
+ ret = init_module(module, size, args);
+
+ if(ret < 0)
+ {
+ printf("insmod module fail(%d)\n",ret);
+ usleep(10000);
+ }
+ else
+ break;
+
+ }
+
+ free(module);
+
+ return ret;
+}
+
+int load_fm_module(int chip_id)
+{
+ int ret=-1;
+ ret = insmod(FMR_MODULES_PATH, "");
+ if(ret)
+ {
+ printf("insert mtk_fm_drv.ko fail(%d)\n",ret);
+ }
+ else
+ {
+ printf("insert mtk_fm_drv.ko ok\n");
+ }
+ return ret;
+}
+
diff --git a/src/connectivity/combo_tool/combo_loader/load_wifi.c b/src/connectivity/combo_tool/combo_loader/load_wifi.c
new file mode 100755
index 0000000..ac040b2
--- /dev/null
+++ b/src/connectivity/combo_tool/combo_loader/load_wifi.c
@@ -0,0 +1,113 @@
+/*
+*WIFI driver kernel module insmod file for wmt dynamic loader
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <cutils/log.h>
+#include <cutils/misc.h>
+#include <linux/module.h>
+//For directory operation
+#include <dirent.h>
+
+extern int load_wifi_module(int chip_id);
+extern int init_module(void *, unsigned long, const char *);
+extern int delete_module(const char *, unsigned int);
+
+static char DRIVER_MODULE_PATH[50] = "/system/lib/modules/wlan_";
+static char DRIVER_MODULE_ARG[50] = "";
+#ifndef WIFI_DRIVER_MODULE_ARG
+#define WIFI_DRIVER_MODULE_ARG ""
+#endif
+
+//insmod
+static int insmod(const char *filename, const char *args)
+{
+ void *module;
+ unsigned int size;
+ int ret;
+
+ module = load_file(filename, &size);
+ if (!module)
+ return -1;
+
+ ret = init_module(module, size, args);
+
+ free(module);
+
+ return ret;
+}
+
+static int rmmod(const char *modname)
+{
+ int ret = -1;
+ int maxtry = 10;
+
+ while (maxtry-- > 0) {
+ ret = delete_module(modname, O_NONBLOCK | O_EXCL);
+ if (ret < 0 && errno == EAGAIN)
+ usleep(500000);
+ else
+ break;
+ }
+
+ if (ret != 0)
+ ALOGD("Unable to unload driver module \"%s\": %s\n",
+ modname, strerror(errno));
+ return ret;
+}
+
+int load_wifi_module(int chip_id)
+{
+ int ret=-1;
+
+ if(chip_id == 0x6630){
+ //insert 6630 driver
+ if(0 == insmod("/system/lib/modules/mtk_wmt_wifi.ko", DRIVER_MODULE_ARG)){
+ ret = 0;
+ printf("Success to insmod wmt wifi module\n");
+ }else
+ printf("Fail to insmod wmt wifi module\n");
+
+ if(0 == insmod("/system/lib/modules/wlan_mt6630.ko", DRIVER_MODULE_ARG)){
+ ret = 0;
+ printf("Success to insmod wlan module\n");
+ }else
+ printf("Fail to insmod wlan module\n");
+ }
+ else if(chip_id == 0x6628){
+ //insert 6628 driver
+ if(0 == insmod("/system/lib/modules/mtk_wmt_wifi.ko", DRIVER_MODULE_ARG)){
+ ret = 0;
+ printf("Success to insmod wmt wifi module\n");
+ }else
+ printf("Fail to insmod wmt wifi module\n");
+
+ if(0 == insmod("/system/lib/modules/wlan_mt6628.ko", DRIVER_MODULE_ARG)){
+ ret = 0;
+ printf("Success to insmod wlan module\n");
+ }else
+ printf("Fail to insmod wlan module\n");
+ }
+ else if(chip_id == 0x6620){
+ //insert 6620 driver
+ }else { //for soc chip, same naming
+ //insert wmt_wifi => for temp naming
+ if(0 == insmod("/system/lib/modules/mtk_wmt_wifi_soc.ko", DRIVER_MODULE_ARG)){
+ ret = 0;
+ printf("Success to insmod wmt wifi module\n");
+ }else
+ printf("Fail to insmod wmt wifi module\n");
+
+ //insert wifi => for temp naming
+ if(0 == insmod("/system/lib/modules/wlan_mt.ko", DRIVER_MODULE_ARG)){
+ ret = 0;
+ printf("Success to insmod the %s\n", DRIVER_MODULE_PATH);
+ }else
+ printf("Fail to insmod the %s\n", DRIVER_MODULE_PATH);
+ }
+ return ret;
+}
diff --git a/src/connectivity/combo_tool/combo_loader/loader.c b/src/connectivity/combo_tool/combo_loader/loader.c
new file mode 100755
index 0000000..7b639e0
--- /dev/null
+++ b/src/connectivity/combo_tool/combo_loader/loader.c
@@ -0,0 +1,740 @@
+
+#include "loader.h"
+#include "loader_pwr.h"
+//#include <syslog.h>
+#include <private/android_filesystem_config.h>
+#include <utils/Log.h>
+#include <string.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "wmt_loader"
+
+#define WCN_COMBO_LOADER_CHIP_ID_PROP "persist.mtk.wcn.combo.chipid"
+#define WCN_DRIVER_READY_PROP "service.wcn.driver.ready"
+#define WCN_COMBO_LOADER_DEV "/dev/wmtdetect"
+#define WCN_COMBO_DEF_CHIPID "0x6582"
+#define WMT_MODULES_PRE "/system/lib/modules/"
+#define WMT_MODULES_SUFF ".ko"
+#define WMT_IOC_MAGIC 'w'
+#define COMBO_IOCTL_GET_CHIP_ID _IOR(WMT_IOC_MAGIC, 0, int)
+#define COMBO_IOCTL_SET_CHIP_ID _IOW(WMT_IOC_MAGIC, 1, int)
+#define COMBO_IOCTL_EXT_CHIP_DETECT _IOR(WMT_IOC_MAGIC, 2, int)
+#define COMBO_IOCTL_GET_SOC_CHIP_ID _IOR(WMT_IOC_MAGIC, 3, int)
+#define COMBO_IOCTL_DO_MODULE_INIT _IOR(WMT_IOC_MAGIC, 4, int)
+#define COMBO_IOCTL_MODULE_CLEANUP _IOR(WMT_IOC_MAGIC, 5, int)
+#define COMBO_IOCTL_EXT_CHIP_PWR_ON _IOR(WMT_IOC_MAGIC, 6, int)
+#define COMBO_IOCTL_EXT_CHIP_PWR_OFF _IOR(WMT_IOC_MAGIC, 7, int)
+#define COMBO_IOCTL_DO_SDIO_AUDOK _IOR(WMT_IOC_MAGIC, 8, int)
+
+
+
+#define STP_WMT_MODULE_PRE_FIX "mtk_stp_wmt"
+#define STP_BT_MODULE_PRE_FIX "mtk_stp_bt"
+#define STP_GPS_MODULE_PRE_FIX "mtk_stp_gps"
+#define HIF_SDIO_MODULE_PRE_FIX "mtk_hif_sdio"
+#define STP_SDIO_MODULE_PRE_FIX "mtk_stp_sdio"
+#define STP_UART_MODULE_PRE_FIX "mtk_stp_uart"
+
+
+
+static int gLoaderFd = -1;
+
+static char DRIVER_MODULE_PATH[64] = {0};
+static char DRIVER_MODULE_ARG[8] = "";
+static int chipid_array[] = {
+0x6620,
+0x6628,
+0x6630,
+0x6572,
+0x6582,
+0x6592,
+0x8127,
+0x6571,
+0x6752,
+0x6735,
+0x0321,
+0x0335,
+0x0337,
+0x8163,
+0x6580,
+0x6755,
+0x0326,
+0x6797,
+0x0279
+};
+static char chip_version[PROPERTY_VALUE_MAX] = {0};
+
+static int g_remove_ko_flag = 1;
+
+
+extern int init_module(void *, unsigned long, const char *);
+extern int delete_module(const char *, unsigned int);
+extern int load_fm_module(int chip_id);
+extern int load_wifi_module(int chip_id);
+extern int load_ant_module(int chip_id);
+//insmod
+static int insmod(const char *filename, const char *args)
+{
+ void *module;
+ unsigned int size;
+ int ret = -1;
+ int retry = 10;
+
+ ALOGI("filename(%s)\n",filename);
+
+ module = load_file(filename, &size);
+ if (!module)
+ {
+ ALOGI("load file fail\n");
+ return -1;
+ }
+
+ while(retry-- > 0){
+ ret = init_module(module, size, args);
+
+ if(ret < 0)
+ {
+ ALOGI("insmod module fail(%d)\n",ret);
+ usleep(30000);
+ }
+ else
+ break;
+
+ }
+
+ free(module);
+
+ return ret;
+}
+static int is_chipId_vaild(int chipid)
+{
+ int iret;
+ unsigned char i;
+ iret = -1;
+
+ for(i = 0;i < sizeof(chipid_array)/sizeof(0x6630); i++){
+ if(chipid == chipid_array[i]){
+ ALOGI("is_chipId_vaild: %d :0x%x!\n",i,chipid);
+ iret = 0;
+ break;
+ }
+ }
+ return iret;
+}
+static int rmmod(const char *modname)
+{
+ int ret = -1;
+ int maxtry = 10;
+
+ while (maxtry-- > 0) {
+ ret = delete_module(modname, O_EXCL);//O_NONBLOCK | O_EXCL);
+ if (ret < 0 && errno == EAGAIN)
+ usleep(500000);
+ else
+ break;
+ }
+
+ if (ret != 0)
+ ALOGI("Unable to unload driver module \"%s\": %s,ret(%d)\n",
+ modname, strerror(errno),ret);
+ return ret;
+}
+
+static int insmod_by_path (char *nameBuf, char * modulePath, char *preFix, char *postFix )
+{
+ int iRet = -1;
+ int len = 0;
+ int path_len = 0;
+
+ /*no need to check, upper layer API will makesure this condition fullfill*/
+ strcat (nameBuf, modulePath);
+ strcat (nameBuf, preFix);
+ strcat (nameBuf, postFix);
+ strcat (nameBuf, WMT_MODULES_SUFF);
+
+ insmod_retry:
+ iRet = insmod(nameBuf, DRIVER_MODULE_ARG);
+ if(iRet)
+ {
+ ALOGI("insert <%s> failed, len(%d), iret(%d), retrying\n", nameBuf, sizeof(nameBuf), iRet);
+ /*break;*/
+ usleep(800000);
+ goto insmod_retry;
+ }else
+ {
+ ALOGI("insert <%s> succeed,len(%d)\n", nameBuf, len);
+ iRet = 0;
+ }
+ return 0;
+}
+
+
+static int insert_wmt_module_for_soc(int chipid, char *modulePath, char *nameBuf, int nameBufLen)
+{
+ int iRet = -1;
+ int len = 0;
+ int path_len = 0;
+ int i = 0;
+ char postFixStr[10] = {0};
+ int totalLen = 0;
+ char *soc_modulse[] = {
+ STP_WMT_MODULE_PRE_FIX,
+ STP_BT_MODULE_PRE_FIX,
+ STP_GPS_MODULE_PRE_FIX,
+ };
+
+#if 0
+ path_len = strlen(modulePath);
+ strncpy(nameBuf, modulePath,path_len);
+ ALOGI("module subpath1(%s),sublen1(%d)\n",nameBuf,path_len);
+ len = path_len;
+#endif
+
+ sprintf(postFixStr, "_%s", "soc");
+
+#if 0
+ switch (chipid)
+ {
+ case 0x6572:
+ case 0x6582:
+ strcpy(postFixStr, "_6582");
+ break;
+ case 0x6571:
+ strcpy(postFixStr, "_6592");
+ case 0x6592:
+ strcpy(postFixStr, "_6592");
+ break;
+ default:
+
+ break;
+ }
+#endif
+
+ if (NULL == modulePath || NULL == nameBuf || 0 >= nameBufLen)
+ {
+ ALOGI("invalid parameter:modulePath(%p), nameBuf(%p), nameBufLen(%d)\n", modulePath, nameBuf, nameBufLen);
+ return iRet;
+ }
+
+ for(i = 0;i < sizeof(soc_modulse)/sizeof(soc_modulse[0]);i++)
+ {
+ totalLen = sizeof (modulePath) + sizeof (soc_modulse[i]) + sizeof(postFixStr) + sizeof(WMT_MODULES_SUFF);
+ if (nameBufLen > totalLen)
+ {
+
+ memset (nameBuf, 0, nameBufLen);
+ insmod_by_path(nameBuf, modulePath, soc_modulse[i], postFixStr);
+ }
+ else
+ {
+ ALOGI("nameBuf length(%d) too short, (%d) needed\n", nameBufLen, totalLen);
+ }
+#if 0
+ len = path_len;
+ len += sprintf(nameBuf + len,"%s",soc_modulse[i]);
+ ALOGI("module subpath2(%s),sublen2(%d)\n",nameBuf,len);
+
+ len += sprintf(nameBuf + len,"%s", postFixStr);
+ ALOGI("module subpath3(%s),sublen3(%d)\n",nameBuf,len);
+
+ len += sprintf(nameBuf + len,"%s",WMT_MODULES_SUFF);
+ ALOGI("module subpath4(%s),sublen4(%d)\n",nameBuf,len);
+
+ nameBuf[len] = '\0';
+ ALOGI("module subpath5(%s),sublen5(%d)\n",nameBuf,len);
+
+ soc_retry:
+ iRet = insmod(nameBuf, DRIVER_MODULE_ARG);
+ if(iRet)
+ {
+ ALOGI("(%d):current modules(%s) insert fail,len(%d),iret(%d), retrying\n", i, nameBuf, len, iRet);
+ /*break;*/
+ usleep(300000);
+ goto soc_retry;
+ }else
+ {
+ ALOGI("(%d):current modules(%s) insert ok,len(%d)\n", i, nameBuf, len);
+ }
+#endif
+
+ }
+
+
+
+ return 0;
+}
+
+static int insert_wmt_module_for_combo(int chipid, char *modulePath, char *nameBuf, int nameBufLen)
+{
+ int iRet = -1;
+ int len = 0;
+ int path_len = 0;
+ int i = 0;
+ char postFixStr[10] = {0};
+ int totalLen = 0;
+
+ char *combo_modulse[] = {
+ HIF_SDIO_MODULE_PRE_FIX,
+ STP_WMT_MODULE_PRE_FIX,
+ STP_UART_MODULE_PRE_FIX,
+ STP_SDIO_MODULE_PRE_FIX,
+ STP_BT_MODULE_PRE_FIX,
+ STP_GPS_MODULE_PRE_FIX
+ };
+
+ if (NULL == modulePath || NULL == nameBuf || 0 >= nameBufLen)
+ {
+ ALOGI("invalid parameter:modulePath(%p), nameBuf(%p), nameBufLen(%d)\n", modulePath, nameBuf, nameBufLen);
+ return iRet;
+ }
+
+#if 0
+ path_len = strlen(modulePath);
+ strncpy(nameBuf, modulePath,path_len);
+ ALOGI("module subpath1(%s),sublen1(%d)\n",nameBuf,path_len);
+
+ len = path_len;
+#endif
+
+ switch (chipid)
+ {
+ case 0x6620:
+ case 0x6628:
+ /*strcpy(postFixStr, "_6620_28");*/
+ strcpy(postFixStr, "");
+ break;
+ case 0x6630:
+ //strcpy(postFixStr, "_6630");
+ strcpy(postFixStr, "");
+ break;
+ default:
+
+ break;
+ }
+
+ for(i = 0;i < sizeof(combo_modulse)/sizeof(combo_modulse[0]);i++)
+ {
+ totalLen = sizeof (modulePath) + sizeof (combo_modulse[i]) + sizeof(postFixStr) + sizeof(WMT_MODULES_SUFF);
+ if (nameBufLen > totalLen)
+ {
+ memset (nameBuf, 0, nameBufLen);
+ insmod_by_path(nameBuf, modulePath, combo_modulse[i], postFixStr);
+ }
+ else
+ {
+ ALOGI("nameBuf length(%d) too short, (%d) needed\n", nameBufLen, totalLen);
+ }
+#if 0
+ len = path_len;
+ len += sprintf(nameBuf + len,"%s",combo_modulse[i]);
+ ALOGI("module subpath2(%s),sublen2(%d)\n",nameBuf,len);
+
+ len += sprintf(nameBuf + len,"%s",postFixStr);
+ ALOGI("module subpath3(%s),sublen3(%d)\n",nameBuf,len);
+
+ len += sprintf(nameBuf + len,"%s",WMT_MODULES_SUFF);
+ ALOGI("module subpath4(%s),sublen4(%d)\n",nameBuf,len);
+
+ nameBuf[len] = '\0';
+ ALOGI("module subpath5(%s),sublen5(%d)\n",nameBuf,len);
+
+ combo_retry:
+ iRet = insmod(nameBuf, DRIVER_MODULE_ARG);
+ if(iRet)
+ {
+ ALOGI("(%d):current modules(%s) insert fail,len(%d),iret(%d), retrying\n", i, nameBuf, len, iRet);
+ /*break;*/
+ usleep(300000);
+ goto combo_retry;
+ }else
+ {
+ ALOGI("(%d):current modules(%s) insert ok,len(%d)\n",i, nameBuf, len);
+ }
+#endif
+ }
+
+
+ return 0;
+}
+
+
+
+/******************************************************
+arg1:
+= 0:there is already a valid chipid in peroperty or there is no external combo chip
+ chipid is just MT6582
+> 0:there is no valid chipid in peroperty, boot system firstly
+
+arg2: // handle combo chip (there is an external combo chip)
+= 0:insert mtk_hif_sdio.ko for detech combo chipid
+> 0:insert combo modules except mtk_hif_sdio.ko
+******************************************************/
+
+static int insert_wmt_modules(int chipid,int arg1,int arg2)
+{
+ int iRet = -1;
+
+ switch (chipid)
+ {
+ case 0x6582:
+ case 0x6572:
+ case 0x6571:
+ case 0x6592:
+ case 0x8127:
+ case 0x6752:
+ case 0x6735:
+ case 0x8163:
+ case 0x6580:
+ case 0x6755:
+ case 0x6797:
+ iRet = insert_wmt_module_for_soc(chipid, WMT_MODULES_PRE, DRIVER_MODULE_PATH, sizeof (DRIVER_MODULE_PATH));
+ break;
+ case 0x6620:
+ case 0x6628:
+ case 0x6630:
+ iRet = insert_wmt_module_for_combo(chipid, WMT_MODULES_PRE, DRIVER_MODULE_PATH, sizeof (DRIVER_MODULE_PATH));
+ break;
+ default:
+ break;
+ }
+
+ return iRet;
+}
+
+int do_kernel_module_init(int gLoaderFd, int chipId)
+{
+ int iRet = 0;
+ if (gLoaderFd < 0)
+ {
+ ALOGI("invalid gLoaderFd: %d\n", gLoaderFd);
+ return -1;
+ }
+
+ iRet = ioctl (gLoaderFd, COMBO_IOCTL_MODULE_CLEANUP, chipId);
+ if (iRet)
+ {
+ ALOGI("do WMT-DETECT module cleanup failed: %d\n", iRet);
+ return -2;
+ }
+ iRet = ioctl (gLoaderFd, COMBO_IOCTL_DO_MODULE_INIT, chipId);
+ if (iRet)
+ {
+ ALOGI("do kernel module init failed: %d\n", iRet);
+ return -3;
+ }
+ ALOGI("do kernel module init succeed: %d\n", iRet);
+ return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int iRet = -1;
+ int noextChip = -1;
+ int chipId = -1;
+ int count = 0;
+ char chipidStr[PROPERTY_VALUE_MAX] = {0};
+ char readyStr[PROPERTY_VALUE_MAX] = {0};
+ int loadFmResult = -1;
+ int loadAntResult = -1;
+ int loadWlanResult = -1;
+ int retryCounter = 1;
+ int autokRet = 0;
+ do{
+ gLoaderFd = open(WCN_COMBO_LOADER_DEV, O_RDWR | O_NOCTTY);
+ if(gLoaderFd < 0)
+ {
+ count ++;
+ ALOGI("Can't open device node(%s) count(%d)\n", WCN_COMBO_LOADER_DEV,count);
+ usleep(300000);
+ }
+ else
+ break;
+ }while(1);
+
+ //read from system property
+ iRet = property_get(WCN_COMBO_LOADER_CHIP_ID_PROP, chipidStr, NULL);
+ chipId = strtoul(chipidStr, NULL, 16);
+
+ if ((0 != iRet) && (-1 != is_chipId_vaild(chipId)))
+ {
+ /*valid chipid detected*/
+ ALOGI("key:(%s)-value:(%s),chipId:0x%04x,iRet(%d)\n", WCN_COMBO_LOADER_CHIP_ID_PROP, chipidStr, chipId,iRet);
+ if (0x6630 == chipId)
+ {
+ retryCounter = 10;
+ /*trigger autok process, incase last autok process is interrupted by abnormal power off or battery down*/
+ do {
+ /*power on combo chip*/
+ iRet = ioctl(gLoaderFd,COMBO_IOCTL_EXT_CHIP_PWR_ON);
+ if (0 != iRet)
+ {
+ ALOGI("external combo chip power on failed\n");
+ noextChip = 1;
+ }
+ else
+ {
+ /*detect is there is an external combo chip*/
+ noextChip = ioctl(gLoaderFd,COMBO_IOCTL_EXT_CHIP_DETECT,NULL);
+ }
+
+ if(noextChip)
+ {
+ // do nothing
+ ALOGI("no external combo chip detected\n");
+ }
+ else
+ {
+ ALOGI("external combo chip detected\n");
+
+ chipId = ioctl(gLoaderFd, COMBO_IOCTL_GET_CHIP_ID, NULL);
+ ALOGI("chipid (0x%x) detected\n", chipId);
+ }
+
+
+ if(0 == noextChip)
+ {
+ autokRet = ioctl(gLoaderFd,COMBO_IOCTL_DO_SDIO_AUDOK,chipId);
+ if (0 != autokRet)
+ {
+ ALOGI("do SDIO3.0 autok failed\n");
+ }
+ else
+ {
+ ALOGI("do SDIO3.0 autok succeed\n");
+ }
+ }
+ iRet = ioctl(gLoaderFd,COMBO_IOCTL_EXT_CHIP_PWR_OFF);
+ if (0 != iRet)
+ {
+ ALOGI("external combo chip power off failed\n");
+ }
+ else
+ {
+ ALOGI("external combo chip power off succeed\n");
+ }
+ if ((0 == noextChip) && (-1 == chipId))
+ {
+ /*extenral chip detected, but no valid chipId detected, retry*/
+ retryCounter--;
+ ALOGI("chipId detect failed, retrying, left retryCounter:%d\n", retryCounter);
+ usleep(500000);
+ }
+ else
+ break;
+ }while (0 < retryCounter);
+ chipId = 0x6630;
+ }
+ }
+ else
+ {
+ /*trigger external combo chip detect and chip identification process*/
+ do {
+ /*power on combo chip*/
+ iRet = ioctl(gLoaderFd,COMBO_IOCTL_EXT_CHIP_PWR_ON);
+ if (0 != iRet)
+ {
+ ALOGI("external combo chip power on failed\n");
+ noextChip = 1;
+ }
+ else
+ {
+ /*detect is there is an external combo chip*/
+ noextChip = ioctl(gLoaderFd,COMBO_IOCTL_EXT_CHIP_DETECT,NULL);
+ }
+
+ if(noextChip)// use soc itself
+ {
+ ALOGI("no external combo chip detected, get current soc chipid\n");
+ chipId = ioctl(gLoaderFd, COMBO_IOCTL_GET_SOC_CHIP_ID, NULL);
+ ALOGI("soc chipid (0x%x) detected\n", chipId);
+ }
+ else
+ {
+ ALOGI("external combo chip detected\n");
+
+ chipId = ioctl(gLoaderFd, COMBO_IOCTL_GET_CHIP_ID, NULL);
+ ALOGI("chipid (0x%x) detected\n", chipId);
+ }
+
+ sprintf (chipidStr, "0x%04x", chipId);
+ iRet = property_set(WCN_COMBO_LOADER_CHIP_ID_PROP,chipidStr);
+ if (0 != iRet)
+ {
+ ALOGI("set property(%s) to %s failed,iRet:%d, errno:%d\n", WCN_COMBO_LOADER_CHIP_ID_PROP, chipidStr, iRet, errno);
+ }
+ else
+ {
+ ALOGI("set property(%s) to %s succeed.\n", WCN_COMBO_LOADER_CHIP_ID_PROP, chipidStr);
+ }
+ if(0 == noextChip)
+ {
+ autokRet = ioctl(gLoaderFd,COMBO_IOCTL_DO_SDIO_AUDOK,chipId);
+ if (0 != autokRet)
+ {
+ ALOGI("do SDIO3.0 autok failed\n");
+ }
+ else
+ {
+ ALOGI("do SDIO3.0 autok succeed\n");
+ }
+ }
+ iRet = ioctl(gLoaderFd,COMBO_IOCTL_EXT_CHIP_PWR_OFF);
+ if (0 != iRet)
+ {
+ ALOGI("external combo chip power off failed\n");
+ }
+ else
+ {
+ ALOGI("external combo chip power off succeed\n");
+ }
+ if ((0 == noextChip) && (-1 == chipId))
+ {
+ /*extenral chip detected, but no valid chipId detected, retry*/
+ retryCounter--;
+ usleep(500000);
+ ALOGI("chipId detect failed, retrying, left retryCounter:%d\n", retryCounter);
+ }
+ else
+ break;
+ }while (0 < retryCounter);
+ }
+
+ /*set chipid to kernel*/
+ ioctl(gLoaderFd,COMBO_IOCTL_SET_CHIP_ID,chipId);
+
+ if (g_remove_ko_flag)
+ {
+ if((0x0321 == chipId) || (0x0335 == chipId) || (0x0337 == chipId))
+ {
+ chipId = 0x6735;
+ }
+ if (0x0326 == chipId) {
+ chipId = 0x6755;
+ }
+ if (0x0279 == chipId) {
+ chipId = 0x6797;
+ }
+ do_kernel_module_init(gLoaderFd, chipId);
+ if(gLoaderFd >= 0)
+ {
+ close(gLoaderFd);
+ gLoaderFd = -1;
+ }
+
+ }
+ else
+ {
+ if(gLoaderFd >= 0)
+ {
+ close(gLoaderFd);
+ gLoaderFd = -1;
+ }
+ ALOGI("rmmod mtk_wmt_detect\n");
+ rmmod("mtk_wmt_detect");
+
+ /*INSERT TARGET MODULE TO KERNEL*/
+
+ iRet = insert_wmt_modules(chipId, 0, -1);
+ /*this process should never fail*/
+ if(iRet)
+ {
+ ALOGI("insert wmt modules fail(%d):(%d)\n",iRet,__LINE__);
+ /*goto done;*/
+ }
+
+
+ loadFmResult = load_fm_module(chipId);
+ if(loadFmResult)
+ {
+ ALOGI("load FM modules fail(%d):(%d)\n",iRet,__LINE__);
+ /*continue, we cannot let this process interrupted by subsystem module load fail*/
+ /*goto done;*/
+ }
+
+ loadAntResult = load_ant_module(chipId);
+ if(loadAntResult)
+ {
+ ALOGI("load ANT modules fail(%d):(%d)\n",iRet,__LINE__);
+ /*continue, we cannot let this process interrupted by subsystem module load fail*/
+ /*goto done;*/
+ }
+
+ loadWlanResult = load_wifi_module(chipId);
+ if(loadWlanResult)
+ {
+ ALOGI("load WIFI modules fail(%d):(%d)\n",iRet,__LINE__);
+ /*continue, we cannot let this process interrupted by subsystem module load fail*/
+ /*goto done;*/
+ }
+ }
+
+
+
+ if((chown("/proc/driver/wmt_dbg",AID_SHELL,AID_SYSTEM) == -1) || (chown("/proc/driver/wmt_aee",AID_SHELL,AID_SYSTEM) == -1))
+ {
+ ALOGI("chown wmt_dbg or wmt_aee fail:%s\n",strerror(errno));
+ }
+
+ if(chown("/proc/wmt_tm/wmt_tm",0,1000) == -1)
+ {
+ ALOGI("chown wmt_tm fail:%s\n",strerror(errno));
+ }
+ if (0/*0x6630 == chipId*/)
+ {
+ retryCounter = 0;
+ int i_ret = -1;
+ do {
+ i_ret = loader_wmt_pwr_ctrl(1);
+ if (0 == i_ret)
+ break;
+ else
+ {
+ loader_wmt_pwr_ctrl(0);
+ ALOGI("power on %x failed, retrying, retry counter:%d\n", chipId, retryCounter);
+ usleep(1000000);
+ }
+ retryCounter++;
+ } while (retryCounter < 20);
+ }
+ iRet = property_get(WCN_DRIVER_READY_PROP, readyStr, NULL);
+ if ((0 >= iRet) || (0 == strcmp(readyStr, "yes"))) {
+ ALOGI("get property(%s) failed iRet:%d or property is %s\n", WCN_DRIVER_READY_PROP, iRet, readyStr);
+ }
+ /*set it to yes anyway*/
+ sprintf(readyStr, "%s", "yes");
+ iRet = property_set(WCN_DRIVER_READY_PROP, readyStr);
+ if (0 != iRet) {
+ ALOGI("set property(%s) to %s failed iRet:%d\n", WCN_DRIVER_READY_PROP, readyStr, iRet);
+ } else {
+ ALOGI("set property(%s) to %s succeed\n", WCN_DRIVER_READY_PROP, readyStr);
+ }
+#if 0
+ while (loadWlanResult || loadFmResult)
+ {
+ if(loadFmResult)
+ {
+ static int retryCounter = 0;
+ retryCounter++;
+ ALOGI("retry loading fm module, retryCounter:%d\n", retryCounter);
+ loadFmResult = load_fm_module(chipId);
+ }
+
+ if(loadWlanResult)
+ {
+ static int retryCounter = 0;
+ retryCounter++;
+ ALOGI("retry loading wlan module, retryCounter:%d\n", retryCounter);
+ loadWlanResult = load_wifi_module(chipId);
+ }
+ usleep(1000000);
+ }
+#endif
+
+ return iRet;
+}
+
+
+
diff --git a/src/connectivity/combo_tool/combo_loader/loader.h b/src/connectivity/combo_tool/combo_loader/loader.h
new file mode 100755
index 0000000..6c7afab
--- /dev/null
+++ b/src/connectivity/combo_tool/combo_loader/loader.h
@@ -0,0 +1,16 @@
+#ifndef __WMT_LOADER_H_
+#define __WMT_LOADER_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+//For directory operation
+#include <dirent.h>
+
+#include <cutils/properties.h>
+#include <cutils/misc.h>
+#include <sys/ioctl.h>
+
+#endif
diff --git a/src/connectivity/combo_tool/combo_loader/loader_pwr.c b/src/connectivity/combo_tool/combo_loader/loader_pwr.c
new file mode 100755
index 0000000..a1f5257
--- /dev/null
+++ b/src/connectivity/combo_tool/combo_loader/loader_pwr.c
@@ -0,0 +1,30 @@
+#include "../src/wmt_ioctl.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+int loader_wmt_pwr_ctrl(int on)
+{
+ int i_ret = -1;
+ int wmt_fd;
+ int para = (on == 0) ? 0 : 1;
+ /* open wmt dev */
+ wmt_fd = open("/dev/stpwmt", O_RDWR | O_NOCTTY);
+ if (wmt_fd < 0) {
+ printf("[%s] Can't open stpwmt \n", __FUNCTION__);
+ return -1;
+ }
+ if(ioctl(wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, para) != 0)
+ {
+ printf("[%s] power on combo chip failed\n", __FUNCTION__);
+ i_ret = -2;
+ } else {
+ printf("[power %s combo chip ok!]\n", para == 0 ? "off" : "on");
+ i_ret = 0;
+ }
+ close(wmt_fd);
+ wmt_fd = -1;
+
+ return i_ret;
+}
\ No newline at end of file
diff --git a/src/connectivity/combo_tool/combo_loader/loader_pwr.h b/src/connectivity/combo_tool/combo_loader/loader_pwr.h
new file mode 100755
index 0000000..bfe370d
--- /dev/null
+++ b/src/connectivity/combo_tool/combo_loader/loader_pwr.h
@@ -0,0 +1,4 @@
+#ifndef __WMT_LOADER_PWR_H_
+#define __WMT_LOADER_PWR_H_
+int loader_wmt_pwr_ctrl(int on);
+#endif /*__WMT_LOADER_PWR_H_*/
\ No newline at end of file
diff --git a/src/connectivity/combo_tool/combo_loader/yocto_loader.c b/src/connectivity/combo_tool/combo_loader/yocto_loader.c
new file mode 100755
index 0000000..34256a4
--- /dev/null
+++ b/src/connectivity/combo_tool/combo_loader/yocto_loader.c
@@ -0,0 +1,460 @@
+#include "loader_pwr.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+// For directory operation
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "wmt_loader"
+
+#define WCN_COMBO_LOADER_CHIP_ID_PROP "persist.mtk.wcn.combo.chipid"
+#ifndef ALOGI
+#define ALOGI printf
+#endif
+#ifndef PROPERTY_VALUE_MAX
+#define PROPERTY_VALUE_MAX (128)
+#endif
+
+#define WCN_COMBO_LOADER_DEV "/dev/wmtdetect"
+#define WCN_COMBO_DEF_CHIPID "0x6582"
+#define WMT_MODULES_PRE "/system/lib/modules/"
+#define WMT_KO_PATH_PREFIX "/lib/modules/"
+#define WMT_WIFI_MODULE_PATH "/kernel/drivers/misc/mediatek/connectivity/wlan/wmt_chrdev_wifi.ko"
+#define WMT_WLAN_MODULE_PATH "/kernel/drivers/misc/mediatek/connectivity/wlan/gen3/wlan_gen3.ko"
+/* connectivity modules are built out of kernel tree */
+#define WMT_OUT_KO_PATH_PREFIX "/lib/modules/mt66xx/"
+#define WMT_OUT_WMT_WIFI_MODULE_PATH "wmt_chrdev_wifi.ko"
+#define WMT_OUT_WLAN_MODULE_PATH "wlan_drv_gen3.ko"
+
+#define WMT_MODULES_SUFF ".ko"
+#define WMT_IOC_MAGIC 'w'
+#define COMBO_IOCTL_GET_CHIP_ID _IOR(WMT_IOC_MAGIC, 0, int)
+#define COMBO_IOCTL_SET_CHIP_ID _IOW(WMT_IOC_MAGIC, 1, int)
+#define COMBO_IOCTL_EXT_CHIP_DETECT _IOR(WMT_IOC_MAGIC, 2, int)
+#define COMBO_IOCTL_GET_SOC_CHIP_ID _IOR(WMT_IOC_MAGIC, 3, int)
+#define COMBO_IOCTL_DO_MODULE_INIT _IOR(WMT_IOC_MAGIC, 4, int)
+#define COMBO_IOCTL_MODULE_CLEANUP _IOR(WMT_IOC_MAGIC, 5, int)
+#define COMBO_IOCTL_EXT_CHIP_PWR_ON _IOR(WMT_IOC_MAGIC, 6, int)
+#define COMBO_IOCTL_EXT_CHIP_PWR_OFF _IOR(WMT_IOC_MAGIC, 7, int)
+#define COMBO_IOCTL_DO_SDIO_AUDOK _IOR(WMT_IOC_MAGIC, 8, int)
+
+
+
+#define STP_WMT_MODULE_PRE_FIX "mtk_stp_wmt"
+#define STP_BT_MODULE_PRE_FIX "mtk_stp_bt"
+#define STP_GPS_MODULE_PRE_FIX "mtk_stp_gps"
+#define HIF_SDIO_MODULE_PRE_FIX "mtk_hif_sdio"
+#define STP_SDIO_MODULE_PRE_FIX "mtk_stp_sdio"
+#define STP_UART_MODULE_PRE_FIX "mtk_stp_uart"
+
+
+
+static int gLoaderFd = -1;
+
+static char DRIVER_MODULE_PATH[64] = {0};
+static char DRIVER_MODULE_ARG[8] = "";
+static int chipid_array[] = {
+0x6620,
+0x6628,
+0x6630,
+0x6572,
+0x6582,
+0x6592,
+0x8127,
+0x6571,
+0x6752,
+0x6735,
+0x0321,
+0x0335,
+0x0337,
+0x8163,
+0x6580,
+0x6755,
+0x0326,
+0x6797,
+0x0279
+};
+static char chip_version[PROPERTY_VALUE_MAX] = {0};
+
+static int g_remove_ko_flag = 1;
+
+
+extern int init_module(void *, unsigned long, const char *);
+extern int delete_module(const char *, unsigned int);
+extern int load_fm_module(int chip_id);
+//extern int load_wifi_module(int chip_id);
+extern int load_ant_module(int chip_id);
+// insmod
+static int is_chipId_vaild(int chipid) {
+ int iret;
+ unsigned char i;
+ iret = -1;
+
+ for (i = 0; i < sizeof(chipid_array)/sizeof(0x6630); i++) {
+ if (chipid == chipid_array[i]) {
+ ALOGI("is_chipId_vaild: %d :0x%x!\n", i, chipid);
+ iret = 0;
+ break;
+ }
+ }
+ return iret;
+}
+
+int do_kernel_module_init(int gLoaderFd, int chipId) {
+ int iRet = 0;
+ if (gLoaderFd < 0) {
+ ALOGI("invalid gLoaderFd: %d\n", gLoaderFd);
+ return -1;
+ }
+
+ iRet = ioctl(gLoaderFd, COMBO_IOCTL_MODULE_CLEANUP, chipId);
+ if (iRet) {
+ ALOGI("do WMT-DETECT module cleanup failed: %d\n", iRet);
+ return -2;
+ }
+ iRet = ioctl(gLoaderFd, COMBO_IOCTL_DO_MODULE_INIT, chipId);
+ if (iRet) {
+ ALOGI("do kernel module init failed: %d\n", iRet);
+ return -3;
+ }
+ ALOGI("do kernel module init succeed: %d\n", iRet);
+ return 0;
+}
+
+void *load_file(const char *fn, unsigned *_sz)
+{
+ char *data;
+ int sz;
+ int fd;
+ data = 0;
+
+ fd = open(fn, O_RDONLY);
+ if(fd < 0) return 0;
+
+ sz = lseek(fd, 0, SEEK_END);
+ if(sz < 0)
+ goto oops;
+
+ if(lseek(fd, 0, SEEK_SET) != 0)
+ goto oops;
+
+ data = (char*) malloc(sz + 1);
+ if(data == 0)
+ goto oops;
+
+ if(read(fd, data, sz) != sz)
+ goto oops;
+
+ close(fd); data[sz] = 0;
+
+ if(_sz)
+ *_sz = sz;
+
+ return data;
+
+oops:
+ close(fd);
+ if(data != 0)
+ free(data);
+
+ return 0;
+}
+
+//insmod
+static int insmod(const char *filename, const char *args)
+{
+ void *module;
+ unsigned int size;
+ int ret;
+
+ module = load_file(filename, &size);
+ if (!module)
+ return -1;
+
+ ret = init_module(module, size, args);
+
+ free(module);
+
+ return ret;
+}
+
+
+int load_wifi_module(int chip_id)
+{
+ int ret = -1;
+ struct utsname utsname;
+ char wifi_module_path[100] = "";
+ char wlan_module_path[100] = "";
+
+ if (!(uname(&utsname))) {
+ /* Use modules built within kernel tree */
+ sprintf(wifi_module_path, "%s%s%s", WMT_KO_PATH_PREFIX, utsname.release, WMT_WIFI_MODULE_PATH);
+ sprintf(wlan_module_path, "%s%s%s", WMT_KO_PATH_PREFIX, utsname.release, WMT_WLAN_MODULE_PATH);
+ } else
+ return -1;
+
+ if ((access(wifi_module_path,0) < 0) && (access(wlan_module_path,0) < 0))
+ {
+ /* Use modules built out of kernel tree */
+ printf("Use modules built out of kernel tree\n");
+ memset(wifi_module_path, 0, sizeof(wifi_module_path));
+ memset(wlan_module_path, 0, sizeof(wlan_module_path));
+ sprintf(wifi_module_path, "%s%s", WMT_OUT_KO_PATH_PREFIX, WMT_OUT_WMT_WIFI_MODULE_PATH);
+ sprintf(wlan_module_path, "%s%s", WMT_OUT_KO_PATH_PREFIX, WMT_OUT_WLAN_MODULE_PATH);
+ }
+
+ if (chip_id == 0x6630) {
+ //insert 6630 driver
+ if(0 == insmod(wifi_module_path, DRIVER_MODULE_ARG)){
+ ret = 0;
+ printf("Success to insmod wmt wifi module\n");
+ } else
+ printf("Fail to insmod wmt wifi module %s\n", wifi_module_path);
+
+ if(0 == insmod(wlan_module_path, DRIVER_MODULE_ARG)){
+ ret = 0;
+ printf("Success to insmod wlan module\n");
+ } else
+ printf("Fail to insmod wlan module %s\n", wlan_module_path);
+ }
+
+ return ret;
+}
+
+
+/* TBD in platform-specific way */
+static int get_persist_chip_id(char *str, size_t len) { return -1; }
+static int set_persist_chip_id(int id) { return 0; }
+static void set_proc_owner(void) { }
+static void update_driver_ready(void) { }
+
+int main(int argc, char *argv[]) {
+ int iRet = -1;
+ int noextChip = -1;
+ int chipId = -1;
+ int count = 0;
+ char chipidStr[PROPERTY_VALUE_MAX] = {0};
+ char readyStr[PROPERTY_VALUE_MAX] = {0};
+ int loadFmResult = -1;
+ int loadAntResult = -1;
+ int loadWlanResult = -1;
+ int retryCounter = 1;
+ int autokRet = 0;
+ do {
+ gLoaderFd = open(WCN_COMBO_LOADER_DEV, O_RDWR | O_NOCTTY);
+ if (gLoaderFd < 0) {
+ count++;
+ ALOGI("Can't open device node(%s) count(%d)\n", WCN_COMBO_LOADER_DEV, count);
+ usleep(300000);
+ } else
+ break;
+ } while (1);
+
+ // read from system property
+ chipId = get_persist_chip_id(chipidStr, sizeof(chipidStr));
+
+ if (-1 != is_chipId_vaild(chipId)) {
+ /*valid chipid detected*/
+ ALOGI("key:(%s)-value:(%s),chipId:0x%04x,iRet(%d)\n",
+ WCN_COMBO_LOADER_CHIP_ID_PROP, chipidStr, chipId, iRet);
+ if (0x6630 == chipId) {
+ retryCounter = 10;
+ /*trigger autok process, incase last autok process is
+ interrupted by abnormal power off or battery down*/
+ do {
+ /*power on combo chip*/
+ iRet = ioctl(gLoaderFd, COMBO_IOCTL_EXT_CHIP_PWR_ON);
+ if (0 != iRet) {
+ ALOGI("external combo chip power on failed\n");
+ noextChip = 1;
+ } else {
+ /*detect is there is an external combo chip*/
+ noextChip = ioctl(gLoaderFd, COMBO_IOCTL_EXT_CHIP_DETECT, NULL);
+ }
+
+ if (noextChip) {
+ // do nothing
+ ALOGI("no external combo chip detected\n");
+ } else {
+ ALOGI("external combo chip detected\n");
+ chipId = ioctl(gLoaderFd, COMBO_IOCTL_GET_CHIP_ID, NULL);
+ ALOGI("chipid (0x%x) detected\n", chipId);
+ }
+
+ if (0 == noextChip) {
+ autokRet = ioctl(gLoaderFd, COMBO_IOCTL_DO_SDIO_AUDOK, chipId);
+ if (0 != autokRet) {
+ ALOGI("do SDIO3.0 autok failed\n");
+ } else {
+ ALOGI("do SDIO3.0 autok succeed\n");
+ }
+ }
+ iRet = ioctl(gLoaderFd, COMBO_IOCTL_EXT_CHIP_PWR_OFF);
+ if (0 != iRet) {
+ ALOGI("external combo chip power off failed\n");
+ } else {
+ ALOGI("external combo chip power off succeed\n");
+ }
+ if ((0 == noextChip) && (-1 == chipId)) {
+ /*extenral chip detected, but no valid chipId detected, retry*/
+ retryCounter--;
+ ALOGI("chipId detect failed, retrying, left retryCounter:%d\n", retryCounter);
+ usleep(500000);
+ } else
+ break;
+ }while (0 < retryCounter);
+ chipId = 0x6630;
+ }
+ } else {
+ /*trigger external combo chip detect and chip identification process*/
+ do {
+ /*power on combo chip*/
+ iRet = ioctl(gLoaderFd, COMBO_IOCTL_EXT_CHIP_PWR_ON);
+ if (0 != iRet) {
+ ALOGI("external combo chip power on failed\n");
+ noextChip = 1;
+ } else {
+ /*detect is there is an external combo chip*/
+ noextChip = ioctl(gLoaderFd, COMBO_IOCTL_EXT_CHIP_DETECT, NULL);
+ }
+
+ if (noextChip) { // use soc itself
+ ALOGI("no external combo chip detected, get current soc chipid\n");
+ chipId = ioctl(gLoaderFd, COMBO_IOCTL_GET_SOC_CHIP_ID, NULL);
+ ALOGI("soc chipid (0x%x) detected\n", chipId);
+ } else {
+ ALOGI("external combo chip detected\n");
+ chipId = ioctl(gLoaderFd, COMBO_IOCTL_GET_CHIP_ID, NULL);
+ ALOGI("chipid (0x%x) detected\n", chipId);
+ }
+
+ sprintf(chipidStr, "0x%04x", chipId);
+ iRet = set_persist_chip_id(chipId);
+ if (0 != iRet) {
+ ALOGI("set property(%s) to %s failed,iRet:%d, errno:%d\n",
+ WCN_COMBO_LOADER_CHIP_ID_PROP, chipidStr, iRet, errno);
+ } else {
+ ALOGI("set property(%s) to %s succeed.\n", WCN_COMBO_LOADER_CHIP_ID_PROP, chipidStr);
+ }
+ if (0 == noextChip) {
+ autokRet = ioctl(gLoaderFd, COMBO_IOCTL_DO_SDIO_AUDOK, chipId);
+ if (0 != autokRet) {
+ ALOGI("do SDIO3.0 autok failed\n");
+ } else {
+ ALOGI("do SDIO3.0 autok succeed\n");
+ }
+ }
+ iRet = ioctl(gLoaderFd, COMBO_IOCTL_EXT_CHIP_PWR_OFF);
+ if (0 != iRet) {
+ ALOGI("external combo chip power off failed\n");
+ } else {
+ ALOGI("external combo chip power off succeed\n");
+ }
+ if ((0 == noextChip) && (-1 == chipId)) {
+ /*extenral chip detected, but no valid chipId detected, retry*/
+ retryCounter--;
+ usleep(500000);
+ ALOGI("chipId detect failed, retrying, left retryCounter:%d\n", retryCounter);
+ } else
+ break;
+ }while (0 < retryCounter);
+ }
+
+ /*set chipid to kernel*/
+ ioctl(gLoaderFd, COMBO_IOCTL_SET_CHIP_ID, chipId);
+
+ if (g_remove_ko_flag) {
+ if ((0x0321 == chipId) || (0x0335 == chipId) || (0x0337 == chipId)) {
+ chipId = 0x6735;
+ }
+ if (0x0326 == chipId) {
+ chipId = 0x6755;
+ }
+ if (0x0279 == chipId) {
+ chipId = 0x6797;
+ }
+ do_kernel_module_init(gLoaderFd, chipId);
+ if (gLoaderFd >= 0) {
+ close(gLoaderFd);
+ gLoaderFd = -1;
+ }
+
+ } else {
+#if 0
+ if (gLoaderFd >= 0) {
+ close(gLoaderFd);
+ gLoaderFd = -1;
+ }
+ ALOGI("rmmod mtk_wmt_detect\n");
+ rmmod("mtk_wmt_detect");
+ /*INSERT TARGET MODULE TO KERNEL*/
+ iRet = insert_wmt_modules(chipId, 0, -1);
+ /*this process should never fail*/
+ if (iRet) {
+ ALOGI("insert wmt modules fail(%d):(%d)\n", iRet, __LINE__);
+ /*goto done;*/
+ }
+
+ loadFmResult = load_fm_module(chipId);
+ if (loadFmResult) {
+ ALOGI("load FM modules fail(%d):(%d)\n", iRet, __LINE__);
+ /*continue, we cannot let this process interrupted by subsystem module load fail*/
+ /*goto done;*/
+ }
+
+ loadAntResult = load_ant_module(chipId);
+ if (loadAntResult) {
+ ALOGI("load ANT modules fail(%d):(%d)\n", iRet, __LINE__);
+ /*continue, we cannot let this process interrupted by subsystem module load fail*/
+ /*goto done;*/
+ }
+
+ loadWlanResult = load_wifi_module(chipId);
+ if (loadWlanResult) {
+ ALOGI("load WIFI modules fail(%d):(%d)\n", iRet, __LINE__);
+ /*continue, we cannot let this process interrupted by subsystem module load fail*/
+ /*goto done;*/
+ }
+#endif
+ }
+
+ // chown to set proc owner
+ set_proc_owner();
+ if (0/*0x6630 == chipId*/) {
+ retryCounter = 0;
+ int i_ret = -1;
+ do {
+ i_ret = loader_wmt_pwr_ctrl(1);
+ if (0 == i_ret)
+ break;
+ else {
+ loader_wmt_pwr_ctrl(0);
+ ALOGI("power on %x failed, retrying, retry counter:%d\n", chipId, retryCounter);
+ usleep(1000000);
+ }
+ retryCounter++;
+ } while (retryCounter < 20);
+ }
+
+ //insmod wmt_chrdev_wifi.ko & wlan_gen3.ko
+ loadWlanResult = load_wifi_module(chipId);
+ if (loadWlanResult) {
+ ALOGI("load WIFI modules fail(%d):(%d)\n", iRet, __LINE__);
+ }
+
+ // update wmt driver ready
+ update_driver_ready();
+
+ return iRet;
+}
+
+
+
diff --git a/src/connectivity/combo_tool/configure.ac b/src/connectivity/combo_tool/configure.ac
new file mode 100755
index 0000000..dfe0c2c
--- /dev/null
+++ b/src/connectivity/combo_tool/configure.ac
@@ -0,0 +1,5 @@
+AC_INIT([wmt_loader], [1.0])
+AM_INIT_AUTOMAKE([foreign])
+AC_PROG_CC
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/src/connectivity/combo_tool/launcher-service b/src/connectivity/combo_tool/launcher-service
new file mode 100644
index 0000000..52846d3
--- /dev/null
+++ b/src/connectivity/combo_tool/launcher-service
@@ -0,0 +1,64 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: launcher
+# Required-Start: $syslog $local_fs $remote_fs
+# Required-Stop: $syslog $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: 66xx launcher Daemon
+### END INIT INFO
+
+. /etc/init.d/init-functions
+prog=launcher
+PIDFILE=/var/run/$prog.pid
+DESC="66xx launcher Daemon"
+start() {
+ log_daemon_msg "Starting $DESC" "$prog"
+ start_daemon_background -p $PIDFILE /usr/bin/6620_launcher -m 4 -p /lib/firmware
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+ exit 0
+}
+
+stop() {
+ log_daemon_msg "Stopping $DESC" "$prog"
+ killproc -p $PIDFILE /usr/bin/6620_launcher
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+}
+
+force_reload() {
+ stop
+ start
+
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ restart)
+ stop
+ start
+ ;;
+
+ *)
+ echo "$Usage: $prog {start|stop|force-reload|restart}"
+ exit 2
+esac
diff --git a/src/connectivity/combo_tool/launcher.service b/src/connectivity/combo_tool/launcher.service
new file mode 100644
index 0000000..f2c5141
--- /dev/null
+++ b/src/connectivity/combo_tool/launcher.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=66xx launcher Daemon
+After=wmtd.service
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/6620_launcher -m 4 -p /lib/firmware
+
+[Install]
+Alias=launcherd
+WantedBy=multi-user.target
diff --git a/src/connectivity/combo_tool/launcher_6627.service b/src/connectivity/combo_tool/launcher_6627.service
new file mode 100755
index 0000000..18c2158
--- /dev/null
+++ b/src/connectivity/combo_tool/launcher_6627.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=66xx launcher Daemon
+After=wmtd.service
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/6620_launcher -p /lib/firmware
+
+[Install]
+Alias=launcherd
+WantedBy=multi-user.target
diff --git a/src/connectivity/combo_tool/patch_folder/LICENSE b/src/connectivity/combo_tool/patch_folder/LICENSE
new file mode 100755
index 0000000..77f59ed
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/connectivity/combo_tool/patch_folder/MNL.bin b/src/connectivity/combo_tool/patch_folder/MNL.bin
new file mode 100755
index 0000000..0b91cf4
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/MNL.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/ROMv1_patch_1_0_hdr.bin b/src/connectivity/combo_tool/patch_folder/ROMv1_patch_1_0_hdr.bin
new file mode 100755
index 0000000..9fa29dc
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/ROMv1_patch_1_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/ROMv1_patch_1_1_hdr.bin b/src/connectivity/combo_tool/patch_folder/ROMv1_patch_1_1_hdr.bin
new file mode 100755
index 0000000..179a1cd
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/ROMv1_patch_1_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_0.bin b/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_0.bin
new file mode 100755
index 0000000..39e50ed
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_0.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_0_hdr.bin b/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_0_hdr.bin
new file mode 100755
index 0000000..5b5685e
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_1.bin b/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_1.bin
new file mode 100755
index 0000000..95d8ddd
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_1.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_1_hdr.bin b/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_1_hdr.bin
new file mode 100755
index 0000000..8d479f8
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/ROMv2_lm_patch_1_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/ROMv2_patch_1_0_hdr.bin b/src/connectivity/combo_tool/patch_folder/ROMv2_patch_1_0_hdr.bin
new file mode 100755
index 0000000..8efc731
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/ROMv2_patch_1_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/ROMv2_patch_1_1_hdr.bin b/src/connectivity/combo_tool/patch_folder/ROMv2_patch_1_1_hdr.bin
new file mode 100755
index 0000000..733a65f
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/ROMv2_patch_1_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/ROMv3_patch_1_0_hdr.bin b/src/connectivity/combo_tool/patch_folder/ROMv3_patch_1_0_hdr.bin
new file mode 100755
index 0000000..e4318e6
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/ROMv3_patch_1_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/ROMv3_patch_1_1_hdr.bin b/src/connectivity/combo_tool/patch_folder/ROMv3_patch_1_1_hdr.bin
new file mode 100755
index 0000000..70b88c8
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/ROMv3_patch_1_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/WIFI_RAM_CODE_8167 b/src/connectivity/combo_tool/patch_folder/WIFI_RAM_CODE_8167
new file mode 100644
index 0000000..592698f
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/WIFI_RAM_CODE_8167
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/WIFI_RAM_CODE_MT6630 b/src/connectivity/combo_tool/patch_folder/WIFI_RAM_CODE_MT6630
new file mode 100644
index 0000000..9151d7e
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/WIFI_RAM_CODE_MT6630
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/audio/WIFI_RAM_CODE_MT6630 b/src/connectivity/combo_tool/patch_folder/audio/WIFI_RAM_CODE_MT6630
new file mode 100644
index 0000000..7a8026b
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/audio/WIFI_RAM_CODE_MT6630
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/mt2731/mt6630_patch_e3_0_hdr.bin b/src/connectivity/combo_tool/patch_folder/mt2731/mt6630_patch_e3_0_hdr.bin
new file mode 100644
index 0000000..fde7b9b
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/mt2731/mt6630_patch_e3_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/mt2731/mt6630_patch_e3_1_hdr.bin b/src/connectivity/combo_tool/patch_folder/mt2731/mt6630_patch_e3_1_hdr.bin
new file mode 100644
index 0000000..d82fc75
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/mt2731/mt6630_patch_e3_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/mt6630_patch_e3_0_hdr.bin b/src/connectivity/combo_tool/patch_folder/mt6630_patch_e3_0_hdr.bin
new file mode 100755
index 0000000..f1a9275
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/mt6630_patch_e3_0_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/patch_folder/mt6630_patch_e3_1_hdr.bin b/src/connectivity/combo_tool/patch_folder/mt6630_patch_e3_1_hdr.bin
new file mode 100755
index 0000000..19f679a
--- /dev/null
+++ b/src/connectivity/combo_tool/patch_folder/mt6630_patch_e3_1_hdr.bin
Binary files differ
diff --git a/src/connectivity/combo_tool/poweronwifi.service b/src/connectivity/combo_tool/poweronwifi.service
new file mode 100644
index 0000000..db06dce
--- /dev/null
+++ b/src/connectivity/combo_tool/poweronwifi.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=power on wifi Daemon
+After=wmtd.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/usr/bin/power_on_wifi
+
+[Install]
+Alias=pwrwifid
+WantedBy=multi-user.target
diff --git a/src/connectivity/combo_tool/product_package.mk b/src/connectivity/combo_tool/product_package.mk
new file mode 100755
index 0000000..326f19c
--- /dev/null
+++ b/src/connectivity/combo_tool/product_package.mk
@@ -0,0 +1,288 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+#
+# MediaTek Inc. (C) 2010. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+# Copyright (C) 2008 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.
+
+# Configuration
+BUILD_PATCH := false
+BUILD_WMT_CFG_L2 := false
+BUILD_WMT_CFG_L1 := false
+BUILD_MT6620 := false
+BUILD_MT6628 := false
+BUILD_MT6630 := false
+BUILD_MT6582_CONSYS :=false
+BUILD_MT6571_CONSYS :=false
+BUILD_MT6752_CONSYS :=false
+BUILD_MT6797_CONSYS :=false
+
+ifeq ($(strip $(MTK_COMBO_SUPPORT)), yes)
+
+LOCAL_PATH := $(call my-dir)
+
+cfg_folder := vendor/mediatek/proprietary/hardware/connectivity/combo_tool/cfg_folder
+patch_folder := vendor/mediatek/proprietary/hardware/connectivity/combo_tool/patch_folder
+
+BUILD_PATCH := true
+BUILD_WMT_CFG_L2 := true
+
+ifneq ($(filter MT6620E3,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6620 := true
+ BUILD_WMT_CFG_L1 := true
+endif
+
+ifneq ($(filter MT6620,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6620 := true
+ BUILD_WMT_CFG_L1 := true
+endif
+
+ifneq ($(filter MT6628,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6628 := true
+ BUILD_WMT_CFG_L1 := true
+endif
+
+ifneq ($(filter MT6630,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6630 := true
+ BUILD_WMT_CFG_L1 := true
+endif
+
+ifneq ($(filter CONSYS_6572,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6582,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6592,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6582_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6571,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6571_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_8127,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6571_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6752,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6752_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6755,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6752_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6797,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6797_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6735,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6752_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_6580,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6752_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_8163,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6752_CONSYS := true
+endif
+
+ifneq ($(filter CONSYS_7623,$(MTK_COMBO_CHIP)),)
+ BUILD_MT6752_CONSYS := true
+endif
+
+##### INSTALL WMT.CFG FOR COMBO CONFIG #####
+ifeq ($(BUILD_WMT_CFG_L1), true)
+PRODUCT_COPY_FILES += $(cfg_folder)/WMT.cfg:system/etc/firmware/WMT.cfg
+endif
+
+ifeq ($(BUILD_MT6620), true)
+ifneq ($(filter mt6620_ant_m1,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6620_ant_m1.cfg:system/etc/firmware/mt6620_ant_m1.cfg
+endif
+
+ifneq ($(filter mt6620_ant_m2,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6620_ant_m2.cfg:system/etc/firmware/mt6620_ant_m2.cfg
+endif
+
+ifneq ($(filter mt6620_ant_m3,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6620_ant_m3.cfg:system/etc/firmware/mt6620_ant_m3.cfg
+endif
+
+ifneq ($(filter mt6620_ant_m4,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6620_ant_m4.cfg:system/etc/firmware/mt6620_ant_m4.cfg
+endif
+
+ifneq ($(filter mt6620_ant_m5,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6620_ant_m5.cfg:system/etc/firmware/mt6620_ant_m5.cfg
+endif
+
+ifneq ($(filter mt6620_ant_m6,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6620_ant_m6.cfg:system/etc/firmware/mt6620_ant_m6.cfg
+endif
+
+ifneq ($(filter mt6620_ant_m7,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6620_ant_m7.cfg:system/etc/firmware/mt6620_ant_m7.cfg
+endif
+
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6620_patch_e3_0_hdr.bin:system/etc/firmware/mt6620_patch_e3_0_hdr.bin
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6620_patch_e3_1_hdr.bin:system/etc/firmware/mt6620_patch_e3_1_hdr.bin
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6620_patch_e3_2_hdr.bin:system/etc/firmware/mt6620_patch_e3_2_hdr.bin
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6620_patch_e3_3_hdr.bin:system/etc/firmware/mt6620_patch_e3_3_hdr.bin
+
+endif
+
+
+ifeq ($(BUILD_MT6628), true)
+
+ifneq ($(filter mt6628_ant_m1,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6628_ant_m1.cfg:system/etc/firmware/mt6628_ant_m1.cfg
+endif
+
+ifneq ($(filter mt6628_ant_m2,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6628_ant_m2.cfg:system/etc/firmware/mt6628_ant_m2.cfg
+endif
+
+ifneq ($(filter mt6628_ant_m3,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6628_ant_m3.cfg:system/etc/firmware/mt6628_ant_m3.cfg
+endif
+
+ifneq ($(filter mt6628_ant_m4,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6628_ant_m4.cfg:system/etc/firmware/mt6628_ant_m4.cfg
+endif
+
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6628_patch_e1_hdr.bin:system/etc/firmware/mt6628_patch_e1_hdr.bin
+
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6628_patch_e2_0_hdr.bin:system/etc/firmware/mt6628_patch_e2_0_hdr.bin
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6628_patch_e2_1_hdr.bin:system/etc/firmware/mt6628_patch_e2_1_hdr.bin
+
+endif
+
+ifeq ($(BUILD_MT6630), true)
+
+ifneq ($(filter mt6630_ant_m1,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6630_ant_m1.cfg:system/etc/firmware/mt6630_ant_m1.cfg
+endif
+
+ifneq ($(filter mt6630_ant_m2,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6630_ant_m2.cfg:system/etc/firmware/mt6630_ant_m2.cfg
+endif
+
+ifneq ($(filter mt6630_ant_m3,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6630_ant_m3.cfg:system/etc/firmware/mt6630_ant_m3.cfg
+endif
+
+ifneq ($(filter mt6630_ant_m4,$(CUSTOM_HAL_ANT)),)
+ PRODUCT_COPY_FILES += $(cfg_folder)/mt6630_ant_m4.cfg:system/etc/firmware/mt6630_ant_m4.cfg
+endif
+
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6630_patch_e1_hdr.bin:system/etc/firmware/mt6630_patch_e1_hdr.bin
+
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6630_patch_e2_hdr.bin:system/etc/firmware/mt6630_patch_e2_hdr.bin
+
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6630_patch_e3_0_hdr.bin:system/etc/firmware/mt6630_patch_e3_0_hdr.bin
+ PRODUCT_COPY_FILES += $(patch_folder)/mt6630_patch_e3_1_hdr.bin:system/etc/firmware/mt6630_patch_e3_1_hdr.bin
+endif
+
+
+ifeq ($(BUILD_MT6582_CONSYS), true)
+
+ PRODUCT_COPY_FILES += $(patch_folder)/ROMv1_patch_1_0_hdr.bin:system/etc/firmware/ROMv1_patch_1_0_hdr.bin
+ PRODUCT_COPY_FILES += $(patch_folder)/ROMv1_patch_1_1_hdr.bin:system/etc/firmware/ROMv1_patch_1_1_hdr.bin
+
+endif
+
+ifeq ($(BUILD_MT6571_CONSYS), true)
+
+ PRODUCT_COPY_FILES += $(patch_folder)/ROMv2_patch_1_0_hdr.bin:system/etc/firmware/ROMv2_patch_1_0_hdr.bin
+ PRODUCT_COPY_FILES += $(patch_folder)/ROMv2_patch_1_1_hdr.bin:system/etc/firmware/ROMv2_patch_1_1_hdr.bin
+
+endif
+
+ifeq ($(BUILD_MT6752_CONSYS), true)
+
+ PRODUCT_COPY_FILES += $(patch_folder)/ROMv2_lm_patch_1_0_hdr.bin:system/etc/firmware/ROMv2_lm_patch_1_0_hdr.bin
+ PRODUCT_COPY_FILES += $(patch_folder)/ROMv2_lm_patch_1_1_hdr.bin:system/etc/firmware/ROMv2_lm_patch_1_1_hdr.bin
+
+endif
+
+ifeq ($(BUILD_MT6797_CONSYS), true)
+
+ PRODUCT_COPY_FILES += $(patch_folder)/ROMv3_patch_1_0_hdr.bin:system/etc/firmware/ROMv3_patch_1_0_hdr.bin
+ PRODUCT_COPY_FILES += $(patch_folder)/ROMv3_patch_1_1_hdr.bin:system/etc/firmware/ROMv3_patch_1_1_hdr.bin
+ PRODUCT_COPY_FILES += $(patch_folder)/MNL.bin:system/etc/firmware/MNL.bin
+
+endif
+
+ifneq ($(wildcard device/mediatek/$(MTK_TARGET_PROJECT)/WMT_SOC.cfg),)
+ PRODUCT_COPY_FILES += device/mediatek/$(MTK_TARGET_PROJECT)/WMT_SOC.cfg:system/etc/firmware/WMT_SOC.cfg
+else
+ ifneq ($(wildcard device/mediatek/$(MTK_PLATFORM_DIR)/WMT_SOC.cfg),)
+ PRODUCT_COPY_FILES += device/mediatek/$(MTK_PLATFORM_DIR)/WMT_SOC.cfg:system/etc/firmware/WMT_SOC.cfg
+ else
+ PRODUCT_COPY_FILES += device/mediatek/common/WMT_SOC.cfg:system/etc/firmware/WMT_SOC.cfg
+ endif
+endif
+
+# PRODUCT_PACKAGES part
+
+ PRODUCT_PACKAGES += 6620_launcher \
+ 6620_wmt_concurrency \
+ 6620_wmt_lpbk \
+ wmt_loader \
+ stp_dump3
+
+
+PRODUCT_PROPERTY_OVERRIDES += persist.mtk.wcn.combo.chipid=-1
+PRODUCT_PROPERTY_OVERRIDES += persist.mtk.wcn.fwlog.status=no
+PRODUCT_PROPERTY_OVERRIDES += persist.mtk.wcn.dynamic.dump=0
+PRODUCT_PROPERTY_OVERRIDES += service.wcn.driver.ready=no
+PRODUCT_PROPERTY_OVERRIDES += service.wcn.coredump.mode=2
+
+endif
diff --git a/src/connectivity/combo_tool/src/Android.mk b/src/connectivity/combo_tool/src/Android.mk
new file mode 100755
index 0000000..c1359e1
--- /dev/null
+++ b/src/connectivity/combo_tool/src/Android.mk
@@ -0,0 +1,109 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+#
+# MediaTek Inc. (C) 2010. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+# Copyright (C) 2008 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.
+
+# Configuration
+BUILD_LAUNCHER := false
+BUILD_WMT_LPBK := false
+BUILD_WMT_CONCURRENCY := false
+BUILD_STP_DUMP := false
+LOCAL_PATH := $(call my-dir)
+
+
+#ifneq ($(MTK_COMBO_CHIP), )
+BUILD_LAUNCHER := true
+BUILD_WMT_LPBK := true
+BUILD_WMT_CONCURRENCY := true
+
+#ifneq ($(filter MT6620E3,$(MTK_COMBO_CHIP)),)
+ BUILD_STP_DUMP := true
+
+#endif
+#endif
+
+$(warning before build launcher)
+ifeq ($(BUILD_LAUNCHER), true)
+include $(CLEAR_VARS)
+
+$(warning after build launcher)
+LOCAL_SRC_FILES := stp_uart_launcher.c
+LOCAL_MODULE := 6620_launcher
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := libcutils
+include $(BUILD_EXECUTABLE)
+endif
+
+ifeq ($(BUILD_WMT_LPBK), true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := wmt_loopback.c
+LOCAL_MODULE := 6620_wmt_lpbk
+LOCAL_MODULE_TAGS := eng
+include $(BUILD_EXECUTABLE)
+endif
+
+
+ifeq ($(BUILD_WMT_CONCURRENCY), true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := wmt_concurrency.c
+LOCAL_MODULE := 6620_wmt_concurrency
+LOCAL_MODULE_TAGS := eng
+include $(BUILD_EXECUTABLE)
+endif
+
+ifeq ($(BUILD_STP_DUMP), true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ stp_dump/stp_dump.c \
+ stp_dump/eloop.c \
+ stp_dump/os_linux.c
+LOCAL_SHARED_LIBRARIES := libc libcutils
+LOCAL_MODULE := stp_dump3
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+endif
+
diff --git a/src/connectivity/combo_tool/src/README b/src/connectivity/combo_tool/src/README
new file mode 100755
index 0000000..5c3e03f
--- /dev/null
+++ b/src/connectivity/combo_tool/src/README
@@ -0,0 +1,20 @@
+This module serves the common part driver of connectivity
+
+WHAT IT DOES?
+=============
+This module creates four executable binary files for configuring/testing
+the common part driver.
+
+HOW IT WAS BUILT?
+==================
+It needs the following library from AOSP:
+
+libcutils, libc
+
+HOW TO USE IT?
+==============
+The executable binary files will be started in init.rc when boot. they will work together
+with wmt_loader to load/configure the common part driver of connectivity, meanwhile some test
+tool was supplied.
+
+The majority of source code was written by MediaTek. Some code from open source codes are used.
diff --git a/src/connectivity/combo_tool/src/power_on_wifi.c b/src/connectivity/combo_tool/src/power_on_wifi.c
new file mode 100755
index 0000000..c913982
--- /dev/null
+++ b/src/connectivity/combo_tool/src/power_on_wifi.c
@@ -0,0 +1,117 @@
+
+/******************************************************************************
+* C O M P I L E R F L A G S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+*******************************************************************************
+*/
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <unistd.h>
+/*#include <syslog.h>*/
+#include <time.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+
+
+/******************************************************************************
+* C O N S T A N T S
+*******************************************************************************
+*/
+/* !defined(ANDROID) */
+#ifndef ALOGI
+#define ALOGI printf
+#endif
+#ifndef ALOGE
+#define ALOGE printf
+#endif
+#ifndef ALOGD
+#define ALOGD printf
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "6620_launcher"
+
+#if TARGET_PLATFORM == mt2635
+#define CUST_COMBO_WIFI_DEV "/dev/wmtWifi"
+#define POWER_ON_WIFI "AP"
+#define POWER_ON_WIFI_LEN 2
+#else
+#define CUST_COMBO_WIFI_DEV "/dev/wmtWifi"
+#define POWER_ON_WIFI "1"
+#define POWER_ON_WIFI_LEN 1
+#endif
+
+/******************************************************************************
+* D A T A T Y P E S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* M A C R O S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* P U B L I C D A T A
+*******************************************************************************
+*/
+
+/******************************************************************************
+* P R I V A T E D A T A
+*******************************************************************************
+*/
+
+static int gWifiFd = -1;
+
+/******************************************************************************
+* F U N C T I O N S
+*******************************************************************************
+*/
+int main(int argc, char *argv[]) {
+ int retryCounter = 0;
+ int i_ret = -1;
+
+ gWifiFd = open(CUST_COMBO_WIFI_DEV, O_RDWR | O_NOCTTY);
+ do {
+ if (gWifiFd < 0) {
+ ALOGI("Can't open device node(%s) error:%d \n", CUST_COMBO_WIFI_DEV, gWifiFd);
+ usleep(300000);
+ } else {
+ break;
+ }
+ retryCounter++;
+ } while (retryCounter < 20);
+
+ if (gWifiFd > 0) {
+ do {
+ i_ret = write(gWifiFd, POWER_ON_WIFI, POWER_ON_WIFI_LEN);
+ if (i_ret == 1) {
+ ALOGI("Power on device node(%s) gWifiFd:%d succeed !!\n", CUST_COMBO_WIFI_DEV, gWifiFd);
+ break;
+ } else {
+ ALOGI("Power on device node(%s) gWifiFd:%d Fail (%d) and retry\n", CUST_COMBO_WIFI_DEV, gWifiFd, i_ret);
+ }
+ retryCounter++;
+ usleep(1000000);
+ } while (retryCounter < 20);
+ }
+ close(gWifiFd);
+
+ return 0;
+}
diff --git a/src/connectivity/combo_tool/src/serial.h b/src/connectivity/combo_tool/src/serial.h
new file mode 100755
index 0000000..4e6b745
--- /dev/null
+++ b/src/connectivity/combo_tool/src/serial.h
@@ -0,0 +1,79 @@
+/* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2014. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* The following software/firmware and/or related documentation ("MediaTek
+* Software") have been modified by MediaTek Inc. All revisions are subject to
+* any receiver's applicable license agreements with MediaTek Inc.
+*/
+
+#ifndef _LINUX_SERIAL_H
+#define _LINUX_SERIAL_H
+
+struct serial_struct {
+ int type;
+ int line;
+ unsigned int port;
+ int irq;
+ int flags;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int baud_base;
+ unsigned short close_delay;
+ char io_type;
+ char reserved_char[1];
+ int hub6;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned char *iomem_base;
+ unsigned short iomem_reg_shift;
+ unsigned int port_high;
+ unsigned long iomap_base;
+};
+
+#define ASYNCB_HUP_NOTIFY 0
+#define ASYNCB_FOURPORT 1
+#define ASYNCB_SAK 2
+#define ASYNCB_SPLIT_TERMIOS 3
+#define ASYNCB_SPD_HI 4
+#define ASYNCB_SPD_VHI 5
+#define ASYNCB_SKIP_TEST 6
+#define ASYNCB_AUTO_IRQ 7
+#define ASYNCB_SESSION_LOCKOUT 8
+#define ASYNCB_PGRP_LOCKOUT 9
+#define ASYNCB_CALLOUT_NOHUP 10
+#define ASYNCB_HARDPPS_CD 11
+#define ASYNCB_SPD_SHI 12
+#define ASYNCB_LOW_LATENCY 13
+#define ASYNCB_BUGGY_UART 14
+#define ASYNCB_AUTOPROBE 15
+
+#endif /* _LINUX_SERIAL_H */
diff --git a/src/connectivity/combo_tool/src/stp_dump/eloop.c b/src/connectivity/combo_tool/src/stp_dump/eloop.c
new file mode 100755
index 0000000..586091d
--- /dev/null
+++ b/src/connectivity/combo_tool/src/stp_dump/eloop.c
@@ -0,0 +1,649 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ */
+
+/*
+ * Event loop based on select() loop
+ * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include <sys/stat.h>
+#include <grp.h>
+#include <stddef.h>
+//#include <cutils/sockets.h>
+//#include <android/log.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <dirent.h>
+//#include <cutils/properties.h>
+#include <sys/un.h>
+#include <dirent.h>
+#include <linux/limits.h>
+//#include <cutils/sockets.h>
+//#include <cutils/memory.h>
+
+#include "os_linux.h"
+#include "stp_dump.h"
+#include "eloop.h"
+
+struct eloop_sock {
+ int sock;
+ void *eloop_data;
+ void *user_data;
+ eloop_sock_handler handler;
+};
+
+struct eloop_timeout {
+ struct os_time time;
+ void *eloop_data;
+ void *user_data;
+ eloop_timeout_handler handler;
+ struct eloop_timeout *next;
+};
+
+struct eloop_signal {
+ int sig;
+ void *user_data;
+ eloop_signal_handler handler;
+ int signaled;
+};
+
+struct eloop_sock_table {
+ int count;
+ struct eloop_sock *table;
+ int changed;
+};
+
+struct eloop_data {
+ void *user_data;
+
+ int max_sock;
+
+ struct eloop_sock_table readers;
+ struct eloop_sock_table writers;
+ struct eloop_sock_table exceptions;
+
+ struct eloop_timeout *timeout;
+
+ int signal_count;
+ struct eloop_signal *signals;
+ int signaled;
+ int pending_terminate;
+
+ int terminate;
+ int reader_table_changed;
+};
+
+static struct eloop_data eloop;
+
+
+int eloop_init(void *user_data)
+{
+ os_memset(&eloop, 0, sizeof(eloop));
+ eloop.user_data = user_data;
+ return 0;
+}
+
+
+static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
+ int sock, eloop_sock_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_sock *tmp;
+
+ if (table == NULL)
+ {
+ ALOGI("table = NULL\n");
+ return -1;
+ }
+ tmp = (struct eloop_sock *)
+ os_realloc(table->table,
+ (table->count + 1) * sizeof(struct eloop_sock));
+ if (tmp == NULL)
+ {
+ ALOGI( "memory allocation for eloop_sock failed\n");
+ return -1;
+ }
+ tmp[table->count].sock = sock;
+ tmp[table->count].eloop_data = eloop_data;
+ tmp[table->count].user_data = user_data;
+ tmp[table->count].handler = handler;
+ table->count++;
+ table->table = tmp;
+ if (sock > eloop.max_sock)
+ {
+ eloop.max_sock = sock;
+ ALOGI("set sock number to %d\n", eloop.max_sock);
+ }
+ table->changed = 1;
+
+ return 0;
+}
+
+
+static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
+ int sock)
+{
+ int i;
+
+ if (table == NULL || table->table == NULL || table->count == 0)
+ return;
+
+ for (i = 0; i < table->count; i++) {
+ if (table->table[i].sock == sock)
+ break;
+ }
+ if (i == table->count)
+ return;
+ if (i != table->count - 1) {
+ os_memmove(&table->table[i], &table->table[i + 1],
+ (table->count - i - 1) *
+ sizeof(struct eloop_sock));
+ }
+ table->count--;
+ table->changed = 1;
+}
+
+
+static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
+ fd_set *fds)
+{
+ int i;
+
+ FD_ZERO(fds);
+
+ if (table->table == NULL)
+ return;
+
+ for (i = 0; i < table->count; i++)
+ FD_SET(table->table[i].sock, fds);
+}
+
+
+static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
+ fd_set *fds)
+{
+ int i;
+
+ if (table == NULL || table->table == NULL)
+ {
+ /*stp_printf(MSG_ERROR, "table == NULL || table->table == NULL\n");*/
+ return;
+ }
+ table->changed = 0;
+ for (i = 0; i < table->count; i++) {
+ if (FD_ISSET(table->table[i].sock, fds)) {
+ table->table[i].handler(table->table[i].sock,
+ table->table[i].eloop_data,
+ table->table[i].user_data);
+ if (table->changed)
+ break;
+ }
+ }
+}
+
+
+static void eloop_sock_table_destroy(struct eloop_sock_table *table)
+{
+ if (table) {
+ int i;
+ for (i = 0; i < table->count && table->table; i++) {
+ printf("ELOOP: remaining socket: sock=%d "
+ "eloop_data=%p user_data=%p handler=%p\n",
+ table->table[i].sock,
+ table->table[i].eloop_data,
+ table->table[i].user_data,
+ table->table[i].handler);
+ }
+ os_free(table->table);
+ }
+}
+
+
+int eloop_register_read_sock(int sock, eloop_sock_handler handler,
+ void *eloop_data, void *user_data)
+{
+ return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
+ eloop_data, user_data);
+}
+
+
+void eloop_unregister_read_sock(int sock)
+{
+ eloop_unregister_sock(sock, EVENT_TYPE_READ);
+}
+
+
+static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
+{
+ switch (type) {
+ case EVENT_TYPE_READ:
+ return &eloop.readers;
+ case EVENT_TYPE_WRITE:
+ return &eloop.writers;
+ case EVENT_TYPE_EXCEPTION:
+ return &eloop.exceptions;
+ }
+ ALOGE("tyep (%d) error\n", type);
+ return NULL;
+}
+
+
+int eloop_register_sock(int sock, eloop_event_type type,
+ eloop_sock_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_sock_table *table;
+
+ table = eloop_get_sock_table(type);
+ return eloop_sock_table_add_sock(table, sock, handler,
+ eloop_data, user_data);
+}
+
+
+void eloop_unregister_sock(int sock, eloop_event_type type)
+{
+ struct eloop_sock_table *table;
+
+ table = eloop_get_sock_table(type);
+ eloop_sock_table_remove_sock(table, sock);
+}
+
+
+int eloop_register_timeout(unsigned int secs, unsigned int usecs,
+ eloop_timeout_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_timeout *timeout, *tmp, *prev;
+
+ timeout = os_malloc(sizeof(*timeout));
+ if (timeout == NULL)
+ return -1;
+ if (os_get_time(&timeout->time) < 0) {
+ os_free(timeout);
+ return -1;
+ }
+ timeout->time.sec += secs;
+ timeout->time.usec += usecs;
+ while (timeout->time.usec >= 1000000) {
+ timeout->time.sec++;
+ timeout->time.usec -= 1000000;
+ }
+ timeout->eloop_data = eloop_data;
+ timeout->user_data = user_data;
+ timeout->handler = handler;
+ timeout->next = NULL;
+
+ if (eloop.timeout == NULL) {
+ eloop.timeout = timeout;
+ return 0;
+ }
+
+ prev = NULL;
+ tmp = eloop.timeout;
+ while (tmp != NULL) {
+ if (os_time_before(&timeout->time, &tmp->time))
+ break;
+ prev = tmp;
+ tmp = tmp->next;
+ }
+
+ if (prev == NULL) {
+ timeout->next = eloop.timeout;
+ eloop.timeout = timeout;
+ } else {
+ timeout->next = prev->next;
+ prev->next = timeout;
+ }
+
+ return 0;
+}
+
+
+int eloop_cancel_timeout(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_timeout *timeout, *prev, *next;
+ int removed = 0;
+
+ prev = NULL;
+ timeout = eloop.timeout;
+ while (timeout != NULL) {
+ next = timeout->next;
+
+ if (timeout->handler == handler &&
+ (timeout->eloop_data == eloop_data ||
+ eloop_data == ELOOP_ALL_CTX) &&
+ (timeout->user_data == user_data ||
+ user_data == ELOOP_ALL_CTX)) {
+ if (prev == NULL)
+ eloop.timeout = next;
+ else
+ prev->next = next;
+ os_free(timeout);
+ removed++;
+ } else
+ prev = timeout;
+
+ timeout = next;
+ }
+
+ return removed;
+}
+
+
+int eloop_is_timeout_registered(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_timeout *tmp;
+
+ tmp = eloop.timeout;
+ while (tmp != NULL) {
+ if (tmp->handler == handler &&
+ tmp->eloop_data == eloop_data &&
+ tmp->user_data == user_data)
+ return 1;
+
+ tmp = tmp->next;
+ }
+
+ return 0;
+}
+
+
+#ifndef CONFIG_NATIVE_WINDOWS
+static void eloop_handle_alarm(int sig)
+{
+ fprintf(stderr, "eloop: could not process SIGINT or SIGTERM in two "
+ "seconds. Looks like there\n"
+ "is a bug that ends up in a busy loop that "
+ "prevents clean shutdown.\n"
+ "Killing program forcefully.\n");
+ exit(1);
+}
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+
+static void eloop_handle_signal(int sig)
+{
+ int i;
+
+#ifndef CONFIG_NATIVE_WINDOWS
+ if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
+ /* Use SIGALRM to break out from potential busy loops that
+ * would not allow the program to be killed. */
+ eloop.pending_terminate = 1;
+ signal(SIGALRM, eloop_handle_alarm);
+ alarm(2);
+ }
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+ eloop.signaled++;
+ for (i = 0; i < eloop.signal_count; i++) {
+ if (eloop.signals[i].sig == sig) {
+ eloop.signals[i].signaled++;
+ break;
+ }
+ }
+}
+
+
+static void eloop_process_pending_signals(void)
+{
+ int i;
+
+ if (eloop.signaled == 0)
+ return;
+ eloop.signaled = 0;
+
+ if (eloop.pending_terminate) {
+#ifndef CONFIG_NATIVE_WINDOWS
+ alarm(0);
+#endif /* CONFIG_NATIVE_WINDOWS */
+ eloop.pending_terminate = 0;
+ }
+
+ for (i = 0; i < eloop.signal_count; i++) {
+ if (eloop.signals[i].signaled) {
+ eloop.signals[i].signaled = 0;
+ eloop.signals[i].handler(eloop.signals[i].sig,
+ eloop.user_data,
+ eloop.signals[i].user_data);
+ }
+ }
+}
+
+
+int eloop_register_signal(int sig, eloop_signal_handler handler,
+ void *user_data)
+{
+ struct eloop_signal *tmp;
+
+ tmp = (struct eloop_signal *)
+ os_realloc(eloop.signals,
+ (eloop.signal_count + 1) *
+ sizeof(struct eloop_signal));
+ if (tmp == NULL)
+ return -1;
+
+ tmp[eloop.signal_count].sig = sig;
+ tmp[eloop.signal_count].user_data = user_data;
+ tmp[eloop.signal_count].handler = handler;
+ tmp[eloop.signal_count].signaled = 0;
+ eloop.signal_count++;
+ eloop.signals = tmp;
+ signal(sig, eloop_handle_signal);
+
+ return 0;
+}
+
+
+int eloop_register_signal_terminate(eloop_signal_handler handler,
+ void *user_data)
+{
+ int ret = eloop_register_signal(SIGINT, handler, user_data);
+ if (ret == 0)
+ ret = eloop_register_signal(SIGTERM, handler, user_data);
+ if (ret == 0)
+ ret = eloop_register_signal(SIGSEGV, handler, user_data);
+ return ret;
+}
+
+
+int eloop_register_signal_reconfig(eloop_signal_handler handler,
+ void *user_data)
+{
+#ifdef CONFIG_NATIVE_WINDOWS
+ return 0;
+#else /* CONFIG_NATIVE_WINDOWS */
+ return eloop_register_signal(SIGHUP, handler, user_data);
+#endif /* CONFIG_NATIVE_WINDOWS */
+}
+
+
+void eloop_run(void)
+{
+ fd_set *rfds, *wfds, *efds;
+ int res;
+ struct timeval _tv;
+ struct os_time tv, now;
+
+ rfds = os_malloc(sizeof(*rfds));
+ wfds = os_malloc(sizeof(*wfds));
+ efds = os_malloc(sizeof(*efds));
+ if (rfds == NULL || wfds == NULL || efds == NULL) {
+ ALOGE("eloop_run - malloc failed\n");
+ goto out;
+ }
+
+ while (!eloop.terminate &&
+ (eloop.timeout || eloop.readers.count > 0 ||
+ eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
+ if (eloop.timeout) {
+ os_get_time(&now);
+ if (os_time_before(&now, &eloop.timeout->time))
+ os_time_sub(&eloop.timeout->time, &now, &tv);
+ else
+ tv.sec = tv.usec = 0;
+#if 1
+ printf("next timeout in %lu.%06lu sec\n",
+ tv.sec, tv.usec);
+#endif
+ _tv.tv_sec = tv.sec;
+ _tv.tv_usec = tv.usec;
+ }
+
+ eloop_sock_table_set_fds(&eloop.readers, rfds);
+ eloop_sock_table_set_fds(&eloop.writers, wfds);
+ eloop_sock_table_set_fds(&eloop.exceptions, efds);
+ res = select(eloop.max_sock + 1, rfds, wfds, efds,
+ eloop.timeout ? &_tv : NULL);
+ if (res < 0 && errno != EINTR && errno != 0) {
+ perror("select");
+ ALOGE("select on socket failed\n");
+ goto out;
+ }
+ eloop_process_pending_signals();
+
+ /* check if some registered timeouts have occurred */
+ if (eloop.timeout) {
+ struct eloop_timeout *tmp;
+
+ os_get_time(&now);
+ if (!os_time_before(&now, &eloop.timeout->time)) {
+ tmp = eloop.timeout;
+ eloop.timeout = eloop.timeout->next;
+ tmp->handler(tmp->eloop_data,
+ tmp->user_data);
+ os_free(tmp);
+ }
+
+ }
+
+ if (res <= 0)
+ continue;
+
+ eloop_sock_table_dispatch(&eloop.readers, rfds);
+ eloop_sock_table_dispatch(&eloop.writers, wfds);
+ eloop_sock_table_dispatch(&eloop.exceptions, efds);
+ }
+
+out:
+ ALOGI("eloop_run exit\n");
+ os_free(rfds);
+ os_free(wfds);
+ os_free(efds);
+}
+
+
+void eloop_terminate(void)
+{
+ eloop.terminate = 1;
+}
+
+
+void eloop_destroy(void)
+{
+ struct eloop_timeout *timeout, *prev;
+ struct os_time now;
+
+ timeout = eloop.timeout;
+ if (timeout)
+ os_get_time(&now);
+ while (timeout != NULL) {
+ int sec, usec;
+ prev = timeout;
+ timeout = timeout->next;
+ sec = prev->time.sec - now.sec;
+ usec = prev->time.usec - now.usec;
+ if (prev->time.usec < now.usec) {
+ sec--;
+ usec += 1000000;
+ }
+ printf("ELOOP: remaining timeout: %d.%06d eloop_data=%p "
+ "user_data=%p handler=%p\n",
+ sec, usec, prev->eloop_data, prev->user_data,
+ prev->handler);
+ os_free(prev);
+ }
+ eloop_sock_table_destroy(&eloop.readers);
+ eloop_sock_table_destroy(&eloop.writers);
+ eloop_sock_table_destroy(&eloop.exceptions);
+ os_free(eloop.signals);
+}
+
+
+int eloop_terminated(void)
+{
+ return eloop.terminate;
+}
+
+
+void eloop_wait_for_read_sock(int sock)
+{
+ fd_set rfds;
+
+ if (sock < 0)
+ return;
+
+ FD_ZERO(&rfds);
+ FD_SET(sock, &rfds);
+ select(sock + 1, &rfds, NULL, NULL, NULL);
+}
+
+
+void * eloop_get_user_data(void)
+{
+ return eloop.user_data;
+}
diff --git a/src/connectivity/combo_tool/src/stp_dump/eloop.h b/src/connectivity/combo_tool/src/stp_dump/eloop.h
new file mode 100755
index 0000000..333ee08
--- /dev/null
+++ b/src/connectivity/combo_tool/src/stp_dump/eloop.h
@@ -0,0 +1,375 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ */
+
+/*
+ * Event loop
+ * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ *
+ * This file defines an event loop interface that supports processing events
+ * from registered timeouts (i.e., do something after N seconds), sockets
+ * (e.g., a new packet available for reading), and signals. eloop.c is an
+ * implementation of this interface using select() and sockets. This is
+ * suitable for most UNIX/POSIX systems. When porting to other operating
+ * systems, it may be necessary to replace that implementation with OS specific
+ * mechanisms.
+ */
+
+#ifndef ELOOP_H
+#define ELOOP_H
+
+/**
+ * ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts
+ */
+#define ELOOP_ALL_CTX (void *) -1
+
+/**
+ * eloop_event_type - eloop socket event type for eloop_register_sock()
+ * @EVENT_TYPE_READ: Socket has data available for reading
+ * @EVENT_TYPE_WRITE: Socket has room for new data to be written
+ * @EVENT_TYPE_EXCEPTION: An exception has been reported
+ */
+typedef enum {
+ EVENT_TYPE_READ = 0,
+ EVENT_TYPE_WRITE,
+ EVENT_TYPE_EXCEPTION
+} eloop_event_type;
+
+
+
+
+
+/**
+ * eloop_sock_handler - eloop socket event callback type
+ * @sock: File descriptor number for the socket
+ * @eloop_ctx: Registered callback context data (eloop_data)
+ * @sock_ctx: Registered callback context data (user_data)
+ */
+typedef void (*eloop_sock_handler)(int sock, void *eloop_ctx, void *sock_ctx);
+
+/**
+ * eloop_event_handler - eloop generic event callback type
+ * @eloop_ctx: Registered callback context data (eloop_data)
+ * @sock_ctx: Registered callback context data (user_data)
+ */
+typedef void (*eloop_event_handler)(void *eloop_data, void *user_ctx);
+
+/**
+ * eloop_timeout_handler - eloop timeout event callback type
+ * @eloop_ctx: Registered callback context data (eloop_data)
+ * @sock_ctx: Registered callback context data (user_data)
+ */
+typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx);
+
+/**
+ * eloop_signal_handler - eloop signal event callback type
+ * @sig: Signal number
+ * @eloop_ctx: Registered callback context data (global user_data from
+ * eloop_init() call)
+ * @signal_ctx: Registered callback context data (user_data from
+ * eloop_register_signal(), eloop_register_signal_terminate(), or
+ * eloop_register_signal_reconfig() call)
+ */
+typedef void (*eloop_signal_handler)(int sig, void *eloop_ctx,
+ void *signal_ctx);
+
+/**
+ * eloop_init() - Initialize global event loop data
+ * @user_data: Pointer to global data passed as eloop_ctx to signal handlers
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function must be called before any other eloop_* function. user_data
+ * can be used to configure a global (to the process) pointer that will be
+ * passed as eloop_ctx parameter to signal handlers.
+ */
+int eloop_init(void *user_data);
+
+/**
+ * eloop_register_read_sock - Register handler for read events
+ * @sock: File descriptor number for the socket
+ * @handler: Callback function to be called when data is available for reading
+ * @eloop_data: Callback context data (eloop_ctx)
+ * @user_data: Callback context data (sock_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a read socket notifier for the given file descriptor. The handler
+ * function will be called whenever data is available for reading from the
+ * socket. The handler function is responsible for clearing the event after
+ * having processed it in order to avoid eloop from calling the handler again
+ * for the same event.
+ */
+int eloop_register_read_sock(int sock, eloop_sock_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_unregister_read_sock - Unregister handler for read events
+ * @sock: File descriptor number for the socket
+ *
+ * Unregister a read socket notifier that was previously registered with
+ * eloop_register_read_sock().
+ */
+void eloop_unregister_read_sock(int sock);
+
+/**
+ * eloop_register_sock - Register handler for socket events
+ * @sock: File descriptor number for the socket
+ * @type: Type of event to wait for
+ * @handler: Callback function to be called when the event is triggered
+ * @eloop_data: Callback context data (eloop_ctx)
+ * @user_data: Callback context data (sock_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register an event notifier for the given socket's file descriptor. The
+ * handler function will be called whenever the that event is triggered for the
+ * socket. The handler function is responsible for clearing the event after
+ * having processed it in order to avoid eloop from calling the handler again
+ * for the same event.
+ */
+int eloop_register_sock(int sock, eloop_event_type type,
+ eloop_sock_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_unregister_sock - Unregister handler for socket events
+ * @sock: File descriptor number for the socket
+ * @type: Type of event for which sock was registered
+ *
+ * Unregister a socket event notifier that was previously registered with
+ * eloop_register_sock().
+ */
+void eloop_unregister_sock(int sock, eloop_event_type type);
+
+/**
+ * eloop_register_event - Register handler for generic events
+ * @event: Event to wait (eloop implementation specific)
+ * @event_size: Size of event data
+ * @handler: Callback function to be called when event is triggered
+ * @eloop_data: Callback context data (eloop_data)
+ * @user_data: Callback context data (user_data)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register an event handler for the given event. This function is used to
+ * register eloop implementation specific events which are mainly targetted for
+ * operating system specific code (driver interface and l2_packet) since the
+ * portable code will not be able to use such an OS-specific call. The handler
+ * function will be called whenever the event is triggered. The handler
+ * function is responsible for clearing the event after having processed it in
+ * order to avoid eloop from calling the handler again for the same event.
+ *
+ * In case of Windows implementation (eloop_win.c), event pointer is of HANDLE
+ * type, i.e., void*. The callers are likely to have 'HANDLE h' type variable,
+ * and they would call this function with eloop_register_event(h, sizeof(h),
+ * ...).
+ */
+int eloop_register_event(void *event, size_t event_size,
+ eloop_event_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_unregister_event - Unregister handler for a generic event
+ * @event: Event to cancel (eloop implementation specific)
+ * @event_size: Size of event data
+ *
+ * Unregister a generic event notifier that was previously registered with
+ * eloop_register_event().
+ */
+void eloop_unregister_event(void *event, size_t event_size);
+
+/**
+ * eloop_register_timeout - Register timeout
+ * @secs: Number of seconds to the timeout
+ * @usecs: Number of microseconds to the timeout
+ * @handler: Callback function to be called when timeout occurs
+ * @eloop_data: Callback context data (eloop_ctx)
+ * @user_data: Callback context data (sock_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a timeout that will cause the handler function to be called after
+ * given time.
+ */
+int eloop_register_timeout(unsigned int secs, unsigned int usecs,
+ eloop_timeout_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_cancel_timeout - Cancel timeouts
+ * @handler: Matching callback function
+ * @eloop_data: Matching eloop_data or %ELOOP_ALL_CTX to match all
+ * @user_data: Matching user_data or %ELOOP_ALL_CTX to match all
+ * Returns: Number of cancelled timeouts
+ *
+ * Cancel matching <handler,eloop_data,user_data> timeouts registered with
+ * eloop_register_timeout(). ELOOP_ALL_CTX can be used as a wildcard for
+ * cancelling all timeouts regardless of eloop_data/user_data.
+ */
+int eloop_cancel_timeout(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_is_timeout_registered - Check if a timeout is already registered
+ * @handler: Matching callback function
+ * @eloop_data: Matching eloop_data
+ * @user_data: Matching user_data
+ * Returns: 1 if the timeout is registered, 0 if the timeout is not registered
+ *
+ * Determine if a matching <handler,eloop_data,user_data> timeout is registered
+ * with eloop_register_timeout().
+ */
+int eloop_is_timeout_registered(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
+ * eloop_register_signal - Register handler for signals
+ * @sig: Signal number (e.g., SIGHUP)
+ * @handler: Callback function to be called when the signal is received
+ * @user_data: Callback context data (signal_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a callback function that will be called when a signal is received.
+ * The callback function is actually called only after the system signal
+ * handler has returned. This means that the normal limits for sighandlers
+ * (i.e., only "safe functions" allowed) do not apply for the registered
+ * callback.
+ *
+ * Signals are 'global' events and there is no local eloop_data pointer like
+ * with other handlers. The global user_data pointer registered with
+ * eloop_init() will be used as eloop_ctx for signal handlers.
+ */
+int eloop_register_signal(int sig, eloop_signal_handler handler,
+ void *user_data);
+
+/**
+ * eloop_register_signal_terminate - Register handler for terminate signals
+ * @handler: Callback function to be called when the signal is received
+ * @user_data: Callback context data (signal_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a callback function that will be called when a process termination
+ * signal is received. The callback function is actually called only after the
+ * system signal handler has returned. This means that the normal limits for
+ * sighandlers (i.e., only "safe functions" allowed) do not apply for the
+ * registered callback.
+ *
+ * Signals are 'global' events and there is no local eloop_data pointer like
+ * with other handlers. The global user_data pointer registered with
+ * eloop_init() will be used as eloop_ctx for signal handlers.
+ *
+ * This function is a more portable version of eloop_register_signal() since
+ * the knowledge of exact details of the signals is hidden in eloop
+ * implementation. In case of operating systems using signal(), this function
+ * registers handlers for SIGINT and SIGTERM.
+ */
+int eloop_register_signal_terminate(eloop_signal_handler handler,
+ void *user_data);
+
+/**
+ * eloop_register_signal_reconfig - Register handler for reconfig signals
+ * @handler: Callback function to be called when the signal is received
+ * @user_data: Callback context data (signal_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a callback function that will be called when a reconfiguration /
+ * hangup signal is received. The callback function is actually called only
+ * after the system signal handler has returned. This means that the normal
+ * limits for sighandlers (i.e., only "safe functions" allowed) do not apply
+ * for the registered callback.
+ *
+ * Signals are 'global' events and there is no local eloop_data pointer like
+ * with other handlers. The global user_data pointer registered with
+ * eloop_init() will be used as eloop_ctx for signal handlers.
+ *
+ * This function is a more portable version of eloop_register_signal() since
+ * the knowledge of exact details of the signals is hidden in eloop
+ * implementation. In case of operating systems using signal(), this function
+ * registers a handler for SIGHUP.
+ */
+int eloop_register_signal_reconfig(eloop_signal_handler handler,
+ void *user_data);
+
+/**
+ * eloop_run - Start the event loop
+ *
+ * Start the event loop and continue running as long as there are any
+ * registered event handlers. This function is run after event loop has been
+ * initialized with event_init() and one or more events have been registered.
+ */
+void eloop_run(void);
+
+/**
+ * eloop_terminate - Terminate event loop
+ *
+ * Terminate event loop even if there are registered events. This can be used
+ * to request the program to be terminated cleanly.
+ */
+void eloop_terminate(void);
+
+/**
+ * eloop_destroy - Free any resources allocated for the event loop
+ *
+ * After calling eloop_destroy(), other eloop_* functions must not be called
+ * before re-running eloop_init().
+ */
+void eloop_destroy(void);
+
+/**
+ * eloop_terminated - Check whether event loop has been terminated
+ * Returns: 1 = event loop terminate, 0 = event loop still running
+ *
+ * This function can be used to check whether eloop_terminate() has been called
+ * to request termination of the event loop. This is normally used to abort
+ * operations that may still be queued to be run when eloop_terminate() was
+ * called.
+ */
+int eloop_terminated(void);
+
+/**
+ * eloop_wait_for_read_sock - Wait for a single reader
+ * @sock: File descriptor number for the socket
+ *
+ * Do a blocking wait for a single read socket.
+ */
+void eloop_wait_for_read_sock(int sock);
+
+/**
+ * eloop_get_user_data - Get global user data
+ * Returns: user_data pointer that was registered with eloop_init()
+ */
+void * eloop_get_user_data(void);
+
+#endif /* ELOOP_H */
diff --git a/src/connectivity/combo_tool/src/stp_dump/os_linux.c b/src/connectivity/combo_tool/src/stp_dump/os_linux.c
new file mode 100755
index 0000000..288b7a2
--- /dev/null
+++ b/src/connectivity/combo_tool/src/stp_dump/os_linux.c
@@ -0,0 +1,492 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <dirent.h>
+//#include <cutils/properties.h>
+#include <sys/un.h>
+#include <dirent.h>
+#include "os_linux.h"
+
+void os_sleep(os_time_t sec, os_time_t usec)
+{
+ if (sec)
+ sleep(sec);
+ if (usec)
+ usleep(usec);
+}
+
+int os_get_time(struct os_time *t)
+{
+ int res;
+ struct timeval tv;
+ res = gettimeofday(&tv, NULL);
+ t->sec = tv.tv_sec;
+ t->usec = tv.tv_usec;
+ return res;
+}
+
+
+int os_mktime(int year, int month, int day, int hour, int min, int sec,
+ os_time_t *t)
+{
+ struct tm tm;
+
+ if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
+ hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
+ sec > 60)
+ return -1;
+
+ os_memset(&tm, 0, sizeof(tm));
+ tm.tm_year = year - 1900;
+ tm.tm_mon = month - 1;
+ tm.tm_mday = day;
+ tm.tm_hour = hour;
+ tm.tm_min = min;
+ tm.tm_sec = sec;
+
+ *t = (os_time_t) mktime(&tm);
+ return 0;
+}
+
+
+int os_daemonize(const char *pid_file)
+{
+ if (daemon(0, 0)) {
+ perror("daemon");
+ return -1;
+ }
+
+ if (pid_file) {
+ FILE *f = fopen(pid_file, "w");
+ if (f) {
+ fprintf(f, "%u\n", getpid());
+ fclose(f);
+ }
+ }
+
+ return -0;
+}
+
+
+void os_daemonize_terminate(const char *pid_file)
+{
+ if (pid_file)
+ unlink(pid_file);
+}
+
+
+int os_get_random(unsigned char *buf, size_t len)
+{
+ FILE *f;
+ size_t rc;
+
+ f = fopen("/dev/urandom", "rb");
+ if (f == NULL) {
+ printf("Could not open /dev/urandom.\n");
+ return -1;
+ }
+
+ rc = fread(buf, 1, len, f);
+ fclose(f);
+
+ return rc != len ? -1 : 0;
+}
+
+
+unsigned long os_random(void)
+{
+ return random();
+}
+
+
+char * os_rel2abs_path(const char *rel_path)
+{
+ char *buf = NULL, *cwd, *ret;
+ size_t len = 128, cwd_len, rel_len, ret_len;
+
+ if (rel_path[0] == '/')
+ return os_strdup(rel_path);
+
+ for (;;) {
+ buf = os_malloc(len);
+ if (buf == NULL)
+ return NULL;
+ cwd = getcwd(buf, len);
+ if (cwd == NULL) {
+ os_free(buf);
+ if (errno != ERANGE) {
+ return NULL;
+ }
+ len *= 2;
+ } else {
+ break;
+ }
+ }
+
+ cwd_len = strlen(cwd);
+ rel_len = strlen(rel_path);
+ ret_len = cwd_len + 1 + rel_len + 1;
+ ret = os_malloc(ret_len);
+ if (ret) {
+ os_memcpy(ret, cwd, cwd_len);
+ ret[cwd_len] = '/';
+ os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
+ ret[ret_len - 1] = '\0';
+ }
+ os_free(buf);
+ return ret;
+}
+
+
+int os_program_init(void)
+{
+ return 0;
+}
+
+
+void os_program_deinit(void)
+{
+}
+
+
+int os_setenv(const char *name, const char *value, int overwrite)
+{
+ return setenv(name, value, overwrite);
+}
+
+
+int os_unsetenv(const char *name)
+{
+ return unsetenv(name);
+}
+
+
+char * os_readfile(const char *name, size_t *len)
+{
+ FILE *f;
+ char *buf;
+
+ f = fopen(name, "rb");
+ if (f == NULL)
+ return NULL;
+
+ fseek(f, 0, SEEK_END);
+ *len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ buf = os_malloc(*len);
+ if (buf == NULL) {
+ fclose(f);
+ return NULL;
+ }
+
+ fread(buf, 1, *len, f);
+ fclose(f);
+
+ return buf;
+}
+
+
+void * os_zalloc(size_t size)
+{
+ void *n = os_malloc(size);
+ if (n)
+ os_memset(n, 0, size);
+ return n;
+}
+
+
+void * os_malloc(size_t size)
+{
+ return malloc(size);
+}
+
+
+void * os_realloc(void *ptr, size_t size)
+{
+ return realloc(ptr, size);
+}
+
+
+void os_free(void *ptr)
+{
+ free(ptr);
+}
+
+
+void * os_memcpy(void *dest, const void *src, size_t n)
+{
+ char *d = dest;
+ const char *s = src;
+ while (n--)
+ *d++ = *s++;
+ return dest;
+}
+
+
+void * os_memmove(void *dest, const void *src, size_t n)
+{
+ if (dest < src)
+ os_memcpy(dest, src, n);
+ else {
+ /* overlapping areas */
+ char *d = (char *) dest + n;
+ const char *s = (const char *) src + n;
+ while (n--)
+ *--d = *--s;
+ }
+ return dest;
+}
+
+
+void * os_memset(void *s, int c, size_t n)
+{
+ char *p = s;
+ while (n--)
+ *p++ = c;
+ return s;
+}
+
+
+int os_memcmp(const void *s1, const void *s2, size_t n)
+{
+ const unsigned char *p1 = s1, *p2 = s2;
+
+ if (n == 0)
+ return 0;
+
+ while (*p1 == *p2) {
+ p1++;
+ p2++;
+ n--;
+ if (n == 0)
+ return 0;
+ }
+
+ return *p1 - *p2;
+}
+
+
+char * os_strdup(const char *s)
+{
+ char *res;
+ size_t len;
+ if (s == NULL)
+ return NULL;
+ len = os_strlen(s);
+ res = os_malloc(len + 1);
+ if (res)
+ os_memcpy(res, s, len + 1);
+ return res;
+}
+
+
+size_t os_strlen(const char *s)
+{
+ const char *p = s;
+ while (*p)
+ p++;
+ return p - s;
+}
+
+
+int os_strcasecmp(const char *s1, const char *s2)
+{
+ /*
+ * Ignoring case is not required for main functionality, so just use
+ * the case sensitive version of the function.
+ */
+ return os_strcmp(s1, s2);
+}
+
+
+int os_strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ /*
+ * Ignoring case is not required for main functionality, so just use
+ * the case sensitive version of the function.
+ */
+ return os_strncmp(s1, s2, n);
+}
+
+
+char * os_strchr(const char *s, int c)
+{
+ while (*s) {
+ if (*s == c)
+ return (char *) s;
+ s++;
+ //printf("==>s = %p\n", s);
+ }
+ return NULL;
+}
+
+
+char * os_strrchr(const char *s, int c)
+{
+ const char *p = s;
+ while (*p)
+ p++;
+ p--;
+ while (p >= s) {
+ if (*p == c)
+ return (char *) p;
+ p--;
+ }
+ return NULL;
+}
+
+
+int os_strcmp(const char *s1, const char *s2)
+{
+ while (*s1 == *s2) {
+ if (*s1 == '\0')
+ break;
+ s1++;
+ s2++;
+ }
+
+ return *s1 - *s2;
+}
+
+
+int os_strncmp(const char *s1, const char *s2, size_t n)
+{
+ if (n == 0)
+ return 0;
+
+ while (*s1 == *s2) {
+ if (*s1 == '\0')
+ break;
+ s1++;
+ s2++;
+ n--;
+ if (n == 0)
+ return 0;
+ }
+
+ return *s1 - *s2;
+}
+
+
+char * os_strncpy(char *dest, const char *src, size_t n)
+{
+ char *d = dest;
+
+ while (n--) {
+ *d = *src;
+ if (*src == '\0')
+ break;
+ d++;
+ src++;
+ }
+
+ return dest;
+}
+
+
+size_t os_strlcpy(char *dest, const char *src, size_t siz)
+{
+ const char *s = src;
+ size_t left = siz;
+
+ if (left) {
+ /* Copy string up to the maximum size of the dest buffer */
+ while (--left != 0) {
+ if ((*dest++ = *s++) == '\0')
+ break;
+ }
+ }
+
+ if (left == 0) {
+ /* Not enough room for the string; force NUL-termination */
+ if (siz != 0)
+ *dest = '\0';
+ while (*s++)
+ ; /* determine total src string length */
+ }
+
+ return s - src - 1;
+}
+
+
+char * os_strstr(const char *haystack, const char *needle)
+{
+ size_t len = os_strlen(needle);
+ while (*haystack) {
+ if (os_strncmp(haystack, needle, len) == 0)
+ return (char *) haystack;
+ haystack++;
+ }
+
+ return NULL;
+}
+
+
+int os_snprintf(char *str, size_t size, const char *format, ...)
+{
+ va_list ap;
+ int ret;
+
+ /* See http://www.ijs.si/software/snprintf/ for portable
+ * implementation of snprintf.
+ */
+
+ va_start(ap, format);
+ ret = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ if (size > 0)
+ str[size - 1] = '\0';
+ return ret;
+}
diff --git a/src/connectivity/combo_tool/src/stp_dump/os_linux.h b/src/connectivity/combo_tool/src/stp_dump/os_linux.h
new file mode 100755
index 0000000..44a10c4
--- /dev/null
+++ b/src/connectivity/combo_tool/src/stp_dump/os_linux.h
@@ -0,0 +1,117 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef OS_LINUX_H
+#define OS_LINUX_H
+
+typedef long os_time_t;
+
+void os_sleep(os_time_t sec, os_time_t usec);
+
+struct os_time {
+ os_time_t sec;
+ os_time_t usec;
+};
+
+
+#define os_time_before(a, b) \
+ ((a)->sec < (b)->sec || \
+ ((a)->sec == (b)->sec && (a)->usec < (b)->usec))
+
+#define os_time_sub(a, b, res) do { \
+ (res)->sec = (a)->sec - (b)->sec; \
+ (res)->usec = (a)->usec - (b)->usec; \
+ if ((res)->usec < 0) { \
+ (res)->sec--; \
+ (res)->usec += 1000000; \
+ } \
+} while (0)
+
+int os_get_time(struct os_time *t);
+int os_mktime(int year, int month, int day, int hour, int min, int sec,
+ os_time_t *t);
+int os_daemonize(const char *pid_file);
+void os_daemonize_terminate(const char *pid_file);
+int os_get_random(unsigned char *buf, size_t len);
+unsigned long os_random(void);
+char * os_rel2abs_path(const char *rel_path);
+int os_program_init(void);
+void os_program_deinit(void);
+int os_setenv(const char *name, const char *value, int overwrite);
+int os_unsetenv(const char *name);
+char * os_readfile(const char *name, size_t *len);
+void * os_zalloc(size_t size);
+void * os_malloc(size_t size);
+void * os_realloc(void *ptr, size_t size);
+void os_free(void *ptr);
+void * os_memcpy(void *dest, const void *src, size_t n);
+void * os_memmove(void *dest, const void *src, size_t n);
+void * os_memset(void *s, int c, size_t n);
+int os_memcmp(const void *s1, const void *s2, size_t n);
+char * os_strdup(const char *s);
+size_t os_strlen(const char *s);
+int os_strcasecmp(const char *s1, const char *s2);
+int os_strncasecmp(const char *s1, const char *s2, size_t n);
+char * os_strchr(const char *s, int c);
+char * os_strrchr(const char *s, int c);
+int os_strcmp(const char *s1, const char *s2);
+int os_strncmp(const char *s1, const char *s2, size_t n);
+char * os_strncpy(char *dest, const char *src, size_t n);
+size_t os_strlcpy(char *dest, const char *src, size_t siz);
+
+char * os_strstr(const char *haystack, const char *needle);
+int os_snprintf(char *str, size_t size, const char *format, ...);
+void os_sleep(os_time_t sec, os_time_t usec);
+int os_get_time(struct os_time *t);
+int os_mktime(int year, int month, int day, int hour, int min, int sec,
+ os_time_t *t);
+#define os_daemon daemon
+int os_daemonize(const char *pid_file);
+void os_daemonize_terminate(const char *pid_file);
+int os_get_random(unsigned char *buf, size_t len);
+unsigned long os_random(void);
+char * os_rel2abs_path(const char *rel_path);
+int os_program_init(void);
+void os_program_deinit(void);
+int os_setenv(const char *name, const char *value, int overwrite);
+int os_unsetenv(const char *name);
+char * os_readfile(const char *name, size_t *len);
+void * os_zalloc(size_t size);
+size_t os_strlcpy(char *dest, const char *src, size_t siz);
+
+#endif
+
diff --git a/src/connectivity/combo_tool/src/stp_dump/stp_dump.c b/src/connectivity/combo_tool/src/stp_dump/stp_dump.c
new file mode 100755
index 0000000..3593240
--- /dev/null
+++ b/src/connectivity/combo_tool/src/stp_dump/stp_dump.c
@@ -0,0 +1,1361 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#include <sys/stat.h>
+#include <grp.h>
+#include <stddef.h>
+//#include <cutils/sockets.h>
+//#include <android/log.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <dirent.h>
+//#include <cutils/properties.h>
+#include <sys/un.h>
+#include <dirent.h>
+#include <linux/limits.h>
+//#include <cutils/sockets.h>
+//#include <cutils/memory.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+//#include <sys/endian.h>
+#include <linux/serial.h> /* struct serial_struct */
+#include <unistd.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <termios.h>
+#include <sys/poll.h>
+#include <linux/serial.h> /* struct serial_struct */
+#include <sched.h>
+#include <netdb.h>
+#include <pthread.h>
+#include "os_linux.h"
+#include "stp_dump.h"
+#include "eloop.h"
+#include <linux/netlink.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#define LOGE printf
+#define LOGD printf
+
+#define GENL_ID_CTRL NLMSG_MIN_TYPE
+#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
+#define COMBO_T32_DIR "/data/misc/stp_dump/"
+#define COMBO_T32_NAME "combo_t32"
+#define COMBO_T32_ENAME ".cmm"
+#define COMBO_T32_NUM_MAX 50
+#define COM_STR_MAX 100
+
+enum {
+ CTRL_CMD_UNSPEC,
+ CTRL_CMD_NEWFAMILY,
+ CTRL_CMD_DELFAMILY,
+ CTRL_CMD_GETFAMILY,
+ CTRL_CMD_NEWOPS,
+ CTRL_CMD_DELOPS,
+ CTRL_CMD_GETOPS,
+ CTRL_CMD_NEWMCAST_GRP,
+ CTRL_CMD_DELMCAST_GRP,
+ CTRL_CMD_GETMCAST_GRP, /* unused */
+ __CTRL_CMD_MAX,
+};
+#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
+
+enum {
+ CTRL_ATTR_UNSPEC,
+ CTRL_ATTR_FAMILY_ID,
+ CTRL_ATTR_FAMILY_NAME,
+ CTRL_ATTR_VERSION,
+ CTRL_ATTR_HDRSIZE,
+ CTRL_ATTR_MAXATTR,
+ CTRL_ATTR_OPS,
+ CTRL_ATTR_MCAST_GROUPS,
+ __CTRL_ATTR_MAX,
+};
+
+#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
+
+struct genlmsghdr {
+ __u8 cmd;
+ __u8 version;
+ __u16 reserved;
+};
+
+#define GENLMSG_DATA(glh) ((void *)((long)NLMSG_DATA(glh) + GENL_HDRLEN))
+#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
+#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
+
+typedef struct _tagGenericNetlinkPacket {
+ struct nlmsghdr n;
+ struct genlmsghdr g;
+ char buf[512*16];
+} GENERIC_NETLINK_PACKET, *P_GENERIC_NETLINK_PACKET;
+
+
+
+////typedef int socklen_t;
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+int stp_debug_level = MSG_MSGDUMP;
+
+struct stp_ctrl_dst {
+ struct stp_ctrl_dst *next;
+ struct sockaddr_un addr;
+ socklen_t addrlen;
+ int debug_level;
+ int errors;
+};
+
+struct ctrl_iface_priv {
+ struct stp_dump *stp_d;
+ int sock;
+ struct stp_ctrl_dst *ctrl_dst;
+};
+
+struct trace_iface_priv {
+ struct stp_dump *stp_d;
+ int sock;
+ struct {
+ FILE *fp_pkt;
+ FILE *fp_drv;
+ FILE *fp_fw;
+ FILE *fp_t32;
+ } log_f;
+};
+
+struct stp_dump {
+ const char *ctrl_interface;
+ const char *ifname;
+ char *ctrl_interface_group;
+ int wmt_fd;
+ struct ctrl_iface_priv *ctrl_iface;
+ struct trace_iface_priv *trace_iface;
+};
+struct list_head {
+ char file_name[100];
+ struct list_head *next, *prev;
+};
+
+struct list_head list_head;
+int combo_t32_num = 0;
+
+static inline void INIT_LIST_HEAD(struct list_head *list) {
+ list->next = list;
+ list->prev = list;
+}
+
+static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) {
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+static inline void list_add(struct list_head *new, struct list_head *head) {
+ __list_add(new, head, head->next);
+}
+
+static inline void list_add_tail(struct list_head *new, struct list_head *head) {
+ __list_add(new, head->prev, head);
+}
+
+static inline void __list_del(struct list_head * prev, struct list_head * next) {
+ next->prev = prev;
+ prev->next = next;
+}
+
+static inline void list_del(struct list_head *entry) {
+ __list_del(entry->prev, entry->next);
+ entry->next = NULL;
+ entry->prev = NULL;
+}
+
+void bubble_sort(char *a[], int n)
+{
+ int i, j, len1, len2, len3;
+ char temp[COM_STR_MAX];
+ for (j = 0; j < n - 1; j++)
+ for (i = 0; i < n - 1 - j; i++) {
+ if (atoi(&a[i][10]) > atoi(&a[i+1][10])) {
+ len1 = (strlen(a[i]) <= COM_STR_MAX) ? strlen(a[i]) : COM_STR_MAX;
+ strncpy(temp, a[i], len1);
+ temp[len1-1] = '\0';
+ len2 = (strlen(a[i+1]) <= COM_STR_MAX) ? strlen(a[i+1]) : COM_STR_MAX;
+ strncpy(a[i], a[i+1], len2);
+ a[i][len2-1] = '\0';
+ len3 = (strlen(a[i+1]) <= COM_STR_MAX) ? strlen(a[i+1]) : COM_STR_MAX;
+ strncpy(a[i+1], temp, len3);
+ a[i+1][len3-1] = '\0';
+ }
+ }
+}
+/*
+void android_printf(int level, char *format, ...)
+{
+ if (level >= stp_debug_level) {
+ va_list ap;
+ if (level == MSG_ERROR) {
+ level = ANDROID_LOG_ERROR;
+ } else if (level == MSG_WARNING) {
+ level = ANDROID_LOG_WARN;
+ } else if (level == MSG_INFO) {
+ level = ANDROID_LOG_INFO;
+ } else {
+ level = ANDROID_LOG_DEBUG;
+ }
+ va_start(ap, format);
+ __android_log_vprint(level, "stp_dump", format, ap);
+ va_end(ap);
+ }
+}
+*/
+
+
+static void _stp_hexdump(int level, const char *title, const u8 *buf,
+ size_t len, int show)
+{
+ size_t i;
+ if (level < stp_debug_level)
+ return;
+
+ printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
+ if (buf == NULL) {
+ printf(" [NULL]");
+ } else if (show) {
+ for (i = 0; i < len; i++)
+ printf(" %02x", buf[i]);
+ } else {
+ printf(" [REMOVED]");
+ }
+ printf("\n");
+}
+
+void stp_hexdump(int level, const char *title, const u8 *buf, size_t len)
+{
+ _stp_hexdump(level, title, buf, len, 1);
+}
+
+static void stp_dump_ctrl_iface_send(struct ctrl_iface_priv *priv,
+ int level, const char *buf,
+ size_t len);
+
+
+static int stp_dump_ctrl_iface_attach(struct ctrl_iface_priv *priv,
+ struct sockaddr_un *from,
+ socklen_t fromlen)
+{
+ struct stp_ctrl_dst *dst;
+
+ dst = os_zalloc(sizeof(*dst));
+ if (dst == NULL)
+ return -1;
+ os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
+ dst->addrlen = fromlen;
+ dst->debug_level = MSG_INFO;
+ dst->next = priv->ctrl_dst;
+ priv->ctrl_dst = dst;
+ stp_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
+ (u8 *) from->sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path));
+ return 0;
+}
+
+static int stp_dump_ctrl_iface_detach(struct ctrl_iface_priv *priv,
+ struct sockaddr_un *from,
+ socklen_t fromlen)
+{
+ struct stp_ctrl_dst *dst, *prev = NULL;
+
+ dst = priv->ctrl_dst;
+ while (dst) {
+ if (fromlen == dst->addrlen &&
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
+ if (prev == NULL)
+ priv->ctrl_dst = dst->next;
+ else
+ prev->next = dst->next;
+ os_free(dst);
+ stp_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
+ (u8 *) from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
+ return 0;
+ }
+ prev = dst;
+ dst = dst->next;
+ }
+ return -1;
+}
+
+static int stp_dump_ctrl_iface_level(struct ctrl_iface_priv *priv,
+ struct sockaddr_un *from,
+ socklen_t fromlen,
+ char *level)
+{
+ struct stp_ctrl_dst *dst;
+
+ ALOGD("CTRL_IFACE LEVEL %s\n", level);
+
+ dst = priv->ctrl_dst;
+ while (dst) {
+ if (fromlen == dst->addrlen &&
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
+ stp_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
+ "level", (u8 *) from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
+ dst->debug_level = atoi(level);
+ return 0;
+ }
+ dst = dst->next;
+ }
+
+ return -1;
+}
+
+static void stp_dump_ctrl_iface_receive(int sock, void *eloop_ctx,
+ void *sock_ctx)
+{
+ struct stp_dump *stp_d = eloop_ctx;
+ struct ctrl_iface_priv *priv = sock_ctx;
+ char buf[256];
+ int res;
+ struct sockaddr_un from;
+ socklen_t fromlen = sizeof(from);
+ char *reply = NULL;
+ size_t reply_len = 0;
+ int new_attached = 0;
+
+ res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
+ (struct sockaddr *) &from, &fromlen);
+ if (res < 0) {
+ perror("recvfrom(ctrl_iface)");
+ return;
+ }
+ buf[res] = '\0';
+
+ if (os_strcmp(buf, "ATTACH") == 0) {
+ if (stp_dump_ctrl_iface_attach(priv, &from, fromlen))
+ reply_len = 1;
+ else {
+ new_attached = 1;
+ reply_len = 2;
+ }
+ } else if (os_strcmp(buf, "DETACH") == 0) {
+ if (stp_dump_ctrl_iface_detach(priv, &from, fromlen))
+ reply_len = 1;
+ else
+ reply_len = 2;
+ } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
+ if (stp_dump_ctrl_iface_level(priv, &from, fromlen,
+ buf + 6))
+ reply_len = 1;
+ else
+ reply_len = 2;
+ } else {
+ //stp_hexdump(MSG_INFO, "stp_dump_ctrl_iface_process", buf, 4);
+ //reply = stp_dump_ctrl_iface_process(stp_d, buf,
+ // &reply_len);
+ }
+#if 0
+ if (reply) {
+ if ( 0 > sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen))
+ perror("send reply error\n");
+ os_free(reply);
+ } else if (reply_len == 1) {
+#else
+ if (reply_len == 1) {
+#endif
+ if (0 > sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, fromlen))
+ perror("send string 'FAIL' to sock error\n");
+ } else if (reply_len == 2) {
+ if ( 0 > sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, fromlen))
+ perror("send string 'OK' to sock error\n");
+ }
+}
+
+
+static char * stp_dump_ctrl_iface_path(struct stp_dump *stp_d)
+{
+ char *buf;
+ size_t len;
+ char *pbuf, *dir = NULL, *gid_str = NULL;
+ int res;
+
+ if (stp_d->ctrl_interface == NULL)
+ {
+ ALOGE("stp_d->ctrl_interface = NULL\n");
+ return NULL;
+ }
+ pbuf = os_strdup(stp_d->ctrl_interface);
+
+ if (pbuf == NULL)
+ {
+ ALOGD("copy string failed\n");
+ return NULL;
+ }
+ if (os_strncmp(pbuf, "DIR=", 4) == 0) {
+ dir = pbuf + 4;
+ gid_str = os_strstr(dir, " GROUP=");
+ if (gid_str) {
+ *gid_str = '\0';
+ gid_str += 7;
+ }
+ } else
+ dir = pbuf;
+
+ len = os_strlen(dir) + os_strlen(stp_d->ifname) + 2;
+ buf = os_malloc(len);
+ if (buf == NULL)
+ {
+ ALOGE("memory allocation failed\n");
+ os_free(pbuf);
+ return NULL;
+ }
+
+ res = os_snprintf(buf, len, "%s/%s", dir, stp_d->ifname);
+ if (res < 0 || (size_t) res >= len)
+ {
+ ALOGE("os_snprintf failed\n");
+ os_free(pbuf);
+ os_free(buf);
+ return NULL;
+ }
+ os_free(pbuf);
+ return buf;
+}
+
+static void stp_dump_ctrl_iface_msg_cb(void *ctx, int level,
+ const char *txt, size_t len)
+{
+ struct stp_dump *stp_d = ctx;
+ if (stp_d == NULL || stp_d->ctrl_iface == NULL)
+ return;
+ stp_dump_ctrl_iface_send(stp_d->ctrl_iface, level, txt, len);
+}
+
+int stp_dump_ctrl_iface_trace_logger_init(struct trace_iface_priv *tr_priv) {
+ char str[100] = {""};
+ char *file_name[50] = {NULL};
+ int i = 0;
+ struct dirent *pDirent = NULL;
+ DIR *pDir = NULL;
+ struct list_head *node;
+
+ sprintf(str, "%s%s%s", COMBO_T32_DIR, COMBO_T32_NAME, COMBO_T32_ENAME);
+ tr_priv->log_f.fp_t32 = fopen(str, "a+");
+ if (tr_priv->log_f.fp_t32 == NULL) {
+ ALOGE("create combo_fw.log fails, exit errno:%d\n", errno);
+ exit(EXIT_FAILURE);
+ }
+ if (0 != remove(str))
+ perror("remove combo_fw fails\n");
+
+ pDir = opendir(COMBO_T32_DIR);
+ if (NULL == pDir) {
+ ALOGE("coredump patch cannot be opened\n");
+ exit(EXIT_FAILURE);
+ }
+ /* stp_printf(MSG_ERROR, "coredump patch opened\n"); */
+
+ while (NULL != (pDirent = readdir(pDir))) {
+ if (0 == strncmp(pDirent->d_name, COMBO_T32_NAME, sizeof(COMBO_T32_NAME)-1)) {
+ if (combo_t32_num < COMBO_T32_NUM_MAX) {
+ file_name[combo_t32_num] = malloc(100);
+ strcpy(file_name[combo_t32_num], pDirent->d_name);
+ /* stp_printf(MSG_ERROR, "file name:%s\n", file_name[combo_t32_num]); */
+ combo_t32_num++;
+ /* stp_printf(MSG_ERROR, "combo_t32_num:%d\n", combo_t32_num); */
+ } else {
+ /* stp_printf(MSG_ERROR, "file num more than the max\n"); */
+ break;
+ }
+ }
+ }
+ closedir(pDir);
+ bubble_sort(file_name, combo_t32_num);
+
+ INIT_LIST_HEAD(&list_head);
+ for (i = 0; i < combo_t32_num; i++) {
+ node = malloc(sizeof(struct list_head));
+ sprintf(node->file_name, "%s%s", COMBO_T32_DIR, file_name[i]);
+ list_add_tail(node, &list_head);
+ /* stp_printf(MSG_ERROR, "file name:%s\n", node->file_name); */
+ free(file_name[i]);
+ }
+ fclose(tr_priv->log_f.fp_t32);
+ ALOGI("close file combo_t32\n");
+ return 0;
+}
+
+int stp_dump_ctrl_iface_trace_logger_decode(int sock, void *eloop_ctx,
+ void *sock_ctx)
+{
+ struct nlattr *na;
+ char *stpmsghdr = NULL;
+ char *packet_raw = NULL;
+ int size;
+ struct trace_iface_priv *tr_priv = sock_ctx;
+ GENERIC_NETLINK_PACKET mBuffer;
+ GENERIC_NETLINK_PACKET *prBuffer;
+ int i;
+ int len;
+
+ if ((size = recv(sock, &mBuffer, sizeof(mBuffer), 0)) < 0)
+ {
+ LOGE("recv failed (%s)\n", strerror(errno));
+ return -1;
+ }
+
+ prBuffer = &mBuffer;
+
+ /* Validate response message */
+ if (!NLMSG_OK(&(prBuffer->n), (unsigned int)size))
+ {
+ LOGE("invalid reply message\n");
+ return -1;
+ }
+ else if (prBuffer->n.nlmsg_type == NLMSG_ERROR)
+ { /* error */
+ LOGE("received error\n");
+ return -1;
+ }
+ else if (!NLMSG_OK((&prBuffer->n), (unsigned int)size))
+ {
+ LOGE("invalid reply message received via Netlink\n");
+ return -1;
+ }
+
+ size = GENLMSG_PAYLOAD(&prBuffer->n);
+ na = (struct nlattr *) GENLMSG_DATA(prBuffer);
+
+ stpmsghdr = (char *)NLA_DATA(na);
+ if ((stpmsghdr[0] == '[') &&
+ (stpmsghdr[1] == 'M') &&
+ (stpmsghdr[2] == ']')) {
+ static char start_dump = 1;
+
+ /* TODO: parsing message to know the action to start dump */
+ if (start_dump) {
+ char combo_t32[100] = {""};
+ char date[64];
+ time_t t = time(0);
+ struct list_head *node;
+
+ strftime(date, sizeof(date), "%Y%m%d%H%M%S", localtime(&t));
+ sprintf(combo_t32, "%s%s_%s%s", COMBO_T32_DIR, COMBO_T32_NAME, date, COMBO_T32_ENAME);
+ /*fclose(tr_priv->log_f.fp_t32);*/
+ tr_priv->log_f.fp_t32 = 0;
+ tr_priv->log_f.fp_t32 = fopen(combo_t32, "w");
+ if (0 != chmod(combo_t32, 00664)) {
+ perror("chmod combo_t32 error\n");
+ return -1;
+ }
+ /* stp_printf(MSG_DEBUG, "create a new file %s\n", combo_t32); */
+ combo_t32_num++;
+
+ if (combo_t32_num < COMBO_T32_NUM_MAX) {
+ node = malloc(sizeof(struct list_head));
+ /* stp_printf(MSG_ERROR, "create a new node\n"); */
+ } else {
+ node = list_head.next;
+ list_del(list_head.next);
+ if (0 != remove(node->file_name)) {
+ perror("remove node->file error\n");
+ }
+ /* stp_printf(MSG_ERROR, "combo_t32_num more than max:%d\n", combo_t32_num); */
+ /* stp_printf(MSG_ERROR, "remove file:%s\n", node->file_name); */
+ }
+ strcpy(node->file_name, combo_t32);
+ list_add_tail(node, &list_head);
+
+ len = stpmsghdr[4];
+ len <<= 8;
+ len += stpmsghdr[3];
+ for (i = 0; i < len; i++)
+ fprintf(tr_priv->log_f.fp_t32, "%c", stpmsghdr[5+i]);
+ fflush(tr_priv->log_f.fp_t32);
+ ioctl(tr_priv->stp_d->wmt_fd, 10, &stpmsghdr[5]);
+ start_dump = 0;
+ /* stp_printf(MSG_DEBUG, "rev coredump len:%d\n", len); */
+ /* stp_printf(MSG_DEBUG, "rev coredump date:%s\n", &stpmsghdr[5]); */
+ } else {
+ len = stpmsghdr[4];
+ len <<= 8;
+ len += stpmsghdr[3];
+ for (i = 0; i < len; i++)
+ fprintf(tr_priv->log_f.fp_t32, "%c", stpmsghdr[5+i]);
+ fflush(tr_priv->log_f.fp_t32);
+ /* stp_printf(MSG_DEBUG, "rev coredump len:%d\n", len); */
+ /* stp_printf(MSG_DEBUG, "rev coredump date:%s\n", &stpmsghdr[5]); */
+ }
+ if (len < 1024) {
+ i = 0;
+ do {
+ i++;
+ }while(('c' != stpmsghdr[len - i]) && (i < 50));
+ }
+ if (strstr(&stpmsghdr[5], "coredump end") || strstr(&stpmsghdr[len - i], "coredump end")) {
+ /* inform user to dump action is done */
+ ioctl(tr_priv->stp_d->wmt_fd, 11, 0);
+ start_dump = 1;
+ ALOGD("coredump end\n");
+ }
+ } else
+ {
+ LOGE("invalid dump data\n");
+ }
+
+ return 0;
+}
+
+int stp_dump_ctrl_iface_trace_logger_sendto_fd(int s, const char *buf, int bufLen)
+{
+ struct sockaddr_nl nladdr;
+ int r;
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+
+ while ((r = sendto(s, buf, bufLen, 0, (struct sockaddr *) &nladdr,
+ sizeof(nladdr))) < bufLen)
+ {
+ if (r > 0)
+ {
+ buf += r;
+ bufLen -= r;
+ }
+ else if (errno != EAGAIN)
+ {
+ ALOGE("%s failed\n", __func__);
+ return -1;
+ }
+ }
+ ALOGI("%s succeed\n", __func__);
+ return 0;
+}
+
+/*
+ * Probe the controller in genetlink to find the family id
+ */
+int stp_dump_ctrl_iface_trace_logger_get_family_id(int sk, const char *family_name)
+{
+ struct nlattr *na;
+ int rep_len;
+ int id = -1;
+ GENERIC_NETLINK_PACKET family_req, ans;
+
+ /* Get family name */
+ family_req.n.nlmsg_type = GENL_ID_CTRL;
+ family_req.n.nlmsg_flags = NLM_F_REQUEST;
+ family_req.n.nlmsg_seq = 0;
+ family_req.n.nlmsg_pid = getpid();
+ family_req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+ family_req.g.cmd = CTRL_CMD_GETFAMILY;
+ family_req.g.version = 0x1;
+
+ na = (struct nlattr *) GENLMSG_DATA(&family_req);
+ na->nla_type = CTRL_ATTR_FAMILY_NAME;
+ na->nla_len = strlen(family_name) + 1 + NLA_HDRLEN;
+ strcpy((char *)NLA_DATA(na), family_name);
+
+ family_req.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
+
+ if (stp_dump_ctrl_iface_trace_logger_sendto_fd(sk, (char *) &family_req, family_req.n.nlmsg_len) < 0)
+ {
+ ALOGE("%s failed\n", __func__);
+ return -1;
+ }
+
+ rep_len = recv(sk, &ans, sizeof(ans), 0);
+ if (rep_len < 0)
+ {
+ ALOGE("no response\n");
+ return -1;
+ }
+ /* Validate response message */
+ else if (!NLMSG_OK((&ans.n), (unsigned int)rep_len))
+ {
+ ALOGE("invalid reply message\n");
+ return -1;
+ }
+ else if (ans.n.nlmsg_type == NLMSG_ERROR)
+ { /* error */
+ ALOGE("received error\n");
+ return -1;
+ }
+
+ na = (struct nlattr *) GENLMSG_DATA(&ans);
+ na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len));
+ if (na->nla_type == CTRL_ATTR_FAMILY_ID)
+ {
+ id = *(__u16 *) NLA_DATA(na);
+ }
+
+ return id;
+}
+
+int stp_dump_ctrl_iface_trace_logger_start(struct trace_iface_priv *tr_priv){
+
+ struct sockaddr_nl nladdr;
+ int sz = 64 * 1024;
+ GENERIC_NETLINK_PACKET ans, req;
+ struct nlattr *na;
+ int id;
+ int mlength = 14;
+ const char *message = "HELLO"; //message
+ int rc;
+ int count = 100;
+
+ stp_dump_ctrl_iface_trace_logger_init(tr_priv);
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+ nladdr.nl_pid = getpid();
+ //nladdr.nl_groups = 0xffffffff;
+
+ if ((tr_priv->sock= socket(AF_NETLINK,
+ SOCK_RAW,NETLINK_GENERIC)) < 0)
+ {
+ ALOGE("Unable to create uevent socket: %s", strerror(errno));
+ return -1;
+ }
+
+ if (setsockopt(tr_priv->sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0)
+ {
+ ALOGE("Unable to set uevent socket options: %s", strerror(errno));
+ return -1;
+ }
+
+ if (bind(tr_priv->sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0)
+ {
+ ALOGD("Unable to bind uevent socket: %d:%s\n", errno, strerror(errno));
+ return -1;
+ }
+
+ while(count--)
+ {
+ id = stp_dump_ctrl_iface_trace_logger_get_family_id(tr_priv->sock, "STP_DBG");
+ if (-1 == id)
+ {
+ ALOGD("Unable to get family id, Retry");
+ sleep(3);
+ }
+ else
+ {
+ ALOGD("[STP_DBG] family id = %d\n", id);
+ printf("[STP_DBG] family id = %d\n", id);
+ break;
+ }
+ }
+
+ req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+ req.n.nlmsg_type = id;
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_seq = 60;
+ req.n.nlmsg_pid = getpid();
+ req.g.cmd = 1;
+
+ na = (struct nlattr *) GENLMSG_DATA(&req);
+ na->nla_type = 1; //MTK_WIFI_ATTR_MSG
+ na->nla_len = mlength + NLA_HDRLEN; //message length
+ memcpy(NLA_DATA(na), message, strlen(message));
+ req.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
+
+ ALOGI( "sending dummy command\n");
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+
+ rc = sendto(tr_priv->sock, (char *)&req, req.n.nlmsg_len, 0,
+ (struct sockaddr *) &nladdr, sizeof(nladdr));
+#if 0
+ if (rc > 0)
+ {
+ stp_printf(MSG_INFO, "sending dummy command okay\n");
+ }
+ else if (errno != EAGAIN)
+ {
+ stp_printf(MSG_ERROR, "%s failed\n", __func__);
+ return -1;
+ }
+#endif
+ eloop_register_read_sock(tr_priv->sock, stp_dump_ctrl_iface_trace_logger_decode,
+ tr_priv->stp_d, tr_priv);
+ return 0;
+}
+
+struct ctrl_iface_priv *
+stp_dump_ctrl_iface_init(struct stp_dump *stp_d)
+{
+ struct ctrl_iface_priv *priv;
+ struct trace_iface_priv *tr_priv;
+ struct sockaddr_un addr;
+ char *fname = NULL;
+ gid_t gid = 0;
+ int gid_set = 0;
+ char *buf, *dir = NULL, *gid_str = NULL;
+ struct group *grp;
+ char *endp;
+
+ priv = os_zalloc(sizeof(*priv));
+ if (priv == NULL)
+ {
+ ALOGE("memory allocation for priv failed\n");
+ return NULL;
+ }
+
+ tr_priv = os_zalloc(sizeof(*tr_priv));
+ if(tr_priv == NULL)
+ {
+ ALOGE("memory allocation for tr_priv failed\n");
+ os_free(priv);
+ priv = NULL;
+ return NULL;
+ }
+
+ priv->stp_d = stp_d;
+ priv->sock = -1;
+
+ tr_priv->stp_d = stp_d;
+ tr_priv->sock = -1;
+
+ if (stp_d->ctrl_interface == NULL)
+ {
+ ALOGE("stp_d->ctrl_interface = NULL\n");
+ os_free(tr_priv);
+ tr_priv = NULL;
+ return priv;
+ }
+
+ buf = os_strdup(stp_d->ctrl_interface);
+ if (buf == NULL)
+ {
+ ALOGE("os_strdup\n");
+ goto fail;
+ }
+
+ os_snprintf(addr.sun_path, sizeof(addr.sun_path), "stp_%s",
+ stp_d->ctrl_interface);
+ ALOGI("addr.sun_path:%s\n", addr.sun_path);
+ /*priv->sock = android_get_control_socket(addr.sun_path);
+ if (priv->sock >= 0)
+ {
+ ALOGI("priv->sock already exist\n");
+ goto havesock;
+ }*/
+
+ if (os_strncmp(buf, "DIR=", 4) == 0) {
+ dir = buf + 4;
+ gid_str = os_strstr(dir, " GROUP=");
+ if (gid_str) {
+ *gid_str = '\0';
+ gid_str += 7;
+ }
+ } else {
+ dir = buf;
+ gid_str = stp_d->ctrl_interface_group;
+ }
+
+ if (mkdir(dir, 00777) < 0)
+ {
+ if (errno == EEXIST)
+ {
+ ALOGI("Using existing control "
+ "interface directory.\n");
+ }
+ else
+ {
+ ALOGE("mkdir (%s) failed\n", dir);
+ perror("mkdir[ctrl_interface]");
+ goto fail;
+ }
+ }
+ ALOGE("mkdir (%s) succeed\n", dir);
+ if (gid_str)
+ {
+ grp = getgrnam("sys");
+ if (grp)
+ {
+ gid = grp->gr_gid;
+ gid_set = 1;
+ ALOGI("ctrl_interface_group=%d"
+ " (from group name '%s')\n",
+ (int) gid, gid_str);
+ }
+ else
+ {
+ // Group name not found - try to parse this as gid
+ gid = strtol(gid_str, &endp, 10);
+ if (*gid_str == '\0' || *endp != '\0') {
+ ALOGE("CTRL: Invalid group "
+ "'%s'\n", gid_str);
+ goto fail;
+ }
+ gid_set = 1;
+ ALOGI("ctrl_interface_group=%d\n",
+ (int) gid);
+ }
+ }
+
+ if (gid_set && chown(dir, getuid(), gid) < 0)
+ {
+ perror("chown[ctrl_interface]");
+ ALOGE("chown (%s) failed\n", dir);
+ goto fail;
+ }
+ ALOGI("chown (%s) succeed\n", dir);
+
+ // Make sure the group can enter and read the directory
+ if (gid_set &&
+ chmod(dir, 00775) < 0)
+ {
+ ALOGE("CTRL: chmod[%s]: %s\n", dir, strerror(errno));
+ goto fail;
+ }
+ ALOGI("CTRL: chmod[%s] succeed\n", dir);
+ if (os_strlen(dir) + 1 + os_strlen(stp_d->ifname) >=
+ sizeof(addr.sun_path))
+ {
+ ALOGE("ctrl_iface path limit exceeded\n");
+ goto fail;
+ }
+
+ stp_dump_ctrl_iface_trace_logger_start(tr_priv);
+ priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (priv->sock < 0)
+ {
+ perror("socket(PF_UNIX)");
+ ALOGE("create socket failed\n");
+ goto fail;
+ }
+
+ os_memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+
+ fname = stp_dump_ctrl_iface_path(stp_d);
+
+ if (fname == NULL)
+ {
+ ALOGE("stp_dump_ctrl_iface_path failed\n");
+ goto fail;
+ }
+ os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
+ if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ ALOGE("ctrl_iface bind(PF_UNIX) failed: %s\n",
+ strerror(errno));
+ if (connect(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ ALOGE("ctrl_iface exists, but does not"
+ " allow connections - assuming it was left"
+ "over from forced program termination\n");
+ if (unlink(fname) < 0) {
+ perror("unlink[ctrl_iface]");
+ ALOGE("Could not unlink "
+ "existing ctrl_iface socket '%s'\n",
+ fname);
+ goto fail;
+ }
+ if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("bind(PF_UNIX)");
+ goto fail;
+ }
+ ALOGE("Successfully replaced leftover " "ctrl_iface socket '%s'\n", fname);
+ } else {
+ ALOGI("ctrl_iface exists and seems to " "be in use - cannot override it\n");
+ ALOGI("Delete '%s' manually if it is "
+ "not used anymore\n", fname);
+ os_free(fname);
+ fname = NULL;
+ goto fail;
+ }
+ }
+ if (gid_set && chown(fname, -1, gid) < 0) {
+ perror("chown[ctrl_interface/ifname]");
+ ALOGE("chown(%s) failed, ", fname);
+ goto fail;
+ }
+
+ if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
+ perror("chmod[ctrl_interface/ifname]");
+ ALOGE("chmod(%s) failed, ", fname);
+ goto fail;
+ }
+ os_free(fname);
+ fname = NULL;
+ /* open wmt dev */
+ stp_d->wmt_fd = open("/dev/stpwmt", O_RDWR | O_NOCTTY);
+ if (stp_d->wmt_fd < 0) {
+ ALOGE("[%s] Can't open stpwmt \n", __FUNCTION__);
+ goto fail;
+ }
+
+havesock:
+ eloop_register_read_sock(priv->sock, stp_dump_ctrl_iface_receive,
+ stp_d, priv);
+
+ os_free(buf);
+ buf = NULL;
+ return priv;
+
+fail:
+ if (priv->sock >= 0)
+ close(priv->sock);
+ os_free(priv);
+ if (fname) {
+ unlink(fname);
+ os_free(fname);
+ fname = NULL;
+ }
+ os_free(buf);
+ buf = NULL;
+ return NULL;
+}
+
+
+void stp_dump_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
+{
+#if 0
+ struct wpa_ctrl_dst *dst, *prev;
+#endif
+ struct stp_ctrl_dst *dst, *prev;
+ ALOGI("%s\n", __func__);
+ os_sleep(1, 0);
+ /* close wmt dev */
+ if (priv->stp_d->wmt_fd >= 0) {
+ close(priv->stp_d->wmt_fd);
+ }
+ if (priv->sock > -1) {
+ char *fname;
+ char *buf, *dir = NULL, *gid_str = NULL;
+ eloop_unregister_read_sock(priv->sock);
+ if (priv->ctrl_dst) {
+ /*
+ * Wait a second before closing the control socket if
+ * there are any attached monitors in order to allow
+ * them to receive any pending messages.
+ */
+ ALOGD("CTRL_IFACE wait for attached "
+ "monitors to receive messages\n");
+ os_sleep(1, 0);
+ }
+ close(priv->sock);
+ priv->sock = -1;
+#if 0
+ fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s);
+#endif
+ fname = stp_dump_ctrl_iface_path(priv->stp_d);
+ if (fname) {
+ unlink(fname);
+ os_free(fname);
+ fname = NULL;
+ }
+#if 0
+ buf = os_strdup(priv->wpa_s->conf->ctrl_interface);
+#endif
+ buf = os_strdup(priv->stp_d->ctrl_interface);
+ if (buf == NULL)
+ goto free_dst;
+ if (os_strncmp(buf, "DIR=", 4) == 0) {
+ dir = buf + 4;
+ gid_str = os_strstr(dir, " GROUP=");
+ if (gid_str) {
+ *gid_str = '\0';
+ gid_str += 7;
+ }
+ } else
+ dir = buf;
+
+ if (rmdir(dir) < 0) {
+ if (errno == ENOTEMPTY) {
+ ALOGE("Control interface "
+ "directory not empty - leaving it "
+ "behind\n");
+ } else {
+ perror("rmdir[ctrl_interface]");
+ }
+ }
+ os_free(buf);
+ }
+
+free_dst:
+ dst = priv->ctrl_dst;
+ while (dst) {
+ prev = dst;
+ dst = dst->next;
+ os_free(prev);
+ }
+ os_free(priv);
+}
+
+
+/**
+ * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors
+ * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
+ * @level: Priority level of the message
+ * @buf: Message data
+ * @len: Message length
+ *
+ * Send a packet to all monitor programs attached to the control interface.
+ */
+static void stp_dump_ctrl_iface_send(struct ctrl_iface_priv *priv,
+ int level, const char *buf,
+ size_t len)
+{
+ struct stp_ctrl_dst *dst, *next;
+ char levelstr[10];
+ int idx, res;
+ struct msghdr msg;
+ struct iovec io[2];
+
+ dst = priv->ctrl_dst;
+ if (priv->sock < 0 || dst == NULL)
+ return;
+
+ res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
+ if (res < 0 || (size_t) res >= sizeof(levelstr))
+ return;
+ io[0].iov_base = levelstr;
+ io[0].iov_len = os_strlen(levelstr);
+ io[1].iov_base = (char *) buf;
+ io[1].iov_len = len;
+ os_memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = io;
+ msg.msg_iovlen = 2;
+
+ idx = 0;
+ while (dst) {
+ next = dst->next;
+ if (level >= dst->debug_level) {
+ stp_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
+ (u8 *) dst->addr.sun_path, dst->addrlen -
+ offsetof(struct sockaddr_un, sun_path));
+ msg.msg_name = (void *) &dst->addr;
+ msg.msg_namelen = dst->addrlen;
+ if (sendmsg(priv->sock, &msg, 0) < 0) {
+ int _errno = errno;
+ ALOGI("CTRL_IFACE monitor[%d]: "
+ "%d - %s\n",
+ idx, errno, strerror(errno));
+ dst->errors++;
+ if (dst->errors > 10 || _errno == ENOENT) {
+ stp_dump_ctrl_iface_detach(
+ priv, &dst->addr,
+ dst->addrlen);
+ }
+ } else
+ dst->errors = 0;
+ }
+ idx++;
+ dst = next;
+ }
+}
+
+
+void stp_dump_ctrl_iface_wait(struct ctrl_iface_priv *priv)
+{
+ char buf[256];
+ int res;
+ struct sockaddr_un from;
+ socklen_t fromlen = sizeof(from);
+
+ for (;;) {
+ ALOGD("CTRL_IFACE - %s - wait for monitor to "
+ "attach\n", priv->stp_d->ifname);
+ eloop_wait_for_read_sock(priv->sock);
+
+ res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0,
+ (struct sockaddr *) &from, &fromlen);
+ if (res < 0) {
+ perror("recvfrom(ctrl_iface)");
+ continue;
+ }
+ buf[res] = '\0';
+
+ if (os_strcmp(buf, "ATTACH") == 0) {
+ /* handle ATTACH signal of first monitor interface */
+ if (!stp_dump_ctrl_iface_attach(priv, &from,
+ fromlen)) {
+ if (0 > sendto(priv->sock, "OK\n", 3, 0, (struct sockaddr *) &from, fromlen))
+ perror("send string 'OK' to sock error\n");
+ /* OK to continue */
+ return;
+ } else {
+ if (0 > sendto(priv->sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, fromlen))
+ perror("send string 'FAIL' to sock error\n");
+ }
+ } else {
+ /* return FAIL for all other signals */
+ if (0 > sendto(priv->sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, fromlen))
+ perror("send string 'FAIL' to sock error\n");
+ }
+ }
+}
+
+static void stp_dump_terminate(int sig, void *eloop_ctx,
+ void *signal_ctx)
+{
+ eloop_terminate();
+}
+
+int stp_dump_run(void)
+{
+ eloop_register_signal_terminate(stp_dump_terminate, NULL);
+ eloop_run();
+ return 0;
+}
+
+void set_sched_prio(void)
+{
+ struct sched_param sched, test_sched;
+ int policy = 0xff;
+ int err=0xff;
+
+ policy = sched_getscheduler(0);
+ sched_getparam(0, &test_sched);
+ printf("Before %s policy = %d, priority = %d\n", "main" , policy, test_sched.sched_priority);
+
+ sched.sched_priority = sched_get_priority_max(SCHED_FIFO);
+ err = sched_setscheduler(0, SCHED_FIFO, &sched);
+ if(err == 0){
+ printf("pthread_setschedparam SUCCESS \n");
+ policy = sched_getscheduler(0);
+ sched_getparam(0, &test_sched);
+ printf("After %s policy = %d, priority = %d\n", "main" ,policy , test_sched.sched_priority);
+ }
+ else{
+ if(err == EINVAL) printf("policy is not one of SCHED_OTHER, SCHED_RR, SCHED_FIFO\n");
+ if(err == EINVAL) printf("the priority value specified by param is not valid for the specified policy\n");
+ if(err == EPERM) printf("the calling process does not have superuser permissions\n");
+ if(err == ESRCH) printf("the target_thread is invalid or has already terminated\n");
+ if(err == EFAULT) printf("param points outside the process memory space\n");
+ printf("pthread_setschedparam FAIL \n");
+ }
+}
+
+int main(int argc, char *argv[]){
+
+ struct stp_dump *stp_d = NULL;
+ const char *conf ="DIR=/data/misc/stp_dump GROUP=stp";
+ const char *ifname = "stpd";
+ char value[PROPERTY_VALUE_MAX];
+
+ ALOGI("==>%s \n", __func__ );
+/*
+ property_get("ro.crypto.state", value, "");
+ if (!strcmp(value, "")) {
+ do {
+ stp_printf(MSG_INFO, "ro.crypto.state is NULL, Retry");
+ sleep(1);
+ property_get("ro.crypto.state", value, "");
+ stp_printf(MSG_INFO, "ro.crypto.state: %s!", value);
+ }while(!strcmp(value, ""));
+ }
+ stp_printf(MSG_INFO, "ro.crypto.state: %s!", value);
+ if (0 == strcmp(value, "encrypted")) {
+ property_get("vold.decrypt", value, "");
+ if (strcmp(value, "trigger_restart_framework")) {
+ do {
+ stp_printf(MSG_INFO, "Waiting for decrypt done");
+ sleep(1);
+ property_get("vold.decrypt", value, "");
+ stp_printf(MSG_INFO, "vold.decrypt: %s!", value);
+ }while(strcmp(value, "trigger_restart_framework"));
+ }
+ stp_printf(MSG_INFO, "vold.decrypt: %s!", value);
+ stp_printf(MSG_INFO, "Decrypt done!");
+ } else
+ stp_printf(MSG_INFO, "Device is unencrypted!");
+*/
+ stp_d = os_zalloc(sizeof(struct stp_dump));
+ if (stp_d == NULL)
+ {
+ ALOGE("memory allocation for stp_dump failed\n");
+ return -1;
+ }
+ stp_d->ctrl_interface = conf;
+ stp_d->ifname = ifname;
+ stp_d->ctrl_iface = stp_dump_ctrl_iface_init(stp_d);
+ if (stp_d->ctrl_iface == NULL)
+ {
+ ALOGE("Failed to initialize control interface '%s'.\n"
+ "You may have another stp_dump process "
+ "already running or the file was\n"
+ "left by an unclean termination of stp_dump "
+ "in which case you will need\n"
+ "to manually remove this file before starting "
+ "wpa_supplicant again.\n",
+ "used by stp_dump\n");
+ return -1;
+ }
+ else
+ {
+ ALOGI("stp_dump_ctrl_iface_init succeed.\n");
+ }
+ ALOGI("==>%s222 \n", __func__ );
+
+ //set_sched_prio();
+
+ stp_dump_run();
+
+ stp_dump_ctrl_iface_deinit(stp_d->ctrl_iface);
+ os_free(stp_d);
+
+ return 0;
+}
diff --git a/src/connectivity/combo_tool/src/stp_dump/stp_dump.h b/src/connectivity/combo_tool/src/stp_dump/stp_dump.h
new file mode 100755
index 0000000..c3fca88
--- /dev/null
+++ b/src/connectivity/combo_tool/src/stp_dump/stp_dump.h
@@ -0,0 +1,68 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef STP_DUMP_H
+#define STP_DUMP_H
+extern int stp_debug_level;
+
+#ifndef ALOGI
+#define ALOGI printf
+#endif
+#ifndef ALOGE
+#define ALOGE printf
+#endif
+#ifndef ALOGD
+#define ALOGD printf
+#endif
+
+#ifndef PROPERTY_VALUE_MAX
+#define PROPERTY_VALUE_MAX (128)
+#endif
+
+
+enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR };
+extern void android_printf(int level, char *format, ...);
+#define stp_printf(level, ...) \
+ do { \
+ if ((level) >= MSG_MSGDUMP) { \
+ android_printf((level), __VA_ARGS__); \
+ } \
+ printf(__VA_ARGS__); \
+ } while (0)
+
+#endif
+
diff --git a/src/connectivity/combo_tool/src/stp_uart_launcher.c b/src/connectivity/combo_tool/src/stp_uart_launcher.c
new file mode 100755
index 0000000..237bc26
--- /dev/null
+++ b/src/connectivity/combo_tool/src/stp_uart_launcher.c
@@ -0,0 +1,1927 @@
+
+/******************************************************************************
+* C O M P I L E R F L A G S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+*******************************************************************************
+*/
+#include "wmt_ioctl.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <pthread.h>
+/*#include <syslog.h>*/
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/endian.h>
+#include <sys/uio.h>
+#include <linux/serial.h> /* struct serial_struct */
+#include <utils/Log.h>
+
+//For directory operation
+#include <dirent.h>
+#include <cutils/properties.h>
+
+
+/******************************************************************************
+* C O N S T A N T S
+*******************************************************************************
+*/
+
+#define WCN_COMBO_CHIP_ID_PROP "persist.mtk.wcn.combo.chipid"
+#define WCN_DRIVER_READY_PROP "service.wcn.driver.ready"
+#define WCN_COMBO_COREDUMP_PROP "service.wcn.coredump.mode"
+#define WCN_FW_DBG_LOG_PROP "persist.mtk.wcn.fwlog.status"
+#define WCN_DYNAMIC_DUMP_PROP "persist.mtk.wcn.dynamic.dump"
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "6620_launcher"
+//#include "cust_mt6620_test.h" /* project custom header file */
+
+#ifndef N_MTKSTP
+#define N_MTKSTP (15 + 1) /* MediaTek WCN Serial Transport Protocol */
+#endif
+
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+
+#define CUST_COMBO_WMT_DEV "/dev/stpwmt"
+#define CUST_COMBO_STP_DEV "/dev/ttyMT2" //-- for ALPS
+#define CUST_COMBO_PATCH_PATH "/etc/firmware" //-- for ALPS
+
+
+#define CUST_BAUDRATE_DFT (115200)
+
+#define CUST_MULTI_PATCH (1)
+#define MTK_WCN_ENABLE_COREDUMP_BY_PROPERTY 0
+
+typedef enum {
+ STP_MIN = 0x0,
+ STP_UART_FULL = 0x1,
+ STP_UART_MAND = 0x2,
+ STP_BTIF_FULL = 0x3,
+ STP_SDIO = 0x4,
+ STP_MAX = 0x5,
+}STP_MODE;
+
+#define MAX_CMD_LEN (NAME_MAX+1)
+
+typedef enum {
+ UART_DISABLE_FC = 0, /*NO flow control*/
+ UART_MTK_SW_FC = 1, /*MTK SW Flow Control, differs from Linux Flow Control*/
+ UART_LINUX_FC = 2, /*Linux SW Flow Control*/
+ UART_HW_FC = 3, /*HW Flow Control*/
+} STP_UART_FC;
+
+typedef struct
+{
+ const char *key;
+ const char *defValue;
+ char value[PROPERTY_VALUE_MAX];
+
+}SYS_PROPERTY;
+
+
+typedef struct {
+ STP_UART_FC fc;
+ int parity;
+ int stop_bit;
+} STP_UART_CONFIG;
+
+typedef struct {
+ STP_MODE eStpMode;
+ char *pPatchPath;
+ char *pPatchName;
+ char *gStpDev;
+ int iBaudrate;
+ STP_UART_CONFIG sUartConfig;
+}STP_PARAMS_CONFIG, *P_STP_PARAMS_CONFIG;
+
+
+#if CUST_MULTI_PATCH
+typedef struct {
+ int dowloadSeq;
+ char addRess[4];
+ char patchName[256];
+}STP_PATCH_INFO,*P_STP_PATCH_INFO;
+#endif
+
+typedef struct {
+ const char *pCfgItem;
+ char cfgItemValue[NAME_MAX + 1];
+}CHIP_ANT_MODE_INFO, *P_CHIP_ANT_MODE_INFO;
+
+
+typedef struct {
+ int chipId;
+ STP_MODE stpMode;
+ CHIP_ANT_MODE_INFO antMode;
+}CHIP_MODE_INFO, *P_CHIP_MODE_INFO;
+#ifndef WMT_PLAT_APEX
+CHIP_MODE_INFO gChipModeInfo[] = {
+ {0x6620, STP_UART_FULL, {"mt6620.defAnt", "mt6620_ant_m3.cfg"}},
+ {0x6628, STP_UART_FULL, {"mt6628.defAnt", "mt6628_ant_m1.cfg"}},
+ {0x6630, STP_UART_FULL, {"mt6630.defAnt", "mt6630_ant_m1.cfg"}},
+};
+#else
+CHIP_MODE_INFO gChipModeInfo[] = {
+ {0x6620, STP_UART_FULL, {"mt6620.defAnt", "WMT.cfg"}},
+ {0x6628, STP_UART_FULL, {"mt6628.defAnt", "WMT.cfg"}},
+ {0x6630, STP_UART_FULL, {"mt6630.defAnt", "WMT.cfg"}},
+};
+#endif
+/******************************************************************************
+* D A T A T Y P E S
+*******************************************************************************
+*/
+struct cmd_hdr{
+ char *pCmd;
+ int (*hdr_func)(P_STP_PARAMS_CONFIG pStpParamsConfig);
+};
+
+struct speed_map {
+ unsigned int baud;
+ speed_t speed;
+};
+
+/******************************************************************************
+* M A C R O S
+*******************************************************************************
+*/
+#define INIT_CMD(c, e, s) {.cmd= c, .cmd_sz=sizeof(c), .evt=e, .evt_sz=sizeof(e), .str=s}
+
+/******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+*******************************************************************************
+*/
+static int set_speed(int fd, struct termios *ti, int speed);
+int setup_uart_param (int hComPort, int iBaudrate, STP_UART_CONFIG *stp_uart);
+
+int cmd_hdr_baud_115k (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_921k (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_2kk (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_2_5kk (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_3kk (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_3_2kk (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_3_25kk (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_3_5kk (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_4kk (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_stp_open (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_stp_close (P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_stp_rst(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_sch_patch (P_STP_PARAMS_CONFIG pStpParamsConfig);
+static int check_chip_id(void);
+static int setHifInfo(int chipId, char *cfgFilePath);
+static int wmt_cfg_item_parser(char *pItem);
+static int get_wmt_cfg (int chipId);
+static speed_t get_speed (int baudrate);
+
+
+/******************************************************************************
+* P U B L I C D A T A
+*******************************************************************************
+*/
+
+/******************************************************************************
+* P R I V A T E D A T A
+*******************************************************************************
+*/
+static struct speed_map speeds[] = {
+ {115200, B115200},
+ {921600, B921600},
+ {1000000, B1000000},
+ {1152000, B1152000},
+ {2000000, B2000000},
+ {2500000, B2500000},
+ {3000000, B3000000},
+ {3500000, B3500000},
+ {4000000, B4000000},
+};
+
+static STP_UART_CONFIG g_stp_uart_config;
+
+struct cmd_hdr cmd_hdr_table[] = {
+ { "baud_115200_0", cmd_hdr_baud_115k},
+ { "baud_921600_0", cmd_hdr_baud_921k},
+ { "baud_2000000_0", cmd_hdr_baud_2kk},
+ { "baud_2500000_0", cmd_hdr_baud_2_5kk},
+ { "baud_3000000_0", cmd_hdr_baud_3kk},
+ //{ "baud_3200000_0", cmd_hdr_baud_3_2kk},
+ //{ "baud_3250000_0", cmd_hdr_baud_3_25kk},
+ { "baud_3500000_0", cmd_hdr_baud_3_5kk},
+ { "baud_4000000_0", cmd_hdr_baud_4kk},
+ { "open_stp", cmd_hdr_stp_open},
+ { "close_stp", cmd_hdr_stp_close},
+ { "rst_stp", cmd_hdr_stp_rst},
+ { "srh_patch", cmd_hdr_sch_patch},
+};
+
+static volatile sig_atomic_t __io_canceled = 0;
+static char gPatchName[NAME_MAX+1]= {0};
+static char gPatchFolder[NAME_MAX+1]= {0};
+static char gStpDev[NAME_MAX+1]= {0};
+static int gStpMode = -1;
+static char gWmtCfgName[NAME_MAX+1] = {0};
+static int gWmtFd = -1;
+static int gTtyFd = -1;
+static char gCmdStr[MAX_CMD_LEN]= {0};
+static char gRespStr[MAX_CMD_LEN]= {0};
+static int gFmMode = 2; /* 1: i2c, 2: comm I/F */
+static const char *gUartName = NULL;
+
+#if CUST_MULTI_PATCH
+static unsigned int gPatchNum = 0;
+static unsigned int gDwonSeq = 0;
+static P_STP_PATCH_INFO pStpPatchInfo = NULL;
+static STP_PATCH_INFO gStpPatchInfo;
+#endif
+
+pthread_t thread_handle = -1;
+/******************************************************************************
+* F U N C T I O N S
+*******************************************************************************
+*/
+
+/* Used as host uart param setup callback */
+int setup_uart_param (
+ int hComPort,
+ int iBaudrate,
+ STP_UART_CONFIG *stpUartConfig)
+{
+ struct termios ti;
+ int fd;
+
+ if(!stpUartConfig){
+ ALOGE("Invalid stpUartConfig");
+ return -2;
+ }
+
+ ALOGI("setup_uart_param %d %d\n", iBaudrate, stpUartConfig->fc);
+
+ fd = hComPort;
+ if (fd < 0) {
+ ALOGE("Invalid serial port");
+ return -2;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (tcgetattr(fd, &ti) < 0) {
+ ALOGE("Can't get port settings");
+ return -3;
+ }
+
+ cfmakeraw(&ti);
+
+ ALOGI("ti.c_cflag = 0x%08x\n", ti.c_cflag);
+ ti.c_cflag |= CLOCAL;
+ ALOGI("CLOCAL = 0x%x\n", CLOCAL);
+ ALOGI("(ori)ti.c_iflag = 0x%08x\n", ti.c_iflag);
+ ALOGI("(ori)ti.c_cflag = 0x%08x\n", ti.c_cflag);
+ ALOGI("stpUartConfig->fc= %d (0:none,sw,hw,linux)\n", stpUartConfig->fc);
+
+ if(stpUartConfig->fc == UART_DISABLE_FC){
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ } else if(stpUartConfig->fc == UART_MTK_SW_FC){
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag |= 0x80000000; /*MTK Software FC*/
+ } else if(stpUartConfig->fc == UART_HW_FC){
+ ti.c_cflag |= CRTSCTS; /*RTS, CTS Enable*/
+ ti.c_iflag &= ~(0x80000000);
+ } else if(stpUartConfig->fc == UART_LINUX_FC){
+ ti.c_iflag |= (IXON | IXOFF | IXANY); /*Linux Software FC*/
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ }else {
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ }
+
+ ALOGI("c_c CRTSCTS = 0x%16x\n", CRTSCTS);
+ ALOGI("c_i IXON = 0x%08x\n", IXON);
+ ALOGI("c_i IXOFF = 0x%08x\n", IXOFF);
+ ALOGI("c_i IXANY = 0x%08x\n", IXANY);
+ ALOGI("(aft)ti.c_iflag = 0x%08x\n", ti.c_iflag);
+ ALOGI("(aft)ti.c_cflag = 0x%08x\n\n", ti.c_cflag);
+
+ if (tcsetattr(fd, TCSANOW, &ti) < 0) {
+ ALOGE("Can't set port settings");
+ return -4;
+ }
+
+ /* Set baudrate */
+ if (set_speed(fd, &ti, iBaudrate) < 0) {
+ ALOGE("Can't set initial baud rate");
+ return -5;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ return 0;
+}
+
+static void sig_hup(int sig)
+{
+ fprintf(stderr, "sig_hup...\n");
+}
+
+static void sig_term(int sig)
+{
+ fprintf(stderr, "sig_term...\n");
+ __io_canceled = 1;
+ ioctl(gWmtFd, WMT_IOCTL_SET_LAUNCHER_KILL, 1);
+}
+
+
+static speed_t get_speed (int baudrate)
+{
+ unsigned int idx;
+ for (idx = 0; idx < sizeof(speeds)/sizeof(speeds[0]); idx++) {
+ if (baudrate == (int)speeds[idx].baud) {
+ return speeds[idx].speed;
+ }
+ }
+ return CBAUDEX;
+}
+
+int set_speed(int fd, struct termios *ti, int speed)
+{
+ struct serial_struct ss;
+ int baudenum = get_speed(speed);
+
+ if (speed != CBAUDEX) {
+ //printf("%s: standard baudrate: %d -> 0x%08x\n", __FUNCTION__, speed, baudenum);
+ if ((ioctl(fd, TIOCGSERIAL, &ss)) < 0) {
+ ALOGI("%s: BAUD: error to get the serial_struct info:%s\n", __FUNCTION__, strerror(errno));
+ return -1;
+ }
+ ss.flags &= ~ASYNC_SPD_CUST;
+#if defined(SERIAL_STRUCT_EXT) /*modified in serial_struct.h*/
+ memset(ss.reserved, 0x00, sizeof(ss.reserved));
+#endif
+ ss.flags |= (1 << 13); /*set UPFLOWLATENCY flat to tty, or serial_core will reset tty->low_latency to 0*/
+ /*set standard buadrate setting*/
+ if ((ioctl(fd, TIOCSSERIAL, &ss)) < 0) {
+ ALOGI("%s: BAUD: error to set serial_struct:%s\n", __FUNCTION__, strerror(errno));
+ return -2;
+ }
+ cfsetospeed(ti, baudenum);
+ cfsetispeed(ti, baudenum);
+ return tcsetattr(fd, TCSANOW, ti);
+ }
+ else {
+ ALOGI("%s: unsupported non-standard baudrate: %d -> 0x%08x\n", __FUNCTION__, speed, baudenum);
+ return -3;
+ }
+}
+
+
+int cmd_hdr_baud_115k (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 115200, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_921k (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 921600, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_2kk (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 2000000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_2_5kk (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 2500000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_3kk (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 3000000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_3_2kk (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 3200000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_3_25kk (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 3250000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_3_5kk (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 3500000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_4kk (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 4000000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_stp_open (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ int ld;
+ if ((STP_UART_FULL == gStpMode) && (-1 == gTtyFd)) {
+ gTtyFd = open(gStpDev, O_RDWR | O_NOCTTY);
+ if (gTtyFd < 0) {
+ fprintf(stderr, "Can't open serial port %s\n", gStpDev);
+ return -2;
+ }
+ ALOGI("real_tty(%s) opened(%d)\n", gStpDev, gTtyFd);
+
+ /* Set TTY to N_MTKSTP line discipline */
+ ld = N_MTKSTP;
+ if (ioctl(gTtyFd, TIOCSETD, &ld) < 0) {
+ fprintf(stderr, "Can't set ldisc to N_MTKSTP\n");
+ return -3;
+ }
+
+ //printf("Set tty->low_latency\n");
+ if (ioctl(gTtyFd, HCIUARTSETPROTO, 0) < 0) {
+ ALOGE("Can't set HCIUARTSETPROTO\n");
+ return -4;
+ }
+ return 0;
+ }
+ else {
+ fprintf(stderr, "stp_open fail: stp_mode(%d) real_tty_fd(%d) \n", gStpMode, gTtyFd);
+ return -1;
+ }
+}
+
+int cmd_hdr_stp_close (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ int ld;
+
+ if ((STP_UART_FULL == gStpMode) && (0 <= gTtyFd)) {
+ /* Restore TTY line discipline */
+ ld = N_TTY;
+ if (ioctl(gTtyFd, TIOCSETD, &ld) < 0) {
+ ALOGE("Can't restore line discipline");
+ return -2;
+ }
+
+ close(gTtyFd);
+ gTtyFd = -1;
+ return 0;
+ } else if (gTtyFd == -1) {
+ return 0;
+ } else {
+ fprintf(stderr, "stp_close fail: stp_mode(%d) real_tty_fd(%d) \n", gStpMode, gTtyFd);
+ return -1;
+ }
+}
+
+int cmd_hdr_stp_rst (P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ int ret = 0;
+ /*this step fail?*/
+ ret = cmd_hdr_stp_close(pStpParamsConfig);
+ /*here, launcher is close state*/
+ ret = cmd_hdr_stp_open(pStpParamsConfig);
+ return ret;
+}
+
+#if CUST_MULTI_PATCH
+int cmd_hdr_sch_patch (P_STP_PARAMS_CONFIG pStpParamsConfig)
+{
+ //#define PATCH_PATH "/system/etc/firmware"
+ int chipId = 0;
+ int hwVersion = 0;
+ int fwVersion = 0;
+ char chipName[16] = {0};
+ char patchFullName[256] = {0};
+ unsigned int patchVer = 0;
+ DIR *pDir = NULL;
+ int patchFd = -1;
+ int iRet = 0;
+ int bytes;
+ unsigned int patchNum = 0;
+ char patchInfo[8] = {0};
+ unsigned int isFirst = 1;
+ P_STP_PATCH_INFO pstPaInfo = NULL;
+ struct dirent* pDirent = NULL;
+
+ if (gWmtFd > 0)
+ {
+ /*1. ioctl to get CHIP ID*/
+ chipId = ioctl(gWmtFd, WMT_IOCTL_GET_CHIP_INFO, 0);
+ if((0x0321 == chipId) || (0x0335 == chipId) || (0x0337 == chipId))
+ {
+ chipId = 0x6735;
+ ALOGI("for denali chipid convert\n");
+ }
+ if (0x0326 == chipId) {
+ chipId = 0x6755;
+ ALOGI("for jade chipid convert\n");
+ }
+ if (0x0279 == chipId) {
+ chipId = 0x6797;
+ ALOGI("for everest chipid convert\n");
+ }
+ strncpy(chipName, "mt",strlen("mt"));
+ sprintf(chipName + strlen("mt"), "%04x", chipId);
+
+#if 0
+ /* single patch 6630 */
+ if(!strcmp(chipName,"mt6630"))//apply to MT6630
+ {
+ strcat (chipName, "_patch");
+ ALOGI ("6630 patch name pre-fix:%s\n", chipName);
+
+ /*2. ioctl to get FIRMWARE VERSION*/
+ fwVersion = ioctl(gWmtFd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI ("fwVersion:0x%04x\n", fwVersion);
+
+ /*3. open directory patch located*/
+ if (NULL == pStpParamsConfig->pPatchPath)
+ {
+ pStpParamsConfig->pPatchPath = CUST_COMBO_PATCH_PATH;
+ }
+ pDir = opendir(pStpParamsConfig->pPatchPath);
+ if (NULL == pDir)
+ {
+ ALOGE("patch path cannot be opened");
+ iRet = -1;
+ return iRet;
+ }
+ while (NULL != (pDirent = readdir(pDir)))
+ {
+ patchVer = 0;
+
+ if (0 == (strncmp(pDirent->d_name, chipName, strlen(chipName))))
+ { /*4.1. search patch name begined with chipName*/
+ strcpy (patchFullName, pStpParamsConfig->pPatchPath);
+ strcat (patchFullName, "/"); // robust, if input patch is /etc/firmwre/ no issue should be happened.
+ strcat (patchFullName, pDirent->d_name);
+
+ ALOGI ("%s\n", patchFullName);
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 < (patchFd = (open(patchFullName, O_RDONLY ))))
+ {
+ /*4.2. read patch header and check if metch with MAJOR+MINOR number in fw version */
+ if (-1 != lseek (patchFd, 22, SEEK_SET))
+ {
+ read(patchFd, ((char *)&patchVer) + 1, 1);
+ read(patchFd, ((char *)&patchVer), 1);
+ /*print hardware version information in patch*/
+ ALOGI ("fw Ver in patch: 0x%04x\n", patchVer);
+ if (0 == ((patchVer ^ fwVersion) & 0x00ff))
+ {
+ ioctl(gWmtFd, WMT_IOCTL_SET_PATCH_NAME, patchFullName);
+ ALOGI ("fw Ver in patch matches with firmware version\n");
+ close (patchFd);
+ break;
+ }
+ }
+ else
+ {
+ ALOGE("seek failed\n");
+ }
+ close (patchFd);
+ patchFd = -1;
+ }
+ else
+ {
+ ALOGI("open patch file(%s) failed\n", patchFullName);
+ //ALOGE(patchFullName);
+ }
+ }
+ }
+ /*5. return value*/
+ closedir(pDir);
+ pDir = NULL;
+ }
+#endif
+
+ if ((!strcmp(chipName, "mt6620")) || (!strcmp(chipName, "mt6628")) || (!strcmp(chipName, "mt6630")) ||
+ (!strcmp(chipName, "mt6572")) || (!strcmp(chipName, "mt6582")) || (!strcmp(chipName, "mt6592")) ||
+ (!strcmp(chipName, "mt8127"))|| (!strcmp(chipName, "mt7623")) || (!strcmp(chipName, "mt6571")) || (!strcmp(chipName, "mt6752")) ||
+ (!strcmp(chipName, "mt8163")) || (!strcmp(chipName, "mt6580")) ||
+ (!strcmp(chipName, "mt6735")) || (!strcmp(chipName, "mt6755")) || (!strcmp(chipName, "mt6797")))
+ {
+ if ((!strcmp(chipName, "mt6572")) || (!strcmp(chipName, "mt6582")) || (!strcmp(chipName, "mt6592")))
+ {
+ strncpy(chipName, "ROMv1", strlen("ROMv1"));
+ chipName[5] = '\0';
+ }else if(!strcmp(chipName,"mt8127") || !strcmp(chipName,"mt6571")){
+ strncpy(chipName,"ROMv2",strlen("ROMv2"));
+ chipName[5] = '\0';
+ } else if (!strcmp(chipName, "mt6755") ||!strcmp(chipName, "mt6752") || !strcmp(chipName, "mt6735")
+ || !strcmp(chipName, "mt8163") || !strcmp(chipName, "mt6580") || !strcmp(chipName, "mt7623")) {
+ strncpy(chipName, "ROMv2_lm", strlen("ROMv2_lm"));
+ } else if (!strcmp(chipName, "mt6797")) {
+ strncpy(chipName, "ROMv3", strlen("ROMv3"));
+ chipName[5] = '\0';
+ }
+ strcat (chipName, "_patch");
+ ALOGI ("patch name pre-fix:%s\n", chipName);
+ /*2. ioctl to get FIRMWARE VERSION*/
+ fwVersion = ioctl(gWmtFd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI ("fwVersion:0x%04x\n", fwVersion);
+ /*3. open directory patch located*/
+ if (NULL == pStpParamsConfig->pPatchPath)
+ {
+ pStpParamsConfig->pPatchPath = CUST_COMBO_PATCH_PATH;
+ }
+
+ {
+ pDir = opendir(pStpParamsConfig->pPatchPath);
+ if (NULL == pDir)
+ {
+ ALOGE("patch path cannot be opened");
+ iRet = -1;
+ return iRet;
+ }
+ while (NULL != (pDirent = readdir(pDir)))
+ {
+ patchVer = 0;
+
+ if (0 == (strncmp(pDirent->d_name, chipName, strlen(chipName))))
+ { /*4.1. search patch name begined with chipName*/
+ strcpy (patchFullName, pStpParamsConfig->pPatchPath);
+ strcat (patchFullName, "/"); // robust, if input patch is /etc/firmwre/ no issue should be happened.
+ strcat (patchFullName, pDirent->d_name);
+
+ ALOGI ("%s\n", patchFullName);
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 <= (patchFd = (open(patchFullName, O_RDONLY ))))
+ {
+ /*4.2. read patch header and check if metch with MAJOR+MINOR number in fw version */
+ if (-1 != lseek (patchFd, 22, SEEK_SET))
+ {
+ memset(&gStpPatchInfo,0,sizeof(gStpPatchInfo));
+ memset(patchInfo,0,sizeof(patchInfo));
+
+ bytes = read(patchFd, ((char *)&patchVer) + 1, 1);
+ if (-1 == bytes) {
+ ALOGI ("read patchVer1 failed!\n");
+ goto readfailed;
+ }
+ bytes = read(patchFd, ((char *)&patchVer), 1);
+ if (-1 == bytes) {
+ ALOGI ("read patchVer failed!\n");
+ goto readfailed;
+ }
+ /*print hardware version information in patch*/
+ ALOGI ("fw Ver in patch: 0x%04x\n", patchVer);
+ if (0 == ((patchVer ^ fwVersion) & 0x00ff)) {
+ bytes = read(patchFd, patchInfo, 4);
+ if (-1 == bytes) {
+ ALOGI ("read patchInfo failed!\n");
+ goto readfailed;
+ }
+ patchInfo[4] = '\0';
+ ALOGI("read patch info:0x%02x,0x%02x,0x%02x,0x%02x\n",patchInfo[0],patchInfo[1],patchInfo[2],patchInfo[3]);
+ if (1 == isFirst) {
+ gPatchNum = (patchInfo[0] & 0xF0) >> 4;
+ ALOGI("gpatchnum = [%d]\n",gPatchNum);
+ ioctl(gWmtFd,WMT_IOCTL_SET_PATCH_NUM,gPatchNum);
+
+ gDwonSeq = (patchInfo[0] & 0x0F);
+ ALOGI("gdwonseq = [%d]\n",gDwonSeq);
+ gStpPatchInfo.dowloadSeq = gDwonSeq;
+ memcpy(gStpPatchInfo.addRess,patchInfo,sizeof(gStpPatchInfo.addRess));
+ gStpPatchInfo.addRess[0] = 0x00;
+ strncpy(gStpPatchInfo.patchName, patchFullName, sizeof(gStpPatchInfo.patchName) - 1);
+ gStpPatchInfo.patchName[sizeof(gStpPatchInfo.patchName) - 1] = '\0';
+ //printf("gStpPatchInfo address info:0x%02x,0x%02x,0x%02x,0x%02x\n",gStpPatchInfo.addRess[0],gStpPatchInfo.addRess[1],gStpPatchInfo.addRess[2],gStpPatchInfo.addRess[3]);
+ ioctl(gWmtFd,WMT_IOCTL_SET_PATCH_INFO,&gStpPatchInfo);
+ isFirst ++;
+ } else {
+ gDwonSeq = (patchInfo[0] & 0x0F);
+ ALOGI("gdwonseq = [%d]\n",gDwonSeq);
+ gStpPatchInfo.dowloadSeq = gDwonSeq;
+ memcpy(gStpPatchInfo.addRess,patchInfo,sizeof(gStpPatchInfo.addRess));
+ gStpPatchInfo.addRess[0] = 0x00;
+ strncpy(gStpPatchInfo.patchName, patchFullName, sizeof(gStpPatchInfo.patchName) - 1);
+ gStpPatchInfo.patchName[sizeof(gStpPatchInfo.patchName) - 1] = '\0';
+ //printf("gStpPatchInfo address info:0x%02x,0x%02x,0x%02x,0x%02x\n",gStpPatchInfo.addRess[0],gStpPatchInfo.addRess[1],gStpPatchInfo.addRess[2],gStpPatchInfo.addRess[3]);
+ ioctl(gWmtFd,WMT_IOCTL_SET_PATCH_INFO,&gStpPatchInfo);
+ }
+ }
+ }
+ else
+ {
+ ALOGE("seek failed\n");
+ }
+readfailed:
+ close (patchFd);
+ patchFd = -1;
+ }
+ else
+ {
+ ALOGI("open patch file(%s) failed\n", patchFullName);
+ //ALOGE(patchFullName);
+ }
+ }
+ }
+ /*5. return value*/
+ closedir(pDir);
+ pDir = NULL;
+ }
+ }
+ }
+ else
+ {
+ ALOGE("file descriptor is not valid\n");
+ iRet = -2;
+ }
+ return iRet;
+}
+#else
+int cmd_hdr_sch_patch (P_STP_PARAMS_CONFIG pStpParamsConfig)
+{
+ //#define PATCH_PATH "/system/etc/firmware"
+ int chipId = 0;
+ int hwVersion = 0;
+ int fwVersion = 0;
+ char chipName[16] = {0};
+ char patchFullName[256] = {0};
+ unsigned int patchVer = 0;
+ DIR *pDir = NULL;
+ int patchFd = -1;
+ struct dirent* pDirent = NULL;
+ int iRet = -1;
+
+ if (gWmtFd > 0)
+ {
+ /*1. ioctl to get CHIP ID*/
+ chipId = ioctl(gWmtFd, WMT_IOCTL_GET_CHIP_INFO, 0);
+ strcpy(chipName, "mt");
+ sprintf (chipName + strlen(chipName), "%04x", chipId);
+ strcat (chipName, "_patch");
+ ALOGI ("patch name pre-fix:%s\n", chipName);
+#if 0
+ /*2. ioctl to get HARDWARE VERSION*/
+ hwVersion = ioctl(gWmtFd, 12, 1);
+ ALOGI ("hwVersion:0x%04x\n", hwVersion);
+#else
+ /*2. ioctl to get FIRMWARE VERSION*/
+ fwVersion = ioctl(gWmtFd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI ("fwVersion:0x%04x\n", fwVersion);
+#endif
+ /*3. open directory patch located*/
+ if (NULL == pStpParamsConfig->pPatchPath)
+ {
+ pStpParamsConfig->pPatchPath = CUST_COMBO_PATCH_PATH;
+ }
+ pDir = opendir(pStpParamsConfig->pPatchPath);
+ if (NULL == pDir)
+ {
+ ALOGE("patch path cannot be opened");
+ iRet = -2;
+ return iRet;
+ }
+ while (NULL != (pDirent = readdir(pDir)))
+ {
+ patchVer = 0;
+
+ if (0 == (strncmp(pDirent->d_name, chipName, strlen(chipName))))
+ { /*4.1. search patch name begined with chipName*/
+ strcpy (patchFullName, pStpParamsConfig->pPatchPath);
+ strcat (patchFullName, "/"); // robust, if input patch is /etc/firmwre/ no issue should be happened.
+ strcat (patchFullName, pDirent->d_name);
+
+ ALOGI ("%s\n", patchFullName);
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 < (patchFd = (open(patchFullName, O_RDONLY ))))
+ {
+
+ /*4.2. read patch header and check if metch with MAJOR+MINOR number in fw version */
+ if (-1 != lseek (patchFd, 22, SEEK_SET))
+ {
+
+ read(patchFd, ((char *)&patchVer) + 1, 1);
+ read(patchFd, ((char *)&patchVer), 1);
+ /*print firmware version information in patch*/
+ ALOGI ("fw Ver in patch: 0x%04x\n", patchVer);
+ if (0 == ((patchVer ^ fwVersion) & 0x00ff))
+ {
+ ioctl(gWmtFd, WMT_IOCTL_SET_PATCH_NAME, patchFullName);
+ ALOGI ("fw Ver in patch matches with firmware version\n");
+ iRet = 0;
+ close (patchFd);
+ break;
+ }
+ }
+ else
+ {
+ ALOGE("seek failed\n");
+ }
+ close (patchFd);
+ patchFd = -1;
+ }
+ else
+ {
+ //printf("open patch file(%s) failed\n", patchFullName);
+ ALOGE(patchFullName);
+ }
+ }
+
+ }
+
+ /*5. return value*/
+ closedir(pDir);
+ pDir = NULL;
+ }
+ else
+ {
+ ALOGE("file descriptor is not valid\n");
+ iRet = -1;
+ }
+ return iRet;
+}
+#endif
+/*
+ret 0: success
+ret 1: cmd not found
+ret -x: handler return value
+*/
+int handle_cmd (P_STP_PARAMS_CONFIG pStpParamsConfig, char *cmd, int len) {
+ int ret = 1;
+ int i;
+ int cmd_len;
+
+ for (i = 0; i < (int)(sizeof(cmd_hdr_table)/sizeof(cmd_hdr_table[0])); ++i) {
+ cmd_len = (int)strlen(cmd_hdr_table[i].pCmd);
+ if (!strncmp(cmd_hdr_table[i].pCmd, cmd, (len < cmd_len) ? len : cmd_len)) {
+ ret = (*cmd_hdr_table[i].hdr_func)(pStpParamsConfig);
+ }
+ }
+
+ return ret;
+}
+
+void display_usage(int chipid)
+{
+ unsigned int index = 0;
+ char * usage1[] = {
+ "MTK WCN combo tool set, version 1.0-release",
+ "Usage: consys_launcher -m mode -p patchfolderpath",
+ " -m (BT/GPS/FM common interface mode selection)",
+ " -1: UART mode (common interface: UART)",
+ " -3: BTIF mode (common interface: BTIF)",
+ " -4: SDIO mode (common interface: SDIO)",
+ " -p (MTK WCN soc conssy chip firmware patch location)",
+ " -e.g. /etc/firmware",
+ "e.g. consys_launcher -m 3 -p /etc/firmware/",
+ };
+ char * usage2[] = {
+ "MTK WCN combo tool set, version 1.0-release",
+ "Usage: 6620_launcher -m mode -p patchfolderpath [-d uartdevicenode] [-b baudrate] [-c uartflowcontrol]",
+// " -m (BT/GPS/FM common interface mode selection)",
+// " -1: UART mode (common interface: UART)",
+// " -1: UART full mode (common interface UART)",
+// " -2: UART mandetary mode (common interface UART)",
+ " -4: UART mode (common interface SDIO)",
+ " -p (MTK WCN Combo chip firmware patch location)",
+ " -e.g. /etc/firmware",
+ " -b (Baudrate set when BT/GPS/FM runs under UART mode, no needed under SDIO mode)",
+ " -115200/921600/2000000/2500000/3000000/3500000/4000000",
+ " -d (UART device node, when under UART mode, no needed under SDIO mode)",
+ " -e.g. /dev/ttyMT1, /dev/ttyMT2, /dev/ttyHS2, etc.",
+ " -c (UART flowcontrol set)",
+ " -0, no flowcontrol default value, please donot modify this parameter",
+ "e.g. 6620_launcher 4 /etc/firmware/mt6628_patch_hdr.bin",
+ "e.g. 6620_launcher -m 1 -p /etc/firmware/",
+ "e.g. 6620_launcher -m 1 -n /etc/firmware/mt6628_patch_hdr.bin",
+ "e.g. 6620_launcher -m 4 -d /dev/ttyMT2 -b 4000000 -n /etc/firmware/mt6628_patch_hdr.bin",
+ };
+ if(0x6582 == chipid || 0x8127 == chipid)
+ {
+ for (index = 0; index < sizeof (usage1)/sizeof (usage1[0]); index++ )
+ {
+ ALOGI("%s\n", usage1[index]);
+ }
+ }else
+ {
+ for (index = 0; index < sizeof (usage2)/sizeof (usage2[0]); index++ )
+ {
+ ALOGI("%s\n", usage2[index]);
+ }
+ }
+ exit(EXIT_FAILURE);
+}
+
+
+int para_valid_check (P_STP_PARAMS_CONFIG pStpParamConfig)
+{
+ if ((NULL != pStpParamConfig->pPatchPath) || (NULL != pStpParamConfig->pPatchName))
+ {
+ if (NULL != pStpParamConfig->pPatchPath){
+ ALOGI ("MCU patch folder path: %s\n", pStpParamConfig->pPatchPath);
+ }
+ if (NULL != pStpParamConfig->pPatchName){
+ ALOGI ("MCU patch full path: %s\n", pStpParamConfig->pPatchName);
+ }
+ }
+ else
+ {
+ puts ("MCU patch name or patch not found, exit.");
+ return -1;
+ }
+ if(pStpParamConfig->eStpMode != STP_SDIO && pStpParamConfig->eStpMode != STP_UART_MAND && pStpParamConfig->eStpMode != STP_UART_FULL)
+ {
+ puts("Stp Mode is not set, common interface use default: SDIO Mode");
+ pStpParamConfig->eStpMode = STP_SDIO;
+ return 0;
+ }
+ //SDIO mode: eStpMode = STP_SDIO && (pPachName != NULL || pPatchPath != NULL)
+ if (pStpParamConfig->eStpMode == STP_SDIO)
+ {
+ ALOGI ("Common Interface: SDIO mode\n");
+ }
+ else if (pStpParamConfig->eStpMode == STP_UART_MAND || pStpParamConfig->eStpMode == STP_UART_FULL)
+ {
+ //UART mode: (eStpMode = STP_MAND_MODE || STP_FULL_MODE) && (pPachName != NULL || pPatchPath != NULL) && (iBaudrate > 0)
+ ALOGI ("Common Interface: UART mode\n");
+ if (NULL == pStpParamConfig->gStpDev){
+ pStpParamConfig->gStpDev = CUST_COMBO_STP_DEV;
+ ALOGI ("no uart device input, use default: %s\n", pStpParamConfig->gStpDev);
+ }
+ if (pStpParamConfig->iBaudrate < 0)
+ {
+ //FixMe:Chaozhong, add baudrate validation check
+ pStpParamConfig->iBaudrate = 4000000;
+ ALOGI ("no baudrate input, use default: %d\n", pStpParamConfig->iBaudrate);
+ }
+
+ }
+ return 0;
+}
+
+static int wmt_cfg_item_parser(char *pItem)
+{
+ int maxIndex = sizeof (gChipModeInfo) / sizeof (gChipModeInfo[0]);
+ int index = 0;
+ int length = 0;
+ char *str = NULL;
+ char *keyStr = NULL;
+ char *valueStr = NULL;
+ if (NULL == pItem)
+ {
+ ALOGI("Warning:pItem is NULL\n");
+ return -1;
+ }
+ /*all item must be start with mt66xx*/
+ str = strstr(pItem, "m");
+ if (NULL == str)
+ {
+ ALOGI("Warning:no string start with 'm' found in %s\n", pItem);
+ return -2;
+ }
+
+ for (index = 0; index < maxIndex; index++)
+ {
+ keyStr = (char*)gChipModeInfo[index].antMode.pCfgItem;
+
+ if (0 == strncasecmp(str, keyStr, strlen (keyStr)))
+ {
+ str = strstr(str, "=");
+ if (NULL == str)
+ {
+ ALOGI("Warning:no '=' found in %s\n", str);
+ return -3;
+ }
+ str = strstr(str, "m");
+ if (NULL == str)
+ {
+ ALOGI("Warning:no 'm' found in %s\n", str);
+ return -4;
+ }
+
+
+ while (((*str)==' ') || ((*str)=='\t') || ((*str)=='\n'))
+ {
+ if (str >= pItem + strlen(pItem))
+ {
+ break;
+ }
+ str++;
+ }
+ valueStr = str;
+
+ while (((*str)!=' ') && ((*str)!='\t') && ((*str)!='\0') && ((*str)!='\n') && ((*str)!='\r'))
+ {
+ if (str >= pItem + strlen(pItem))
+ {
+ ALOGI("break\n");
+ break;
+ }
+ str++;
+
+ }
+ *str = '\0';
+ length = sizeof(gChipModeInfo[index].antMode.cfgItemValue);
+ strncpy(gChipModeInfo[index].antMode.cfgItemValue, valueStr, length - 1);
+ gChipModeInfo[index].antMode.cfgItemValue[length - 1] = '\0';
+ ALOGI("Info:key:%s value:%s\n", keyStr, gChipModeInfo[index].antMode.cfgItemValue);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void set_coredump_flag(void)
+{
+#define ANDROID_BUILD_TYPE "ro.build.type"
+#define COREDUMP_CTRL_FILE "/data/coredump"
+ SYS_PROPERTY buildTypeProp;
+ buildTypeProp.key = ANDROID_BUILD_TYPE;
+ buildTypeProp.defValue = NULL;
+ SYS_PROPERTY coredump_mode;
+ coredump_mode.key = WCN_COMBO_COREDUMP_PROP;
+ coredump_mode.defValue = NULL;
+ int coredumpEnableFlag = 0;
+ int iRet = -1;
+ int coredumpFd = -1;
+ if (gWmtFd < 0) {
+ ALOGI("%s:invalid wmt fd\n", __func__);
+ return;
+ }
+#if MTK_WCN_ENABLE_COREDUMP_BY_PROPERTY
+ iRet = property_get(coredump_mode.key, coredump_mode.value, NULL);
+ if (0 != iRet) {
+ ALOGI("key:(%s)-value:(%s)\n", coredump_mode.key, coredump_mode.value);
+ } else {
+ ALOGI("get coredump_mode property(%s) failed\n", coredump_mode.key);
+ iRet = property_set(coredump_mode.key, "0");
+ if (0 != iRet)
+ ALOGI("set property(%s) to %s failed,iRet:%d, errno:%d\n", coredump_mode.key, "0", iRet, errno);
+ else
+ ALOGI("set property(%s) default value is %s succeed.\n", coredump_mode.key, "0");
+ }
+ if (0 == strcmp(coredump_mode.value, "1")) {
+ coredumpEnableFlag = 1;
+ ALOGI("Connectivity coredump set aee mode: %d\n", coredumpEnableFlag);
+ } else if (0 == strcmp(coredump_mode.value, "2")) {
+ coredumpEnableFlag = 2;
+ ALOGI("Connectivity coredump set stp_dump mode: %d\n", coredumpEnableFlag);
+ } else {
+ coredumpEnableFlag = 0;
+ ALOGI("Connectivity coredump is disabled!\n");
+ }
+
+#else
+ //read from system property
+ iRet = property_get(buildTypeProp.key, buildTypeProp.value, buildTypeProp.defValue);
+ if (0 != iRet)
+ {
+ ALOGI("key:(%s)-value:(%s)\n", buildTypeProp.key, buildTypeProp.value);
+ if (0 == strcmp(buildTypeProp.value, "eng")) {
+ coredumpEnableFlag = 1;
+ ALOGI("Connectivity coredump set default aee mode: %d\n", coredumpEnableFlag);
+ } else if (0 == strcmp(buildTypeProp.value, "userdebug")) {
+ iRet = property_get(coredump_mode.key, coredump_mode.value, NULL);
+ if (0 != iRet) {
+ ALOGI("key:(%s)-value:(%s)\n", coredump_mode.key, coredump_mode.value);
+ if (0 == strcmp(coredump_mode.value, "1")) {
+ coredumpEnableFlag = 1;
+ ALOGI("Connectivity coredump set aee mode: %d\n", coredumpEnableFlag);
+ } else if (0 == strcmp(coredump_mode.value, "2")) {
+ coredumpEnableFlag = 2;
+ ALOGI("Connectivity coredump set stp_dump mode: %d\n", coredumpEnableFlag);
+ } else {
+ coredumpEnableFlag = 0;
+ ALOGI("Connectivity coredump is disabled!\n");
+ }
+ } else {
+ ALOGI("get coredump_mode property(%s) failed\n", coredump_mode.key);
+ coredumpEnableFlag = 0;
+ ALOGI("Connectivity coredump is disabled!\n");
+ }
+ } else {
+ coredumpEnableFlag = 0;
+ iRet = property_set(coredump_mode.key, "0");
+ if (0 != iRet)
+ ALOGI("set property(%s) to %s failed,iRet:%d, errno:%d\n", coredump_mode.key, "0", iRet, errno);
+ else
+ ALOGI("set property(%s) to %s succeed.\n", coredump_mode.key, "0");
+ }
+ }
+ else
+ {
+ ALOGI("get system build type(%s) failed\n", buildTypeProp.key);
+ }
+#endif
+#if 0
+ coredumpFd = open(COREDUMP_CTRL_FILE, O_RDWR | O_NOCTTY);
+ if (coredumpFd >= 0)
+ {
+ ALOGI("coredump control file: %s found.\n", COREDUMP_CTRL_FILE);
+ coredumpEnableFlag = 1;
+ if (0 == close(coredumpFd))
+ {
+ ALOGI("close %s succeed\n", COREDUMP_CTRL_FILE);
+ }
+ else
+ {
+ ALOGE("close %s failed, errno:%d\n", COREDUMP_CTRL_FILE, errno);
+ }
+ coredumpFd = -1;
+ } else
+ {
+ ALOGI("coredump control file: %s not found, errno:%d.\n", COREDUMP_CTRL_FILE, errno);
+ }
+ if (coredumpEnableFlag)
+#endif
+ /*set coredump mode to kernel driver*/
+ ioctl(gWmtFd, WMT_IOCTL_WMT_COREDUMP_CTRL, coredumpEnableFlag);
+ return;
+}
+
+
+static int get_wmt_cfg (int chipId)
+{
+#define WMTCFGFILEPATH "/system/etc/firmware/WMT.cfg"
+#define OPENMODE "r"
+#define MAXLINELEN 512
+ FILE * file = NULL;
+ int iRet = -1;
+ char *pStr = NULL;
+ char line[MAXLINELEN];
+
+ file = fopen(WMTCFGFILEPATH, OPENMODE);
+ if (NULL == file)
+ {
+ ALOGI("%s cannot be opened, errno:%d\n", WMTCFGFILEPATH, errno);
+ return -2;
+ }
+ iRet = 0;
+ do {
+ pStr = fgets(line, MAXLINELEN, file);
+ if (NULL == pStr)
+ {
+ ALOGI("NULL is returned, eighter EOF or error maybe found\n");
+ break;
+ }
+
+ wmt_cfg_item_parser(line);
+
+ memset(line, 0, MAXLINELEN);
+
+ }while (pStr != NULL);
+
+ if (NULL != file)
+ {
+
+ if (0 == fclose(file))
+ {
+ ALOGI("close %s succeed\n", WMTCFGFILEPATH);
+ }
+ else
+ {
+ ALOGI("close %s failed, errno:%d\n", WMTCFGFILEPATH, errno);
+ }
+ }
+ return iRet;
+}
+
+
+static int get_chip_info_index (int chipId)
+{
+
+ int i = 0;
+ int index = -1;
+
+ int left = 0;
+ int middle = 0;
+ int right = sizeof (gChipModeInfo) / sizeof (gChipModeInfo[0]) - 1;
+
+ if ((chipId < gChipModeInfo[left].chipId) || (chipId > gChipModeInfo[right].chipId))
+ return index;
+
+ middle = (left + right) / 2;
+
+ while (left <= right)
+ {
+ if (chipId > gChipModeInfo[middle].chipId)
+ {
+ left = middle + 1;
+ }
+ else if (chipId < gChipModeInfo[middle].chipId)
+ {
+ right = middle - 1;
+ }
+ else
+ {
+ index = middle;
+ break;
+ }
+ middle = (left + right) / 2;
+ }
+
+ if (0 > index)
+ ALOGI("no supported chipid found\n");
+ else
+ ALOGI("index:%d, chipId:0x%x\n", index, gChipModeInfo[index].chipId);
+
+ return index;
+}
+
+static int query_chip_id(void)
+{
+
+ int chipId = -1;
+ int iRet = -1;
+ SYS_PROPERTY chipIdProp;
+ chipIdProp.key = WCN_COMBO_CHIP_ID_PROP;
+ chipIdProp.defValue = NULL;
+
+ //read from system property
+ iRet = property_get(chipIdProp.key, chipIdProp.value, chipIdProp.defValue);
+ if (0 != iRet)
+ {
+ chipId = strtoul(chipIdProp.value, NULL, 16);
+ ALOGI("key:(%s)-value:(%s),chipId:0x%04x\n", chipIdProp.key, chipIdProp.value, chipId);
+ }
+ else
+ {
+ ALOGI("get chipId property(%s) failed\n", chipIdProp.key);
+ // we do not return here, use another way to get chip id
+ }
+#if 1
+ //read from config file
+ if (0 > get_chip_info_index(chipId))
+ {
+ //no wcn.combo.chipid property information found
+ //get chip id
+ chipId = ioctl(gWmtFd, WMT_IOCTL_WMT_QUERY_CHIPID, NULL);
+ if(chipId > 0)
+ {
+ ALOGI ("chip id is 0x%x\n", chipId);
+ ALOGI("chiId:0x%x, setting to property(%s)\n", chipId, chipIdProp.key);
+ sprintf (chipIdProp.value, "0x%04x", chipId);
+ iRet = property_set(chipIdProp.key, chipIdProp.value);
+ if (0 != iRet)
+ {
+ ALOGI("set property(%s) to %s failed,iRet:%d, errno:%d\n", chipIdProp.key, chipIdProp.value, iRet, errno);
+ }
+ else
+ {
+ ALOGI("set property(%s) to %s succeed.\n", chipIdProp.key, chipIdProp.value);
+ }
+
+ // read again
+ if (0 != property_get(chipIdProp.key, chipIdProp.value, chipIdProp.defValue))
+ {
+ ALOGI("chipIdProp:key(%s)value(%s)\n", chipIdProp.key, chipIdProp.value);
+ }
+ else
+ {
+ ALOGI("get chipId property failed, errno:%d\n", errno);
+ chipId = -1;
+ }
+ }
+ }
+#endif
+ return chipId;
+}
+
+
+static int check_chip_id(void)
+{
+
+#define COMBO_IOC_MAGIC 'h'
+#define COMBO_IOCTL_GET_CHIP_ID _IOR(COMBO_IOC_MAGIC, 0, int)
+#define COMBO_IOCTL_SET_CHIP_ID _IOW(COMBO_IOC_MAGIC, 1, int)
+
+ int chipId = -1;
+ SYS_PROPERTY chipIdProp;
+ chipIdProp.key = WCN_COMBO_CHIP_ID_PROP;
+ chipIdProp.defValue = NULL;
+ int fdHifsdio = -1;
+
+#if 1
+ //read from system property
+ if (0 != property_get(chipIdProp.key, chipIdProp.value, chipIdProp.defValue))
+ {
+ chipId = strtoul(chipIdProp.value, NULL, 16);
+ ALOGI("key:(%s)-value:(%s),chipId:0x%04x\n", chipIdProp.key, chipIdProp.value, chipId);
+ }
+ else
+ {
+ ALOGI("get chipId property(%s) failed\n", chipIdProp.key);
+ // we do not return here, use another way to get chip id
+ }
+#else
+ /*read from config file*/
+
+#endif
+ //open HIF-SDIO
+ fdHifsdio = open("/dev/hifsdiod", O_RDWR | O_NOCTTY);
+ if (fdHifsdio < 0)
+ {
+ ALOGI ("open hifsdiod fail\n");
+ return -1;
+ }
+
+ //read from config file
+ if (0 > get_chip_info_index(chipId))
+ {
+ //no wcn.combo.chipid property information found
+ //get chip id
+ chipId = ioctl(fdHifsdio, COMBO_IOCTL_GET_CHIP_ID, NULL);
+ ALOGI ("chip id is 0x%x\n", chipId);
+ //assume we get 0x6628 here
+ ALOGI("chiId:0x%x, setting to property(%s)\n", chipId, chipIdProp.key);
+ sprintf (chipIdProp.value, "0x%04x", chipId);
+ property_set(chipIdProp.key, chipIdProp.value);
+ ALOGI("set property(%s) to %s done.\n", chipIdProp.key, chipIdProp.value);
+ // read again
+ if (0 != property_get(chipIdProp.key, chipIdProp.value, chipIdProp.defValue))
+ {
+ ALOGI("chipIdProp:key(%s)value(%s)\n", chipIdProp.key, chipIdProp.value);
+ }
+ else
+ {
+ ALOGI("get chipId property failed, errno:%d\n", errno);
+ chipId = -1;
+ }
+ }
+ else
+ {
+ ioctl(fdHifsdio, COMBO_IOCTL_SET_CHIP_ID, chipId);
+ ALOGI("set chipId(0x%x) to HIF-SDIO module\n", chipId);
+ }
+
+ //close HIF-SDIO
+ close (fdHifsdio);
+ fdHifsdio = -1;
+
+ return chipId;
+}
+
+static int setHifInfo(int chipId, char *cfgFilePath)
+{
+ int index = -1;
+ index = get_chip_info_index(chipId);
+ if ((gStpMode <= STP_MIN) || (STP_SDIO < gStpMode))
+ {
+ ALOGI ("STP Mode is not set, fetching default mode...\n");
+
+ if (0 <= index)
+ {
+ gStpMode = gChipModeInfo[index].stpMode;
+ }
+ else
+ {
+ //gStpMode = STP_UART_FULL;
+ gStpMode = -1;
+ }
+
+ }
+
+ if ((0 <= index) && (NULL != cfgFilePath))
+ {
+ memset(gWmtCfgName, 0, sizeof(gWmtCfgName));
+ strncpy (gWmtCfgName, cfgFilePath, sizeof(gWmtCfgName) - 1);
+ gWmtCfgName[sizeof(gWmtCfgName) - 1] = '\0';
+ strcat (gWmtCfgName, "/");
+ strcat (gWmtCfgName, gChipModeInfo[index].antMode.cfgItemValue);
+ gWmtCfgName[strlen(cfgFilePath) + strlen("/") + strlen(gChipModeInfo[index].antMode.cfgItemValue)] = '\0';
+ #if 0
+ ALOGI ("strlen(cfgFilePath):%d, strlen('/'):%d, strlen(gChipModeInfo[index].antMode.cfgItemValue):%d\n", strlen(cfgFilePath),\
+ strlen("/"), \
+ strlen(gChipModeInfo[index].antMode.cfgItemValue)\
+ );
+ #endif
+ }
+ else
+ {
+ memset(gWmtCfgName, 0, sizeof(gWmtCfgName));
+ }
+ ALOGI ("chipId(0x%04x), default Mode(%d), strlen(gWmtCfgName)(%u), wmtCfgFile(%s)\n", chipId, gStpMode, strlen(gWmtCfgName), gWmtCfgName);
+ return gStpMode;
+}
+
+static void* launcher_pwr_on_chip(void * arg)
+{
+ int retryCounter = 0;
+ int i_ret = -1;
+ int chipid = *(int*) arg;
+ char readyStr[PROPERTY_VALUE_MAX] = {0};
+ int iRet = -1;
+
+ pthread_setname_np(pthread_self(), "pwr_on_conn");
+
+ ALOGI("enter power on connsys flow");
+ do {
+ i_ret = ioctl(gWmtFd, WMT_IOCTL_LPBK_POWER_CTRL, 1);
+ if (0 == i_ret){
+ break;
+ } else {
+ ioctl(gWmtFd, WMT_IOCTL_LPBK_POWER_CTRL, 0);
+ ALOGI("power on %x failed, retrying, retry counter:%d\n", chipid, retryCounter);
+ usleep(1000000);
+ }
+ retryCounter++;
+ }while (retryCounter < 20);
+
+ pthread_detach(thread_handle);
+ thread_handle = -1;
+
+ return NULL;
+}
+static void* launcher_set_fwdbg_flag(void * arg)
+{
+ int i_ret = -1;
+ int flag = *(int*) arg;
+
+ pthread_setname_np(pthread_self(), "dump_fwemi_log");
+ ALOGI("dump firmware dbg log from emi buffer ");
+ i_ret = ioctl(gWmtFd, WMT_IOCTL_FW_DBGLOG_CTRL, flag);
+ if (i_ret < 0) {
+ ALOGI("ioctl error: err msg: %s\n", strerror(errno));
+ pthread_detach(thread_handle);
+ thread_handle = -1;
+ }
+ return NULL;
+}
+
+/*
+ * -m: mode (SDIO/UART)
+ * -d: uart device node
+ * -b: baudrate
+ * -c: enable SW FC or not
+ * -p: patch folder path
+ * -n: patch file name (fullpath)
+ *
+ */
+int main(int argc, char *argv[])
+{
+ static const char *opString = "m:d:b:c:p:n:?";
+ struct uart_t *u = NULL;
+ int opt, ld, err;
+ int baud = 0;
+ struct sigaction sa;
+ struct pollfd fds[2];
+ int fd_num = 0;
+ int len = 0;
+ int uartFcCtrl = 0;
+ int argCount = 0;
+ int chipId = -1;
+ int i_ret = 1;
+ int retry = 0;
+ int polling_flag = 0;
+ int dynamicdump_flag = 0;
+ int dump_retry = 0;
+ int fwdbgEnableFlag = 0;
+ char readyStr[PROPERTY_VALUE_MAX] = {0};
+ STP_PARAMS_CONFIG sStpParaConfig;
+ char fwStateStr0[PROPERTY_VALUE_MAX] = {0};
+ char fwStateStr[PROPERTY_VALUE_MAX] = {0};
+ char dynamicDump0[PROPERTY_VALUE_MAX] = {0};
+ char dynamicDump[PROPERTY_VALUE_MAX] = {0};
+
+ do {
+ i_ret = property_get(WCN_DRIVER_READY_PROP, readyStr, NULL);
+ if (0 >= i_ret) {
+ ALOGI("get property(%s) failed i_ret:%d\n", WCN_DRIVER_READY_PROP, i_ret);
+ } else {
+ ALOGI("get property(%s) is %s\n", WCN_DRIVER_READY_PROP, readyStr);
+ if (!strcmp(readyStr, "yes"))
+ break;
+ }
+ usleep(300000);
+ } while (1);
+
+ do {
+ gWmtFd = open(CUST_COMBO_WMT_DEV, O_RDWR | O_NOCTTY);
+ if (gWmtFd < 0) {
+ ALOGI("Can't open device node(%s) error:%d \n", CUST_COMBO_WMT_DEV,gWmtFd);
+ usleep(300000);
+ }
+ else
+ break;
+ }while(1);
+ ALOGE("open device node succeed.(Node:%s, fd:%d) \n", CUST_COMBO_WMT_DEV, gWmtFd);
+
+ do{
+ chipId = query_chip_id();
+ if(0 > chipId)
+ {
+ usleep(300000);
+ chipId = ioctl(gWmtFd,WMT_IOCTL_WMT_QUERY_CHIPID,NULL);
+ ALOGI("chiId from kernel by ioctl:0x%04x\n", chipId);
+ if(-1 != chipId)
+ break;
+ }else
+ break;
+ }while(1);
+ ALOGI("chiId:0x%04x\n", chipId);
+
+ if((0x0321 == chipId) || (0x0335 == chipId) || (0x0337 == chipId))
+ {
+ chipId = 0x6735;
+ ALOGI("for denali chipid convert\n");
+ }
+ if (0x0326 == chipId)
+ {
+ chipId = 0x6755;
+ ALOGI("for jade chipid convert\n");
+ }
+ if ((0x6735 == chipId) || (0x6752 == chipId) || (0x6582 == chipId) || (0x6592 == chipId)
+ || (0x6572 == chipId) || (0x6571 == chipId) || (0x8127 == chipId)
+ || (0x8163 == chipId) || (0x6580 == chipId) || (0x6755 == chipId) || (0x6797 == chipId) || (0x7623 == chipId) ) {
+ ALOGI("run SOC chip flow\n");
+ gStpMode = STP_BTIF_FULL;
+ memset(gPatchFolder, 0, sizeof(gPatchFolder));
+
+ opt = getopt(argc, argv, opString);
+ while (opt != -1)
+ {
+ switch (opt)
+ {
+ case 'm':
+ gStpMode = atoi(optarg);
+ sStpParaConfig.eStpMode = gStpMode;
+ ALOGI("stpmode[%d]\n",gStpMode);
+ break;
+ case 'p':
+ //gPatchFolder = optarg;
+ strcpy(gPatchFolder, optarg);
+ sStpParaConfig.pPatchPath = gPatchFolder;
+ break;
+ case '?':
+ default:
+ display_usage(chipId);
+ break;
+ }
+ opt = getopt(argc, argv, opString);
+ }
+ /* send default patch file name path to driver */
+ ioctl(gWmtFd, WMT_IOCTL_SET_PATCH_NAME, gPatchName);
+ /* set fm mode & stp mode*/
+ ioctl(gWmtFd, WMT_IOCTL_SET_STP_MODE, ((gFmMode & 0x0F) << 4) |(gStpMode & 0x0F));
+#ifndef WMT_PLAT_APEX
+ set_coredump_flag();
+#endif
+ }else
+ {
+ ALOGI("run combo chip flow\n");
+ sStpParaConfig.pPatchPath = NULL;
+ sStpParaConfig.pPatchName = NULL;
+ sStpParaConfig.gStpDev = NULL;
+ sStpParaConfig.eStpMode = -1;
+ sStpParaConfig.iBaudrate = -1;
+ sStpParaConfig.sUartConfig.fc = UART_DISABLE_FC;
+ sStpParaConfig.sUartConfig.parity = 0;
+ sStpParaConfig.sUartConfig.stop_bit = 0;
+
+ /*Default parameters starts*/
+ baud = 4000000;
+ gStpMode = -1;
+ uartFcCtrl = UART_DISABLE_FC;
+ strncpy(gStpDev, CUST_COMBO_STP_DEV, sizeof(gStpDev) - 1);
+ gStpDev[sizeof(gStpDev) - 1] = '\0';
+ memset(gPatchFolder, 0, sizeof(gPatchFolder));
+ memset(gPatchName, 0, sizeof(gPatchName));
+ /*Default parameters ends*/
+
+ opt = getopt(argc, argv, opString);
+ while (opt != -1)
+ {
+ switch (opt)
+ {
+ case 'm':
+ gStpMode = atoi(optarg);
+ sStpParaConfig.eStpMode = gStpMode;
+ break;
+ case 'd':
+ strncpy(gStpDev, optarg, sizeof(gStpDev) - 1);
+ gStpDev[sizeof(gStpDev) - 1] = '\0';
+ sStpParaConfig.gStpDev = gStpDev;
+ break;
+ case 'b':
+ baud = atoi(optarg);
+ sStpParaConfig.iBaudrate = baud;
+ break;
+ case 'c':
+ uartFcCtrl = atoi(optarg);
+ sStpParaConfig.sUartConfig.fc = uartFcCtrl;
+ ALOGI("c found\n");
+ break;
+ case 'p':
+ //gPatchFolder = optarg;
+ strcpy(gPatchFolder, optarg);
+ sStpParaConfig.pPatchPath = gPatchFolder;
+ break;
+ case 'n':
+ //gPatchName = optarg;
+ strcpy(gPatchName, optarg);
+ sStpParaConfig.pPatchName = gPatchName;
+ break;
+ case '?':
+ default:
+ display_usage(chipId);
+ break;
+ }
+ opt = getopt(argc, argv, opString);
+ }
+#if 0
+ ALOGI ("argc = %d, optind= %d\n", argc, optind);
+ {
+ int i = 0;
+ for (i = 0; i < argc; i++)
+ {
+ ALOGI("arg[%d] = %s\n", i, argv[i]);
+ }
+ }
+#endif
+
+
+ if (0 > get_chip_info_index(chipId))
+ {
+ ALOGI("invalid chip, check again\n");
+ chipId = query_chip_id();
+ ALOGI("chiId:0x%04x\n", chipId);
+ }
+
+ ioctl(gWmtFd, WMT_IOCTL_WMT_TELL_CHIPID, chipId);
+ ALOGI("set chipId(0x%x) to HIF-SDIO module\n", chipId);
+
+ get_wmt_cfg(chipId);
+
+ setHifInfo(chipId, sStpParaConfig.pPatchPath);
+ ALOGI("HifConfig:0x%04x, wmtCfgFile:%s\n", sStpParaConfig.eStpMode, gWmtCfgName);
+#ifndef WMT_PLAT_APEX
+ set_coredump_flag();
+#endif
+ if (0 != para_valid_check(&sStpParaConfig))
+ {
+ //Try to use custom method to check parameters
+ if (argc > optind)//argv[optind]
+ {
+ // For this competible usage , we only left STP mode set and firmware patch input, omit flowcontrol set
+ //First baud for STP UART mode, otherwise, SDIO mode
+ baud = atoi(argv[optind]);
+ if (baud >= CUST_BAUDRATE_DFT) {
+ ALOGI("get baud rate(%d) for UART mode\n", baud);
+ gStpMode = STP_UART_FULL;
+ sStpParaConfig.iBaudrate = baud;
+ }
+ else if (baud == 1){
+ ALOGI("Definitively use SDIO mode\n");
+ gStpMode = STP_SDIO;
+ }
+ else {
+ ALOGI("invalid baud rate(%d) for UART, use SDIO mode\n", baud);
+ gStpMode = STP_SDIO;
+ }
+ sStpParaConfig.eStpMode = gStpMode;
+
+ //Firmare patch analysis
+ optind++;
+ memset(gPatchName, 0, sizeof(gPatchName));
+ if (argc > optind)
+ {
+ strncat(gPatchName, argv[optind], sizeof(gPatchName)-1);
+ sStpParaConfig.pPatchName = gPatchName;
+ ALOGI("PatchFile:%s\n", sStpParaConfig.pPatchName);
+ }
+ else
+ {
+ sStpParaConfig.pPatchName = NULL;
+ ALOGI("no patch file \n");
+ }
+ //Flow Control analysis
+ optind++;
+ if (argc > optind)
+ {
+ uartFcCtrl = atoi(argv[optind]);
+ sStpParaConfig.sUartConfig.fc = uartFcCtrl;
+ ALOGI("flowcontrol flag: %d\n", sStpParaConfig.sUartConfig.fc);
+ }
+ else
+ {
+ ALOGI("no flow control flat set\n");
+ }
+
+ }
+ }
+ if (0 != para_valid_check(&sStpParaConfig))
+ {
+ display_usage(chipId);
+ }
+
+ /* send default patch file name path to driver */
+ ioctl(gWmtFd, WMT_IOCTL_SET_PATCH_NAME, gPatchName);
+ /* send uart name to driver*/
+ if (sStpParaConfig.gStpDev) {
+ gUartName = strstr(sStpParaConfig.gStpDev, "tty");
+ if (!gUartName) {
+ ALOGI("no uart name found in %s\n", sStpParaConfig.gStpDev);
+ } else {
+ ALOGI("uart name %s\n", gUartName);
+ }
+ }
+
+ if (!gUartName) {
+ gUartName = "ttyMT2";
+ ALOGI("use default uart %s\n", gUartName);
+ }
+
+ ioctl(gWmtFd, WMT_IOCTL_PORT_NAME, gUartName);
+
+ /* send hardware interface configuration to driver */
+ ioctl(gWmtFd, WMT_IOCTL_SET_STP_MODE, ((baud & 0xFFFFFF) << 8) | ((gFmMode & 0x0F) << 4) |(gStpMode & 0x0F));
+
+ /* send WMT config name configuration to driver */
+ ioctl(gWmtFd, WMT_IOCTL_WMT_CFG_NAME, gWmtCfgName);
+ }
+
+ ioctl(gWmtFd, WMT_IOCTL_SET_LAUNCHER_KILL, 0);
+
+ i_ret = ioctl(gWmtFd, WMT_IOCTL_GET_APO_FLAG, NULL);
+ if (i_ret != 0) {
+ if (pthread_create(&thread_handle, NULL, launcher_pwr_on_chip, &chipId)) {
+ ALOGE("create pwr on thread fail\n");
+ } else {
+ ALOGI("create pwr on thread ok\n");
+ }
+ } else {
+ ALOGI("no supported always power on\n");
+ }
+ /*set signal handler*/
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGCHLD, &sa, NULL);
+ sigaction(SIGPIPE, &sa, NULL);
+
+ sa.sa_handler = sig_term;
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+
+ sa.sa_handler = sig_hup;
+ sigaction(SIGHUP, &sa, NULL);
+
+
+ fds[0].fd = gWmtFd; /* stp_wmt fd */
+ fds[0].events = POLLIN | POLLRDNORM; /* wait read events */
+ ++fd_num;
+ i_ret = property_get(WCN_FW_DBG_LOG_PROP, fwStateStr0, NULL);
+ if (0 >= i_ret) {
+ ALOGI("get property(%s) failed ret:%d\n", WCN_FW_DBG_LOG_PROP, i_ret);
+ } else
+ ALOGI("get property fwStateStr0 (%s) is %s\n", WCN_FW_DBG_LOG_PROP, fwStateStr0);
+ i_ret = property_get(WCN_DYNAMIC_DUMP_PROP, dynamicDump0, NULL);
+ if (0 >= i_ret) {
+ ALOGI("get property(%s) failed ret:%d\n", WCN_DYNAMIC_DUMP_PROP, i_ret);
+ } else
+ ALOGI("get property dynamicDump0 (%s) is %s\n", WCN_DYNAMIC_DUMP_PROP, dynamicDump0);
+#if 0 //does this part needed?, no uart device is opened at this time.
+ if (gStpMode == STP_UART_FULL) {
+ fds[1].fd = gTtyFd; /* real tty fd */
+ fds[1].events = POLLERR | POLLHUP; /* POLLERR | POLLHUP is unnecessary? */
+ ++fd_num;
+ }
+#endif
+
+ while (!__io_canceled) {
+ fds[0].revents = 0;
+#if 0 //does this part needed?, do we need to poll on uart?
+ if (gStpMode == STP_UART_FULL) {
+ fds[1].revents = 0;
+ }
+#endif
+ err = poll(fds, fd_num, 2000); // 5 seconds
+ if (err < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ else {
+ ALOGI("poll error:%d errno:%d, %s\n", err, errno, strerror(errno));
+ break;
+ }
+ }
+ else if (!err) {
+ continue;
+ }
+#if 0 //does this part needed?, do we need to poll on uart?
+ if (gStpMode == STP_UART_FULL) {
+ if (fds[1].revents & (POLLERR | POLLHUP)) {
+ ALOGI("poll result: pa[1].revents:0x%x\n", fds[1].revents);
+ break;
+ }
+ }
+#endif
+ if (fds[0].revents & POLLIN) {
+ memset(gCmdStr, 0, sizeof(gCmdStr));
+ len = read(gWmtFd, gCmdStr, sizeof(gCmdStr)-1);
+ if (len > 0 && len < (int)sizeof(gCmdStr)) {
+ //printf ("POLLIN(%d) and read(%d)\n", gWmtFd, len);
+ }
+ else {
+ ALOGI("POLLIN(%d) but read fail:%d\n", gWmtFd, len);
+ continue;
+ }
+ gCmdStr[len] = '\0';
+ //ALOGI("rx_cmd_str:%s\n", gCmdStr);
+ err = handle_cmd(&sStpParaConfig, gCmdStr, len);
+ if (!err) {
+ //ALOGI("handle_cmd(%s), respond ok \n", gCmdStr);
+ snprintf(gRespStr, sizeof(gRespStr), "ok");
+ }
+ else {
+ if (err == 1) {
+ snprintf(gRespStr, sizeof(gRespStr), "cmd not found");
+ }
+ else {
+ snprintf(gRespStr, sizeof(gRespStr), "resp_%d", err);
+ }
+ }
+ ALOGI("cmd(%s) resp(%s)\n", gCmdStr, gRespStr);
+ len = write(gWmtFd, gRespStr, strlen(gRespStr));
+ if (len != (int)strlen(gRespStr)) {
+ fprintf(stderr, "write resp(%d) fail: len(%d), errno(%d, %s)\n", gWmtFd, len, errno, (len == -1) ? strerror(errno) : "");
+ }
+ }
+ if (polling_flag == 0) {
+ if (retry++ <= 5) {
+ i_ret = property_get(WCN_FW_DBG_LOG_PROP, fwStateStr, NULL);
+ if (0 >= i_ret) {
+ ALOGI("get property(%s) failed ret:%d\n", WCN_FW_DBG_LOG_PROP, i_ret);
+ } else {
+ ALOGI("get property(%s) is %s\n", WCN_FW_DBG_LOG_PROP, fwStateStr);
+ if (strcmp(fwStateStr, fwStateStr0))
+ polling_flag = 1;
+ }
+ }
+ }
+ if (polling_flag == 1 || retry == 6) {
+ ALOGI("polling_flag:%d, retry: %d\n", polling_flag, retry);
+ if (!strcmp(fwStateStr, "yes")) {
+ fwdbgEnableFlag = 1;
+ i_ret = pthread_create(&thread_handle, NULL, launcher_set_fwdbg_flag, &fwdbgEnableFlag);
+ if (i_ret) {
+ ALOGE("create enable firmware dbglog thread fail\n");
+ } else
+ ALOGI("create enable firmware dbglog thread ok\n");
+ } else {
+ i_ret = ioctl(gWmtFd, WMT_IOCTL_FW_DBGLOG_CTRL, fwdbgEnableFlag);
+ if (i_ret < 0)
+ ALOGI("ioctl error: err msg: %s\n", strerror(errno));
+ }
+ }
+
+ if (dynamicdump_flag == 0) {
+ if (dump_retry++ <= 5) {
+ i_ret = property_get(WCN_DYNAMIC_DUMP_PROP, dynamicDump, NULL);
+ if (0 >= i_ret) {
+ ALOGI("get property(%s) failed ret:%d\n", WCN_DYNAMIC_DUMP_PROP, i_ret);
+ } else {
+ ALOGI("get property(%s) is %s\n", WCN_DYNAMIC_DUMP_PROP, dynamicDump);
+ if (strcmp(dynamicDump, dynamicDump0))
+ dynamicdump_flag = 1;
+ }
+ }
+ }
+ if (dynamicdump_flag == 1) {
+ ALOGI("dynamicdump_flag:%d, dump_retry: %d\n", dynamicdump_flag, dump_retry);
+ ALOGI("get property(%s) is %s\n", WCN_DYNAMIC_DUMP_PROP, dynamicDump);
+ i_ret = ioctl(gWmtFd, WMT_IOCTL_DYNAMIC_DUMP_CTRL, dynamicDump);
+ if (i_ret < 0)
+ ALOGI("ioctl error: err msg: %s\n", strerror(errno));
+ }
+ }
+
+clean_up:
+
+ if (gWmtFd >= 0) {
+ close(gWmtFd);
+ gWmtFd = -1;
+ }
+
+ if (gStpMode == STP_UART_FULL && gTtyFd >= 0) {
+ /* Restore TTY line discipline */
+ ld = N_TTY;
+ if (ioctl(gTtyFd, TIOCSETD, &ld) < 0) {
+ ALOGE("Can't restore line discipline");
+ exit(1);
+ }
+
+ close(gTtyFd);
+ gTtyFd = -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/connectivity/combo_tool/src/wmt_concurrency.c b/src/connectivity/combo_tool/src/wmt_concurrency.c
new file mode 100755
index 0000000..1163eb6
--- /dev/null
+++ b/src/connectivity/combo_tool/src/wmt_concurrency.c
@@ -0,0 +1,383 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#define _GNU_SOURCE
+#include "wmt_ioctl.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/endian.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <linux/serial.h> /* struct serial_struct */
+#include <pthread.h>
+#include <sched.h>
+#define FIBER_STACK 8192
+
+pthread_mutex_t mutex;
+
+typedef enum DRV_INDEX
+{
+ DRV_BT = 0,
+ DRV_FM,
+ DRV_GPS,
+ DRV_WIFI,
+ DRV_MAX,
+}ENUM_DRV_INDEX;
+
+typedef enum ARG_DRV_INDEX
+{
+ ARG_DRV_BT = 1 << DRV_BT,
+ ARG_DRV_FM = 1 << DRV_FM,
+ ARG_DRV_GPS = 1 << DRV_GPS,
+ ARG_DRV_WIFI = 1 << DRV_WIFI,
+ ARG_DRV_ALL = ARG_DRV_BT + ARG_DRV_FM + ARG_DRV_GPS + ARG_DRV_WIFI,
+}ENUM_ARG_DRV_INDEX;
+
+#define is_bt_mask_on(a) ((a) & ARG_DRV_BT)
+#define is_fm_mask_on(a) ((a) & ARG_DRV_FM)
+#define is_gps_mask_on(a) ((a) & ARG_DRV_GPS)
+#define is_wifi_mask_on(a) ((a) & ARG_DRV_WIFI)
+
+#define QUICK_FUNC_ON_OFF_SUPPORT
+#ifdef QUICK_FUNC_ON_OFF_SUPPORT
+ #define MIN_INTERVAL 1
+#else
+ #define MIN_FUNC_ON_TIME 4
+ #define MIN_FUNC_OFF_TIME 1
+ #define MIN_INTERVAL MIN_FUNC_ON_TIME + MIN_FUNC_OFF_TIME
+#endif
+
+#define MAX_FUNC_ON_TIME 9
+#define MAX_FUNC_OFF_TIME 3
+#define MAX_INTERVAL MAX_FUNC_ON_TIME + MAX_FUNC_OFF_TIME
+//enum bool {false = 0, true = !false};
+
+char *src_name[]={
+ "BT",
+ "FM",
+ "GPS",
+ "WIFI",
+ "UNKNOWN DEVICE",
+ };
+
+static int g_wmt_fd = -1;
+static int g_reference = 0;
+static int g_count = 2;
+int g_on2off_interval = MAX_INTERVAL;
+int g_off2on_interval = MAX_INTERVAL;
+volatile int g_state[5] = {0};
+
+void dump_state(void)
+{
+ //printf("%s:++, pid =%d\n", __FUNCTION__, getpid());
+ printf("%d: %s:g_state:[BT]%d, [FM]:%d, [GPS]:%d, [WIFI]:%d\n", getpid(), __FUNCTION__, g_state[0], g_state[1], g_state[2], g_state[3]);
+ //printf("%s:--, pid =%d\n", __FUNCTION__, getpid());
+}
+
+int read_reference(ENUM_DRV_INDEX index)
+{
+ int ref = 0;
+ volatile int flag = 0;
+ pthread_mutex_lock(&mutex);
+ if(index >= 4)
+ {
+ if(g_state[0] || g_state[1] || g_state[2] || g_state[3])
+ {
+ flag = 1;
+ }
+ else
+ {
+ flag = 0;
+ }
+ }
+ else
+ {
+ flag = g_state[index];
+ }
+ pthread_mutex_unlock(&mutex);
+ return flag;
+}
+
+void get_reference(ENUM_DRV_INDEX index)
+{
+ pthread_mutex_lock(&mutex);
+ g_reference++;
+ g_state[index] = 1;
+ dump_state();
+ pthread_mutex_unlock(&mutex);
+}
+
+
+void put_reference(ENUM_DRV_INDEX index)
+{
+ pthread_mutex_lock(&mutex);
+ g_reference--;
+ g_state[index] = 0;
+ dump_state();
+ pthread_mutex_unlock(&mutex);
+}
+
+void func_on_off(ENUM_DRV_INDEX index)
+{
+ pid_t pid = -1;
+ int count = g_count;
+// printf("%s:++, index =%d\n", __FUNCTION__, index);
+ if(DRV_MAX > index && g_wmt_fd > 0)
+ {
+ while(count--)
+ {
+ //turn on src_name[index] function
+ if (0 == ioctl(g_wmt_fd, WMT_IOCTL_FUNC_ONOFF_CTRL, 0x80000000 | index))
+ {
+ printf("pid:%d, turn on %s success.\n", getpid(), src_name[index]);
+ //exit(0);
+ }
+ else
+ {
+ printf("pid:%d, turn on %s fail.\n", getpid(), src_name[index]);
+ exit(-1);
+ }
+
+ //printf("%s:-- pid: %d, finish turn on %s\n", __FUNCTION__, getpid(), src_name[index]);
+ /*
+ //turn off src_name[index] function
+ */
+ sleep(g_on2off_interval);
+ if ( 0 == ioctl(g_wmt_fd, WMT_IOCTL_FUNC_ONOFF_CTRL, 0x00000000 | index))
+ {
+ printf("pid:%d, turn off %s success.\n", getpid(), src_name[index]);
+ //exit(0);
+ }
+ else
+ {
+ printf("pid:%d, turn off %s fail.\n", getpid(), src_name[index]);
+ exit(-1);
+ }
+ printf("%d:%s test:left count = %d.\n", getpid(), src_name[index], count);
+ sleep(g_off2on_interval);
+
+ }
+ }
+ else
+ {
+ printf("pid:%d, undnown device with index:%d.\n", getpid(), index);
+ }
+ // printf("%s:--, index =%d\n", __FUNCTION__, index);
+ //exit(-2);
+ //return;
+ exit(0);
+}
+
+
+static void sig_child_term(int sig)
+{
+ printf("%s ++.\n", __FUNCTION__);
+ int pid = -1;
+ int stat;
+ while((pid = waitpid(0, &stat, WNOHANG)) != 0)
+ {
+ printf("%s:pid = %d, exit event.\n", __FUNCTION__, pid);
+ }
+ printf("%s:pid = %d.\n", __FUNCTION__, pid);
+ printf("%s --.\n", __FUNCTION__);
+}
+
+int main(int argc, char *argv[])
+{
+
+ int bitmask = ARG_DRV_ALL;
+
+ int i = 0;
+ int status;
+ void *stack[8];
+ struct sigaction sa;
+ if(argc != 5)
+ {
+ printf("wmt_concurrency usage:\n\
+ wmt_concurrency looptimes bitmask on2offtime off2ontime\n\
+ -looptimes on<->off switch times (<1000000)\n\
+ -bitmask\n\
+ -1:BT on<->off test\n\
+ -2:FM on<->off test\n\
+ -4:GPS on<->off test\n\
+ -8:WIFI on<->off test\n\
+ -x: can be combination of the upper 4 bitmasks\n\
+ -on2offtime (0~12s)\n\
+ -function on hold time before turn off\n\
+ -off2ontime (0~12s)\n\
+ -function off hold time before turn on\n\
+ ");
+ return -1;
+ }
+ if ((argc > 1) && (argv[1] != NULL)) {
+
+ g_count = atoi(argv[1]);
+ printf("%s:argv[1] g_count param = %d\n", __FUNCTION__, g_count);
+ if(g_count < 0)
+ {
+ g_count = 2;
+ }
+ g_count = g_count > 1000000 ? 1000000 : g_count;
+ printf("%s:g_count = %d\n", __FUNCTION__, g_count);
+ }
+ if ((argc > 2) && (argv[2] != NULL)) {
+
+ bitmask = atoi(argv[2]);
+ printf("%s:argv[2] bitmask param = %d\n", __FUNCTION__, bitmask);
+ if(bitmask <= 0 || bitmask > ARG_DRV_ALL)
+ {
+ bitmask = ARG_DRV_ALL;
+ }
+ printf("%s:bitmask = %d\n", __FUNCTION__, bitmask);
+ }
+
+ if ((argc > 3) && (argv[3] != NULL)) {
+
+ g_on2off_interval = atoi(argv[3]);
+ printf("%s:argv[3] g_on2off_interval param = %d\n", __FUNCTION__, g_on2off_interval);
+ if(g_on2off_interval < MIN_INTERVAL)
+ {
+ g_on2off_interval = MIN_INTERVAL;
+ }
+ if(g_on2off_interval > MAX_INTERVAL)
+ {
+ g_on2off_interval = MAX_INTERVAL;
+ }
+ printf("%s:g_on2off_interval = %d\n", __FUNCTION__, g_on2off_interval);
+ }
+ if ((argc > 4) && (argv[4] != NULL)) {
+
+ g_off2on_interval = atoi(argv[4]);
+ printf("%s:argv[4] g_off2on_interval param = %d\n", __FUNCTION__, g_off2on_interval);
+ if(g_off2on_interval < MIN_INTERVAL)
+ {
+ g_off2on_interval = MIN_INTERVAL;
+ }
+ if(g_off2on_interval > MAX_INTERVAL)
+ {
+ g_off2on_interval = MAX_INTERVAL;
+ }
+ printf("%s:g_off2on_interval = %d\n", __FUNCTION__, g_off2on_interval);
+ }
+
+ for (i = sizeof(g_state)/sizeof(g_state[0]); i > 0; )
+ {
+ g_state[--i] = 0;
+ }
+
+ printf("pid = %d\n", getpid());
+ for(i = sizeof(stack)/sizeof(void *); i > 0; )
+ {
+ stack[--i] = malloc(FIBER_STACK);
+ if(stack[i] == NULL)
+ {
+ printf("pid = %d, malloc error\n", getpid());
+ goto out;
+ }
+ }
+
+ g_wmt_fd = open("/dev/stpwmt", O_RDWR | O_NOCTTY);
+ printf("%s:argc = %d\n", __FUNCTION__, argc);
+
+ if(pthread_mutex_init(&mutex, NULL) != 0)
+ {
+ printf("%s:pthread_mutex_init fail\n", __FUNCTION__);
+ goto out;
+ }
+ if(g_wmt_fd > 0)
+ {
+ memset(&sa, 0, sizeof(sa));
+ //signal(SIGCHLD, sig_child_term);
+ sa.sa_handler = sig_child_term;
+ sa.sa_flags = SA_NOCLDSTOP;
+ sigaction(SIGCHLD, &sa, 0);
+ int sleepCOunter = g_count;
+
+ if(is_bt_mask_on(bitmask) && read_reference(DRV_BT) == 0)
+ {
+ clone(&func_on_off, (char *)stack[0] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_BT);
+ //clone(&func_off, (char *)stack[4] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_BT);
+ }
+
+ if(is_wifi_mask_on(bitmask) && read_reference(DRV_WIFI) == 0)
+ {
+ clone(&func_on_off, (char *)stack[1] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_WIFI);
+ //clone(&func_off, (char *)stack[5] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_WIFI);
+ }
+ if(is_fm_mask_on(bitmask) && read_reference(DRV_FM) == 0)
+ {
+ clone(&func_on_off, (char *)stack[2] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_FM);
+ //clone(&func_off, (char *)stack[6] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_FM);
+ }
+ if(is_gps_mask_on(bitmask) && read_reference(DRV_GPS) == 0)
+ {
+ clone(&func_on_off, (char *)stack[3] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_GPS);
+ //clone(&func_off, (char *)stack[7] + FIBER_STACK, CLONE_VM | CLONE_FS | CLONE_FILES /*| CLONE_SIGHAND*/, (void *)DRV_GPS);
+ }
+ //printf("%s:left g_count = %d.\n", __FUNCTION__, g_count);
+ sleep(sleepCOunter * (g_on2off_interval + g_off2on_interval));
+ }
+out:
+
+ for(i = sizeof(stack)/sizeof(void *); i > 0; )
+ {
+ printf("%s:pid = %d, free stack information.\n", __FUNCTION__, getpid());
+ if (NULL != stack[--i])
+ {
+ free(stack[i]);
+ }
+ stack[i] = NULL;
+ }
+ if(g_wmt_fd > 0)
+ {
+ close(g_wmt_fd);
+ g_wmt_fd = -1;
+ }
+ printf("%s:pid = %d, exit.\n", __FUNCTION__, getpid());
+ return 0;
+}
diff --git a/src/connectivity/combo_tool/src/wmt_ioctl.h b/src/connectivity/combo_tool/src/wmt_ioctl.h
new file mode 100755
index 0000000..78d7f25
--- /dev/null
+++ b/src/connectivity/combo_tool/src/wmt_ioctl.h
@@ -0,0 +1,27 @@
+#ifndef _WMT_IOCTL_H_
+#define _WMT_IOCTL_H_
+
+#include <sys/ioctl.h>
+
+#define WMT_IOC_MAGIC 0xa0
+#define WMT_IOCTL_SET_PATCH_NAME _IOW(WMT_IOC_MAGIC,4,char*)
+#define WMT_IOCTL_SET_STP_MODE _IOW(WMT_IOC_MAGIC,5,int)
+#define WMT_IOCTL_FUNC_ONOFF_CTRL _IOW(WMT_IOC_MAGIC,6,int)
+#define WMT_IOCTL_LPBK_POWER_CTRL _IOW(WMT_IOC_MAGIC,7,int)
+#define WMT_IOCTL_LPBK_TEST _IOWR(WMT_IOC_MAGIC,8,char*)
+#define WMT_IOCTL_GET_CHIP_INFO _IOR(WMT_IOC_MAGIC,12,int)
+#define WMT_IOCTL_SET_LAUNCHER_KILL _IOW(WMT_IOC_MAGIC,13,int)
+#define WMT_IOCTL_SET_PATCH_NUM _IOW(WMT_IOC_MAGIC,14,int)
+#define WMT_IOCTL_SET_PATCH_INFO _IOW(WMT_IOC_MAGIC,15,char*)
+#define WMT_IOCTL_PORT_NAME _IOWR(WMT_IOC_MAGIC, 20, char*)
+#define WMT_IOCTL_WMT_CFG_NAME _IOWR(WMT_IOC_MAGIC, 21, char*)
+#define WMT_IOCTL_WMT_QUERY_CHIPID _IOR(WMT_IOC_MAGIC, 22, int)
+#define WMT_IOCTL_WMT_TELL_CHIPID _IOW(WMT_IOC_MAGIC, 23, int)
+#define WMT_IOCTL_WMT_COREDUMP_CTRL _IOW(WMT_IOC_MAGIC, 24, int)
+#define WMT_IOCTL_SEND_BGW_DS_CMD _IOW(WMT_IOC_MAGIC,25,char*)
+#define WMT_IOCTL_ADIE_LPBK_TEST _IOWR(WMT_IOC_MAGIC,26,char*)
+#define WMT_IOCTL_GET_APO_FLAG _IOR(WMT_IOC_MAGIC, 28, int)
+#define WMT_IOCTL_FW_DBGLOG_CTRL _IOR(WMT_IOC_MAGIC, 29, int)
+#define WMT_IOCTL_DYNAMIC_DUMP_CTRL _IOR(WMT_IOC_MAGIC, 30, char*)
+
+#endif
diff --git a/src/connectivity/combo_tool/src/wmt_loopback.c b/src/connectivity/combo_tool/src/wmt_loopback.c
new file mode 100755
index 0000000..ea0065e
--- /dev/null
+++ b/src/connectivity/combo_tool/src/wmt_loopback.c
@@ -0,0 +1,321 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include "wmt_ioctl.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <endian.h>
+#include <linux/serial.h> /* struct serial_struct */
+
+#define LEN_MAX 1024
+
+typedef enum {
+ LEN_FIXED = 0,
+ LEN_INC = 1,
+ LEN_DEC = 2,
+ LEN_RAND = 3,
+ COMBO_POWER_ON = 4,
+ COMBO_POWER_OFF = 5,
+ ADIE_LPK = 6,
+ LPBK_OP_MAX
+} LPBK_OP_ENUM;
+
+unsigned char WMT_TEST_LPBK_CMD[] = {0x1, 0x2, 0x0, 0x0, 0x7};
+unsigned char WMT_TEST_LPBK_EVT[] = {0x2, 0x2, 0x0, 0x0, 0x0};
+/*
+unsigned char out_buf[2048] = {0};
+unsigned char in_buf[2048] = {0};
+*/
+struct lpbk_package{
+ long payload_length;
+ unsigned char out_payload[2048];
+ unsigned char in_payload[2048];
+};
+
+static int wmt_loopback(int type, int count, int max, int delay) {
+ ssize_t s_result = 0;
+ int wmt_fd;
+ int ret = -1;
+ int loop = 0;
+ int offset;
+ unsigned short buf_length = 0;
+ unsigned short len_in_cmd;
+ struct lpbk_package lpbk_buffer;
+ printf("*type(%d) count(%d) max(%d) \n", type, count, max);
+
+ if(type >= LPBK_OP_MAX){
+ printf("[%s] cannot support %d opeartion\n", __FUNCTION__, type);
+ return -1;
+ }
+
+ /* open wmt dev */
+ wmt_fd = open("/dev/stpwmt", O_RDWR | O_NOCTTY);
+ if (wmt_fd < 0) {
+ printf("[%s] Can't open stpwmt \n", __FUNCTION__);
+ return -1;
+ }
+
+ if(type == COMBO_POWER_ON){
+ printf("[power on combo chip]\n");
+ if(ioctl(wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, 1) != 0)
+ {
+ printf("[%s] power on combo chip failed\n", __FUNCTION__);
+ close(wmt_fd);
+ wmt_fd = -1;
+ return -1;
+ } else {
+ close(wmt_fd);
+ printf("[power on combo chip ok!]\n");
+ }
+ return 0;
+ }
+
+ if(type == COMBO_POWER_OFF){
+ printf("[power off combo chip]\n");
+ if(ioctl(wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, 0) != 0)
+ {
+ printf("[%s] power off combo chip failed\n", __FUNCTION__);
+ close(wmt_fd);
+ ret = -1;
+ } else {
+ close(wmt_fd);
+ printf("[power off combo chip ok!]\n");
+ }
+ return 0;
+ }
+
+ /*turn LPBK function on*/
+ printf("[power on combo chip]\n");
+ if(ioctl(wmt_fd, WMT_IOCTL_LPBK_POWER_CTRL, 1) != 0)
+ {
+ printf("[%s] Can't power on combo chip ok! failed\n", __FUNCTION__);
+ close(wmt_fd);
+ wmt_fd = -1;
+ return -1;
+ } else {
+ printf("[power on combo chip ok!]\n");
+ }
+
+ /* init length */
+ switch (type) {
+ case LEN_FIXED:
+ buf_length = (unsigned short)max;
+ break;
+ case LEN_INC:
+ buf_length = 1;
+ break;
+ case LEN_DEC:
+ buf_length = max;
+ break;
+ default:
+ /* random */
+ break;
+ }
+
+ if( (type >= LEN_FIXED) && (type <= LEN_RAND) )
+ {
+ for (loop = 0; loop < count; loop++) {
+ //<1> init buffer
+ memset((void *)&lpbk_buffer, 0, sizeof(struct lpbk_package));
+ lpbk_buffer.payload_length = buf_length;
+ for (offset = 0; offset < buf_length; offset++) {
+ lpbk_buffer.out_payload[offset] = (offset + 1)/*for test use: begin from 1*/ & 0xFF;
+ }
+
+ /*<2> do LPBK*/
+ usleep(delay * 1000);
+
+ if(( ret = ioctl(wmt_fd, WMT_IOCTL_LPBK_TEST, &lpbk_buffer)) != lpbk_buffer.payload_length){
+ printf("[%s] LPBK operation failed, return length = %d\n", __FUNCTION__, ret);
+ break;
+ }
+
+ /*<3> compare result*/
+ if (memcmp(lpbk_buffer.in_payload, lpbk_buffer.out_payload, lpbk_buffer.payload_length)) {
+ printf("[%s] WMT_TEST_LPBK_CMD payload compare error\n", __FUNCTION__);
+ break;
+ }
+ printf("[%s] exec WMT_TEST_LPBK_CMD succeed(loop = %d, size = %ld) \n", __FUNCTION__, loop, lpbk_buffer.payload_length);
+
+ /*<4> update buffer length */
+ switch (type) {
+ case LEN_INC:
+ buf_length = (buf_length == max) ? 1 : buf_length + 1;
+ break;
+ case LEN_DEC:
+ buf_length = (buf_length == 1) ? max : buf_length - 1;
+ break;
+ case LEN_RAND:
+ buf_length = rand() % max + 1;
+ break;
+ default:
+ /* no change */
+ break;
+ }
+ }
+ }
+ else if( type == ADIE_LPK )
+ {
+ int adie_chipID = 0;
+ for (loop = 0; loop < count; loop++) {
+ //<1> init buffer
+ memset((void *)&lpbk_buffer, 0, sizeof(struct lpbk_package));
+ adie_chipID = 0;
+
+ /*<2> do LPBK*/
+ usleep(delay * 1000);
+
+ if(( ret = ioctl(wmt_fd, WMT_IOCTL_ADIE_LPBK_TEST, &lpbk_buffer)) != 2){
+ printf("[%s] ADIE_LPK operation failed, return length = %d\n", __FUNCTION__, ret);
+ break;
+ }
+ adie_chipID = ((lpbk_buffer.out_payload[1] >> 4) & 0xf)*1000 +
+ (lpbk_buffer.out_payload[1] & 0xf)*100 +
+ ((lpbk_buffer.out_payload[0] >> 4) & 0xf)*10 +
+ (lpbk_buffer.out_payload[0] & 0xf);
+
+ /*<3> compare result*/
+ if ( adie_chipID != max ) {
+ printf("[%s] ADIE_LPK payload compare error\n", __FUNCTION__);
+ break;
+ }
+ printf("[%s] exec ADIE_LPK succeed(loop = %d, ChipID = %d) \n", __FUNCTION__,
+ loop, adie_chipID);
+ }
+ }
+
+ /*Not to power off chip on default, please manually to do this*/
+#if 0
+ /*turn off LPBK function*/
+ if(ioctl(wmt_fd, 7, 0) != 0)
+ {
+ printf("[%s] turn lpbk function off failed\n", __FUNCTION__);
+ ret = -1;
+ }
+ else
+ {
+ ret = 0;
+ }
+#endif
+ ret = 0;
+
+end:
+ if (loop != count) {
+ printf("fail at loop(%d) buf_length(%d)\n", loop, buf_length);
+ }
+
+ /* close wmt dev */
+ if (wmt_fd >= 0) {
+ close(wmt_fd);
+ }
+
+ return ret;
+}
+static void print_usage(void)
+{
+ unsigned int usage_lines = 0;
+ static char *(usage[]) = {
+ "6620_wmt_lpbk type count length delay",
+ " --type: essential",
+ " -0: loopback test with fixed packet length",
+ " -1: loopback test with packet length increase 1 per packet based on 1",
+ " -2: loopback test packet length decrease 1 per packet based on 1024",
+ " -3: loopback test with random packet length",
+ " -4: only turn loopback function on without test",
+ " -5: only turn loopback function off without test",
+ " -6: loopback test spi bus by get Adie chpid in SOC chip",
+ " --count: optional, total packet count, 1000 by default",
+ " --length: optional, 1 ~ 1024, 1024 by default",
+ " --delay: optional, interval between packets (ms), 0 by default",
+
+ };
+ for (usage_lines = 0 ; usage_lines < sizeof (usage)/sizeof(usage[0]); usage_lines++)
+ {
+ printf("%s\n", usage[usage_lines]);
+ }
+
+}
+
+int main(int argc, char *argv[])
+{
+ int type = LEN_FIXED;
+ int count = 1000;
+ int length = 1024;
+ int delay = 0;
+ if(argc <= 1)
+ {
+ printf ("Error lack of arguments\n");
+ print_usage();
+ return -1;
+ }
+
+ if ((argc > 1) && (argv[1] != NULL)) {
+ printf("type: argv[1] %s %d\n", argv[1], atoi(argv[1]));
+ type = atoi(argv[1]);
+ }
+
+ if ((argc > 2) && (argv[2] != NULL)) {
+ printf("count: argv[2] %s %d\n", argv[2], atoi(argv[2]));
+ count = atoi(argv[2]);
+ }
+
+ if ((argc > 3) && (argv[3] != NULL)) {
+ printf("count: argv[3] %s %d\n", argv[3], atoi(argv[3]));
+ length = atoi(argv[3]);
+ if (0 == length) {
+ printf("length is zero, reset default value 1024\n");
+ length = 1024;
+ }
+ }
+
+ if ((argc > 4) && (argv[4] != NULL)) {
+ printf("count: argv[4] %s %d\n", argv[4], atoi(argv[4]));
+ delay = atoi(argv[4]);
+ }
+ return wmt_loopback(type, count, length, delay);
+}
+
diff --git a/src/connectivity/combo_tool/src/yocto_stp_uart_launcher.c b/src/connectivity/combo_tool/src/yocto_stp_uart_launcher.c
new file mode 100755
index 0000000..1166cf5
--- /dev/null
+++ b/src/connectivity/combo_tool/src/yocto_stp_uart_launcher.c
@@ -0,0 +1,1549 @@
+// SPDX-License-Identifier: MediaTekProprietary
+/******************************************************************************
+* C O M P I L E R F L A G S
+*******************************************************************************
+*/
+
+/******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+*******************************************************************************
+*/
+#include "wmt_ioctl.h"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <pthread.h>
+/*#include <syslog.h>*/
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+// For directory operation
+#include <dirent.h>
+#include <sys/uio.h>
+#include <linux/serial.h> /* struct serial_struct */
+
+/******************************************************************************
+* C O N S T A N T S
+*******************************************************************************
+*/
+/* !defined(ANDROID) */
+#ifndef ALOGI
+#define ALOGI printf
+#endif
+#ifndef ALOGE
+#define ALOGE printf
+#endif
+#ifndef ALOGD
+#define ALOGD printf
+#endif
+#ifndef PROPERTY_VALUE_MAX
+#define PROPERTY_VALUE_MAX (128)
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "6620_launcher"
+
+#ifndef N_MTKSTP
+#define N_MTKSTP (15 + 1) /* MediaTek WCN Serial Transport Protocol */
+#endif
+
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+
+#define CUST_COMBO_WMT_DEV "/dev/stpwmt"
+#define CUST_COMBO_STP_DEV "/dev/ttyMT2" //-- for ALPS
+#define CUST_COMBO_PATCH_PATH "/etc/firmware" //-- for ALPS
+
+#define CUST_BAUDRATE_DFT (115200)
+
+#define CUST_MULTI_PATCH (1)
+#define MTK_WCN_ENABLE_COREDUMP_BY_PROPERTY 0
+
+typedef enum {
+ STP_MIN = 0x0,
+ STP_UART_FULL = 0x1,
+ STP_UART_MAND = 0x2,
+ STP_BTIF_FULL = 0x3,
+ STP_SDIO = 0x4,
+ STP_MAX = 0x5,
+}STP_MODE;
+
+#define MAX_CMD_LEN (NAME_MAX+1)
+
+typedef enum {
+ UART_DISABLE_FC = 0, /*NO flow control*/
+ UART_MTK_SW_FC = 1, /*MTK SW Flow Control, differs from Linux Flow Control*/
+ UART_LINUX_FC = 2, /*Linux SW Flow Control*/
+ UART_HW_FC = 3, /*HW Flow Control*/
+} STP_UART_FC;
+
+typedef struct {
+ const char *key;
+ const char *defValue;
+ char value[PROPERTY_VALUE_MAX];
+} SYS_PROPERTY;
+
+typedef struct {
+ STP_UART_FC fc;
+ int parity;
+ int stop_bit;
+} STP_UART_CONFIG;
+
+typedef struct {
+ STP_MODE eStpMode;
+ char *pPatchPath;
+ char *pPatchName;
+ char *gStpDev;
+ int iBaudrate;
+ STP_UART_CONFIG sUartConfig;
+}STP_PARAMS_CONFIG, *P_STP_PARAMS_CONFIG;
+
+
+#if CUST_MULTI_PATCH
+typedef struct {
+ int dowloadSeq;
+ char addRess[4];
+ char patchName[256];
+} STP_PATCH_INFO, *P_STP_PATCH_INFO;
+#endif
+
+typedef struct {
+ const char *pCfgItem;
+ char cfgItemValue[NAME_MAX + 1];
+} CHIP_ANT_MODE_INFO, *P_CHIP_ANT_MODE_INFO;
+
+
+typedef struct {
+ int chipId;
+ STP_MODE stpMode;
+ CHIP_ANT_MODE_INFO antMode;
+}CHIP_MODE_INFO, *P_CHIP_MODE_INFO;
+#ifndef WMT_PLAT_APEX
+CHIP_MODE_INFO gChipModeInfo[] = {
+ {0x6620, STP_UART_FULL, {"mt6620.defAnt", "mt6620_ant_m3.cfg"}},
+ {0x6628, STP_UART_FULL, {"mt6628.defAnt", "mt6628_ant_m1.cfg"}},
+ {0x6630, STP_UART_FULL, {"mt6630.defAnt", "mt6630_ant_m1.cfg"}},
+};
+#else
+CHIP_MODE_INFO gChipModeInfo[] = {
+ {0x6620, STP_UART_FULL, {"mt6620.defAnt", "WMT.cfg"}},
+ {0x6628, STP_UART_FULL, {"mt6628.defAnt", "WMT.cfg"}},
+ {0x6630, STP_UART_FULL, {"mt6630.defAnt", "WMT.cfg"}},
+};
+#endif
+/******************************************************************************
+* D A T A T Y P E S
+*******************************************************************************
+*/
+struct cmd_hdr{
+ char *pCmd;
+ int (*hdr_func)(P_STP_PARAMS_CONFIG pStpParamsConfig);
+};
+
+struct speed_map {
+ unsigned int baud;
+ speed_t speed;
+};
+
+/******************************************************************************
+* M A C R O S
+*******************************************************************************
+*/
+#define INIT_CMD(c, e, s) {.cmd = c, .cmd_sz = sizeof(c), .evt = e, .evt_sz = sizeof(e), .str = s}
+
+/******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+*******************************************************************************
+*/
+static int set_speed(int fd, struct termios *ti, int speed);
+int setup_uart_param(int hComPort, int iBaudrate, STP_UART_CONFIG *stp_uart);
+
+int cmd_hdr_baud_115k(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_921k(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_2kk(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_2_5kk(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_3kk(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_3_2kk(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_3_25kk(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_3_5kk(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_baud_4kk(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_stp_open(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_stp_close(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_stp_rst(P_STP_PARAMS_CONFIG pStpParamsConfig);
+int cmd_hdr_sch_patch(P_STP_PARAMS_CONFIG pStpParamsConfig);
+static int check_chip_id(void);
+static int setHifInfo(int chipId, char *cfgFilePath);
+static int wmt_cfg_item_parser(char *pItem);
+static int get_wmt_cfg(int chipId);
+static speed_t get_speed(int baudrate);
+
+
+/******************************************************************************
+* P U B L I C D A T A
+*******************************************************************************
+*/
+
+/******************************************************************************
+* P R I V A T E D A T A
+*******************************************************************************
+*/
+static struct speed_map speeds[] = {
+ {115200, B115200},
+ {921600, B921600},
+ {1000000, B1000000},
+ {1152000, B1152000},
+ {2000000, B2000000},
+ {2500000, B2500000},
+ {3000000, B3000000},
+ {3500000, B3500000},
+ {4000000, B4000000},
+};
+
+static STP_UART_CONFIG g_stp_uart_config;
+
+struct cmd_hdr cmd_hdr_table[] = {
+ { "baud_115200_0", cmd_hdr_baud_115k},
+ { "baud_921600_0", cmd_hdr_baud_921k},
+ { "baud_2000000_0", cmd_hdr_baud_2kk},
+ { "baud_2500000_0", cmd_hdr_baud_2_5kk},
+ { "baud_3000000_0", cmd_hdr_baud_3kk},
+ //{ "baud_3200000_0", cmd_hdr_baud_3_2kk},
+ //{ "baud_3250000_0", cmd_hdr_baud_3_25kk},
+ { "baud_3500000_0", cmd_hdr_baud_3_5kk},
+ { "baud_4000000_0", cmd_hdr_baud_4kk},
+ { "open_stp", cmd_hdr_stp_open},
+ { "close_stp", cmd_hdr_stp_close},
+ { "rst_stp", cmd_hdr_stp_rst},
+ { "srh_patch", cmd_hdr_sch_patch},
+};
+
+static volatile sig_atomic_t __io_canceled = 0;
+static char gPatchName[NAME_MAX+1]= {0};
+static char gPatchFolder[NAME_MAX+1]= {0};
+static char gStpDev[NAME_MAX+1]= {0};
+static int gStpMode = -1;
+static char gWmtCfgName[NAME_MAX+1] = {0};
+static int gWmtFd = -1;
+static int gTtyFd = -1;
+static char gCmdStr[MAX_CMD_LEN]= {0};
+static char gRespStr[MAX_CMD_LEN]= {0};
+static int gFmMode = 2; /* 1: i2c, 2: comm I/F */
+static const char *gUartName = NULL;
+
+#if CUST_MULTI_PATCH
+static unsigned int gPatchNum = 0;
+static unsigned int gDwonSeq = 0;
+static P_STP_PATCH_INFO pStpPatchInfo = NULL;
+static STP_PATCH_INFO gStpPatchInfo;
+#endif
+
+pthread_t thread_handle = -1;
+/******************************************************************************
+* F U N C T I O N S
+*******************************************************************************
+*/
+
+/* Used as host uart param setup callback */
+int setup_uart_param(
+ int hComPort,
+ int iBaudrate,
+ STP_UART_CONFIG *stpUartConfig) {
+ struct termios ti;
+ int fd;
+
+ if (!stpUartConfig) {
+ ALOGE("Invalid stpUartConfig");
+ return -2;
+ }
+
+ ALOGI("setup_uart_param %d %d\n", iBaudrate, stpUartConfig->fc);
+
+ fd = hComPort;
+ if (fd < 0) {
+ ALOGE("Invalid serial port");
+ return -2;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (tcgetattr(fd, &ti) < 0) {
+ ALOGE("Can't get port settings");
+ return -3;
+ }
+
+ cfmakeraw(&ti);
+
+ ALOGI("ti.c_cflag = 0x%08x\n", ti.c_cflag);
+ ti.c_cflag |= CLOCAL;
+ ALOGI("CLOCAL = 0x%x\n", CLOCAL);
+ ALOGI("(ori)ti.c_iflag = 0x%08x\n", ti.c_iflag);
+ ALOGI("(ori)ti.c_cflag = 0x%08x\n", ti.c_cflag);
+ ALOGI("stpUartConfig->fc= %d (0:none,sw,hw,linux)\n", stpUartConfig->fc);
+
+ if (stpUartConfig->fc == UART_DISABLE_FC) {
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ } else if (stpUartConfig->fc == UART_MTK_SW_FC) {
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag |= 0x80000000; /*MTK Software FC*/
+ } else if (stpUartConfig->fc == UART_HW_FC) {
+ ti.c_cflag |= CRTSCTS; /*RTS, CTS Enable*/
+ ti.c_iflag &= ~(0x80000000);
+ } else if (stpUartConfig->fc == UART_LINUX_FC) {
+ ti.c_iflag |= (IXON | IXOFF | IXANY); /*Linux Software FC*/
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ } else {
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(0x80000000);
+ }
+
+ ALOGI("c_c CRTSCTS = 0x%16x\n", CRTSCTS);
+ ALOGI("c_i IXON = 0x%08x\n", IXON);
+ ALOGI("c_i IXOFF = 0x%08x\n", IXOFF);
+ ALOGI("c_i IXANY = 0x%08x\n", IXANY);
+ ALOGI("(aft)ti.c_iflag = 0x%08x\n", ti.c_iflag);
+ ALOGI("(aft)ti.c_cflag = 0x%08x\n\n", ti.c_cflag);
+
+ if (tcsetattr(fd, TCSANOW, &ti) < 0) {
+ ALOGE("Can't set port settings");
+ return -4;
+ }
+
+ /* Set baudrate */
+ if (set_speed(fd, &ti, iBaudrate) < 0) {
+ ALOGE("Can't set initial baud rate");
+ return -5;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ return 0;
+}
+
+static void sig_hup(int sig) {
+ fprintf(stderr, "sig_hup...\n");
+}
+
+static void sig_term(int sig) {
+ fprintf(stderr, "sig_term...\n");
+ __io_canceled = 1;
+ ioctl(gWmtFd, WMT_IOCTL_SET_LAUNCHER_KILL, 1);
+}
+
+
+static speed_t get_speed(int baudrate) {
+ unsigned int idx;
+ for (idx = 0; idx < sizeof(speeds)/sizeof(speeds[0]); idx++) {
+ if (baudrate == (int)speeds[idx].baud) {
+ return speeds[idx].speed;
+ }
+ }
+ return CBAUDEX;
+}
+
+int set_speed(int fd, struct termios *ti, int speed) {
+ struct serial_struct ss;
+ int baudenum = get_speed(speed);
+
+ if (speed != CBAUDEX) {
+ // printf("%s: standard baudrate: %d -> 0x%08x\n", __FUNCTION__, speed, baudenum);
+ if ((ioctl(fd, TIOCGSERIAL, &ss)) < 0) {
+ ALOGI("%s: BAUD: error to get the serial_struct info:%s\n", __FUNCTION__, strerror(errno));
+ return -1;
+ }
+ ss.flags &= ~ASYNC_SPD_CUST;
+#if defined(SERIAL_STRUCT_EXT) /*modified in serial_struct.h*/
+ memset(ss.reserved, 0x00, sizeof(ss.reserved));
+#endif
+ ss.flags |= (1 << 13); /*set UPFLOWLATENCY flat to tty, or serial_core will reset tty->low_latency to 0*/
+ /*set standard buadrate setting*/
+ if ((ioctl(fd, TIOCSSERIAL, &ss)) < 0) {
+ ALOGI("%s: BAUD: error to set serial_struct:%s\n", __FUNCTION__, strerror(errno));
+ return -2;
+ }
+ cfsetospeed(ti, baudenum);
+ cfsetispeed(ti, baudenum);
+ return tcsetattr(fd, TCSANOW, ti);
+ }
+ else {
+ ALOGI("%s: unsupported non-standard baudrate: %d -> 0x%08x\n", __FUNCTION__, speed, baudenum);
+ return -3;
+ }
+}
+
+int cmd_hdr_baud_115k(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 115200, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_921k(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 921600, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_2kk(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 2000000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_2_5kk(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 2500000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_3kk(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 3000000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_3_2kk(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 3200000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_3_25kk(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 3250000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_3_5kk(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 3500000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_baud_4kk(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ STP_UART_CONFIG *gStpUartConfig = &pStpParamsConfig->sUartConfig;
+ return (gTtyFd != -1) ? setup_uart_param(gTtyFd, 4000000, gStpUartConfig) : -1;
+}
+
+int cmd_hdr_stp_open(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ int ld;
+ if ((STP_UART_FULL == gStpMode) && (-1 == gTtyFd)) {
+ gTtyFd = open(gStpDev, O_RDWR | O_NOCTTY);
+ if (gTtyFd < 0) {
+ fprintf(stderr, "Can't open serial port %s\n", gStpDev);
+ return -2;
+ }
+ ALOGI("real_tty(%s) opened(%d)\n", gStpDev, gTtyFd);
+
+ /* Set TTY to N_MTKSTP line discipline */
+ ld = N_MTKSTP;
+ if (ioctl(gTtyFd, TIOCSETD, &ld) < 0) {
+ fprintf(stderr, "Can't set ldisc to N_MTKSTP\n");
+ return -3;
+ }
+
+ // printf("Set tty->low_latency\n");
+ if (ioctl(gTtyFd, HCIUARTSETPROTO, 0) < 0) {
+ ALOGE("Can't set HCIUARTSETPROTO\n");
+ return -4;
+ }
+ return 0;
+ }
+ else {
+ fprintf(stderr, "stp_open fail: stp_mode(%d) real_tty_fd(%d) \n", gStpMode, gTtyFd);
+ return -1;
+ }
+}
+
+int cmd_hdr_stp_close(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ int ld;
+
+ if ((STP_UART_FULL == gStpMode) && (0 <= gTtyFd)) {
+ /* Restore TTY line discipline */
+ ld = N_TTY;
+ if (ioctl(gTtyFd, TIOCSETD, &ld) < 0) {
+ ALOGE("Can't restore line discipline");
+ return -2;
+ }
+
+ close(gTtyFd);
+ gTtyFd = -1;
+ return 0;
+ } else if (gTtyFd == -1) {
+ return 0;
+ } else {
+ fprintf(stderr, "stp_close fail: stp_mode(%d) real_tty_fd(%d) \n", gStpMode, gTtyFd);
+ return -1;
+ }
+}
+
+int cmd_hdr_stp_rst(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ int ret = 0;
+ /*this step fail?*/
+ ret = cmd_hdr_stp_close(pStpParamsConfig);
+ /*here, launcher is close state*/
+ ret = cmd_hdr_stp_open(pStpParamsConfig);
+ return ret;
+}
+
+#if CUST_MULTI_PATCH
+int cmd_hdr_sch_patch(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ // #define PATCH_PATH "/system/etc/firmware"
+ int chipId = 0;
+ int hwVersion = 0;
+ int fwVersion = 0;
+ char chipName[16] = {0};
+ char patchFullName[256] = {0};
+#if (MTK_COMBO_USING_PATCH_NAME==1)
+ char patchName[128] = {0};
+#endif /* MTK_COMBO_USING_PATCH_NAME */
+ unsigned int patchVer = 0;
+ DIR *pDir = NULL;
+ int patchFd = -1;
+ int iRet = 0;
+ int bytes;
+ unsigned int patchNum = 0;
+ char patchInfo[8] = {0};
+ unsigned int isFirst = 1;
+ P_STP_PATCH_INFO pstPaInfo = NULL;
+ struct dirent* pDirent = NULL;
+
+ if (gWmtFd > 0) {
+ /*1. ioctl to get CHIP ID*/
+ chipId = ioctl(gWmtFd, WMT_IOCTL_GET_CHIP_INFO, 0);
+ if ((0x0321 == chipId) || (0x0335 == chipId) || (0x0337 == chipId)) {
+ chipId = 0x6735;
+ ALOGI("for denali chipid convert\n");
+ }
+ if (0x0326 == chipId) {
+ chipId = 0x6755;
+ ALOGI("for jade chipid convert\n");
+ }
+ if (0x0279 == chipId) {
+ chipId = 0x6797;
+ ALOGI("for everest chipid convert\n");
+ }
+ strncpy(chipName, "mt", strlen("mt"));
+ sprintf(chipName + strlen("mt"), "%04x", chipId);
+
+ if ((!strcmp(chipName, "mt6620")) || (!strcmp(chipName, "mt6628")) || (!strcmp(chipName, "mt6630")) ||
+ (!strcmp(chipName, "mt6572")) || (!strcmp(chipName, "mt6582")) || (!strcmp(chipName, "mt6592")) ||
+ (!strcmp(chipName, "mt8127"))|| (!strcmp(chipName, "mt7623")) || (!strcmp(chipName, "mt6571")) ||
+ (!strcmp(chipName, "mt6752")) ||
+ (!strcmp(chipName, "mt8163")) || (!strcmp(chipName, "mt6580")) ||
+ (!strcmp(chipName, "mt6735")) || (!strcmp(chipName, "mt6755")) || (!strcmp(chipName, "mt6797")) ||
+ (!strcmp(chipName, "mt8167"))) {
+ if ((!strcmp(chipName, "mt6572")) || (!strcmp(chipName, "mt6582")) || (!strcmp(chipName, "mt6592"))) {
+ strncpy(chipName, "ROMv1", strlen("ROMv1"));
+ chipName[5] = '\0';
+ } else if (!strcmp(chipName, "mt8127") || !strcmp(chipName, "mt6571")) {
+ strncpy(chipName, "ROMv2", strlen("ROMv2"));
+ chipName[5] = '\0';
+ } else if (!strcmp(chipName, "mt6755") ||!strcmp(chipName, "mt6752") || !strcmp(chipName, "mt6735")
+ || !strcmp(chipName, "mt8163") || !strcmp(chipName, "mt6580") || !strcmp(chipName, "mt7623")
+ || !strcmp(chipName, "mt8167")) {
+ strncpy(chipName, "ROMv2_lm", strlen("ROMv2_lm"));
+ } else if (!strcmp(chipName, "mt6797")) {
+ strncpy(chipName, "ROMv3", strlen("ROMv3"));
+ chipName[5] = '\0';
+ }
+ strcat(chipName, "_patch");
+ ALOGI("patch name pre-fix:%s\n", chipName);
+ /*2. ioctl to get FIRMWARE VERSION*/
+ fwVersion = ioctl(gWmtFd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI("fwVersion:0x%04x\n", fwVersion);
+ /*3. open directory patch located*/
+ if (NULL == pStpParamsConfig->pPatchPath) {
+ pStpParamsConfig->pPatchPath = CUST_COMBO_PATCH_PATH;
+ }
+
+ {
+ pDir = opendir(pStpParamsConfig->pPatchPath);
+ if (NULL == pDir) {
+ ALOGE("patch path cannot be opened");
+ iRet = -1;
+ return iRet;
+ }
+ while (NULL != (pDirent = readdir(pDir))) {
+ patchVer = 0;
+
+ if (0 == (strncmp(pDirent->d_name, chipName, strlen(chipName)))) {
+ /*4.1. search patch name begined with chipName*/
+ strcpy(patchFullName, pStpParamsConfig->pPatchPath);
+ strcat(patchFullName, "/");
+ // robust, if input patch is /etc/firmwre/ no issue should be happened.
+ strcat(patchFullName, pDirent->d_name);
+
+ ALOGI("%s\n", patchFullName);
+#if (MTK_COMBO_USING_PATCH_NAME==1)
+ strcpy (patchName, pDirent->d_name);
+#endif /* MTK_COMBO_USING_PATCH_NAME */
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 <= (patchFd = (open(patchFullName, O_RDONLY)))) {
+ /*4.2. read patch header and check if metch with
+ MAJOR+MINOR number in fw version */
+ if (-1 != lseek(patchFd, 22, SEEK_SET)) {
+ memset(&gStpPatchInfo, 0, sizeof(gStpPatchInfo));
+ memset(patchInfo, 0, sizeof(patchInfo));
+
+ bytes = read(patchFd, ((char *)&patchVer) + 1, 1);
+ if (-1 == bytes) {
+ ALOGI("read patchVer1 failed!\n");
+ goto readfailed;
+ }
+ bytes = read(patchFd, ((char *)&patchVer), 1);
+ if (-1 == bytes) {
+ ALOGI("read patchVer failed!\n");
+ goto readfailed;
+ }
+ /*print hardware version information in patch*/
+ ALOGI("fw Ver in patch: 0x%04x\n", patchVer);
+ if (0 == ((patchVer ^ fwVersion) & 0x00ff)) {
+ bytes = read(patchFd, patchInfo, 4);
+ if (-1 == bytes) {
+ ALOGI("read patchInfo failed!\n");
+ goto readfailed;
+ }
+ patchInfo[4] = '\0';
+ ALOGI("read patch info:0x%02x,0x%02x,0x%02x,0x%02x\n",
+ patchInfo[0], patchInfo[1], patchInfo[2], patchInfo[3]);
+ if (1 == isFirst) {
+ gPatchNum = (patchInfo[0] & 0xF0) >> 4;
+ ALOGI("gpatchnum = [%d]\n", gPatchNum);
+ ioctl(gWmtFd, WMT_IOCTL_SET_PATCH_NUM, gPatchNum);
+
+ gDwonSeq = (patchInfo[0] & 0x0F);
+ ALOGI("gdwonseq = [%d]\n", gDwonSeq);
+ gStpPatchInfo.dowloadSeq = gDwonSeq;
+ memcpy(gStpPatchInfo.addRess, patchInfo, sizeof(gStpPatchInfo.addRess));
+ gStpPatchInfo.addRess[0] = 0x00;
+#if (MTK_COMBO_USING_PATCH_NAME==1)
+ strncpy(gStpPatchInfo.patchName, patchName,
+ sizeof(gStpPatchInfo.patchName) - 1);
+#else
+ strncpy(gStpPatchInfo.patchName, patchFullName,
+ sizeof(gStpPatchInfo.patchName) - 1);
+#endif /* MTK_COMBO_USING_PATCH_NAME */
+ gStpPatchInfo.patchName[sizeof(gStpPatchInfo.patchName) - 1] = '\0';
+ ioctl(gWmtFd, WMT_IOCTL_SET_PATCH_INFO, &gStpPatchInfo);
+ isFirst++;
+ } else {
+ gDwonSeq = (patchInfo[0] & 0x0F);
+ ALOGI("gdwonseq = [%d]\n", gDwonSeq);
+ gStpPatchInfo.dowloadSeq = gDwonSeq;
+ memcpy(gStpPatchInfo.addRess, patchInfo, sizeof(gStpPatchInfo.addRess));
+ gStpPatchInfo.addRess[0] = 0x00;
+#if (MTK_COMBO_USING_PATCH_NAME==1)
+ strncpy(gStpPatchInfo.patchName, patchName,
+ sizeof(gStpPatchInfo.patchName) - 1);
+#else
+ strncpy(gStpPatchInfo.patchName, patchFullName,
+ sizeof(gStpPatchInfo.patchName) - 1);
+#endif /* MTK_COMBO_USING_PATCH_NAME */
+ gStpPatchInfo.patchName[sizeof(gStpPatchInfo.patchName) - 1] = '\0';
+ ioctl(gWmtFd, WMT_IOCTL_SET_PATCH_INFO, &gStpPatchInfo);
+ }
+ }
+ }
+ else {
+ ALOGE("seek failed\n");
+ }
+readfailed:
+ close(patchFd);
+ patchFd = -1;
+ }
+ else {
+ ALOGI("open patch file(%s) failed\n", patchFullName);
+ // ALOGE(patchFullName);
+ }
+ }
+ }
+ /*5. return value*/
+ closedir(pDir);
+ pDir = NULL;
+ }
+ }
+ }
+ else {
+ ALOGE("file descriptor is not valid\n");
+ iRet = -2;
+ }
+ return iRet;
+}
+#else
+int cmd_hdr_sch_patch(P_STP_PARAMS_CONFIG pStpParamsConfig) {
+ // #define PATCH_PATH "/system/etc/firmware"
+ int chipId = 0;
+ int hwVersion = 0;
+ int fwVersion = 0;
+ char chipName[16] = {0};
+ char patchFullName[256] = {0};
+ unsigned int patchVer = 0;
+ DIR *pDir = NULL;
+ int patchFd = -1;
+ struct dirent* pDirent = NULL;
+ int iRet = -1;
+
+ if (gWmtFd > 0) {
+ /*1. ioctl to get CHIP ID*/
+ chipId = ioctl(gWmtFd, WMT_IOCTL_GET_CHIP_INFO, 0);
+ strcpy(chipName, "mt");
+ sprintf(chipName + strlen(chipName), "%04x", chipId);
+ strcat(chipName, "_patch");
+ ALOGI("patch name pre-fix:%s\n", chipName);
+ fwVersion = ioctl(gWmtFd, WMT_IOCTL_GET_CHIP_INFO, 2);
+ ALOGI("fwVersion:0x%04x\n", fwVersion);
+ /*3. open directory patch located*/
+ if (NULL == pStpParamsConfig->pPatchPath) {
+ pStpParamsConfig->pPatchPath = CUST_COMBO_PATCH_PATH;
+ }
+ pDir = opendir(pStpParamsConfig->pPatchPath);
+ if (NULL == pDir) {
+ ALOGE("patch path cannot be opened");
+ iRet = -2;
+ return iRet;
+ }
+ while (NULL != (pDirent = readdir(pDir))) {
+ patchVer = 0;
+
+ if (0 == (strncmp(pDirent->d_name, chipName, strlen(chipName)))) {
+ /*4.1. search patch name begined with chipName*/
+ strcpy(patchFullName, pStpParamsConfig->pPatchPath);
+ strcat(patchFullName, "/"); // robust, if input patch is /etc/firmwre/ no issue should be happened.
+ strcat(patchFullName, pDirent->d_name);
+
+ ALOGI("%s\n", patchFullName);
+ /*4.1. search patch name mt[CHIP ID]xxx.bin*/
+ if (0 < (patchFd = (open(patchFullName, O_RDONLY)))) {
+ /*4.2. read patch header and check if metch with MAJOR+MINOR number in fw version */
+ if (-1 != lseek(patchFd, 22, SEEK_SET)) {
+ read(patchFd, ((char *)&patchVer) + 1, 1);
+ read(patchFd, ((char *)&patchVer), 1);
+ /*print firmware version information in patch*/
+ ALOGI("fw Ver in patch: 0x%04x\n", patchVer);
+ if (0 == ((patchVer ^ fwVersion) & 0x00ff)) {
+ ioctl(gWmtFd, WMT_IOCTL_SET_PATCH_NAME, patchFullName);
+ ALOGI("fw Ver in patch matches with firmware version\n");
+ iRet = 0;
+ close(patchFd);
+ break;
+ }
+ }
+ else {
+ ALOGE("seek failed\n");
+ }
+ close(patchFd);
+ patchFd = -1;
+ }
+ else {
+ // printf("open patch file(%s) failed\n", patchFullName);
+ ALOGE(patchFullName);
+ }
+ }
+ }
+
+ /*5. return value*/
+ closedir(pDir);
+ pDir = NULL;
+ }
+ else {
+ ALOGE("file descriptor is not valid\n");
+ iRet = -1;
+ }
+ return iRet;
+}
+#endif
+/*
+ret 0: success
+ret 1: cmd not found
+ret -x: handler return value
+*/
+int handle_cmd(P_STP_PARAMS_CONFIG pStpParamsConfig, char *cmd, int len) {
+ int ret = 1;
+ int i;
+ int cmd_len;
+
+ for (i = 0; i < (int)(sizeof(cmd_hdr_table)/sizeof(cmd_hdr_table[0])); ++i) {
+ cmd_len = (int)strlen(cmd_hdr_table[i].pCmd);
+ if (!strncmp(cmd_hdr_table[i].pCmd, cmd, (len < cmd_len) ? len : cmd_len)) {
+ ret = (*cmd_hdr_table[i].hdr_func)(pStpParamsConfig);
+ }
+ }
+
+ return ret;
+}
+
+void display_usage(int chipid) {
+ unsigned int index = 0;
+ char * usage1[] = {
+ "MTK WCN combo tool set, version 1.0-release",
+ "Usage: consys_launcher -m mode -p patchfolderpath",
+ " -m (BT/GPS/FM common interface mode selection)",
+ " -1: UART mode (common interface: UART)",
+ " -3: BTIF mode (common interface: BTIF)",
+ " -4: SDIO mode (common interface: SDIO)",
+ " -p (MTK WCN soc conssy chip firmware patch location)",
+ " -e.g. /etc/firmware",
+ "e.g. consys_launcher -m 3 -p /etc/firmware/",
+ };
+ char * usage2[] = {
+ "MTK WCN combo tool set, version 1.0-release",
+ "Usage: 6620_launcher -m mode -p patchfolderpath [-d uartdevicenode] [-b baudrate] [-c uartflowcontrol]",
+// " -m (BT/GPS/FM common interface mode selection)",
+// " -1: UART mode (common interface: UART)",
+// " -1: UART full mode (common interface UART)",
+// " -2: UART mandetary mode (common interface UART)",
+ " -4: UART mode (common interface SDIO)",
+ " -p (MTK WCN Combo chip firmware patch location)",
+ " -e.g. /etc/firmware",
+ " -b (Baudrate set when BT/GPS/FM runs under UART mode, no needed under SDIO mode)",
+ " -115200/921600/2000000/2500000/3000000/3500000/4000000",
+ " -d (UART device node, when under UART mode, no needed under SDIO mode)",
+ " -e.g. /dev/ttyMT1, /dev/ttyMT2, /dev/ttyHS2, etc.",
+ " -c (UART flowcontrol set)",
+ " -0, no flowcontrol default value, please donot modify this parameter",
+ "e.g. 6620_launcher 4 /etc/firmware/mt6628_patch_hdr.bin",
+ "e.g. 6620_launcher -m 1 -p /etc/firmware/",
+ "e.g. 6620_launcher -m 1 -n /etc/firmware/mt6628_patch_hdr.bin",
+ "e.g. 6620_launcher -m 4 -d /dev/ttyMT2 -b 4000000 -n /etc/firmware/mt6628_patch_hdr.bin",
+ };
+ if (0x6582 == chipid || 0x8127 == chipid) {
+ for (index = 0; index < sizeof(usage1)/sizeof(usage1[0]); index++) {
+ ALOGI("%s\n", usage1[index]);
+ }
+ } else {
+ for (index = 0; index < sizeof(usage2)/sizeof(usage2[0]); index++) {
+ ALOGI("%s\n", usage2[index]);
+ }
+ }
+ exit(EXIT_FAILURE);
+}
+
+int para_valid_check(P_STP_PARAMS_CONFIG pStpParamConfig) {
+ if ((NULL != pStpParamConfig->pPatchPath) || (NULL != pStpParamConfig->pPatchName)) {
+ if (NULL != pStpParamConfig->pPatchPath) {
+ ALOGI("MCU patch folder path: %s\n", pStpParamConfig->pPatchPath);
+ }
+ if (NULL != pStpParamConfig->pPatchName) {
+ ALOGI("MCU patch full path: %s\n", pStpParamConfig->pPatchName);
+ }
+ }
+ else {
+ puts("MCU patch name or patch not found, exit.");
+ return -1;
+ }
+ if (pStpParamConfig->eStpMode != STP_SDIO && pStpParamConfig->eStpMode != STP_UART_MAND &&
+ pStpParamConfig->eStpMode != STP_UART_FULL) {
+ puts("Stp Mode is not set, common interface use default: SDIO Mode");
+ pStpParamConfig->eStpMode = STP_SDIO;
+ return 0;
+ }
+ // SDIO mode: eStpMode = STP_SDIO && (pPachName != NULL || pPatchPath != NULL)
+ if (pStpParamConfig->eStpMode == STP_SDIO) {
+ ALOGI("Common Interface: SDIO mode\n");
+ }
+ else if (pStpParamConfig->eStpMode == STP_UART_MAND || pStpParamConfig->eStpMode == STP_UART_FULL) {
+ ALOGI("Common Interface: UART mode\n");
+ if (NULL == pStpParamConfig->gStpDev) {
+ pStpParamConfig->gStpDev = CUST_COMBO_STP_DEV;
+ ALOGI("no uart device input, use default: %s\n", pStpParamConfig->gStpDev);
+ }
+ if (pStpParamConfig->iBaudrate < 0) {
+ // FixMe:Chaozhong, add baudrate validation check
+ pStpParamConfig->iBaudrate = 4000000;
+ ALOGI("no baudrate input, use default: %d\n", pStpParamConfig->iBaudrate);
+ }
+ }
+ return 0;
+}
+
+static int wmt_cfg_item_parser(char *pItem) {
+ int maxIndex = sizeof (gChipModeInfo) / sizeof (gChipModeInfo[0]);
+ int index = 0;
+ int length = 0;
+ char *str = NULL;
+ char *keyStr = NULL;
+ char *valueStr = NULL;
+ if (NULL == pItem) {
+ ALOGI("Warning:pItem is NULL\n");
+ return -1;
+ }
+ /*all item must be start with mt66xx*/
+ str = strstr(pItem, "m");
+ if (NULL == str) {
+ ALOGI("Warning:no string start with 'm' found in %s\n", pItem);
+ return -2;
+ }
+
+ for (index = 0; index < maxIndex; index++) {
+ keyStr = (char*)gChipModeInfo[index].antMode.pCfgItem;
+ if (0 == strncasecmp(str, keyStr, strlen(keyStr))) {
+ str = strstr(str, "=");
+ if (NULL == str) {
+ ALOGI("Warning:no '=' found in %s\n", str);
+ return -3;
+ }
+ str = strstr(str, "m");
+ if (NULL == str) {
+ ALOGI("Warning:no 'm' found in %s\n", str);
+ return -4;
+ }
+ while (((*str) == ' ') || ((*str) == '\t') || ((*str) == '\n')) {
+ if (str >= pItem + strlen(pItem)) {
+ break;
+ }
+ str++;
+ }
+ valueStr = str;
+ while (((*str) != ' ') && ((*str) != '\t') && ((*str) != '\0') &&
+ ((*str) != '\n') && ((*str) != '\r')) {
+ if (str >= pItem + strlen(pItem)) {
+ ALOGI("break\n");
+ break;
+ }
+ str++;
+ }
+ *str = '\0';
+ length = sizeof(gChipModeInfo[index].antMode.cfgItemValue);
+ strncpy(gChipModeInfo[index].antMode.cfgItemValue, valueStr, length - 1);
+ gChipModeInfo[index].antMode.cfgItemValue[length - 1] = '\0';
+ ALOGI("Info:key:%s value:%s\n", keyStr, gChipModeInfo[index].antMode.cfgItemValue);
+ break;
+ }
+ }
+ return 0;
+}
+
+static int get_coredump_flag(void) {
+ return 2; /* default disable */
+}
+
+static void set_coredump_flag(void) {
+#define COREDUMP_CTRL_FILE "/data/coredump"
+ int coredumpEnableFlag = 0;
+ int iRet = -1;
+ int coredumpFd = -1;
+ if (gWmtFd < 0) {
+ ALOGI("%s:invalid wmt fd\n", __func__);
+ return;
+ }
+ /* simplify flag in linux and android property & buildtype cases */
+ coredumpEnableFlag = get_coredump_flag();
+ ioctl(gWmtFd, WMT_IOCTL_WMT_COREDUMP_CTRL, coredumpEnableFlag);
+ return;
+}
+
+static int get_wmt_cfg(int chipId) {
+#define WMTCFGFILEPATH "/system/etc/firmware/WMT.cfg"
+#define OPENMODE "r"
+#define MAXLINELEN 512
+ FILE * file = NULL;
+ int iRet = -1;
+ char *pStr = NULL;
+ char line[MAXLINELEN];
+
+ file = fopen(WMTCFGFILEPATH, OPENMODE);
+ if (NULL == file) {
+ ALOGI("%s cannot be opened, errno:%d\n", WMTCFGFILEPATH, errno);
+ return -2;
+ }
+ iRet = 0;
+ do {
+ pStr = fgets(line, MAXLINELEN, file);
+ if (NULL == pStr) {
+ ALOGI("NULL is returned, eighter EOF or error maybe found\n");
+ break;
+ }
+
+ wmt_cfg_item_parser(line);
+ memset(line, 0, MAXLINELEN);
+ } while (pStr != NULL);
+
+ if (NULL != file) {
+ if (0 == fclose(file)) {
+ ALOGI("close %s succeed\n", WMTCFGFILEPATH);
+ }
+ else {
+ ALOGI("close %s failed, errno:%d\n", WMTCFGFILEPATH, errno);
+ }
+ }
+ return iRet;
+}
+
+
+static int get_chip_info_index(int chipId) {
+ int i = 0;
+ int index = -1;
+ int left = 0;
+ int middle = 0;
+ int right = sizeof(gChipModeInfo) / sizeof(gChipModeInfo[0]) - 1;
+ if ((chipId < gChipModeInfo[left].chipId) || (chipId > gChipModeInfo[right].chipId))
+ return index;
+
+ middle = (left + right) / 2;
+ while (left <= right) {
+ if (chipId > gChipModeInfo[middle].chipId) {
+ left = middle + 1;
+ } else if (chipId < gChipModeInfo[middle].chipId) {
+ right = middle - 1;
+ } else {
+ index = middle;
+ break;
+ }
+ middle = (left + right) / 2;
+ }
+
+ if (0 > index)
+ ALOGI("no supported chipid found\n");
+ else
+ ALOGI("index:%d, chipId:0x%x\n", index, gChipModeInfo[index].chipId);
+
+ return index;
+}
+
+/* TBD in platform-specific way */
+static int get_persist_chip_id(void) { return -1; }
+static int set_persist_chip_id(const int id) { return 0; }
+
+/* return 0 for not ready, otherwise ready */
+static int get_drv_rdy(void) {
+ /* GeK: no property to communicate with wmt_loader, and we need another way
+ * to check driver ready. Maybe query ioctl(COMBO_IOCTL_DO_MODULE_INIT) to
+ * WCN_COMBO_LOADER_DEV is a possible way for both android and non-android.
+ */
+ ALOGI("WARNING!!! Need a correct way to check driver ready!!!");
+ return 1;
+}
+
+static int query_chip_id(void) {
+ int chipId;
+ int chk_id;
+ int iRet = -1;
+
+ chipId = get_persist_chip_id();
+
+ if (get_chip_info_index(chipId) >= 0)
+ return chipId;
+
+ // no persistent information found
+ // get chip id
+ chipId = ioctl(gWmtFd, WMT_IOCTL_WMT_QUERY_CHIPID, NULL);
+ if (chipId <= 0)
+ return -1;
+
+ ALOGI("chip id is 0x%x\n", chipId);
+ iRet = set_persist_chip_id(chipId);
+
+ if (iRet) {
+ ALOGI("set persistent fail:%d\n", iRet);
+ return -1;
+ }
+ return chipId;
+}
+
+static int check_chip_id(void) {
+#define COMBO_IOC_MAGIC 'h'
+#define COMBO_IOCTL_GET_CHIP_ID _IOR(COMBO_IOC_MAGIC, 0, int)
+#define COMBO_IOCTL_SET_CHIP_ID _IOW(COMBO_IOC_MAGIC, 1, int)
+ int chipId = -1;
+ int fdHifsdio = -1;
+
+ // read from system property
+ chipId = get_persist_chip_id();
+ // open HIF-SDIO
+ fdHifsdio = open("/dev/hifsdiod", O_RDWR | O_NOCTTY);
+ if (fdHifsdio < 0) {
+ ALOGI("open hifsdiod fail\n");
+ return -1;
+ }
+
+ // read from config file
+ if (0 > get_chip_info_index(chipId)) {
+ int ret;
+ // no wcn.combo.chipid property information found
+ // get chip id
+ chipId = ioctl(fdHifsdio, COMBO_IOCTL_GET_CHIP_ID, NULL);
+ ALOGI("chip id is 0x%x\n", chipId);
+ // assume we get 0x6628 here
+ ALOGI("chiId:0x%x, setting to persistent\n", chipId);
+ ret = set_persist_chip_id(chipId);
+ if (ret)
+ chipId = -1;
+ } else {
+ ioctl(fdHifsdio, COMBO_IOCTL_SET_CHIP_ID, chipId);
+ ALOGI("set chipId(0x%x) to HIF-SDIO module\n", chipId);
+ }
+ // close HIF-SDIO
+ close(fdHifsdio);
+ fdHifsdio = -1;
+ return chipId;
+}
+
+static int setHifInfo(int chipId, char *cfgFilePath) {
+ int index = -1;
+ index = get_chip_info_index(chipId);
+ if ((gStpMode <= STP_MIN) || (STP_SDIO < gStpMode)) {
+ ALOGI("STP Mode is not set, fetching default mode...\n");
+ if (0 <= index) {
+ gStpMode = gChipModeInfo[index].stpMode;
+ } else {
+ // gStpMode = STP_UART_FULL;
+ gStpMode = -1;
+ }
+ }
+
+ if ((0 <= index) && (NULL != cfgFilePath)) {
+#if (MTK_COMBO_USING_PATCH_NAME==1)
+ memset(gWmtCfgName, 0, sizeof(gWmtCfgName));
+ strncpy(gWmtCfgName, gChipModeInfo[index].antMode.cfgItemValue, sizeof(gWmtCfgName) - 1);
+ gWmtCfgName[strlen(gChipModeInfo[index].antMode.cfgItemValue)] = '\0';
+#else
+ memset(gWmtCfgName, 0, sizeof(gWmtCfgName));
+ strncpy (gWmtCfgName, cfgFilePath, sizeof(gWmtCfgName) - 1);
+ gWmtCfgName[sizeof(gWmtCfgName) - 1] = '\0';
+ strcat(gWmtCfgName, "/");
+ strcat(gWmtCfgName, gChipModeInfo[index].antMode.cfgItemValue);
+ gWmtCfgName[strlen(cfgFilePath) + strlen("/") + strlen(gChipModeInfo[index].antMode.cfgItemValue)] = '\0';
+#endif /* MTK_COMBO_USING_PATCH_NAME */
+ } else {
+ memset(gWmtCfgName, 0, sizeof(gWmtCfgName));
+ }
+ ALOGI("chipId(0x%04x), default Mode(%d), strlen(gWmtCfgName)(%u), wmtCfgFile(%s)\n",
+ chipId, gStpMode, strlen(gWmtCfgName), gWmtCfgName);
+ return gStpMode;
+}
+
+#if (MTK_COMBO_ENABLE_WIFI_IN_LAUNCHER==1)
+#define CUST_COMBO_WIFI_DEV "/dev/wmtWifi"
+#define POWER_ON_WIFI "1"
+#define POWER_ON_WIFI_LEN 1
+static int gWifiFd = -1;
+
+static int enable_wifi(void) {
+ int retryCounter = 0;
+ int i_ret = -1;
+
+ gWifiFd = open(CUST_COMBO_WIFI_DEV, O_RDWR | O_NOCTTY);
+ do {
+ if (gWifiFd < 0) {
+ ALOGI("Can't open device node(%s) error:%d \n", CUST_COMBO_WIFI_DEV, gWifiFd);
+ usleep(300000);
+ gWifiFd = open(CUST_COMBO_WIFI_DEV, O_RDWR | O_NOCTTY);
+ } else {
+ break;
+ }
+ retryCounter++;
+ } while (retryCounter < 20);
+
+ if (gWifiFd > 0) {
+ do {
+ i_ret = write(gWifiFd, POWER_ON_WIFI, POWER_ON_WIFI_LEN);
+ if (i_ret == 1) {
+ ALOGI("Power on device node(%s) gWifiFd:%d succeed !!\n", CUST_COMBO_WIFI_DEV, gWifiFd);
+ break;
+ } else {
+ ALOGI("Power on device node(%s) gWifiFd:%d Fail (%d) and retry\n", CUST_COMBO_WIFI_DEV, gWifiFd, i_ret);
+ }
+ retryCounter++;
+ usleep(300000);
+ } while (retryCounter < 20);
+ }
+ close(gWifiFd);
+
+ return 0;
+}
+#endif /* MTK_COMBO_ENABLE_WIFI_IN_LAUNCHER */
+
+static void* launcher_pwr_on_chip(void * arg) {
+ int retryCounter = 0;
+ int i_ret = -1;
+ int chipid = *(int*) arg;
+ char readyStr[PROPERTY_VALUE_MAX] = {0};
+ int iRet = -1;
+
+ pthread_setname_np(pthread_self(), "pwr_on_conn");
+
+ ALOGI("enter power on connsys flow");
+ do {
+ i_ret = ioctl(gWmtFd, WMT_IOCTL_LPBK_POWER_CTRL, 1);
+ if (0 == i_ret) {
+ break;
+ } else {
+ ioctl(gWmtFd, WMT_IOCTL_LPBK_POWER_CTRL, 0);
+ ALOGI("power on %x failed, retrying, retry counter:%d\n", chipid, retryCounter);
+ usleep(1000000);
+ }
+ retryCounter++;
+ } while (retryCounter < 20);
+
+#if (MTK_COMBO_ENABLE_WIFI_IN_LAUNCHER==1)
+ ALOGI("enter enable wifi");
+ enable_wifi();
+#endif /* MTK_COMBO_ENABLE_WIFI_IN_LAUNCHER */
+
+ pthread_detach(thread_handle);
+ thread_handle = -1;
+
+ return NULL;
+}
+static void* launcher_set_fwdbg_flag(void * arg) {
+ int i_ret = -1;
+ int flag = *(int*) arg;
+
+ pthread_setname_np(pthread_self(), "dump_fwemi_log");
+ ALOGI("dump firmware dbg log from emi buffer ");
+ i_ret = ioctl(gWmtFd, WMT_IOCTL_FW_DBGLOG_CTRL, flag);
+ if (i_ret < 0) {
+ ALOGI("ioctl error: err msg: %s\n", strerror(errno));
+ pthread_detach(thread_handle);
+ thread_handle = -1;
+ }
+ return NULL;
+}
+
+/*
+ * -m: mode (SDIO/UART)
+ * -d: uart device node
+ * -b: baudrate
+ * -c: enable SW FC or not
+ * -p: patch folder path
+ * -n: patch file name (fullpath)
+ *
+ */
+int main(int argc, char *argv[]) {
+ static const char *opString = "m:d:b:c:p:n:?";
+ struct uart_t *u = NULL;
+ int opt, ld, err;
+ int baud = 0;
+ struct sigaction sa;
+ struct pollfd fds[2];
+ int fd_num = 0;
+ int len = 0;
+ int uartFcCtrl = 0;
+ int argCount = 0;
+ int chipId = -1;
+ int i_ret = 1;
+ int retry = 0;
+ int polling_flag = 0;
+ int fwdbgEnableFlag = 0;
+ char readyStr[PROPERTY_VALUE_MAX] = {0};
+ STP_PARAMS_CONFIG sStpParaConfig;
+ char fwStateStr0[PROPERTY_VALUE_MAX] = {0};
+ char fwStateStr[PROPERTY_VALUE_MAX] = {0};
+
+ do {
+ i_ret = get_drv_rdy();
+ if (i_ret)
+ break;
+ usleep(300000);
+ } while (1);
+
+ do {
+ gWmtFd = open(CUST_COMBO_WMT_DEV, O_RDWR | O_NOCTTY);
+ if (gWmtFd < 0) {
+ ALOGI("Can't open device node(%s) error:%d \n", CUST_COMBO_WMT_DEV, gWmtFd);
+ usleep(300000);
+ } else
+ break;
+ } while (1);
+ ALOGE("open device node succeed.(Node:%s, fd:%d) \n", CUST_COMBO_WMT_DEV, gWmtFd);
+ do {
+ chipId = query_chip_id();
+ if (0 > chipId) {
+ usleep(300000);
+ chipId = ioctl(gWmtFd, WMT_IOCTL_WMT_QUERY_CHIPID, NULL);
+ ALOGI("chiId from kernel by ioctl:0x%04x\n", chipId);
+ if (-1 != chipId)
+ break;
+ } else
+ break;
+ } while (1);
+ ALOGI("chiId:0x%04x\n", chipId);
+
+ if ((0x0321 == chipId) || (0x0335 == chipId) || (0x0337 == chipId)) {
+ chipId = 0x6735;
+ ALOGI("for denali chipid convert\n");
+ }
+ if (0x0326 == chipId) {
+ chipId = 0x6755;
+ ALOGI("for jade chipid convert\n");
+ }
+ if ((0x6735 == chipId) || (0x6752 == chipId) || (0x6582 == chipId) || (0x6592 == chipId)
+ || (0x6572 == chipId) || (0x6571 == chipId) || (0x8127 == chipId)
+ || (0x8163 == chipId) || (0x6580 == chipId) || (0x6755 == chipId)
+ || (0x6797 == chipId) || (0x7623 == chipId) || (0x8167 == chipId)) {
+ ALOGI("run SOC chip flow\n");
+ gStpMode = STP_BTIF_FULL;
+ memset(gPatchFolder, 0, sizeof(gPatchFolder));
+ opt = getopt(argc, argv, opString);
+ while (opt != -1) {
+ switch (opt) {
+ case 'm':
+ gStpMode = atoi(optarg);
+ sStpParaConfig.eStpMode = gStpMode;
+ ALOGI("stpmode[%d]\n", gStpMode);
+ break;
+ case 'p':
+ // gPatchFolder = optarg;
+ strcpy(gPatchFolder, optarg);
+ sStpParaConfig.pPatchPath = gPatchFolder;
+ break;
+ case '?':
+ default:
+ display_usage(chipId);
+ break;
+ }
+ opt = getopt(argc, argv, opString);
+ }
+ /* send default patch file name path to driver */
+ ioctl(gWmtFd, WMT_IOCTL_SET_PATCH_NAME, gPatchName);
+ /* set fm mode & stp mode*/
+ ioctl(gWmtFd, WMT_IOCTL_SET_STP_MODE, ((gFmMode & 0x0F) << 4) |(gStpMode & 0x0F));
+#ifndef WMT_PLAT_APEX
+ set_coredump_flag();
+#endif
+ } else {
+ ALOGI("run combo chip flow\n");
+ sStpParaConfig.pPatchPath = NULL;
+ sStpParaConfig.pPatchName = NULL;
+ sStpParaConfig.gStpDev = NULL;
+ sStpParaConfig.eStpMode = -1;
+ sStpParaConfig.iBaudrate = -1;
+ sStpParaConfig.sUartConfig.fc = UART_DISABLE_FC;
+ sStpParaConfig.sUartConfig.parity = 0;
+ sStpParaConfig.sUartConfig.stop_bit = 0;
+ /*Default parameters starts*/
+ baud = 4000000;
+ gStpMode = -1;
+ uartFcCtrl = UART_DISABLE_FC;
+ strncpy(gStpDev, CUST_COMBO_STP_DEV, sizeof(gStpDev) - 1);
+ gStpDev[sizeof(gStpDev) - 1] = '\0';
+ memset(gPatchFolder, 0, sizeof(gPatchFolder));
+ memset(gPatchName, 0, sizeof(gPatchName));
+ /*Default parameters ends*/
+ opt = getopt(argc, argv, opString);
+ while (opt != -1) {
+ switch (opt) {
+ case 'm':
+ gStpMode = atoi(optarg);
+ sStpParaConfig.eStpMode = gStpMode;
+ break;
+ case 'd':
+ strncpy(gStpDev, optarg, sizeof(gStpDev) - 1);
+ gStpDev[sizeof(gStpDev) - 1] = '\0';
+ sStpParaConfig.gStpDev = gStpDev;
+ break;
+ case 'b':
+ baud = atoi(optarg);
+ sStpParaConfig.iBaudrate = baud;
+ break;
+ case 'c':
+ uartFcCtrl = atoi(optarg);
+ sStpParaConfig.sUartConfig.fc = uartFcCtrl;
+ ALOGI("c found\n");
+ break;
+ case 'p':
+ // gPatchFolder = optarg;
+ strcpy(gPatchFolder, optarg);
+ sStpParaConfig.pPatchPath = gPatchFolder;
+ break;
+ case 'n':
+ // gPatchName = optarg;
+ strcpy(gPatchName, optarg);
+ sStpParaConfig.pPatchName = gPatchName;
+ break;
+ case '?':
+ default:
+ display_usage(chipId);
+ break;
+ }
+ opt = getopt(argc, argv, opString);
+ }
+ if (0 > get_chip_info_index(chipId)) {
+ ALOGI("invalid chip, check again\n");
+ chipId = query_chip_id();
+ ALOGI("chiId:0x%04x\n", chipId);
+ }
+ ioctl(gWmtFd, WMT_IOCTL_WMT_TELL_CHIPID, chipId);
+ ALOGI("set chipId(0x%x) to HIF-SDIO module\n", chipId);
+
+ get_wmt_cfg(chipId);
+
+ setHifInfo(chipId, sStpParaConfig.pPatchPath);
+ ALOGI("HifConfig:0x%04x, wmtCfgFile:%s\n", sStpParaConfig.eStpMode, gWmtCfgName);
+#ifndef WMT_PLAT_APEX
+ set_coredump_flag();
+#endif
+ if (0 != para_valid_check(&sStpParaConfig)) {
+ // Try to use custom method to check parameters
+ if (argc > optind) {
+ // For this competible usage , we only left STP mode set and firmware patch input, omit flowcontrol set
+ // First baud for STP UART mode, otherwise, SDIO mode
+ baud = atoi(argv[optind]);
+ if (baud >= CUST_BAUDRATE_DFT) {
+ ALOGI("get baud rate(%d) for UART mode\n", baud);
+ gStpMode = STP_UART_FULL;
+ sStpParaConfig.iBaudrate = baud;
+ }
+ else if (baud == 1) {
+ ALOGI("Definitively use SDIO mode\n");
+ gStpMode = STP_SDIO;
+ } else {
+ ALOGI("invalid baud rate(%d) for UART, use SDIO mode\n", baud);
+ gStpMode = STP_SDIO;
+ }
+ sStpParaConfig.eStpMode = gStpMode;
+ // Firmare patch analysis
+ optind++;
+ memset(gPatchName, 0, sizeof(gPatchName));
+ if (argc > optind) {
+ strncat(gPatchName, argv[optind], sizeof(gPatchName)-1);
+ sStpParaConfig.pPatchName = gPatchName;
+ ALOGI("PatchFile:%s\n", sStpParaConfig.pPatchName);
+ } else {
+ sStpParaConfig.pPatchName = NULL;
+ ALOGI("no patch file \n");
+ }
+ // Flow Control analysis
+ optind++;
+ if (argc > optind) {
+ uartFcCtrl = atoi(argv[optind]);
+ sStpParaConfig.sUartConfig.fc = uartFcCtrl;
+ ALOGI("flowcontrol flag: %d\n", sStpParaConfig.sUartConfig.fc);
+ } else {
+ ALOGI("no flow control flat set\n");
+ }
+ }
+ }
+ if (0 != para_valid_check(&sStpParaConfig)) {
+ display_usage(chipId);
+ }
+ /* send default patch file name path to driver */
+ ioctl(gWmtFd, WMT_IOCTL_SET_PATCH_NAME, gPatchName);
+ /* send uart name to driver*/
+ if (sStpParaConfig.gStpDev) {
+ gUartName = strstr(sStpParaConfig.gStpDev, "tty");
+ if (!gUartName) {
+ ALOGI("no uart name found in %s\n", sStpParaConfig.gStpDev);
+ } else {
+ ALOGI("uart name %s\n", gUartName);
+ }
+ }
+
+ if (!gUartName) {
+ gUartName = "ttyMT2";
+ ALOGI("use default uart %s\n", gUartName);
+ }
+
+ ioctl(gWmtFd, WMT_IOCTL_PORT_NAME, gUartName);
+
+ /* send hardware interface configuration to driver */
+ ioctl(gWmtFd, WMT_IOCTL_SET_STP_MODE, ((baud & 0xFFFFFF) << 8) | ((gFmMode & 0x0F) << 4) |(gStpMode & 0x0F));
+
+ /* send WMT config name configuration to driver */
+ ioctl(gWmtFd, WMT_IOCTL_WMT_CFG_NAME, gWmtCfgName);
+ }
+
+ ioctl(gWmtFd, WMT_IOCTL_SET_LAUNCHER_KILL, 0);
+
+ i_ret = ioctl(gWmtFd, WMT_IOCTL_GET_APO_FLAG, NULL);
+ if (i_ret != 0) {
+ if (pthread_create(&thread_handle, NULL, launcher_pwr_on_chip, &chipId)) {
+ ALOGE("create pwr on thread fail\n");
+ } else {
+ ALOGI("create pwr on thread ok\n");
+ }
+ } else {
+ ALOGI("no supported always power on\n");
+ }
+ /*set signal handler*/
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGCHLD, &sa, NULL);
+ sigaction(SIGPIPE, &sa, NULL);
+
+ sa.sa_handler = sig_term;
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+
+ sa.sa_handler = sig_hup;
+ sigaction(SIGHUP, &sa, NULL);
+
+ fds[0].fd = gWmtFd; /* stp_wmt fd */
+ fds[0].events = POLLIN | POLLRDNORM; /* wait read events */
+ ++fd_num;
+
+ while (!__io_canceled) {
+ fds[0].revents = 0;
+ err = poll(fds, fd_num, 2000); // 5 seconds
+ if (err < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ else {
+ ALOGI("poll error:%d errno:%d, %s\n", err, errno, strerror(errno));
+ break;
+ }
+ }
+ else if (!err) {
+ continue;
+ }
+ if (fds[0].revents & POLLIN) {
+ memset(gCmdStr, 0, sizeof(gCmdStr));
+ len = read(gWmtFd, gCmdStr, sizeof(gCmdStr)-1);
+ if (len > 0 && len < (int)sizeof(gCmdStr)) {
+ // printf ("POLLIN(%d) and read(%d)\n", gWmtFd, len);
+ }
+ else {
+ ALOGI("POLLIN(%d) but read fail:%d\n", gWmtFd, len);
+ continue;
+ }
+ gCmdStr[len] = '\0';
+ // ALOGI("rx_cmd_str:%s\n", gCmdStr);
+ err = handle_cmd(&sStpParaConfig, gCmdStr, len);
+ if (!err) {
+ // ALOGI("handle_cmd(%s), respond ok \n", gCmdStr);
+ snprintf(gRespStr, sizeof(gRespStr), "ok");
+ }
+ else {
+ if (err == 1) {
+ snprintf(gRespStr, sizeof(gRespStr), "cmd not found");
+ }
+ else {
+ snprintf(gRespStr, sizeof(gRespStr), "resp_%d", err);
+ }
+ }
+ ALOGI("cmd(%s) resp(%s)\n", gCmdStr, gRespStr);
+ len = write(gWmtFd, gRespStr, strlen(gRespStr));
+ if (len != (int)strlen(gRespStr)) {
+ fprintf(stderr, "write resp(%d) fail: len(%d), errno(%d, %s)\n",
+ gWmtFd, len, errno, (len == -1) ? strerror(errno) : "");
+ }
+ }
+ }
+clean_up:
+
+ if (gWmtFd >= 0) {
+ close(gWmtFd);
+ gWmtFd = -1;
+ }
+
+ if (gStpMode == STP_UART_FULL && gTtyFd >= 0) {
+ /* Restore TTY line discipline */
+ ld = N_TTY;
+ if (ioctl(gTtyFd, TIOCSETD, &ld) < 0) {
+ ALOGE("Can't restore line discipline");
+ exit(1);
+ }
+
+ close(gTtyFd);
+ gTtyFd = -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/connectivity/combo_tool/stp_dump-service b/src/connectivity/combo_tool/stp_dump-service
new file mode 100644
index 0000000..87504bf
--- /dev/null
+++ b/src/connectivity/combo_tool/stp_dump-service
@@ -0,0 +1,64 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: stp_dump
+# Required-Start: $syslog $local_fs $remote_fs
+# Required-Stop: $syslog $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: stp dump Daemon
+### END INIT INFO
+
+. /etc/init.d/init-functions
+prog=stp_dump
+PIDFILE=/var/run/$prog.pid
+DESC="stp dump Daemon"
+start() {
+ log_daemon_msg "Starting $DESC" "$prog"
+ start_daemon_background -p $PIDFILE /usr/bin/stp_dump
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+ exit 0
+}
+
+stop() {
+ log_daemon_msg "Stopping $DESC" "$prog"
+ killproc -p $PIDFILE /usr/bin/stp_dump
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+}
+
+force_reload() {
+ stop
+ start
+
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ restart)
+ stop
+ start
+ ;;
+
+ *)
+ echo "$Usage: $prog {start|stop|force-reload|restart}"
+ exit 2
+esac
diff --git a/src/connectivity/combo_tool/stp_dump.service b/src/connectivity/combo_tool/stp_dump.service
new file mode 100755
index 0000000..d08df2d
--- /dev/null
+++ b/src/connectivity/combo_tool/stp_dump.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=stp dump Daemon
+After=wmtd.service
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/stp_dump
+
+[Install]
+Alias=stp_dump
+WantedBy=multi-user.target
diff --git a/src/connectivity/combo_tool/wmtd-service b/src/connectivity/combo_tool/wmtd-service
new file mode 100644
index 0000000..c369f41
--- /dev/null
+++ b/src/connectivity/combo_tool/wmtd-service
@@ -0,0 +1,64 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: wmtd
+# Required-Start: $syslog $local_fs $remote_fs $network
+# Required-Stop: $syslog $local_fs $remote_fs $network
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: WMT Daemon
+### END INIT INFO
+
+. /etc/init.d/init-functions
+prog=wmtd
+PIDFILE=/var/run/$prog.pid
+DESC="WMT Daemon"
+start() {
+ log_daemon_msg "Starting $DESC" "$prog"
+ start_daemon_background -p $PIDFILE /usr/bin/wmt_loader
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+ exit 0
+}
+
+stop() {
+ log_daemon_msg "Stopping $DESC" "$prog"
+ killproc -p $PIDFILE /usr/bin/wmt_loader
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+}
+
+force_reload() {
+ stop
+ start
+
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ restart)
+ stop
+ start
+ ;;
+
+ *)
+ echo "$Usage: $prog {start|stop|force-reload|restart}"
+ exit 2
+esac
diff --git a/src/connectivity/combo_tool/wmtd.service b/src/connectivity/combo_tool/wmtd.service
new file mode 100644
index 0000000..dff20b3
--- /dev/null
+++ b/src/connectivity/combo_tool/wmtd.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=WMT Daemon
+After=network.target
+Requires=nvram_daemon.service
+After=nvram_daemon.service
+
+[Service]
+ExecStart=/usr/bin/wmt_loader
+Type=oneshot
+
+[Install]
+Alias=wmtd
+WantedBy=multi-user.target