diff mbox

[2/3] linaro_generic: Add qcom wcnss wifi support

Message ID 1467074768-16803-2-git-send-email-john.stultz@linaro.org
State New
Headers show

Commit Message

John Stultz June 28, 2016, 12:46 a.m. UTC
This patch addds wcnss wifi support for qualcom devices.

Most of these were copied over from device/asus/flo, then
integrated with the generic build.

Signed-off-by: John Stultz <john.stultz@linaro.org>

---
 BoardConfig.mk                       |   2 +
 Kconfig                              |   4 +
 sepolicy/conn_init.te                |  10 +
 sepolicy/file_contexts               |   2 +
 wifi/Android.mk                      |   2 +
 wifi/device.mk                       |   6 +
 wifi/qcom/Android.mk                 |  58 +++
 wifi/qcom/NOTICE                     | 190 ++++++++++
 wifi/qcom/WCNSS_cfg.dat              | Bin 0 -> 10394 bytes
 wifi/qcom/WCNSS_qcom_cfg.ini         | 254 +++++++++++++
 wifi/qcom/WCNSS_qcom_wlan_nv_deb.bin | Bin 0 -> 29776 bytes
 wifi/qcom/WCNSS_qcom_wlan_nv_flo.bin | Bin 0 -> 29776 bytes
 wifi/qcom/conn_init.c                |  56 +++
 wifi/qcom/device.mk                  |  14 +
 wifi/qcom/qcom-wifi.rc               |   8 +
 wifi/qcom/start_qcom_wifi.sh         |  10 +
 wifi/qcom/wfc_util_common.c          | 135 +++++++
 wifi/qcom/wfc_util_common.h          |  51 +++
 wifi/qcom/wfc_util_fctrl.c           | 662 +++++++++++++++++++++++++++++++++
 wifi/qcom/wfc_util_fctrl.h           |  92 +++++
 wifi/qcom/wfc_util_log.h             |  32 ++
 wifi/qcom/wfc_util_main.c            | 139 +++++++
 wifi/qcom/wfc_util_qcom.c            | 690 +++++++++++++++++++++++++++++++++++
 wifi/qcom/wfc_util_qcom.h            |  52 +++
 24 files changed, 2469 insertions(+)
 create mode 100644 sepolicy/conn_init.te
 create mode 100644 sepolicy/file_contexts
 create mode 100644 wifi/qcom/Android.mk
 create mode 100644 wifi/qcom/NOTICE
 create mode 100644 wifi/qcom/WCNSS_cfg.dat
 create mode 100644 wifi/qcom/WCNSS_qcom_cfg.ini
 create mode 100644 wifi/qcom/WCNSS_qcom_wlan_nv_deb.bin
 create mode 100644 wifi/qcom/WCNSS_qcom_wlan_nv_flo.bin
 create mode 100644 wifi/qcom/conn_init.c
 create mode 100644 wifi/qcom/device.mk
 create mode 100644 wifi/qcom/qcom-wifi.rc
 create mode 100755 wifi/qcom/start_qcom_wifi.sh
 create mode 100644 wifi/qcom/wfc_util_common.c
 create mode 100644 wifi/qcom/wfc_util_common.h
 create mode 100644 wifi/qcom/wfc_util_fctrl.c
 create mode 100644 wifi/qcom/wfc_util_fctrl.h
 create mode 100644 wifi/qcom/wfc_util_log.h
 create mode 100644 wifi/qcom/wfc_util_main.c
 create mode 100644 wifi/qcom/wfc_util_qcom.c
 create mode 100644 wifi/qcom/wfc_util_qcom.h

-- 
1.9.1
diff mbox

Patch

diff --git a/BoardConfig.mk b/BoardConfig.mk
index b3f2be2..c6abae2 100644
--- a/BoardConfig.mk
+++ b/BoardConfig.mk
@@ -21,6 +21,8 @@  endif
 
 WITH_DEXPREOPT := $(CONFIG_DEX_PREOPT)
 
+BOARD_SEPOLICY_DIRS += device/linaro/generic/sepolicy
+
 # generic wifi
 WPA_SUPPLICANT_VERSION := VER_0_8_X
 BOARD_WPA_SUPPLICANT_DRIVER := NL80211
diff --git a/Kconfig b/Kconfig
index 6fb1083..fafe435 100644
--- a/Kconfig
+++ b/Kconfig
@@ -74,8 +74,12 @@  menuconfig WIFI
 
 if WIFI
 
+config QCOM_WIFI
+	bool "Qualcomm WCNSS wifi support"
+
 endif
 
+
 config ETHERNET
 	bool "Ethernet support"
 
diff --git a/sepolicy/conn_init.te b/sepolicy/conn_init.te
new file mode 100644
index 0000000..becb3b5
--- /dev/null
+++ b/sepolicy/conn_init.te
@@ -0,0 +1,10 @@ 
+# wifi connection service
+type conn_init, domain, domain_deprecated;
+type conn_init_exec, exec_type, file_type;
+
+init_daemon_domain(conn_init)
+
+# Runs start_qcom_wifi.sh
+allow conn_init shell_exec:file rx_file_perms;
+allow conn_init conn_init_exec:file rx_file_perms;
+
diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts
new file mode 100644
index 0000000..1c5409c
--- /dev/null
+++ b/sepolicy/file_contexts
@@ -0,0 +1,2 @@ 
+/system/bin/conn_init              u:object_r:conn_init_exec:s0
+/system/bin/start_qcom_wifi\.sh    u:object_r:conn_init_exec:s0
diff --git a/wifi/Android.mk b/wifi/Android.mk
index d31a80c..5125461 100644
--- a/wifi/Android.mk
+++ b/wifi/Android.mk
@@ -7,3 +7,5 @@  LOCAL_MODULE:= wifi.rc
 LOCAL_INIT_RC := $(LOCAL_MODULE)
 
 include $(BUILD_PHONY_PACKAGE)
+
+include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/wifi/device.mk b/wifi/device.mk
index 6cfae76..ecd0f1c 100644
--- a/wifi/device.mk
+++ b/wifi/device.mk
@@ -12,3 +12,9 @@  PRODUCT_COPY_FILES += \
 PRODUCT_PROPERTY_OVERRIDES += \
 		wifi.interface=wlan0 \
 		wifi.supplicant_scan_interval=15
+
+
+subdirs-true :=
+subdirs-$(CONFIG_QCOM_WIFI) += qcom
+include $(foreach dir,$(subdirs-true), $(LOCAL_PATH)/wifi/$(dir)/device.mk)
+PRODUCT_COPY_FILES += $(PRODUCT_COPY_FILES-true)
diff --git a/wifi/qcom/Android.mk b/wifi/qcom/Android.mk
new file mode 100644
index 0000000..f758de7
--- /dev/null
+++ b/wifi/qcom/Android.mk
@@ -0,0 +1,58 @@ 
+#
+# Copyright 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libwfcu
+LOCAL_SRC_FILES := wfc_util_fctrl.c \
+                   wfc_util_common.c
+LOCAL_CFLAGS := -Wall \
+                -Werror
+LOCAL_CFLAGS += -DCONFIG_LGE_WLAN_WIFI_PATCH
+LOCAL_SRC_FILES += wfc_util_qcom.c
+LOCAL_CFLAGS += -DCONFIG_LGE_WLAN_QCOM_PATCH
+LOCAL_CFLAGS += -DWLAN_CHIP_VERSION_WCNSS
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_OWNER := qcom
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := conn_init.c
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+LOCAL_SHARED_LIBRARIES += libwfcu
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT)/bin
+LOCAL_MODULE := conn_init
+LOCAL_MODULE_OWNER := qcom
+
+# Make sure the symlinks get created as well.
+LOCAL_POST_INSTALL_CMD := \
+  mkdir -p $(TARGET_OUT_VENDOR)/firmware/wlan/prima/; \
+  ln -sf /data/misc/wifi/WCNSS_qcom_cfg.ini \
+    $(TARGET_OUT_VENDOR)/firmware/wlan/prima/WCNSS_qcom_cfg.ini; \
+  ln -sf /data/misc/wifi/WCNSS_qcom_wlan_nv.bin \
+    $(TARGET_OUT_VENDOR)/firmware/wlan/prima/WCNSS_qcom_wlan_nv.bin
+
+include $(BUILD_EXECUTABLE)
+
+
+include $(CLEAR_VARS)
+LOCAL_MODULE:= qcom-wifi.rc
+LOCAL_INIT_RC := $(LOCAL_MODULE)
+include $(BUILD_PHONY_PACKAGE)
diff --git a/wifi/qcom/NOTICE b/wifi/qcom/NOTICE
new file mode 100644
index 0000000..33ff961
--- /dev/null
+++ b/wifi/qcom/NOTICE
@@ -0,0 +1,190 @@ 
+
+   Copyright (c) 2005-2012, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/wifi/qcom/WCNSS_cfg.dat b/wifi/qcom/WCNSS_cfg.dat
new file mode 100644
index 0000000000000000000000000000000000000000..16ba06f087a4ce2d0a0ee50f54e3f3db56d3fc13
GIT binary patch
literal 10394
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

literal 0
HcmV?d00001

diff --git a/wifi/qcom/WCNSS_qcom_cfg.ini b/wifi/qcom/WCNSS_qcom_cfg.ini
new file mode 100644
index 0000000..aa7e616
--- /dev/null
+++ b/wifi/qcom/WCNSS_qcom_cfg.ini
@@ -0,0 +1,254 @@ 
+# This file allows user to override the factory
+# defaults for the WLAN Driver
+
+# Enable IMPS or not
+gEnableImps=1
+
+# Enable/Disable Idle Scan
+gEnableIdleScan=0
+
+# Increase sleep duration (seconds) during IMPS
+# 0 implies no periodic wake up from IMPS. Periodic wakeup is
+# unnecessary if Idle Scan is disabled.
+gImpsModSleepTime=0
+
+# Enable BMPS or not
+gEnableBmps=1
+
+# Enable Close Loop or not
+gEnableCloseLoop=1
+
+# Enable suspend or not
+# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter
+gEnableSuspend=3
+
+# Phy Mode (auto, b, g, n, etc)
+gDot11Mode=0
+
+# Handoff Enable(1) Disable(0)
+gEnableHandoff=0
+
+# CSR Roaming Enable(1) Disable(0)
+gRoamingTime=0
+
+# Assigned MAC Addresses - This will be used until NV items are in place
+# Each byte of MAC address is represented in Hex format as XX
+Intf0MacAddress=000AF58989FF
+Intf1MacAddress=000AF58989FE
+Intf2MacAddress=000AF58989FD
+Intf3MacAddress=000AF58989FC
+
+# UAPSD service interval for VO,VI, BE, BK traffic
+InfraUapsdVoSrvIntv=0
+InfraUapsdViSrvIntv=0
+InfraUapsdBeSrvIntv=0
+InfraUapsdBkSrvIntv=0
+
+# Enable Firmware RSSI monitoring for roaming
+gEnableFWRssiMonitoring=1
+
+# Make 1x1 the default antenna configuration
+gNumRxAnt=1
+
+# Beacon filtering frequency (unit in beacon intervals)
+gNthBeaconFilter=50
+
+# Enable WAPI or not
+# WAPIIsEnabled=0
+
+# Flags to filter Mcast and Bcast RX packets.
+# Value 0: No filtering, 1: Filter all Multicast.
+# 2: Filter all Broadcast. 3: Filter all Mcast and Bcast
+McastBcastFilter=3
+
+# Flag to enable Active mode offload
+gEnableActiveModeOffload=1
+
+# Flag to enable HostARPOffload feature or not
+hostArpOffload=1
+
+# Flag to enable Host IPv6 NS Offload feature or not
+hostNSOffload=1
+
+#SoftAP Related Parameters
+# AP MAc addr (obsolete)
+gAPMacAddr=000AF58989EF
+
+# Enable Random BSSID
+gEnableApRandomBssid=1
+
+# 802.11n Protection flag
+gEnableApProt=1
+
+# Enable OBSS protection
+gEnableApOBSSProt=0
+
+# Enable/Disable UAPSD for SoftAP
+gEnableApUapsd=1
+
+# Fixed Rate
+gFixedRate=0
+
+# Maximum Tx power
+# gTxPowerCap=30
+
+# Fragmentation Threshold
+# gFragmentationThreshold=2346
+
+# RTS threshold
+RTSThreshold=2347
+
+# Intra-BSS forward
+gDisableIntraBssFwd=0
+
+# WMM Enable/Disable
+WmmIsEnabled=0
+
+# 802.11d support
+g11dSupportEnabled=1
+
+# CCX Support and fast transition
+CcxEnabled=0
+FastTransitionEnabled=1
+ImplicitQosIsEnabled=1
+gNeighborScanTimerPeriod=200
+
+gNeighborLookupThreshold=76
+gNeighborReassocThreshold=81
+
+gNeighborScanChannelMinTime=20
+gNeighborScanChannelMaxTime=30
+gMaxNeighborReqTries=3
+
+# Legacy (non-CCX, non-802.11r) Fast Roaming Support
+# To enable, set FastRoamEnabled=1, gEnableFWRssiMonitoring=1, FastTransitionEnabled=1
+# To disable, set FastRoamEnabled=0, gEnableFWRssiMonitoring=0, FastTransitionEnabled=0
+FastRoamEnabled=1
+
+#Check if the AP to which we are roaming is better than current AP in terms of RSSI.
+#Checking is disabled if set to Zero.Otherwise it will use this value as to how better
+#the RSSI of the new/roamable AP should be for roaming
+RoamRssiDiff=3
+
+#Configure the RSSI gap that will be used to partition/categorize width of
+#each  individual category (aka bucket).
+gRssiCatGap=5
+
+# SAP Country code
+# Default Country Code is 2 bytes, 3rd byte is optional indoor or out door.
+# Example
+#   US Indoor, USI
+#   Korea Outdoor, KRO
+#   Japan without optional byte, JP
+#   France without optional byte, FR
+#gAPCntryCode=USI
+
+#Short Guard Interval Enable/disable
+gShortGI20Mhz=1
+gShortGI40Mhz=1
+
+#Auto Shutdown  Value in seconds. A value of 0 means Auto shutoff is disabled
+gAPAutoShutOff=0
+
+# SAP auto channel selection configuration
+# 0 = disable auto channel selection
+# 1 = enable auto channel selection, channel provided by supplicant will be ignored
+gApAutoChannelSelection=0
+
+# Listen Energy Detect Mode Configuration
+# Valid values 0-128
+# 128 means disable Energy Detect feature
+# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled.
+# 10-128 are reserved.
+# The EDET threshold mapping is as follows in 3dB step:
+# 0 = -60 dBm
+# 1 = -63 dBm
+# 2 = -66 dBm
+# ...
+# 7 = -81 dBm
+# 8 = -84 dBm
+# 9 = -87 dBm
+# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as:
+#
+#  Range Loss  (dB)  =  EDET threshold level (dBm) + 97 dBm.
+#
+gEnablePhyAgcListenMode=128
+
+#Preferred band (both or 2.4 only or 5 only)
+BandCapability=0
+
+#Forced Device Listen Interval in multiples of DTIM Period aligned to DTIM
+gEnableModulatedDTIM=3
+
+#Beacon Early Termination (1 = enable the BET feature, 0 = disable)
+enableBeaconEarlyTermination=1
+beaconEarlyTerminationWakeInterval=11
+
+#Bluetooth Alternate Mac Phy (1 = enable the BT AMP feature, 0 = disable)
+gEnableBtAmp=0
+
+#Preferred channel to start BT AMP AP mode (0 means, any channel)
+BtAmpPreferredChannel=0
+
+#SOFTAP Channel Range selection
+gAPChannelSelectStartChannel=1
+gAPChannelSelectEndChannel=11
+
+#SOFTAP Channel Range selection Operating band
+# 0:2.4GHZ 1: LOW-5GHZ 2:MID-5GHZ 3:HIGH-5GHZ 4: 4.9HZ BAND
+gAPChannelSelectOperatingBand=0
+
+#Enable Keep alive with non-zero period value
+gStaKeepAlivePeriod = 25
+
+#If set will start with active scan after driver load, otherwise will start with
+#passive scan to find out the domain
+gEnableBypass11d=1
+
+#If set to 0, will not scan DFS channels
+gEnableDFSChnlScan=1
+
+# Enable logp/SSR
+gEnableLogp=1
+
+# Enable HT40
+gChannelBondingMode5GHz=1
+
+# Enable Automatic Tx Power control
+gEnableAutomaticTxPowerControl=1
+
+# Derive P2P MAC address from primary MAC address
+isP2pDeviceAddrAdministrated=1
+
+# Disable channel 165 for Indonesia
+gIgnore_Chan165=1
+
+btcStaticLenLeBt=120000
+btcStaticLenLeWlan=30000
+
+#Data Inactivity Timeout when in powersave (in ms)
+gDataInactivityTimeout=200
+
+gCountryCodePriority=1
+
+gNumChanCombinedConc=255
+
+# TDLS configuration
+gEnableTDLSSupport=1
+gEnableTDLSImplicitTrigger=1
+gTDLSExternalControl=1
+gTDLSTxStatsPeriod=500
+gTDLSTxPacketThreshold=10
+gTDLSDiscoveryPeriod=20000
+gTDLSMaxDiscoveryAttempt=5
+gTDLSIdleTimeout=40000
+gTDLSRssiHysteresis=100
+gTDLSRSSITriggerThreshold=-60
+gTDLSIdlePacketThreshold=5
+gTDLSRSSITeardownThreshold=-70
+
+# Enable IPv6 RA filtering
+gMCAddrListEnable=1
+
+END
+# Note: Configuration parser would not read anything past the END marker
diff --git a/wifi/qcom/WCNSS_qcom_wlan_nv_deb.bin b/wifi/qcom/WCNSS_qcom_wlan_nv_deb.bin
new file mode 100644
index 0000000000000000000000000000000000000000..505319b640ff906a1dc68a3cbc74a762a5588e68
GIT binary patch
literal 29776
zcmeI5OLr7S6vwMZL>C-QBxf?1bLMzlK@!9lj|4~t5CI90Cm{inkO!!2S-4{52jBzn
zA^aG+5Hk4SsOZ|yz-GMnR#m^ItEWv!y65n(d-^dw)zx)>_g}ZFv&ghst(H={qV<E#
zp|$Br*-y!STJ|$4XX(-3y{XhrZ9nW$YCGEm-M^i!lV85R@iYH@L#gj++e#h2H@a~<
zA0*mx&+yet``*=c?e$UY^3=-`!wYI-JDclMQAhSaYwOf6X8Ee>aE$Y`#r5*WE^j@=
z*v}p@?mWgj>2{~T&l<y7InMR#b%=4+7{_<rLqPYpSyfk6U94Y4O!pd7HEY%2%(yGp
zb={iM)!@8N=SoMQ=svLl&31s=86XP_e=<D?ui>n40yb(UcHw@%-k<E6(^OPH_S{r8
zx(aS<Z#no%xwgzP)(ThRmQYGZpgp2|MX|kSW9V{AuQG<bQo1PaPKR`l&*=G1C34I+
z2idu!PJfrc9JD(j+_k5qE2UCri)y9PU+J}0s~D@=qx)=*awp%NrIkvb*g%Et0JUSz
zqI=uUu7SXVIug+Dd#s0U-9lao*0abf9octV1^uqipp|Zm<xclkzvHu{R_w~QH+WOV
zJM&Hlr)2HxeLgE$N70?a3GA7lxugya9X|5OXGf2p7(IDvY`k&i+!yD+ym0Z-SC=nO
zT)BGn+T_&q^vulc-1Y18Hx?EaZ{ECh>-O!XrRC-2m6bbpR##Wo*4Eb7*EcrqQn^Rv
zYbxJx`8HARr<bBB82>*%c4Fk@sncVPGiPG}t{DKcb93Z>9KcExzy=iqAl?6T-}!1;
z{69W2n&Q6|z$^)1UIf4jU;&T<*nd)h6M*$!1Yi^(GH4e<Oc#awKREo+$E<&Gf4mV7
zf86~W3yT>8Am+at1QtQcaBvjL5&xs2|FLnA|M?3SIRVi47x~NZH_;D=f2e*L{ZZ!w
zpPh@D$CCKZ`R_F6zq2m?O<W=WCn^7V{I}V!&3&i+RIl6fKzaP9;UCq1=)WEPartMB
zeuqGmkjf#vShW8K2YLRZ{4ep3q<`c86vaPf_Dgu5Nd0NUy*={gO40rwqWt%%xX;sn
znEpD9{)GCY6Mu5%_jz6t|A&r{|C0Y>%O4wljy})*wDwu#wU3$jWa%RlUu4>kt3BK6
z@Y|x}KR7J%m-&y=-#NSdbN&bNkIa36`eVt@to?ZXLnW95I-C^kzH<8K<zKu1F8#~u
z&nTcx0<`#b)1Ms%20=awMFZgVj~)NwznlJK`VXeRVD)bn|2YJZR{=%)e~{mQ7{G{q
z0SZ!}tbk+%$SZ*80@%I+$r^~?fp`sU3yp~XSBmx@&j$ez009sH0T2KI5C8!X009sH
z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X=o$jg|9tV!
z-+%o<<@s;F{`8|Mo6Y7kF2BhBS+lvh`Sj_NCqD;OrCO{~lPYnQu5lb41pyEM0T2KI
z5C8!X009sH0T2KI5C8!X009sH0T3vZz&btsb>Fm({+5ZNkMRo+TYf7vc=q9sTYii8
z?~#t%lJ?t6^)i0*mOuIFJ*3|nEWY^ZJx=s5PVZ3$y(RtX_|Z?g(Qm&s_BQq^`XQY}
smpu4tk$-7i(>48}9ws{`#-EF}yKj3sUXshBZ<VAYo^Je3TIh!IALW7REC2ui

literal 0
HcmV?d00001

diff --git a/wifi/qcom/WCNSS_qcom_wlan_nv_flo.bin b/wifi/qcom/WCNSS_qcom_wlan_nv_flo.bin
new file mode 100644
index 0000000000000000000000000000000000000000..8f98da69c7480e4da626c3f82b9a1f1910f73b50
GIT binary patch
literal 29776
zcmeI5*=`g^6o#uB0=Ynm9jx&XOQR@PV4M&j25i6{AOr|zwT<zHjTf?T!(|>I7kLOC
zA`id=co}kqq7X%qA|d3b@Z_9YdavmYW4n8jzm9skr@Okk&UgN*I_(Qjv)OD4Aw4PQ
znu9+-ol&2&>T^zg&WoI-OZL1cglqeeuC=rMvR{aHwlTWDoh_^HuD<azxAqC~6K(HO
zhwlw<+|DPlw(K)p_0q1}y0$%zTb_EY#K8Brv)Miswa@B%R==3#PSxQU=V^=U<&9n5
zdWf-`Jz|_a#<O(0+t)FU^%~J?9OK%5gMjQ!SVdMuO<Au9ne5gks>Uk*kw&4;%bGDE
zEB<kfj)e>XlRe7%B-;^cr;jWs{7v^DIESOc37Dwq*ae@5<>7eOtfs>HF~_>9)|G!-
zvSt60ux;smq!q5jEuoZ-Kr*6yMzDQkVrb`<ZlMkHO6j7wHyx5)E~DpLm8gBbHOQ<T
zHTt^*)}Xx!;hsGuT`69TEvyx<*XuS`^|V#Y-hS76btm85N-JKEvObUP2(_b+!k?y{
zJp+LUWfG7dJFJUteTR9)&u1~OWU}wH3i3mjK`WgW%iZp;{J>>#t(eTV+kaEWJM(S_
zr)2HRLoO>>N70?a3GAO5zafqt|Lnxc(}QQv4WGX-GFrcM<*Tb-U%P(eo0~VsZr#3p
z=kC4x_s7R4CLcVQdN@5jGdnvsH$VUA(Za&Q;^O1SOG``3%gZY(E32zdsC-N1J1XCE
z`5{)GrkA2AX#c-Fb8hJTg^MHgOP3=6?q~oLlau6s6u@E_z$z6DAl?6T-}!7={69N1
zoZ`O`zyt|kN(q1!zycrzu>Yh0D*)ra5`b2Kl0i}k5nUASfB(SeU$Fj_`=j+}_@nMW
zoStbh03!a|L0}N13<pc09PuAi`X3op^1piRI!^#J{+0aI@Ym4~hJT=bHTuKO`#xJ2
zTkcEZKhJ*`dH%a>=fAOA<o{io{~Z3C*)QR~)qbki$$6kW{?qUe>p$?{jQ*(nTaA8;
zKq(=WLvXTa|Bv?b`bYD>ihpSO*Z$w5_@}IXG4Eqjf7)<QMqZyO+W%uT|D96q^YR}|
ze;K1crvC84A7A-ho|nY`<0r^}HUCG_9}|9#KCk_h`^<3eqZdAv`ly93wCqRK-rDQn
zYSHoUA5ijF>mN^lS4{e6{rBY`TKjzUM<zd=`*Hq5#a{$64vKbPSp9SQm-OFG|0?^_
z3P?zRl3%<0nPH$2<fBkD0M38R_*eeh<xegD{_^K%|2p~4A%MIJDBAy{{QkoLhRh3)
zKLx4`NM(SW0fZA^^9rPLAbtnp9M}{Z5&y0f?LVFm0w4eaAOHd&00JNY0w4eaAOHd&
z00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0wB;a1m3*e+S+>i
z=I_7${NwfSuh(>0-`LpP+-x+~*4H;^M`iQZmoFO)zpARX!L=HVbz6z*G#VY_I64Xf
zAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&P$+>Fdiwu;lQR5UCW5|3PdwXpTcN=-
z4}Z1owrKxecu{-ablY0=);7Mm={?(SquCw1)lKhJtbb8@FFZHB=gpntM?dLCzx`G}
zP(L8(hji%Y8FQ3s=wBLFWmSGE2guGS<L^b=llOBtQDBwfg9Sc3$D@BEEp$Tp2OaM8
A4*&oF

literal 0
HcmV?d00001

diff --git a/wifi/qcom/conn_init.c b/wifi/qcom/conn_init.c
new file mode 100644
index 0000000..2cb5591
--- /dev/null
+++ b/wifi/qcom/conn_init.c
@@ -0,0 +1,56 @@ 
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+extern int wfc_util_qcom_check_config(unsigned char *nv_mac_addr);
+extern void wfc_util_atoh(char *pAsciiString, int szAsciiString, unsigned char *pHexaBuff, int szHexaBuff);
+
+static int wifi_check_qcom_cfg_files()
+{
+    char macAddress[13];
+    char hex[7];
+    memset(macAddress, 0, 13);
+    memset(hex, 0, 7);
+
+    // Read MAC String
+    FILE *fp = NULL;
+    int n = 0;
+    fp = fopen("/persist/wifi/.macaddr", "r");
+    if ( fp == NULL )
+    {
+        wfc_util_qcom_check_config((unsigned char *)macAddress);
+        return 0;
+    }
+    else
+    {
+        n = fread(macAddress, 12, 1, fp);
+        fclose(fp);
+
+        // Write MAC String
+        wfc_util_atoh( macAddress, 12, (unsigned char *)hex, 6);
+        wfc_util_qcom_check_config((unsigned char *)hex);
+    }
+    return 1;
+}
+
+int main(void)
+{
+    wifi_check_qcom_cfg_files();
+
+    return 0;
+}
diff --git a/wifi/qcom/device.mk b/wifi/qcom/device.mk
new file mode 100644
index 0000000..3d7effd
--- /dev/null
+++ b/wifi/qcom/device.mk
@@ -0,0 +1,14 @@ 
+#these are all qcom specific (need to split them out somewhere)
+PRODUCT_PACKAGES += \
+		libwfcu \
+		conn_init \
+		qcom-wifi.rc \
+
+PRODUCT_COPY_FILES += \
+	device/linaro/generic/wifi/qcom/start_qcom_wifi.sh:system/bin/start_qcom_wifi.sh \
+	device/linaro/generic/wifi/qcom/WCNSS_cfg.dat:system/vendor/firmware/wlan/prima/WCNSS_cfg.dat \
+	device/linaro/generic/wifi/qcom/WCNSS_qcom_cfg.ini:system/etc/wifi/WCNSS_qcom_cfg.ini \
+	device/linaro/generic/wifi/qcom/WCNSS_qcom_wlan_nv_flo.bin:system/etc/wifi/WCNSS_qcom_wlan_nv_flo.bin \
+	device/linaro/generic/wifi/qcom/WCNSS_qcom_wlan_nv_deb.bin:system/etc/wifi/WCNSS_qcom_wlan_nv_deb.bin
+
+
diff --git a/wifi/qcom/qcom-wifi.rc b/wifi/qcom/qcom-wifi.rc
new file mode 100644
index 0000000..61335c4
--- /dev/null
+++ b/wifi/qcom/qcom-wifi.rc
@@ -0,0 +1,8 @@ 
+on property:sys.boot_completed=1
+	start wcnss_init
+
+service wcnss_init /system/bin/start_qcom_wifi.sh
+	user root
+	group root root
+	oneshot
+
diff --git a/wifi/qcom/start_qcom_wifi.sh b/wifi/qcom/start_qcom_wifi.sh
new file mode 100755
index 0000000..14a5394
--- /dev/null
+++ b/wifi/qcom/start_qcom_wifi.sh
@@ -0,0 +1,10 @@ 
+#!/system/bin/sh
+
+# Workaround for conn_init not copying the updated firmware
+rm /data/misc/wifi/WCNSS_qcom_cfg.ini
+rm /data/misc/wifi/WCNSS_qcom_wlan_nv.bin
+
+/system/bin/conn_init
+
+echo 1 > /dev/wcnss_wlan
+echo start > /sys/kernel/debug/remoteproc/remoteproc0/state
diff --git a/wifi/qcom/wfc_util_common.c b/wifi/qcom/wfc_util_common.c
new file mode 100644
index 0000000..b149920
--- /dev/null
+++ b/wifi/qcom/wfc_util_common.c
@@ -0,0 +1,135 @@ 
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "wfc_util_log.h"
+
+#define WFC_UTIL_RANDOM_MAC_HEADER "001122"
+
+void wfc_util_htoa(unsigned char *pHexaBuff, int szHexaBuff, char *pAsciiStringBuff, int szAsciiStringBuff)
+{
+	int i, j;
+	char hex_table[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+	                                 'A', 'B', 'C', 'D', 'E', 'F'};
+
+	if ((szHexaBuff*2) > szAsciiStringBuff) {
+		wfc_util_log_error("wfc_util_htoa : not enough buffer size(%d)", szAsciiStringBuff);
+		return;
+	}
+
+	memset(pAsciiStringBuff, 0, szAsciiStringBuff);
+
+	/* for (i = szHexaBuff-1, j = 0; i >= 0; i--, j += 2) { */
+	for (i = 0, j = 0; i < szHexaBuff; i++, j += 2) {
+		/*pAsciiStringBuff[j]     = hex_table[(pHexaBuff[i] >> 4) & 0x0F];
+		*/
+		pAsciiStringBuff[j]     = hex_table[pHexaBuff[i] >> 4];
+		pAsciiStringBuff[j + 1] = hex_table[pHexaBuff[i] & 0x0F];
+	}
+
+	return;
+}
+
+void wfc_util_atoh(char *pAsciiString, int szAsciiString, unsigned char *pHexaBuff, int szHexaBuff)
+{
+	int i, pos;
+	char temp;
+
+	if ( 0!=(szAsciiString%2) || (szHexaBuff*2) < szAsciiString) {
+		wfc_util_log_error("wfc_util_atoh : not enough buffer size(%d)", szHexaBuff);
+		return;
+	}
+
+	memset(pHexaBuff, 0, szHexaBuff);
+
+	for (i=0 ; i<szAsciiString ; i++) {
+
+		/* pos = (szAsciiString - i - 1) / 2; */
+		pos = i / 2;
+		temp = pAsciiString[i];
+
+		if (temp >= '0' && temp <= '9') {
+			temp = temp - '0';
+		} else if ( temp >= 'a' && temp <= 'f' ) {
+			temp = temp - 'a' + 10;
+		} else if ( temp >= 'A' && temp <= 'F' ) {
+			temp = temp - 'A' + 10;
+		} else {
+			temp = 0;
+		}
+
+		if (0==i%2) {
+			pHexaBuff[pos] = temp<<4;
+		} else {
+			pHexaBuff[pos] |= temp;
+		}
+	}
+
+	return;
+}
+
+/*
+ * wfc_util_is_random_mac
+ *
+ * return : it will return 1 if [mac_add] is same with WFC_UTIL_RANDOM_MAC_HEADER
+ *          or will return 0 if not.
+ */
+int wfc_util_is_random_mac(char *mac_add)
+{
+	if(0 == strncmp(mac_add, WFC_UTIL_RANDOM_MAC_HEADER, 6)) {
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * wfc_util_random_mac
+ *
+ * Create random MAC address
+ *
+ * return : void
+ */
+void wfc_util_random_mac(unsigned char* mac_addr)
+{
+	unsigned long int rand_mac;
+
+	if(NULL == mac_addr) {
+		wfc_util_log_error("wfc_util_random_mac : buffer is NULL");
+		return;
+	}
+
+	/* Create random MAC address: offset 3, 4 and 5 */
+	srandom(time(NULL));
+	rand_mac=random();
+
+	#ifndef WFC_UTIL_RANDOM_MAC_HEADER
+	mac_addr[0] = (unsigned char)0x00;
+	mac_addr[1] = (unsigned char)0x11;
+	mac_addr[2] = (unsigned char)0x22;
+	#else  /* WFC_UTIL_RANDOM_MAC_HEADER */
+	wfc_util_atoh(WFC_UTIL_RANDOM_MAC_HEADER, 6, mac_addr, 3);
+	#endif /* WFC_UTIL_RANDOM_MAC_HEADER */
+	mac_addr[3] = (unsigned char)rand_mac;
+	mac_addr[4] = (unsigned char)(rand_mac >> 8);
+	mac_addr[5] = (unsigned char)(rand_mac >> 16);
+
+	return;
+}
diff --git a/wifi/qcom/wfc_util_common.h b/wifi/qcom/wfc_util_common.h
new file mode 100644
index 0000000..c91f899
--- /dev/null
+++ b/wifi/qcom/wfc_util_common.h
@@ -0,0 +1,51 @@ 
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WFC_UTIL_COMMON_H__
+#define __WFC_UTIL_COMMON_H__
+
+/*
+ * wfc_util_htoa
+ *
+ * return : void
+ */
+extern void wfc_util_htoa(unsigned char *pHexaBuff, int szHexaBuff, char *pAsciiStringBuff, int szAsciiStringBuff);
+
+/*
+ * wfc_util_atoh
+ *
+ * return : void
+ */
+extern void wfc_util_atoh(char *pAsciiString, int szAsciiString, unsigned char *pHexaBuff, int szHexaBuff);
+
+/*
+ * wfc_util_is_random_mac
+ *
+ * return : it will return 1 if [mac_add] is same with WFC_UTIL_RANDOM_MAC_HEADER
+ *          or will return 0 if not.
+ */
+extern int wfc_util_is_random_mac(char *mac_add);
+
+/*
+ * wfc_util_random_mac
+ *
+ * Create random MAC address
+ *
+ * return : void
+ */
+void wfc_util_random_mac(unsigned char* mac_addr);
+
+#endif
diff --git a/wifi/qcom/wfc_util_fctrl.c b/wifi/qcom/wfc_util_fctrl.c
new file mode 100644
index 0000000..cd532a9
--- /dev/null
+++ b/wifi/qcom/wfc_util_fctrl.c
@@ -0,0 +1,662 @@ 
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "wfc_util_log.h"
+
+/*
+static void wfc_util_printf(char *pSPointer, int length)
+{
+	char *pPrintBuff = NULL;
+
+	if( NULL == pSPointer || 0 >= length ) {
+		wfc_util_log_error("wfc_util_printf : unvalid parameters");
+		return;
+	}
+
+	wfc_util_log_error("wfc_util_printf : lenght is (%d)", length);
+	pPrintBuff = malloc(length+1);
+
+	if( NULL != pPrintBuff ) {
+		memset( pPrintBuff, 0, (length+1) );
+		memcpy(pPrintBuff, pSPointer, length);
+
+		wfc_util_log_error("wfc_util_printf : %s", pPrintBuff);
+
+		free(pPrintBuff);
+	} else {
+		wfc_util_log_error("wfc_util_printf : can not malloc(%d)", (length+1));
+	}
+	return;
+}
+*/
+
+static void wfc_util_finsert_new_string(int fd, char **ppReadedBuff, char *pNewStringValue, char *pEndOfCfg)
+{
+	off_t sz_file;
+	int   sz_backupBuff = 0;
+	char *pReadBuff = NULL, *pBackupBuff = NULL;
+	char *pSPointer = NULL, *pETagPointer = NULL;
+
+	if( 0 == fd || NULL == pNewStringValue || 0 == strlen(pNewStringValue) ) {
+		wfc_util_log_error("wfc_util_finsert_new_string : unvalid parameters");
+		return;
+	}
+
+	if( NULL == ppReadedBuff) {
+		// TODO:
+		return;
+	} else {
+		pReadBuff = *ppReadedBuff;
+	}
+
+	/*
+	 * find END TAG string
+	 */
+	pETagPointer = strstr(pReadBuff, pEndOfCfg);
+	pSPointer = pETagPointer - 1;
+
+	/*
+	 * calcurate file size and size of the tail of file
+	 */
+	sz_file = lseek( fd,  0, SEEK_END );
+	sz_backupBuff = (int)sz_file - (pETagPointer - pReadBuff);
+
+	/*
+	 * prefare the buffer to store the tail of file
+	 */
+	pBackupBuff = malloc(sz_backupBuff);
+
+	if( NULL != pBackupBuff ) {
+		/*
+		 * copy the tail of file.
+		 */
+		memset( pBackupBuff, 0, sz_backupBuff );
+		memcpy( pBackupBuff, pETagPointer, sz_backupBuff );
+
+		/*
+		 * write new string.
+		 */
+		lseek( fd, (int)(pSPointer-pReadBuff), SEEK_SET );
+		write( fd, pNewStringValue, strlen(pNewStringValue));
+
+		/*
+		 * update pETagPointer.
+		 */
+		pETagPointer = pSPointer + strlen(pNewStringValue);
+
+		/*
+		 * write the tail of file.
+		 */
+		lseek( fd, (int)(pETagPointer-pReadBuff), SEEK_SET );
+		write( fd, pBackupBuff, sz_backupBuff );
+
+		ftruncate(fd, sz_file + strlen(pNewStringValue) - 1); /* we use "-1" becasue of "pSPointer = pETagPointer - 1"*/
+
+		free(pBackupBuff);
+
+		/*
+		 * make new *ppReadedBuff
+		 */
+		if( NULL != ppReadedBuff) {
+			// TODO:
+		}
+	} else {
+		wfc_util_log_error("wfc_util_finsert_new_string : can not malloc(%d)", sz_backupBuff);
+	}
+
+	return;
+}
+
+static void wfc_util_fupdate_string(int fd, char **ppReadedBuff,
+                                    char *pETagPointer, char *pSValuePointer, char *pNewValueString)
+{
+	off_t sz_file;
+	int   sz_newReadBuff = 0;
+	char *pReadBuff = NULL, *pNewReadBuff = NULL, *pCurReadBuff = NULL;
+
+	if( 0 == fd ) {
+		wfc_util_log_error("wfc_util_fupdate_string : unvalid parameters");
+		return;
+	}
+
+	if( NULL == ppReadedBuff) {
+		// TODO:
+		return;
+	} else {
+		pReadBuff = *ppReadedBuff;
+	}
+
+	/*
+	 * calcurate file size and new file size
+	 */
+	sz_file  = lseek( fd,  0, SEEK_END );
+	sz_newReadBuff = (int)sz_file - (int)(pETagPointer - pSValuePointer) + strlen(pNewValueString);
+
+	/*
+	 * prefare the buffer to read file
+	 */
+	pNewReadBuff = malloc(sz_newReadBuff);
+
+	if( NULL != pNewReadBuff ) {
+		/*
+		 * copy buffer
+		 */
+		memset( pNewReadBuff, 0, sz_file );
+		pCurReadBuff = pNewReadBuff;
+		memcpy( pNewReadBuff, pReadBuff, (int)(pSValuePointer-pReadBuff) );
+		pCurReadBuff += (int)(pSValuePointer-pReadBuff);
+
+		/*
+		 * copy new value string
+		 */
+		memcpy( pCurReadBuff, pNewValueString, strlen(pNewValueString));
+		pCurReadBuff += strlen(pNewValueString);
+
+		/*
+		 * copy the remained buffer
+		 */
+		memcpy( pCurReadBuff, pETagPointer, ((int)(sz_file) - (int)(pETagPointer - pReadBuff) + 1));
+
+		/*
+		 * write file and update the file size
+		 */
+		lseek( fd,  0, SEEK_SET );
+		write( fd, pNewReadBuff, sz_newReadBuff);
+		ftruncate(fd, sz_newReadBuff);
+
+		free(pNewReadBuff);
+	} else {
+		wfc_util_log_error("wfc_util_fupdate_string : can not malloc(%d)", (int)sz_newReadBuff);
+	}
+
+	return;
+}
+
+/*
+ * wfc_util_fset_buffer
+ *
+ * return : void
+ */
+void wfc_util_fset_buffer(char *pFileName, int positionStart, unsigned char *pNewValue, int newValueLength)
+{
+	int fd;
+	off_t sz_file;
+	char *pReadBuff = NULL;
+
+	fd = open( pFileName, O_RDWR );
+
+	if( fd >= 0 ) {
+		/*
+		 * calcurate file size
+		 */
+		sz_file  = lseek( fd,  0, SEEK_END );
+
+		/*
+		 * prefare the buffer to read file
+		 */
+		pReadBuff = malloc(sz_file + 1);  // null terminated
+
+		if( NULL != pReadBuff ) {
+			/*
+			 * read file
+			 */
+			memset( pReadBuff, 0, sz_file + 1);
+			lseek( fd,  0, SEEK_SET );
+			read( fd, pReadBuff, sz_file );
+
+			if(sz_file >= (positionStart+newValueLength)) {
+				lseek( fd, positionStart, SEEK_SET );
+				write( fd, pNewValue, newValueLength );
+			} else {
+				/*
+				 * insert with new length value buffer
+				 */
+				wfc_util_log_error("wfc_util_fset_buffer : file size(%d) is less than to write position(%d)", (int)sz_file, (positionStart+newValueLength));
+				// TODO:
+			}
+
+			free(pReadBuff);
+		} else {
+			wfc_util_log_error("wfc_util_fset_buffer : can not malloc(%d)", (int)sz_file);
+		}
+
+		if ( -1 == fsync( fd ) ) {
+			wfc_util_log_error("wfc_util_fset_buffer : fail to fsync()");
+		}
+
+		close( fd );
+	} else {
+		wfc_util_log_error("wfc_util_fset_buffer : can not open file");
+	}
+
+	return;
+}
+
+/*
+ * wfc_util_fget_buffer
+ *
+ * return : it will return the length of the stored buffer value if procedure is success
+ *          or will return 0 if not.
+ */
+int wfc_util_fget_buffer(char *pFileName, int positionStart, int lengthToRead, unsigned char *pValueBuff, int buffLength)
+{
+	int result = 0;
+	int fd;
+	off_t sz_file;
+	char *pReadBuff = NULL;
+	char *pSValuePointer = NULL, *pETagPointer = NULL;
+
+	fd = open( pFileName, O_RDONLY );
+
+	if( fd >= 0 ) {
+		/*
+		 * calcurate file size
+		 */
+		sz_file  = lseek( fd,  0, SEEK_END );
+
+		if(sz_file >= (positionStart+lengthToRead)) {
+			/*
+			 * prefare the buffer to read file
+			 */
+			pReadBuff = malloc(sz_file + 1); // null terminated
+
+			if( NULL != pReadBuff ) {
+				/*
+				 * read file
+				 */
+				memset( pReadBuff, 0, sz_file + 1 );
+				lseek( fd,  0, SEEK_SET );
+				read( fd, pReadBuff, sz_file );
+
+				/*
+				 * calculate the start buffer pointer
+				 */
+				pSValuePointer = pReadBuff + positionStart;
+
+				/*
+				 * calculate the end buffer pointer
+				 */
+				pETagPointer = pSValuePointer + lengthToRead;
+
+				/*
+				 * read the string value
+				 */
+				if( buffLength >= (int)(pETagPointer-pSValuePointer) ) {
+					memset( pValueBuff, 0, buffLength );
+					memcpy( pValueBuff, pSValuePointer, (int)(pETagPointer-pSValuePointer) );
+					result = (int)(pETagPointer-pSValuePointer);
+				} else {
+					wfc_util_log_error("wfc_util_fget_buffer : not enough string value buffer(%d)", (int)(pETagPointer-pSValuePointer));
+				}
+
+				free(pReadBuff);
+			} else {
+				wfc_util_log_error("wfc_util_fget_buffer : can not malloc(%d)", (int)sz_file);
+			}
+		} else {
+			wfc_util_log_error("wfc_util_fget_buffer : file size(%d) is less than to read position(%d)", (int)sz_file, (positionStart+lengthToRead));
+		}
+		close( fd );
+	} else {
+		wfc_util_log_error("wfc_util_fget_buffer : can not open file");
+	}
+
+	return result;
+}
+
+/*
+ * wfc_util_fset_string
+ *
+ * The following format string will be added or updated to the file pFileName.
+ * [pSTagString][pNewValueString][pETagString]
+ *
+ * pFileName       : file name and path
+ * pEndOfCfg       : tag string to notify the end of configuration file
+ * pSTagString     : tag string to notify purpose of the value
+ * pETagString     : tag string to notify the end of the value
+ * pNewValueString : string to set for pSTagString
+ *
+ * return : void
+ */
+void wfc_util_fset_string(char *pFileName, char *pEndOfCfg, char *pSTagString, char *pETagString, char *pNewValueString)
+{
+	int fd;
+	off_t sz_file;
+	int   sz_NewValueBuff = 0;
+	char *pReadBuff = NULL, *pNewValueBuff = NULL;
+	char *pSPointer = NULL, *pETagPointer = NULL, *pSValuePointer = NULL;
+
+	fd = open( pFileName, O_RDWR );
+
+	if( fd >= 0 ) {
+		/*
+		 * calcurate file size
+		 */
+		sz_file  = lseek( fd,  0, SEEK_END );
+
+		/*
+		 * prefare the buffer to read file
+		 */
+		if (sz_file > 0)
+			pReadBuff = malloc(sz_file + 1); // null terminated
+
+		if( NULL != pReadBuff ) {
+			/*
+			 * read file
+			 */
+			memset( pReadBuff, 0x00, sz_file + 1);
+			if(lseek(fd, 0, SEEK_SET) != 0) {
+				wfc_util_log_error("lseek failure");
+			}
+			read( fd, pReadBuff, sz_file );
+
+			/* WBT fix, make sure it is terminated with \0 */
+			pReadBuff[sz_file] = '\0';
+
+			/*
+			 * find TAG string
+			 */
+			pSPointer = strstr(pReadBuff, pSTagString);
+
+			if(NULL != pSPointer) {
+				/*
+				 * find END OF LINE string
+				 */
+				pETagPointer = strstr(pSPointer, pETagString);
+
+				if(NULL != pETagPointer) {
+					/*
+					 * write the new string value
+					 */
+					pSValuePointer = pSPointer+strlen(pSTagString);
+					if(strlen(pNewValueString) == (unsigned int)(pETagPointer-pSValuePointer)) {
+						lseek( fd, (int)(pSValuePointer-pReadBuff), SEEK_SET );
+						write( fd, pNewValueString, strlen(pNewValueString));
+					} else {
+						/*
+						 * insert with new length value string
+						 */
+						wfc_util_fupdate_string(fd, &pReadBuff, pETagPointer, pSValuePointer, pNewValueString);
+					}
+				} else {
+					wfc_util_log_error("wfc_util_fset_string : can not find End TAG");
+				}
+			} else {
+				/*
+				 * "\n""[Start TAG][String Value][End TAG]""\n"
+				 */
+				sz_NewValueBuff = strlen(pSTagString) +
+				                  strlen(pNewValueString) +
+				                  strlen(pETagString) +
+				                  2 + 1;
+				pNewValueBuff = malloc( sz_NewValueBuff);
+
+				if( NULL != pNewValueBuff ) {
+					/*
+					 * prefare the new string to insert
+					 */
+					memset( pNewValueBuff, 0, sz_NewValueBuff );
+					sprintf( pNewValueBuff, "%c%s%s%s%c", '\n', pSTagString, pNewValueString, pETagString,'\n' );
+
+					/*
+					 * insert new string to the file
+					 */
+					wfc_util_finsert_new_string(fd, &pReadBuff, pNewValueBuff, pEndOfCfg);
+
+					free( pNewValueBuff );
+				} else {
+					wfc_util_log_error("wfc_util_fset_string : can not malloc(%d)", (int)sz_file);
+				}
+			}
+
+			free(pReadBuff);
+		} else {
+			wfc_util_log_error("wfc_util_fset_string : can not malloc(%d)", (int)sz_file);
+		}
+
+		if ( -1 == fsync( fd ) ) {
+			wfc_util_log_error("wfc_util_fset_string : fail to fsync()");
+		}
+
+		close( fd );
+	} else {
+		wfc_util_log_error("wfc_util_fset_string : can not open file");
+	}
+
+	return;
+}
+
+/*
+ * wfc_util_fget_string
+ *
+ * Read value from the following format string in the file pFileName.
+ * [pSTagString][string value to read][pETagString]
+ *
+ * pFileName        : file name and path
+ * pEndOfCfg        : tag string to notify the end of configuration file
+ * pSTagString      : tag string to notify purpose of the value
+ * pETagString      : tag string to notify the end of the value
+ * pValueStringBuff : string buffer to get string value
+ * stringBuffLength : the length of pValueStringBuff
+ *
+ * return : it will return the length of the stored string value if procedure is success
+ *          or will return 0 if not.
+ */
+int wfc_util_fget_string(char *pFileName, char *pEndOfCfg __attribute__((unused)), char *pSTagString,
+			 char *pETagString, char *pValueStringBuff, int stringBuffLength)
+{
+	int result = 0;
+	int fd;
+	off_t sz_file;
+	char *pReadBuff = NULL;
+	char *pSPointer = NULL, *pETagPointer = NULL, *pSValuePointer = NULL;
+
+	fd = open( pFileName, O_RDONLY );
+
+	if( fd >= 0 ) {
+		/*
+		 * calcurate file size
+		 */
+		sz_file  = lseek( fd,  0, SEEK_END );
+
+		/*
+		 * prefare the buffer to read file
+		 */
+		if (sz_file > 0)		// skip when value is 0
+			pReadBuff = malloc(sz_file + 1);
+
+		if( NULL != pReadBuff ) {
+			/*
+			 * read file
+			 */
+			memset( pReadBuff, 0, sz_file + 1);
+			if(lseek(fd, 0, SEEK_SET) != 0) {
+				wfc_util_log_error("lseek failure");
+			}
+			read( fd, pReadBuff, sz_file );
+
+			/* WBT fix, make sure it is terminated with \0 */
+			pReadBuff[sz_file] = '\0';
+
+			/*
+			 * find TAG string
+			 */
+			pSPointer = strstr( pReadBuff, pSTagString );
+
+			if( NULL != pSPointer ) {
+				/*
+				 * find END OF LINE string
+				 */
+				pETagPointer = strstr(pSPointer, pETagString);
+
+				if( NULL != pETagPointer ) {
+					/*
+					 * read the string value
+					 */
+					pSValuePointer = pSPointer+strlen(pSTagString);
+					if( stringBuffLength >= (int)(pETagPointer-pSValuePointer) ) {
+						memset( pValueStringBuff, 0, stringBuffLength );
+						memcpy( pValueStringBuff, pSValuePointer, (int)(pETagPointer-pSValuePointer) );
+						result = (int)(pETagPointer-pSValuePointer);
+					} else {
+						wfc_util_log_error("wfc_util_fget_string : not enough string value buffer(%d)", (int)(pETagPointer-pSValuePointer));
+					}
+				} else {
+					wfc_util_log_error("wfc_util_fget_string : can not find End TAG");
+				}
+			} else {
+				wfc_util_log_error("wfc_util_fget_string : can not find Start TAG");
+			}
+			free(pReadBuff);
+		} else {
+			wfc_util_log_error("wfc_util_fget_string : can not malloc(%d)", (int)sz_file);
+		}
+		close( fd );
+	} else {
+		wfc_util_log_error("wfc_util_fget_string : can not open file");
+	}
+
+	return result;
+}
+
+/*
+ * wfc_util_ffile_check
+ *
+ * check whether pDestFName file exist or not
+ *
+ * pFileName   : file name and path
+ * access_mode : R_OK | W_OK | X_OK | F_OK
+ *
+ * return : it will return 0 if the file exist
+ *          or will return -1 if not.
+ */
+int wfc_util_ffile_check(char *pDestFName, int access_mode)
+{
+	struct stat st;
+
+	if (access(pDestFName, access_mode) == 0) {
+		if( stat( pDestFName, &st ) < 0 ) {
+			wfc_util_log_error("Cannot stat the file \"%s\": %s", pDestFName, strerror(errno));
+			return -1;
+		}
+		//check if config file has some data or is it empty due to previous errors
+		if( st.st_size ) {
+			return 0;
+		}
+	} else {
+		wfc_util_log_error("Cannot access \"%s\": %s", pDestFName, strerror(errno));
+	}
+
+	return -1;
+}
+
+/*
+ * wfc_util_ffile_check_copy
+ *
+ * check whether pDestFName file exist if not it will copy from pSourceFName file
+ *
+ * return : it will return 0 if procedure is success
+ *          or will return -1 if not.
+ */
+int wfc_util_ffile_check_copy(char *pDestFName, char *pSourceFName, mode_t mode, uid_t uID, gid_t gID)
+{
+#define WFC_BUFFER_SIZE 2048
+	char buf[WFC_BUFFER_SIZE] = {0}; // Null terminated
+	int srcfd, destfd;
+	int nread;
+	struct stat st;
+
+	if (access(pDestFName, R_OK|W_OK) == 0) {
+		if( stat( pDestFName, &st ) < 0 ) {
+			wfc_util_log_error("Cannot stat the file \"%s\": %s", pDestFName, strerror(errno));
+			return -1;
+		}
+		//check if config file has some data or is it empty due to previous errors
+		if( st.st_size ) {
+			return 0;
+		}
+	//else continue to write the config from default template.
+	} else if (errno != ENOENT) {
+		wfc_util_log_error("Cannot access \"%s\": %s", pDestFName, strerror(errno));
+		return -1;
+	}
+
+	srcfd = open(pSourceFName, O_RDONLY);
+	if (srcfd < 0) {
+		wfc_util_log_error("Cannot open \"%s\": %s", pSourceFName, strerror(errno));
+		return -1;
+	}
+
+	destfd = open(pDestFName, O_CREAT|O_WRONLY, mode);
+	if (destfd < 0) {
+		close(srcfd);
+		wfc_util_log_error("Cannot create \"%s\": %s", pDestFName, strerror(errno));
+		return -1;
+	}
+
+	while ((nread = read(srcfd, buf, WFC_BUFFER_SIZE-1)) != 0) {
+		if (nread < 0) {
+			wfc_util_log_error("Error reading \"%s\": %s", pSourceFName, strerror(errno));
+			close(srcfd);
+			close(destfd);
+			unlink(pDestFName);
+			return -1;
+		}
+		// WBT fix, according to manual, the number of bytes read can't be bigger than read_size. I don't know why WBT complains for this.
+		if (nread < WFC_BUFFER_SIZE)
+			buf[nread] = '\0';
+		else {
+			buf[WFC_BUFFER_SIZE-1] = '\0';
+			nread = WFC_BUFFER_SIZE-1;
+		}
+		write(destfd, buf, nread);
+	}
+
+	close(destfd);
+	close(srcfd);
+
+	/* remove this code because of permission problem when it is accessed from "atd" having system permission. */
+	{
+	#ifndef CONFIG_LGE_WLAN_WIFI_PATCH
+	uid_t uid = getuid();
+	gid_t gid = getgid();
+	wfc_util_log_error("Error changing group ownership (%d) of %s to %d: %s", gid, pDestFName, gID, strerror(errno));
+	if (0 == uid) {
+	#endif /* CONFIG_LGE_WLAN_WIFI_PATCH */
+		if (chown(pDestFName, uID, gID) < 0) {
+			wfc_util_log_error("Error changing group ownership of %s to %d: %s", pDestFName, gID, strerror(errno));
+			unlink(pDestFName);
+			return -1;
+		}
+	#ifndef CONFIG_LGE_WLAN_WIFI_PATCH
+	} else {
+		wfc_util_log_error("wfc_util_ffile_check_copy : we can not excute chown[uid = %d, gid = %d]", uid, getgid());
+	}
+	#endif /* CONFIG_LGE_WLAN_WIFI_PATCH */
+	}
+
+	return 0;
+}
+
diff --git a/wifi/qcom/wfc_util_fctrl.h b/wifi/qcom/wfc_util_fctrl.h
new file mode 100644
index 0000000..5c49899
--- /dev/null
+++ b/wifi/qcom/wfc_util_fctrl.h
@@ -0,0 +1,92 @@ 
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WFC_UTIL_FCTRL_H__
+#define __WFC_UTIL_FCTRL_H__
+
+/*
+ * wfc_util_fset_buffer
+ *
+ * return : void
+ */
+void wfc_util_fset_buffer(char *pFileName, int positionStart, unsigned char *pNewValue, int newValueLength);
+
+/*
+ * wfc_util_fget_buffer
+ *
+ * return : it will return the length of the stored buffer value if procedure is success
+ *          or will return 0 if not.
+ */
+extern int wfc_util_fget_buffer(char *pFileName, int positionStart, int lengthToRead, unsigned char *pValueBuff, int buffLength);
+
+/*
+ * wfc_util_fset_string
+ *
+ * The following format string will be added or updated to the file pFileName.
+ * [pSTagString][pNewValueString][pETagString]
+ *
+ * pFileName       : file name and path
+ * pEndOfCfg       : tag string to notify the end of configuration file
+ * pSTagString     : tag string to notify purpose of the value
+ * pETagString     : tag string to notify the end of the value
+ * pNewValueString : string to set for pSTagString
+ *
+ * return : void
+ */
+extern void wfc_util_fset_string(char *pFileName, char *pEndOfCfg, char *pSTagString, char *pETagString, char *pNewValueString);
+
+/*
+ * wfc_util_fget_string
+ *
+ * Read value from the following format string in the file pFileName.
+ * [pSTagString][string value to read][pETagString]
+ *
+ * pFileName        : file name and path
+ * pEndOfCfg        : tag string to notify the end of configuration file
+ * pSTagString      : tag string to notify purpose of the value
+ * pETagString      : tag string to notify the end of the value
+ * pValueStringBuff : string buffer to get string value
+ * stringBuffLength : the length of pValueStringBuff
+ *
+ * return : it will return the length of the stored string value if procedure is success
+ *          or will return 0 if not.
+ */
+extern int wfc_util_fget_string(char *pFileName, char *pEndOfCfg, char *pSTagString, char *pETagString, char *pValueStringBuff, int stringBuffLength);
+
+/*
+ * wfc_util_ffile_check
+ *
+ * check whether pDestFName file exist or not
+ *
+ * pFileName   : file name and path
+ * access_mode : R_OK | W_OK | X_OK | F_OK
+ *
+ * return : it will return 0 if the file exist
+ *          or will return -1 if not.
+ */
+extern int wfc_util_ffile_check(char *pDestFName, int access_mode);
+
+/*
+ * wfc_util_ffile_check_copy
+ *
+ * check whether pDestFName file exist if not it will copy from pSourceFName file
+ *
+ * return : it will return 0 if procedure is success
+ *          or will return -1 if not.
+ */
+extern int wfc_util_ffile_check_copy(char *pDestFName, char *pSourceFName, mode_t mode,  uid_t uID, gid_t gID);
+
+#endif
diff --git a/wifi/qcom/wfc_util_log.h b/wifi/qcom/wfc_util_log.h
new file mode 100644
index 0000000..fcc4239
--- /dev/null
+++ b/wifi/qcom/wfc_util_log.h
@@ -0,0 +1,32 @@ 
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WFC_UTIL_LOG_H__
+#define __WFC_UTIL_LOG_H__
+
+#ifdef ANDROID
+#define LOG_TAG "WifiUtil"
+#include <cutils/log.h>
+
+#define wfc_util_log_info(...)  ALOGI(__VA_ARGS__)
+#define wfc_util_log_error(...) ALOGE(__VA_ARGS__)
+#else  /* ANDROID */
+#define wfc_util_log_info(...)  printf(__VA_ARGS__);printf("\n")
+#define wfc_util_log_error(...) printf(__VA_ARGS__);printf("\n")
+#endif /* ANDROID */
+
+#endif
+
diff --git a/wifi/qcom/wfc_util_main.c b/wifi/qcom/wfc_util_main.c
new file mode 100644
index 0000000..01e1c86
--- /dev/null
+++ b/wifi/qcom/wfc_util_main.c
@@ -0,0 +1,139 @@ 
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include "wfc_util_fctrl.h"
+#include "wfc_util_common.h"
+
+#ifdef WLAN_CHIP_VERSION_WCNSS
+#ifndef WFC_UTIL_CFG_FILE_NAME
+#define WFC_UTIL_CFG_FILE_NAME          "./WCNSS_qcom_cfg.ini"
+#endif
+#ifndef WFC_UTIL_NV_BIN_FILE_NAME
+#define WFC_UTIL_NV_BIN_FILE_NAME       "./WCNSS_qcom_wlan_nv.bin"
+#endif
+#else  /* WLAN_CHIP_VERSION_WCN1314 */
+#ifndef WFC_UTIL_CFG_FILE_NAME
+#define WFC_UTIL_CFG_FILE_NAME          "./WCN1314_qcom_cfg.ini"
+#endif
+#ifndef WFC_UTIL_NV_BIN_FILE_NAME
+#define WFC_UTIL_NV_BIN_FILE_NAME       "./WCN1314_qcom_wlan_nv.bin"
+#endif
+#endif /* WLAN_CHIP_VERSION_XXXX */
+#define WFC_UTIL_CFG_TAG_END_OF_CFG     "END"
+#define WFC_UTIL_CFG_TAG_MAC_ADDRESS    "NetworkAddress="
+#define WFC_UTIL_CFG_TAG_AP_MAC_ADDRESS "gAPMacAddr="
+#define WFC_UTIL_CFG_TAG_END_OF_LINE    "\n"
+#define WFC_UTIL_CFG_LENGHT_MAC         (6)
+#define WFC_UTIL_CFG_LENGHT_MAC_STRING  (WFC_UTIL_CFG_LENGHT_MAC*2)
+
+/*
+ * persist/WCNSS_qcom_wlan_nv.bin
+ *
+ * typedef PACKED_PRE struct PACKED_POST
+ * {
+ *     //always ensure fields are aligned to 32-bit boundaries
+ *     tANI_U16  productId;
+ *     tANI_U8   productBands;
+ *     tANI_U8   wlanNvRevId;
+ *
+ *     tANI_U8   numOfTxChains;
+ *     tANI_U8   numOfRxChains;
+ *     tANI_U8   macAddr[NV_FIELD_MAC_ADDR_SIZE];
+ *     tANI_U8   mfgSN[NV_FIELD_MFG_SN_SIZE];
+ * } sNvFields;
+ */
+#define WFC_UTIL_NV_BIN_HEADER_LENGTH    (4)
+#define WFC_UTIL_NV_BIN_POS_PRODUCT_ID   (WFC_UTIL_NV_BIN_HEADER_LENGTH + 0)
+#define WFC_UTIL_NV_BIN_POS_PRODUCT_BAND (WFC_UTIL_NV_BIN_HEADER_LENGTH + 2)
+#define WFC_UTIL_NV_BIN_POS_MAC_ADDR     (WFC_UTIL_NV_BIN_HEADER_LENGTH + 6)
+
+int main(int argc, char **argv)
+{
+	int ret = 0;
+	char mac_add_buff[WFC_UTIL_CFG_LENGHT_MAC_STRING+1];
+	unsigned char mac_add_buff_2[WFC_UTIL_CFG_LENGHT_MAC] = {0x88, 0xcd, 0xba, 0x0c, 0x90, 0x00};
+	unsigned char mac_add_buff_3[WFC_UTIL_CFG_LENGHT_MAC] = {0x00, 0x90, 0x0c, 0xba, 0xcd, 0x88};
+
+	printf("wfc_util_main is started\n");
+
+	if(0 < wfc_util_fget_string(WFC_UTIL_CFG_FILE_NAME,
+	                            WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                            WFC_UTIL_CFG_TAG_MAC_ADDRESS,
+	                            WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                            mac_add_buff,
+	                            WFC_UTIL_CFG_LENGHT_MAC_STRING+1)) {
+		printf("wfc_util_main : %s%s\n", WFC_UTIL_CFG_TAG_MAC_ADDRESS, mac_add_buff);
+	} else {
+		printf("wfc_util_main : %s is not found\n", WFC_UTIL_CFG_TAG_MAC_ADDRESS);
+	}
+
+	wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+	                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                     WFC_UTIL_CFG_TAG_AP_MAC_ADDRESS,
+	                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                     "00900cbacd88");
+
+	wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+	                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                     WFC_UTIL_CFG_TAG_MAC_ADDRESS,
+	                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                     "00900cbacd88");
+
+	if(0 < wfc_util_fget_string(WFC_UTIL_CFG_FILE_NAME,
+	                            WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                            WFC_UTIL_CFG_TAG_MAC_ADDRESS,
+	                            WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                            mac_add_buff,
+	                            WFC_UTIL_CFG_LENGHT_MAC_STRING+1)) {
+		printf("wfc_util_main : %s%s\n", WFC_UTIL_CFG_TAG_MAC_ADDRESS, mac_add_buff);
+
+		wfc_util_atoh(mac_add_buff, strlen(mac_add_buff), mac_add_buff_2, WFC_UTIL_CFG_LENGHT_MAC);
+		printf("wfc_util_main : %s%02x:%02x:%02x:%02x:%02x:%02x\n",
+		                        WFC_UTIL_CFG_TAG_MAC_ADDRESS,
+		                        mac_add_buff_2[0], mac_add_buff_2[1], mac_add_buff_2[2],
+		                        mac_add_buff_2[3], mac_add_buff_2[4], mac_add_buff_2[5]);
+
+		wfc_util_htoa(mac_add_buff_2, WFC_UTIL_CFG_LENGHT_MAC, mac_add_buff, WFC_UTIL_CFG_LENGHT_MAC_STRING);
+		printf("wfc_util_main : %s%s\n", WFC_UTIL_CFG_TAG_MAC_ADDRESS, mac_add_buff);
+
+	} else {
+		printf("wfc_util_main : %s is not found\n", WFC_UTIL_CFG_TAG_MAC_ADDRESS);
+	}
+
+	wfc_util_fset_buffer(WFC_UTIL_NV_BIN_FILE_NAME,
+	                     WFC_UTIL_NV_BIN_POS_MAC_ADDR,
+	                     mac_add_buff_3,
+	                     WFC_UTIL_CFG_LENGHT_MAC);
+
+	if(0 < wfc_util_fget_buffer(WFC_UTIL_NV_BIN_FILE_NAME,
+	                            WFC_UTIL_NV_BIN_POS_MAC_ADDR,
+	                            6,
+	                            mac_add_buff_2,
+	                            WFC_UTIL_CFG_LENGHT_MAC)) {
+		printf("wfc_util_main : wfc_util_fget_buffer[%02x:%02x:%02x:%02x:%02x:%02x]\n",
+		                        mac_add_buff_2[0], mac_add_buff_2[1], mac_add_buff_2[2],
+		                        mac_add_buff_2[3], mac_add_buff_2[4], mac_add_buff_2[5]);
+	} else {
+		printf("wfc_util_main : %s is not found\n", WFC_UTIL_CFG_TAG_MAC_ADDRESS);
+	}
+
+	return ret;
+}
+
diff --git a/wifi/qcom/wfc_util_qcom.c b/wifi/qcom/wfc_util_qcom.c
new file mode 100644
index 0000000..8508893
--- /dev/null
+++ b/wifi/qcom/wfc_util_qcom.c
@@ -0,0 +1,690 @@ 
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef CONFIG_LGE_WLAN_QCOM_PATCH
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wfc_util_log.h"
+#include "wfc_util_fctrl.h"
+#include "wfc_util_common.h"
+
+#include "cutils/properties.h"
+
+#include "private/android_filesystem_config.h"
+
+#define WFC_UTIL_FEAUTRE_COPY_NV_BIN
+
+#ifdef WLAN_CHIP_VERSION_WCNSS
+#ifndef WFC_UTIL_CFG_FILE_NAME
+#define WFC_UTIL_CFG_FILE_NAME          "/data/misc/wifi/WCNSS_qcom_cfg.ini"
+#endif
+#ifndef WFC_UTIL_CFG_TEMPFILE_NAME
+#define WFC_UTIL_CFG_TEMPFILE_NAME      "/system/etc/wifi/WCNSS_qcom_cfg.ini"
+#endif
+#else  /* WLAN_CHIP_VERSION_WCN1314 */
+#ifndef WFC_UTIL_CFG_FILE_NAME
+#define WFC_UTIL_CFG_FILE_NAME          "/data/misc/wifi/WCN1314_qcom_cfg.ini"
+#endif
+#ifndef WFC_UTIL_CFG_TEMPFILE_NAME
+#define WFC_UTIL_CFG_TEMPFILE_NAME      "/system/etc/wifi/WCN1314_qcom_cfg.ini"
+#endif
+#endif /* WLAN_CHIP_VERSION_XXXX */
+
+#ifdef WFC_UTIL_FEAUTRE_COPY_NV_BIN
+#ifdef WLAN_CHIP_VERSION_WCNSS
+#ifndef WFC_UTIL_NV_BIN_TEMPFILE_NAME
+#define WFC_UTIL_NV_BIN_TEMPFILE_NAME   "/system/etc/wifi/WCNSS_qcom_wlan_nv.bin"
+#endif
+#ifndef WFC_UTIL_NV_BIN_FILE_NAME
+#define WFC_UTIL_NV_BIN_FILE_NAME       "/data/misc/wifi/WCNSS_qcom_wlan_nv.bin"
+#endif
+#else  /* WLAN_CHIP_VERSION_WCN1314 */
+#ifndef WFC_UTIL_NV_BIN_TEMPFILE_NAME
+#define WFC_UTIL_NV_BIN_TEMPFILE_NAME   "/persist/WCN1314_qcom_wlan_nv.bin"
+#endif
+#ifndef WFC_UTIL_NV_BIN_FILE_NAME
+#define WFC_UTIL_NV_BIN_FILE_NAME       "/data/misc/wifi/WCN1314_qcom_wlan_nv.bin"
+#endif
+#endif /* WLAN_CHIP_VERSION_XXXX */
+#else  /* WFC_UTIL_FEAUTRE_COPY_NV_BIN */
+#ifndef WFC_UTIL_NV_BIN_FILE_NAME
+#ifdef WLAN_CHIP_VERSION_WCNSS
+#define WFC_UTIL_NV_BIN_FILE_NAME       "/persist/WCNSS_qcom_wlan_nv.bin"
+#else  /* WLAN_CHIP_VERSION_WCN1314 */
+#define WFC_UTIL_NV_BIN_FILE_NAME       "/persist/WCN1314_qcom_wlan_nv.bin"
+#endif /* WLAN_CHIP_VERSION_XXXX */
+#endif
+#endif /* WFC_UTIL_FEAUTRE_COPY_NV_BIN */
+
+#define WFC_UTIL_CFG_TAG_END_OF_CFG     "END"
+/*
+ * Station Mode MAC Address
+ */
+#ifdef WLAN_CHIP_VERSION_WCNSS
+#define WFC_UTIL_CFG_TAG_MAC_ADDRESS    "Intf0MacAddress="
+#else  /* WLAN_CHIP_VERSION_WCN1314 */
+#define WFC_UTIL_CFG_TAG_MAC_ADDRESS    "NetworkAddress="
+#endif /* WLAN_CHIP_VERSION_XXXX */
+/*
+ * AP Mode MAC Address
+ */
+#define WFC_UTIL_CFG_TAG_AP_MAC_ADDRESS "gAPMacAddr="
+
+/*
+ * Idle Mode Power Save enable/disable for OTA test
+ */
+#define WFC_UTIL_CFG_TAG_IDLE_MODE_POWER_SAVE "gEnableImps="
+
+/*
+ * Beacon Mode Power Save enable/disable for OTA test
+ */
+#define WFC_UTIL_CFG_TAG_POWER_SAVE "gEnableBmps="
+
+/*
+ * L2 roaming on/off for OTA test
+ */
+#define WFC_UTIL_CFG_TAG_L2Roaming "gEnableHandoff="
+
+/*
+ * Heartbeat24 changing for OtA test
+ */
+#define WFC_UTIL_CFG_TAG_HEARTBEAT24 "gHeartbeat24="
+
+/*
+ * TAG for end of line
+ */
+#define WFC_UTIL_CFG_TAG_END_OF_LINE    "\n"
+
+#define WFC_UTIL_CFG_LENGHT_MAC         (6)
+#define WFC_UTIL_CFG_LENGHT_MAC_STRING  (WFC_UTIL_CFG_LENGHT_MAC*2)
+
+/*
+ * persist/WCNSS_qcom_wlan_nv.bin
+ *
+ * NV validity bitmap (4 bytes)
+ * {
+ *     Bit 0 - Regulatory domain tables
+ *     Bit 1 - Fields(including product ID, product bands, number of Tx/Rx chains, MAC address, manufacturing board number)
+ *     Bit 2 - Optimal power per rate table
+ *     Bit 3 - Default regulatory domain and country code
+ *     Bit 4:31 - Reserved; always 0
+ * }
+ *
+ * typedef PACKED_PRE struct PACKED_POST
+ * {
+ *     //always ensure fields are aligned to 32-bit boundaries
+ *     tANI_U16  productId;
+ *     tANI_U8   productBands;        //0: 0.4 GHz, 1: 2.4+5.0 GHz, 2: 5.0 GHz
+ *     tANI_U8   wlanNvRevId;         //0: WCN1312, 1: WCN1314, 2: PRIMA
+ *
+ *     tANI_U8   numOfTxChains;
+ *     tANI_U8   numOfRxChains;
+ *     tANI_U8   macAddr[NV_FIELD_MAC_ADDR_SIZE];
+ *     tANI_U8   mfgSN[NV_FIELD_MFG_SN_SIZE];
+ * } sNvFields;
+ */
+#define WFC_UTIL_NV_BIN_HEADER_LENGTH   (4)
+#define WFC_UTIL_NV_BIN_POS_PRODUCT_ID  (WFC_UTIL_NV_BIN_HEADER_LENGTH + 0)
+#define WFC_UTIL_NV_BIN_POS_MAC_ADDR    (WFC_UTIL_NV_BIN_HEADER_LENGTH + 6)
+
+#ifdef WLAN_CHIP_VERSION_WCNSS
+/* refer to prima/CORE/WDA/src/wlan_nv.c */
+static unsigned char nvFilelds_default[6] = {0, 0, /* productId */
+                                             1,    /* productBands */
+                                             2,    /* wlanNvRevId */
+                                             1,    /* numOfTxChains */
+                                             2};   /* numOfRxChains */
+#else  /* WLAN_CHIP_VERSION_WCN1314 */
+static unsigned char nvFilelds_default[6] = {1, 0, /* productId */
+                                             1,    /* productBands */
+                                             1,    /* wlanNvRevId */
+                                             1,    /* numOfTxChains */
+                                             1};   /* numOfRxChains */
+#endif /* WLAN_CHIP_VERSION_XXXX */
+
+/*
+ * wfc_util_qcom_is_default_mac
+ *
+ *
+ *
+ * return : it will return 1 if mac_add is default mac address,
+ *          2 if mac_add is RFT mac address
+ *          or 0 if not.
+ */
+static int wfc_util_qcom_is_default_mac(char *mac_add)
+{
+#define WFC_UTIL_CFG_DEFAULT_MAC_RFT     "00900CBACD88"
+#define WFC_UTIL_CFG_DEFAULT_MAC_00      "000000000000"
+#define WFC_UTIL_CFG_DEFAULT_MAC_FF      "FFFFFFFFFFFF"
+#define WFC_UTIL_CFG_DEFAULT_MAC_QCOM_I0 "000AF58989FF"
+#define WFC_UTIL_CFG_DEFAULT_MAC_QCOM_I1 "000AF58989FE"
+#define WFC_UTIL_CFG_DEFAULT_MAC_QCOM_I2 "000AF58989FD"
+#define WFC_UTIL_CFG_DEFAULT_MAC_QCOM_I3 "000AF58989FC"
+#define WFC_UTIL_CFG_DEFAULT_MAC_QCOM_AP "000AF58989EF"
+
+	int i, sZarray=0;
+	/*
+	 * default mac address array
+	 */
+	char mac_add_buff[][WFC_UTIL_CFG_LENGHT_MAC_STRING+1] = {
+			{WFC_UTIL_CFG_DEFAULT_MAC_00},
+			{WFC_UTIL_CFG_DEFAULT_MAC_FF},
+			{WFC_UTIL_CFG_DEFAULT_MAC_QCOM_I0}
+	};
+
+	sZarray = sizeof(mac_add_buff) / sizeof(mac_add_buff[0]);
+
+	for(i=0; i<sZarray ;i++) {
+		if(0 == strncmp(mac_add, mac_add_buff[i], WFC_UTIL_CFG_LENGHT_MAC_STRING)) {
+			wfc_util_log_error("This is default MAC address [%s]", mac_add_buff[i]);
+			return 1;
+		}
+	}
+
+	/*
+	if(1 == wfc_util_is_random_mac(mac_add)) {
+		wfc_util_log_error("This is Random MAC address");
+		return 1;
+	}
+	*/
+
+	if(0 == strncmp(mac_add, WFC_UTIL_CFG_DEFAULT_MAC_RFT, WFC_UTIL_CFG_LENGHT_MAC_STRING)) {
+		wfc_util_log_error("This is RFT MAC address [%s]", WFC_UTIL_CFG_DEFAULT_MAC_RFT);
+		return 2;
+	}
+
+	return 0;
+}
+
+static void wfc_util_qcom_write_mac(char *mac_add)
+{
+	/*
+	 * Station Mode MAC Address
+	 */
+	wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+	                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                     WFC_UTIL_CFG_TAG_MAC_ADDRESS,
+	                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                     mac_add);
+
+	/*
+	 * AP Mode MAC Address
+	 */
+	wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+	                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                     WFC_UTIL_CFG_TAG_AP_MAC_ADDRESS,
+	                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                     mac_add);
+
+	return;
+}
+
+/*
+ *  When OTA is enabled, power save mode and L2 roaming trigger should be off
+ */
+static void wfc_util_qcom_write_ota_enable(void)
+{
+/*
+ * write Beacon Mode Power Save off and L2 Roaming off
+ */
+	char *PowerSaveOff = "0";
+	//char *L2RoamingOff = "0";
+	char *Heartbeat24 = "120";
+
+	char string_buff[5];
+
+	wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+	                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                     WFC_UTIL_CFG_TAG_IDLE_MODE_POWER_SAVE,
+	                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                     PowerSaveOff);
+
+	wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+	                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                     WFC_UTIL_CFG_TAG_POWER_SAVE,
+	                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                     PowerSaveOff);
+
+/* We don't need to change this becasue the default value of WFC_UTIL_CFG_TAG_L2Roaming is 0.
+	wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+	                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                     WFC_UTIL_CFG_TAG_L2Roaming,
+	                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                     L2RoamingOff);
+*/
+
+	if(0 < wfc_util_fget_string(WFC_UTIL_CFG_FILE_NAME,
+	                            WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                            WFC_UTIL_CFG_TAG_HEARTBEAT24,
+	                            WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                            string_buff,
+	                            5)) {
+		wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+		                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+		                     WFC_UTIL_CFG_TAG_HEARTBEAT24,
+		                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+		                     Heartbeat24);
+	} else {
+		wfc_util_log_error("%s is not exist", WFC_UTIL_CFG_TAG_HEARTBEAT24);
+	}
+
+	return;
+}
+
+/*
+ *  When OTA is enabled, power save mode and L2 roaming trigger should be off
+ */
+static void wfc_util_qcom_write_ota_disable(void)
+{
+/*
+ * write Beacon Mode Power Save on and L2 Roaming on
+ */
+	char *PowerSaveOff = "1";
+	//char *L2RoamingOff = "1";
+	char *Heartbeat24 = "40";
+
+	char string_buff[5];
+
+	wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+	                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                     WFC_UTIL_CFG_TAG_IDLE_MODE_POWER_SAVE,
+	                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                     PowerSaveOff);
+
+	wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+	                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                     WFC_UTIL_CFG_TAG_POWER_SAVE,
+	                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                     PowerSaveOff);
+
+/* We don't need to change this becasue the default value of WFC_UTIL_CFG_TAG_L2Roaming is 0.
+	wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+	                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                     WFC_UTIL_CFG_TAG_L2Roaming,
+	                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                     L2RoamingOff);
+*/
+
+	if(0 < wfc_util_fget_string(WFC_UTIL_CFG_FILE_NAME,
+	                            WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                            WFC_UTIL_CFG_TAG_HEARTBEAT24,
+	                            WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                            string_buff,
+	                            5)) {
+		wfc_util_fset_string(WFC_UTIL_CFG_FILE_NAME,
+		                     WFC_UTIL_CFG_TAG_END_OF_CFG,
+		                     WFC_UTIL_CFG_TAG_HEARTBEAT24,
+		                     WFC_UTIL_CFG_TAG_END_OF_LINE,
+		                     Heartbeat24);
+	} else {
+		wfc_util_log_error("%s is not exist", WFC_UTIL_CFG_TAG_HEARTBEAT24);
+	}
+
+	return;
+}
+
+static void wfc_util_qcom_write_mac_to_bin(unsigned char *mac_add)
+{
+	unsigned char nvValidityBitmap[WFC_UTIL_NV_BIN_HEADER_LENGTH];
+
+	if(0 != wfc_util_ffile_check(WFC_UTIL_NV_BIN_FILE_NAME,
+	                             F_OK|R_OK|W_OK)) {
+		wfc_util_log_error("We don't access file [%s]", WFC_UTIL_NV_BIN_FILE_NAME);
+		return;
+	}
+
+	memset(nvValidityBitmap, 0, WFC_UTIL_NV_BIN_HEADER_LENGTH);
+
+	/*
+	 * Write RFT MAC Address
+	 */
+	wfc_util_fset_buffer(WFC_UTIL_NV_BIN_FILE_NAME,
+	                     WFC_UTIL_NV_BIN_POS_MAC_ADDR,
+	                     mac_add,
+	                     WFC_UTIL_CFG_LENGHT_MAC);
+
+	/*
+	 * Read NV validity bitmap
+	 */
+	if (0 < wfc_util_fget_buffer(WFC_UTIL_NV_BIN_FILE_NAME,
+	                             0,
+	                             WFC_UTIL_NV_BIN_HEADER_LENGTH,
+	                             nvValidityBitmap,
+	                             WFC_UTIL_NV_BIN_HEADER_LENGTH)){
+	        /*
+	         * Check whether Fields bit(Bit 1) is set
+	         */
+		if (0x02 & nvValidityBitmap[0]) {
+			wfc_util_log_info("We don't need to write the default value for NvFilelds");
+		} else {
+		        /*
+		         * Update the Fields bit(Bit 1)
+		         */
+			nvValidityBitmap[0] |= 0x02;
+			wfc_util_fset_buffer(WFC_UTIL_NV_BIN_FILE_NAME,
+			                     0,
+			                     nvValidityBitmap,
+			                     WFC_UTIL_NV_BIN_HEADER_LENGTH);
+
+		        /*
+		         * Write the default value for NvFilelds
+		         */
+			wfc_util_fset_buffer(WFC_UTIL_NV_BIN_FILE_NAME,
+			                     WFC_UTIL_NV_BIN_POS_PRODUCT_ID,
+			                     nvFilelds_default,
+			                     6);
+		}
+	} else {
+		wfc_util_log_error("Read Fail nvValidityBitmap");
+	}
+
+	return;
+}
+
+/*
+ * wfc_util_qcom_reset_mac_to_bin
+ *
+ * reset the mac address of nv bin file
+ *
+ * return : void
+ */
+static void wfc_util_qcom_reset_mac_to_bin(void)
+{
+	unsigned char mac_addr[WFC_UTIL_CFG_LENGHT_MAC];
+
+	if(0 != wfc_util_ffile_check(WFC_UTIL_NV_BIN_FILE_NAME,
+	                             F_OK|R_OK|W_OK)) {
+		wfc_util_log_error("We don't access file [%s]", WFC_UTIL_NV_BIN_FILE_NAME);
+		return;
+	}
+
+	if(0 < wfc_util_fget_buffer(WFC_UTIL_NV_BIN_FILE_NAME,
+	                            WFC_UTIL_NV_BIN_POS_MAC_ADDR,
+	                            WFC_UTIL_CFG_LENGHT_MAC,
+	                            mac_addr,
+	                            WFC_UTIL_CFG_LENGHT_MAC)) {
+		if(0x00 == mac_addr[0] && 0x00 == mac_addr[1] && 0x00 == mac_addr[2] &&
+		   0x00 == mac_addr[3] && 0x00 == mac_addr[4] && 0x00 == mac_addr[5])
+		{
+			return;
+		}
+	}
+
+	memset(mac_addr, 0, WFC_UTIL_CFG_LENGHT_MAC);
+
+	wfc_util_fset_buffer(WFC_UTIL_NV_BIN_FILE_NAME,
+	                     WFC_UTIL_NV_BIN_POS_MAC_ADDR,
+	                     mac_addr,
+	                     WFC_UTIL_CFG_LENGHT_MAC);
+
+	return;
+}
+
+static int wfc_util_qcom_write_mac_process(unsigned char *nv_mac_addr, char *mac_add_buff)
+{
+	char nv_mac_add_buff[WFC_UTIL_CFG_LENGHT_MAC_STRING+1];
+	int  is_default_nv_mac = 0;
+	int  is_same_mac = -1;
+
+	if (NULL == nv_mac_addr) {
+		return 0;
+	}
+
+	wfc_util_htoa(nv_mac_addr, WFC_UTIL_CFG_LENGHT_MAC,
+	              nv_mac_add_buff, WFC_UTIL_CFG_LENGHT_MAC_STRING+1);
+
+	is_default_nv_mac = wfc_util_qcom_is_default_mac(nv_mac_add_buff);
+
+	is_same_mac = strncmp(mac_add_buff, nv_mac_add_buff, WFC_UTIL_CFG_LENGHT_MAC_STRING);
+
+	/*
+	 * 1. nv mac address is not a default mac address
+	 * 2. same with mac address of config file
+	 */
+	if (((!is_default_nv_mac) && (0==is_same_mac)) ||
+	/*
+	 * 1. nv mac address is RFT mac address
+	 * 2. same with mac address of config file
+	 */
+	    ((2==is_default_nv_mac) && (0==is_same_mac))
+	   ) {
+		return 1;
+	}
+	/*
+	 * 1. nv mac address not a default mac address excepting RFT mac address
+	 * 2. does not same with mac address of config file
+	 */
+	else if ((1!=is_default_nv_mac) && (0!=is_same_mac)) {
+		wfc_util_log_error("Change %s%s", WFC_UTIL_CFG_TAG_MAC_ADDRESS, nv_mac_add_buff);
+		/*
+		 * Update MAC address
+		 */
+		wfc_util_qcom_write_mac(nv_mac_add_buff);
+
+#ifdef WFC_UTIL_FEATURE_DO_NOT_WRITE_MAC_TO_BIN
+		/*
+		 * Write RFT MAC address to nv.bin
+		 */
+		if (2==is_default_nv_mac) {
+			wfc_util_qcom_write_mac_to_bin(nv_mac_addr);
+		/*
+		 * reset mac address of nv.bin if nv_mac_addr is not RFT mac address
+		 */
+		} else {
+			wfc_util_qcom_reset_mac_to_bin();
+		}
+#else  /* WFC_UTIL_FEATURE_DO_NOT_WRITE_MAC_TO_BIN */
+		/*
+		 * Write MAC address to nv.bin
+		 */
+		wfc_util_qcom_write_mac_to_bin(nv_mac_addr);
+#endif /* WFC_UTIL_FEATURE_DO_NOT_WRITE_MAC_TO_BIN */
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static void wfc_util_qcom_create_random_mac(void)
+{
+	unsigned char random_mac_addr[WFC_UTIL_CFG_LENGHT_MAC];
+	char mac_add_buff[WFC_UTIL_CFG_LENGHT_MAC_STRING+1];
+
+	wfc_util_log_info("wfc_util_qcom_create_random_mac");
+
+	wfc_util_random_mac(random_mac_addr);
+
+	wfc_util_htoa(random_mac_addr, WFC_UTIL_CFG_LENGHT_MAC, mac_add_buff, WFC_UTIL_CFG_LENGHT_MAC_STRING+1);
+
+	wfc_util_qcom_write_mac(mac_add_buff);
+
+#ifdef WFC_UTIL_FEATURE_DO_NOT_WRITE_MAC_TO_BIN
+	wfc_util_qcom_reset_mac_to_bin();
+#else  /* WFC_UTIL_FEATURE_DO_NOT_WRITE_MAC_TO_BIN */
+	wfc_util_qcom_write_mac_to_bin(random_mac_addr);
+#endif /* WFC_UTIL_FEATURE_DO_NOT_WRITE_MAC_TO_BIN */
+
+	return;
+}
+
+/*
+ * wfc_util_qcom_check_config
+ *
+ * check the qcom wlan driver config file
+ *
+ * return : it will return 0 if procedure is success
+ *          or will return -1 if not.
+ */
+int wfc_util_qcom_check_config(unsigned char *nv_mac_addr)
+{
+	char mac_add_buff[WFC_UTIL_CFG_LENGHT_MAC_STRING+1];
+
+	/* make sure driver config file exists */
+	if(0 > wfc_util_ffile_check_copy(WFC_UTIL_CFG_FILE_NAME,
+	                             WFC_UTIL_CFG_TEMPFILE_NAME,
+	                             0660,
+	                             AID_SYSTEM,
+	                             /* we use "radio" for gid to access from "rild" for AT cmd. */
+	                             AID_WIFI/*AID_WIFI*/)) {
+		wfc_util_log_error("Fail to Access [%s]", WFC_UTIL_CFG_FILE_NAME);
+		return -1;
+	}
+
+#ifdef WFC_UTIL_FEAUTRE_COPY_NV_BIN
+	char nv_bin_tempfile_name[50];
+	char baseband[PROPERTY_VALUE_MAX];
+
+	// Default use WCNSS_qcom_wlan_nv_flo.bin
+	property_get("ro.boot.baseband", baseband, "apq");
+	if(!strncmp(baseband, "apq", 3)) {
+		sprintf(nv_bin_tempfile_name, "/system/etc/wifi/WCNSS_qcom_wlan_nv_flo.bin");
+	} else if( !strncmp(baseband, "mdm", 3)){
+		sprintf(nv_bin_tempfile_name, "/system/etc/wifi/WCNSS_qcom_wlan_nv_deb.bin");
+	}
+	wfc_util_log_error("nv bin : %s", nv_bin_tempfile_name);
+
+	if(0 > wfc_util_ffile_check_copy(WFC_UTIL_NV_BIN_FILE_NAME,
+	                             nv_bin_tempfile_name,
+	                             0660,
+	                             AID_SYSTEM,
+	                             /* we use "radio" for gid to access from "rild" for AT cmd. */
+	                             AID_WIFI/*AID_WIFI*/)) {
+		wfc_util_log_error("Fail to Access [%s]", WFC_UTIL_NV_BIN_FILE_NAME);
+		return -1;
+	}
+#endif /* WFC_UTIL_FEAUTRE_COPY_NV_BIN */
+
+	/*
+	 * Read MAC address from config file
+	 */
+	if(0 < wfc_util_fget_string(WFC_UTIL_CFG_FILE_NAME,
+	                        WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                        WFC_UTIL_CFG_TAG_MAC_ADDRESS,
+	                        WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                        mac_add_buff,
+	                        WFC_UTIL_CFG_LENGHT_MAC_STRING+1)) {
+		wfc_util_log_info("%s%s", WFC_UTIL_CFG_TAG_MAC_ADDRESS, mac_add_buff);
+
+		/*
+		 * Write nv mac address
+		 */
+		if (1 != wfc_util_qcom_write_mac_process(nv_mac_addr, mac_add_buff)) {
+			/*
+			 * Check whether this is default mac address or not
+			 */
+			if (wfc_util_qcom_is_default_mac(mac_add_buff)) {
+				/*
+				 * Create random MAC address
+				 */
+				wfc_util_qcom_create_random_mac();
+			}
+		}
+	} else {
+		wfc_util_log_error("%s does not have mac address", WFC_UTIL_CFG_FILE_NAME);
+
+		memset( mac_add_buff, 0, WFC_UTIL_CFG_LENGHT_MAC_STRING+1 );
+
+		/*
+		 * Write nv mac address
+		 */
+		if (1 != wfc_util_qcom_write_mac_process(nv_mac_addr, mac_add_buff)) {
+			/*
+			 * Create random MAC address
+			 */
+			wfc_util_qcom_create_random_mac();
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * wfc_util_qcom_reset_mac
+ *
+ * reset the mac address of config file
+ *
+ * return : void
+ */
+void wfc_util_qcom_reset_mac(void)
+{
+	wfc_util_qcom_write_mac("000000000000");
+
+	wfc_util_qcom_reset_mac_to_bin();
+
+	return;
+}
+
+/*
+ * wfc_util_qcom_ota_enable
+ *
+ * enable ota mode by reconfiguring BMPS and L2Roaming
+ *
+ * return : int (boolean)
+ */
+int wfc_util_qcom_ota_enable(void)
+{
+	wfc_util_qcom_write_ota_enable();
+	return 1;
+}
+
+/*
+ * wfc_util_qcom_ota_disable
+ *
+ * disable ota mode by reconfiguring BMPS and L2Roaming
+ *
+ * return : int (boolean)
+ */
+int wfc_util_qcom_ota_disable(void)
+{
+	wfc_util_qcom_write_ota_disable();
+	return 1;
+}
+
+/*
+ * wfc_util_qcom_checkt_roaming_off
+ *
+ * Check L2Roaming configuration
+ *
+ * return : int (boolean)
+ */
+int wfc_util_qcom_checkt_roaming_off(void)
+{
+	char string_buff[5];
+	/*
+	 * check whether OTA test is enabled or not.
+	 */
+	if(0 < wfc_util_fget_string(WFC_UTIL_CFG_FILE_NAME,
+	                            WFC_UTIL_CFG_TAG_END_OF_CFG,
+	                            //WFC_UTIL_CFG_TAG_L2Roaming,
+	                            WFC_UTIL_CFG_TAG_POWER_SAVE,
+	                            WFC_UTIL_CFG_TAG_END_OF_LINE,
+	                            string_buff,
+	                            5)) {
+		//wfc_util_log_info("%s%s", WFC_UTIL_CFG_TAG_L2Roaming, string_buff);
+		wfc_util_log_info("%s%s", WFC_UTIL_CFG_TAG_POWER_SAVE, string_buff);
+		if(0 == strncmp(string_buff, "0", 1)) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+#endif /* CONFIG_LGE_WLAN_QCOM_PATCH */
+
diff --git a/wifi/qcom/wfc_util_qcom.h b/wifi/qcom/wfc_util_qcom.h
new file mode 100644
index 0000000..1bd4cc1
--- /dev/null
+++ b/wifi/qcom/wfc_util_qcom.h
@@ -0,0 +1,52 @@ 
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WFC_UTIL_QCOM_H__
+#define __WFC_UTIL_QCOM_H__
+
+#ifdef CONFIG_LGE_WLAN_QCOM_PATCH
+/*
+ * wfc_util_qcom_check_config
+ *
+ * check the qcom wlan driver config file
+ *
+ * return : it will return 0 if procedure is success
+ *          or will return -1 if not.
+ */
+extern int wfc_util_qcom_check_config(unsigned char *nv_mac_addr);
+
+/*
+ * wfc_util_qcom_reset_mac
+ *
+ * reset the mac address of config file
+ *
+ * return : void
+ */
+extern void wfc_util_qcom_reset_mac(void);
+
+/*
+ * wfc_util_qcom_ota_enable/disable
+ *
+ * enable OTA mode for Wi-Fi related certificiation
+ *
+ * return : int (boolean)
+ */
+extern int wfc_util_qcom_ota_enable(void);
+extern int wfc_util_qcom_ota_disable(void);
+extern int wfc_util_qcom_checkt_roaming_off(void);
+#endif /* CONFIG_LGE_WLAN_QCOM_PATCH */
+#endif
+