wigig: Adding debug tools

Adding the debug tools package for 11ad

Change-Id: I171d7534614ec8941e0b48bb01d757ccd3be8960
Signed-off-by: Vadim Iosevich <vadimi@codeaurora.org>
diff --git a/Android.mk b/Android.mk
new file mode 100755
index 0000000..416702e
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,5 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
+
diff --git a/debug-tools/Android.mk b/debug-tools/Android.mk
new file mode 100644
index 0000000..8e4e086
--- /dev/null
+++ b/debug-tools/Android.mk
@@ -0,0 +1,6 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
+
diff --git a/debug-tools/LogCollector/Android.mk b/debug-tools/LogCollector/Android.mk
new file mode 100644
index 0000000..001ac1c
--- /dev/null
+++ b/debug-tools/LogCollector/Android.mk
@@ -0,0 +1,35 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := wigig_logcollector
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPPFLAGS := -Wall -fexceptions
+
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH)/../lib/WlctPciAcss \
+	$(LOCAL_PATH)/../lib/inc \
+	$(LOCAL_PATH)/../lib/utils \
+
+LOCAL_SHARED_LIBRARIES := \
+	libwigig_utils \
+	libwigig_pciaccess \
+
+LOCAL_SRC_FILES := \
+	LogCollector.cpp
+
+include $(BUILD_EXECUTABLE)
+
+# LogCollector configuration file
+
+include $(CLEAR_VARS)
+LOCAL_MODULE       := wigig_logcollector.ini
+LOCAL_MODULE_TAGS  := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH  := $(TARGET_OUT_ETC)
+LOCAL_SRC_FILES    := linux/wigig_logcollector.ini
+include $(BUILD_PREBUILT)
+
+
diff --git a/debug-tools/LogCollector/LogCollector.cpp b/debug-tools/LogCollector/LogCollector.cpp
new file mode 100644
index 0000000..b59737f
--- /dev/null
+++ b/debug-tools/LogCollector/LogCollector.cpp
@@ -0,0 +1,826 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <stdarg.h>
+#include <ctime>
+
+#ifndef _WINDOWS	// Linux
+#include <unistd.h>
+#include <getopt.h>
+#include <err.h>
+#else				// Windows
+#include <windows.h>
+#endif  //#ifdef _WINDOWS
+
+
+
+#include "WlctPciAcss.h"
+
+using namespace std;
+
+////////// TYPE DEFINITIONS //////////
+enum TRACER_TYPE
+{
+    TRACER_TYPE_FW,
+    TRACER_TYPE_UCODE
+};
+
+enum MODULES
+{
+	SYSTEM,
+	DRIVERS,
+	MAC_MON,
+	HOST_CMD,
+	PHY_MON,
+	INFRA,
+	CALIBS,
+	TXRX,
+	RAD_MGR,
+	SCAN,
+	MLME,
+	L2_MGR,
+	DISC,
+	MGMT_SRV,
+	SECURITY,
+	PSM,
+	WBE_MNGR,
+	NUM_MODULES,
+};
+
+string module_names[NUM_MODULES] = {"SYSTEM", "DRIVERS", "MAC_MON", "HOST_CMD", "PHY_MON", "INFRA", "CALIBS", "TXRX", "RAD_MGR", "SCAN", "MLME", "L2_MGR", "DISC", "MGMT_SRV", "SECURITY", "PSM", "WBE_MNGR"};
+
+typedef uint32_t u32;
+typedef int32_t s32;
+typedef unsigned int uint;
+
+#ifdef _WINDOWS
+struct module_level_enable { /* Little Endian */
+	uint error_level_enable : 1;
+	uint warn_level_enable : 1;
+	uint info_level_enable : 1;
+	uint verbose_level_enable : 1;
+	uint reserved0 : 4;
+};
+struct log_trace_header { /* Little Endian */
+	uint strring_offset : 20;
+	uint module : 4; /* module that outputs the trace */
+	uint level : 2;
+	uint parameters_num : 2; /* [0..3] */
+	uint is_string : 1; /* indicate if the printf uses %s */
+	uint signature : 3; /* should be 5 (2'101) in valid header */
+};
+#else
+struct module_level_enable { /* Little Endian */
+	uint error_level_enable : 1;
+	uint warn_level_enable : 1;
+	uint info_level_enable : 1;
+	uint verbose_level_enable : 1;
+	uint reserved0 : 4;
+} __attribute__((packed));
+
+struct log_trace_header { /* Little Endian */
+	/* the offset of the trace string in the strings sections */
+	uint strring_offset : 20;
+	uint module : 4; /* module that outputs the trace */
+	/*	0 - Error
+		1- WARN
+		2 - INFO
+		3 - VERBOSE */
+	uint level : 2;
+	uint parameters_num : 2; /* [0..3] */
+	uint is_string : 1; /* indicate if the printf uses %s */
+	uint signature : 3; /* should be 5 (2'101) in valid header */
+} __attribute__((packed));
+#endif
+
+union log_event {
+	struct log_trace_header hdr;
+	u32 param;
+};
+
+struct log_table_header {
+	u32 write_ptr; /* incremented by trace producer every write */
+	struct module_level_enable module_level_enable[NUM_MODULES];
+	union log_event evt[0];
+};
+
+enum {
+	str_mask = 0xFFFFF,
+};
+
+////////// END - TYPE DEFINITIONS ///////
+
+/////////// CONSTANTS ///////////////////
+
+const int SECOND_IN_MILLISECONDS = 1000;
+
+// 50 MB file size
+const int MAX_FILE_FRAGMENT_SIZE = 1024 * 1024 * 50;
+
+// RGFs containing log buffer addresses
+// FW log address
+const int REG_FW_USAGE_1 = 0x880004;
+// uCode log address
+const int REG_FW_USAGE_2 = 0x880008;
+
+// Firmware version RGFs
+const int FW_VERSION_MAJOR 	= 0x880a2c;
+const int FW_VERSION_MINOR 	= 0x880a30;
+const int FW_VERSION_SUB 	= 0x880a34;
+const int FW_VERSION_BUILD 	= 0x880a38;
+
+// Firmware Compilation Time RGFs
+const int FW_COMP_TIME_HOUR 	= 0x880a14;
+const int FW_COMP_TIME_MINUTE 	= 0x880a18;
+const int FW_COMP_TIME_SECOND 	= 0x880a1c;
+const int FW_COMP_TIME_DAY 		= 0x880a20;
+const int FW_COMP_TIME_MONTH 	= 0x880a24;
+const int FW_COMP_TIME_YEAR 	= 0x880a28;
+
+// Log buffer offsets
+// FW log address offset
+const int FW_LOG_ADDRESS_OFFSET = 0xc8000;
+// uCode log address offset
+//const int UCODE_LOG_ADDRESS_OFFSET = 0;
+
+// Entries in the fw log buf
+const size_t fw_log_buf_entries = 0x1000/4;
+
+// Config file filename
+#ifdef _WINDOWS
+const char* const DEFAULT_CONFIG_FILE_NAME = "wigig_logcollector.ini";
+#else
+const char* const DEFAULT_CONFIG_FILE_NAME = "/etc/wigig_logcollector.ini";
+#endif
+
+//////////// END - CONSTANTS ////////////
+
+//////////// Global Variables ///////////
+
+// Log addresses
+int fw_log_address = 0;
+int ucode_log_address = 0;
+
+/////// Config file parameters /////////
+int pollingInterval = 100;
+string resultPath = "";
+string deviceName = "";
+string deviceType = "";
+int fileFragmentSize = MAX_FILE_FRAGMENT_SIZE;
+bool debugPrint = false;
+DType_t devType = MST_NONE;
+
+log_table_header logHeader;
+
+//// END - Config file parameters /////
+
+void* handler = NULL;
+
+DWORD fwVersionMajor;
+DWORD fwVersionMinor;
+DWORD fwVersionSub;
+DWORD fwVersionBuild;
+
+DWORD fwCompTimeHour;
+DWORD fwCompTimeMinute;
+DWORD fwCompTimeSecond;
+DWORD fwCompTimeDay;
+DWORD fwCompTimeMonth;
+DWORD fwCompTimeYear;
+
+std::string configFilePath;
+const char *mod;
+int i;
+unsigned long x;
+char *endptr;
+int help; /* = 0; */
+
+void *log_bu; /* memory allocated for the log buf */
+
+ void *str_buf;
+ size_t str_sz;
+ u32 rptr; /* = 0; */
+ u32 last_wptr; /* = 0; */
+ const char *const levels[] = {
+	"E",
+	"W",
+	"I",
+	"V",
+};
+
+const char *modules[16];
+
+//////////// END - Global Variables //////
+
+static inline size_t log_size(size_t entry_num)
+{
+	return sizeof(struct log_table_header) + entry_num * 4;
+}
+
+// OS Agnostic system time
+struct tm OSGetSystemTime()
+{
+	time_t current_time;
+	time(&current_time);
+
+	struct tm *pTimeStruct = localtime(&current_time);
+	struct tm timeStruct = {};
+    if (pTimeStruct)
+    {
+        timeStruct = *pTimeStruct;
+    }
+
+	return timeStruct;
+}
+
+// OS agnostic debug print function
+void DebugPrint(const char* error_message, ...)
+{
+	if (debugPrint == false) return;
+
+	va_list argptr;
+	va_start(argptr, error_message);
+
+	vfprintf(stderr, error_message, argptr);
+
+	va_end(argptr);
+}
+
+void DisplayHelp()
+{
+		static char *help_str = (char*)("Usage: LogCollector [OPTION]...\n"
+								"Extract trace log from firmware\n"
+								"\n"
+								"Mandatory arguments to long options are mandatory for short options too.\n"
+								" The following switches are mandatory:\n"
+								"  -m, --memdump=FILE		File to read memory dump from\n"
+								"  -l, --logsize=NUMBER		Log buffer size, entries\n");
+		printf("%s", help_str);
+		exit(1);
+}
+
+// OS agnostic sleep function
+void OSSleep(int sleep_period)
+{
+#ifdef _WINDOWS
+	Sleep(sleep_period);
+#else
+	usleep(sleep_period * SECOND_IN_MILLISECONDS);
+#endif
+}
+
+// OS agnostic error print function
+void OSError(const char* error_message, ...)
+{
+	va_list argptr;
+    va_start(argptr, error_message);
+
+#ifdef _WINDOWS
+	vfprintf(stderr, error_message, argptr);
+
+	exit(0);
+#else
+	vfprintf(stderr, error_message, argptr);
+
+	exit(0);
+#endif
+
+	va_end(argptr);
+}
+
+void ParseModuelLevel(string moduleString)
+{
+	for (int i = 0; i < NUM_MODULES; i++)
+	{
+		if (moduleString.find(module_names[i]) == 0)
+		{
+			// + 1 for '='
+			string levels = moduleString.substr(module_names[i].size() + 1);
+
+			if (levels.find("V") != string::npos)
+			{
+				logHeader.module_level_enable[i].verbose_level_enable = 1;
+			}
+			if (levels.find("I") != string::npos)
+			{
+				logHeader.module_level_enable[i].info_level_enable = 1;
+			}
+			if (levels.find("E") != string::npos)
+			{
+				logHeader.module_level_enable[i].error_level_enable = 1;
+			}
+			if (levels.find("W") != string::npos)
+			{
+				logHeader.module_level_enable[i].warn_level_enable = 1;
+			}
+		}
+	}
+}
+
+// OS agnostic get arguments function
+void ParseConfigLine(string line)
+{
+	const char* device_name = "device_name=";
+	const char* device_type = "device_type=";
+	const char* polling_interval = "polling_interval=";
+	const char* result_path = "result_path=";
+	const char* module_level_prefix = "MODULE_LEVEL_";
+	const char* debug_print = "debug_print=";
+	const char* log_fragment_size = "log_fragment_size=";
+
+	DebugPrint("configuration line = %s\n", line.c_str());
+
+	// Skip comments
+	if (line.find("//") == 0)
+	{
+		return;
+	}
+
+	try
+	{
+		if (line.find(debug_print) == 0)
+		{
+			debugPrint = (line.substr(strlen(debug_print)).find("TRUE") == 0);
+			DebugPrint("Debug Prints Enabled\n");
+		}
+		else if (line.find(log_fragment_size) == 0)
+		{
+			fileFragmentSize = atoi(line.substr(strlen(log_fragment_size)).c_str()) * 1024 * 1024;
+			DebugPrint("File fragment size is %d MB\n", atoi(line.substr(strlen(log_fragment_size)).c_str()));
+		}
+		else if (line.find(device_name) == 0)
+		{
+			deviceName = line.substr(strlen(device_name));
+			DebugPrint("Device Name Requested: %s\n", deviceName.c_str());
+		}
+		else if (line.find(polling_interval) == 0)
+		{
+			pollingInterval = atoi(line.substr(strlen(polling_interval)).c_str());
+			DebugPrint("Polling Interval Is:%d\n", pollingInterval);
+		}
+		else if (line.find(result_path) == 0)
+		{
+			resultPath = line.substr(strlen(result_path));
+			DebugPrint("Result path = %s\n", resultPath.c_str());
+		}
+		else if (line.find(module_level_prefix) == 0)
+		{
+			ParseModuelLevel(line.substr(strlen(module_level_prefix)));
+		}
+		else if (line.find(device_type) == 0)
+		{
+			deviceType = line.substr(strlen(device_type));
+
+			DebugPrint("Device Type = %s\n", deviceType.c_str());
+
+			if (deviceType.find("MARLON") == 0)
+			{
+				DebugPrint("Device selected MARLON=%d\n", MST_MARLON);
+				devType = MST_MARLON;
+			}
+			else if (deviceType.find("SPARROW") == 0)
+			{
+				DebugPrint("Device selected SPARROW=%d\n", MST_SPARROW);
+				devType = MST_SPARROW;
+			}
+			else if (deviceType.find("TALYN") == 0)
+			{
+				DebugPrint("Device selected TALYN=%d\n", MST_LAST);
+				devType = MST_LAST;
+			}
+			else
+			{
+				DebugPrint("Device selected NONE=%d\n", MST_NONE);
+				devType = MST_NONE;
+			}
+
+		}
+		else
+		{
+		}
+	}
+	catch (int)
+	{
+		OSError("Error: Failed to parse Config File");
+	}
+}
+
+// Open device interface
+static void OpenDevice()
+{
+	INTERFACE_LIST interfaces;
+	int num_items;
+	int res;
+	res = GetInterfaces(&interfaces, &num_items);
+
+	if (res != 0 || num_items == 0)
+	{
+		OSError("Error: retrieving interfaces");
+	}
+
+	string currentDeviceName;
+
+	// No specific device was requested or only one device is available
+	// Select first device in device list
+	bool deviceFound = false;
+
+	if (deviceName.compare("") == 0 || num_items == 1)
+	{
+		cout << "Selecting device: " << interfaces.list[0].ifName << "\n";
+		currentDeviceName = interfaces.list[0].ifName;
+	}
+	else
+	{
+		// Iterate through all found devices to find the one in config file
+		for (int i = 0 ; i < MAX_INTERFACES; i ++)
+		{
+			currentDeviceName = interfaces.list[i].ifName;
+
+			if (deviceName.compare(currentDeviceName) == 0)
+			{
+				// We have found the device we are looking for
+				cout << "Found device: " << currentDeviceName.c_str() << "\n";
+				deviceFound = true;
+				break;
+			}
+		}
+
+		if (!deviceFound)
+		{
+			OSError("A device named: %s, was not found", deviceName.c_str());
+		}
+	}
+
+	DebugPrint ("Opening Device: %s\n", currentDeviceName.c_str());
+
+	// Create a handler to the device
+	DWORD err = CreateDeviceAccessHandler(currentDeviceName.c_str(), devType, &handler);
+	if (!(err == 0 && isInit(handler)))
+	{
+		OSError("Failed to open device: %s, Error code: %d\n", currentDeviceName.c_str(), err);
+	}
+}
+
+// Get log address
+static int GetLogAddress(TRACER_TYPE type)
+{
+	DWORD val;
+	DWORD addr = REG_FW_USAGE_1;
+
+	if (type == TRACER_TYPE_UCODE)
+	{
+		addr = REG_FW_USAGE_2;
+	}
+	else if (type == TRACER_TYPE_FW)
+	{
+		addr = REG_FW_USAGE_1;
+	}
+	else
+	{
+		OSError("Invalid log tracer type - using FW as default");
+	}
+
+
+	// Read log offset
+	WlctAccssRead(handler, addr, val);
+
+	if (val == 0)
+	{
+		OSError("Invalid log buffer pointer address");
+	}
+
+	return val;
+}
+
+// OS agnostic read log function
+static bool OSReadLog(void *buf, size_t size)
+{
+	// Check if the device is open
+	if ((NULL == handler) || (!isInit(handler)))
+	{
+		OSError("Device not opened when trying the read log");
+	}
+
+	// Update FW & uCode log addresses
+	if (!fw_log_address) fw_log_address = GetLogAddress(TRACER_TYPE_FW) + FW_LOG_ADDRESS_OFFSET;
+	//if (!ucode_log_address) ucode_log_address = GetLogAddress(TRACER_TYPE_UCODE);
+
+	// Read the actual log
+	if(0 != readBlock(handler, fw_log_address, size, (char*)buf))
+	{
+		return false;
+		// OSError("Failed to read log buffer");
+	}
+	return true;
+}
+
+// OS agnostic read configuration file function
+static void OSReadConfigFile()
+{
+	try
+	{
+            ifstream file(configFilePath.c_str());
+
+		if(!file || !file.good())
+		{
+                    OSError("Error: failed to read config file: %s. %s \n", configFilePath.c_str(), strerror(errno));
+		}
+
+		string line;
+		while(std::getline(file, line))
+		{
+			ParseConfigLine(line);
+		}
+	}
+	catch (int i)
+	{
+            OSError("Exception while trying to open config file: %s\n", configFilePath.c_str());
+	}
+}
+
+ void AddTimestamp(ofstream& outputFile)
+{
+	struct tm now = OSGetSystemTime();
+
+	std::ostringstream timeStampBuilder;
+
+	timeStampBuilder << "<Log_Content>"
+		<< "<Sample_Time>"
+		<< "<Hour>" << now.tm_hour << "</Hour>"
+		<< "<Minute>" << now.tm_min << "</Minute>"
+		<< "<Second>" << now.tm_sec << "</Second>"
+		<< "<Day>" << now.tm_mday << "</Day>"
+		<< "<Month>" << now.tm_mon + 1 << "</Month>"
+		<< "<Year>" << now.tm_year + 1900 << "</Year>"
+		<< "</Sample_Time>";
+
+	outputFile << timeStampBuilder.str();
+}
+
+static int ParseLog(void* log_buf, size_t log_buf_entries, ofstream& outputFile)
+{
+//	DebugPrint("Parsing log\n");
+
+	int sizeAdded = 0;
+
+	// Prepare a header pointing to log buffer top
+	struct log_table_header *h = (struct log_table_header*)log_buf;
+
+	u32 wptr = h->write_ptr;
+
+	if ((wptr - rptr) <= 0)
+	{
+		// Nothing to read.
+		return 0;
+	}
+
+	if ((wptr - rptr) >= log_buf_entries)
+	{
+		// overflow; try to parse last wrap
+		rptr = wptr - log_buf_entries;
+	}
+	DebugPrint("  wptr = %d rptr = %d\n", wptr, rptr);
+
+	AddTimestamp(outputFile);
+	outputFile << "<Content>";
+
+	for (; ((s32)(wptr - rptr) > 0) && (wptr != last_wptr); rptr++)
+	{
+		DebugPrint("wptr = %d, rptr = %d\n", wptr, rptr);
+
+		int i;
+		u32 p[3] = {0};
+		union log_event *evt = &h->evt[rptr % log_buf_entries];
+
+		if (evt->hdr.signature != 5)
+		{
+			continue;
+		}
+		if (evt->hdr.strring_offset > str_sz)
+		{
+//			continue;
+		}
+		if (evt->hdr.parameters_num > 3)
+		{
+			DebugPrint("Parameter Num = %d", evt->hdr.parameters_num);
+			continue;
+		}
+		for (i = 0; i < evt->hdr.parameters_num; i++)
+			p[i] = h->evt[(rptr + i + 1) % log_buf_entries].param;
+		/*DebugPrint("%d,%s,%d:", evt->hdr.module,
+					levels[evt->hdr.level],
+					evt->hdr.strring_offset);
+
+		DebugPrint("%d,%d,%d\n",
+			(p[0]),
+			(p[1]),
+			(p[2]));*/
+
+		outputFile << evt->hdr.module << "," << levels[evt->hdr.level] << "," << evt->hdr.strring_offset << ":" << p[0] << "," << p[1] << "," << p[2] << "\n";
+
+		// (paramters) (verbosity type) (delimiters)
+		sizeAdded += (5 * sizeof(int)) + (1 * sizeof(char)) + (4 * sizeof(char));
+
+		rptr += evt->hdr.parameters_num;
+	}
+
+	last_wptr = wptr;
+
+	outputFile << "</Content></Log_Content>";
+
+	fflush(stdout);
+	return sizeAdded;
+}
+
+void SetModuleVerbosity()
+{
+	// Check if the device is open
+	if ((NULL == handler) || (!isInit(handler)))
+	{
+		OSError("Device not opened when trying to set module verbosity");
+	}
+
+	// Update FW & uCode log addresses
+	if (!fw_log_address) fw_log_address = GetLogAddress(TRACER_TYPE_FW) + FW_LOG_ADDRESS_OFFSET;
+	//if (!ucode_log_address) ucode_log_address = GetLogAddress(TRACER_TYPE_UCODE);
+
+	DebugPrint("fw log address = %d\n", fw_log_address);
+
+	// Write verbosity to the device
+	if(-1 == writeBlock(handler, fw_log_address + sizeof(logHeader.write_ptr), sizeof(logHeader.module_level_enable), (char*)logHeader.module_level_enable))
+	{
+		OSError("Failed to write module verbosity structure");
+	}
+}
+
+void ReadDeviceInfo()
+{
+	// Check if the device is open
+	if ((NULL == handler) || (!isInit(handler)))
+	{
+		OSError("Device not opened when trying to read device info");
+	}
+
+	// Read FW Version
+	WlctAccssRead(handler, FW_VERSION_MAJOR, fwVersionMajor);
+	WlctAccssRead(handler, FW_VERSION_MINOR, fwVersionMinor);
+	WlctAccssRead(handler, FW_VERSION_SUB, fwVersionSub);
+	WlctAccssRead(handler, FW_VERSION_BUILD, fwVersionBuild);
+
+	// Read compilation Time
+	WlctAccssRead(handler, FW_COMP_TIME_HOUR, fwCompTimeHour);
+	WlctAccssRead(handler, FW_COMP_TIME_MINUTE, fwCompTimeMinute);
+	WlctAccssRead(handler, FW_COMP_TIME_SECOND, fwCompTimeSecond);
+	WlctAccssRead(handler, FW_COMP_TIME_DAY, fwCompTimeDay);
+	WlctAccssRead(handler, FW_COMP_TIME_MONTH, fwCompTimeMonth);
+	WlctAccssRead(handler, FW_COMP_TIME_YEAR, fwCompTimeYear);
+}
+
+void* AllocateBuffer()
+{
+	void* log_buf = malloc(log_size(fw_log_buf_entries));
+	if (!log_buf)
+	{
+		OSError("Error: Unable to allocate log buffer %zd bytes", log_size(fw_log_buf_entries));
+	}
+
+	return log_buf;
+}
+
+bool CreateNewOutputFile(string path, ofstream& outputFile)
+{
+	std::ostringstream fileNameBuilder;
+	fileNameBuilder << path << "logFile_" << time(0);
+
+	DebugPrint("Path: %s\n", path.c_str());
+	DebugPrint("Creating output file: %s\n", fileNameBuilder.str().c_str());
+
+	outputFile.open(fileNameBuilder.str().c_str());
+
+	if (outputFile.fail())
+	{
+		printf("Error opening output file: %s\n", fileNameBuilder.str().c_str());
+		return false;
+	}
+
+	std::ostringstream headerBuilder;
+
+	headerBuilder << "<LogFile>"
+		<< "<FW_Ver>"
+		<< "<Major>" << fwVersionMajor << "</Major>"
+		<< "<Minor>" << fwVersionMinor <<"</Minor>"
+		<< "<Sub>" << fwVersionSub << "</Sub>"
+		<< "<Build>" << fwVersionBuild << "</Build>"
+		<< "</FW_Ver>"
+		<< "<Compilation_Time>"
+		<< "<Hour>" << fwCompTimeHour << "</Hour>"
+		<< "<Minute>" << fwCompTimeMinute << "</Minute>"
+		<< "<Second>" << fwCompTimeSecond << "</Second>"
+		<< "<Day>" << fwCompTimeDay << "</Day>"
+		<< "<Month>" << fwCompTimeMonth << "</Month>"
+		<< "<Year>" << fwCompTimeYear << "</Year>"
+		<< "</Compilation_Time>"
+		<< "<Logs>";
+
+	outputFile << headerBuilder.str();
+	return true;
+}
+
+void CloseOutputFile(ofstream& outputFile)
+{
+	outputFile << "</Logs></LogFile>";
+	outputFile.close();
+	DebugPrint("Output file closed\n");
+}
+
+int main(int argc, char *argv[])
+{
+    configFilePath = DEFAULT_CONFIG_FILE_NAME;
+	if (argc == 2)
+	{
+            configFilePath = argv[1];
+	}
+
+	// Read configuration file
+	OSReadConfigFile();
+
+	if (false) // TODO decide when to show help
+	{
+		help = 1;
+	}
+
+	if (help)
+	{
+		DisplayHelp();
+	}
+
+	OpenDevice();
+
+	ReadDeviceInfo();
+
+	SetModuleVerbosity();
+
+	// Allocate log buffer
+	void* log_buf = AllocateBuffer();
+
+	long currentFileSize = 0;
+
+	ofstream outputFile;
+
+	bool status = CreateNewOutputFile(resultPath, outputFile);
+	if (!status) return 1;
+
+	while (true)
+	{
+		if (currentFileSize > fileFragmentSize)
+		{
+			currentFileSize = 0;
+			CloseOutputFile(outputFile);
+			status = CreateNewOutputFile(resultPath, outputFile);
+			if (!status) return 1;
+		}
+
+		// Read the log
+		if (!OSReadLog(log_buf, log_size(fw_log_buf_entries)))
+		{
+			OSSleep(pollingInterval);
+			continue;
+		}
+
+		currentFileSize += ParseLog(log_buf, fw_log_buf_entries, outputFile);
+		DebugPrint("Current File Size = %d\n", currentFileSize);
+
+		OSSleep(pollingInterval);
+	}
+
+	return 0;
+}
diff --git a/debug-tools/LogCollector/Makefile b/debug-tools/LogCollector/Makefile
new file mode 100644
index 0000000..88d91ed
--- /dev/null
+++ b/debug-tools/LogCollector/Makefile
@@ -0,0 +1,45 @@
+-include $(TOPDIR)/rules.mk
+
+CFLAGS := -fPIE -Wall -g -MMD
+LDFLAGS := -pie -fPIE -pthread -lwigig_pciaccess -lwigig_utils
+
+ifneq ($(CONFIG_TARGET_ipq)$(CONFIG_TARGET_ipq806x),)
+is_ipq806x = 1
+endif
+
+ifeq ($(is_ipq806x), 1)
+ifneq ($(strip $(TOOLPREFIX)),)
+CROSS:=$(TOOLPREFIX)
+endif
+endif
+
+CC = $(CROSS)gcc
+CXX = $(CROSS)g++
+
+.DEFAULT_GOAL = all
+PROG = wigig_logcollector
+
+INCLUDES = -I ../lib/WlctPciAcss \
+           -I ../lib/inc \
+           -I ../lib/utils \
+
+LIBS = -L../lib/WlctPciAcss \
+       -L../lib/utils \
+
+CPP_FILES = $(shell find . -type f -name '*.cpp')
+OBJ_FILES = $(CPP_FILES:.cpp=.o)
+
+all: $(PROG)
+
+$(PROG): $(OBJ_FILES)
+	$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)
+
+%.o : %.cpp
+	$(CXX) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+
+clean:
+	rm -rf $(PROG)
+	find . -type f \( -name "*.d" -o -name "*.o" \) -delete
+
+-include $(OBJ_FILES:%.o=%.d)
diff --git a/debug-tools/LogCollector/linux/wigig_logcollector.ini b/debug-tools/LogCollector/linux/wigig_logcollector.ini
new file mode 100644
index 0000000..0ad18b4
--- /dev/null
+++ b/debug-tools/LogCollector/linux/wigig_logcollector.ini
@@ -0,0 +1,28 @@
+debug_print=FALSE
+device_name=
+device_type=SPARROW
+polling_interval=100
+log_fragment_size=10
+result_path=/tmp/
+
+// Log Module Levels
+// V - Verbose, I - Info, E - Error, W - Warning
+// For example: MODULE_LEVEL_SYSTEM=VIE
+// Or: MODULE_LEVEL_DRIVERS=WIV
+MODULE_LEVEL_SYSTEM=VIEW
+MODULE_LEVEL_DRIVERS=VIEW
+MODULE_LEVEL_MAC_MON=VIEW
+MODULE_LEVEL_HOST_CMD=VIEW
+MODULE_LEVEL_PHY_MON=VIEW
+MODULE_LEVEL_INFRA=VIEW
+MODULE_LEVEL_CALIBS=VIEW
+MODULE_LEVEL_TXRX=VIEW
+MODULE_LEVEL_RAD_MGR=VIEW
+MODULE_LEVEL_SCAN=VIEW
+MODULE_LEVEL_MLME=VIEW
+MODULE_LEVEL_L2_MGR=VIEW
+MODULE_LEVEL_DISC=VIEW
+MODULE_LEVEL_MGMT_SRV=VIEW
+MODULE_LEVEL_SECURITY=VIEW
+MODULE_LEVEL_PSM=VIEW
+MODULE_LEVEL_WBE_MNGR=VIEW
diff --git a/debug-tools/Makefile b/debug-tools/Makefile
new file mode 100644
index 0000000..e82e937
--- /dev/null
+++ b/debug-tools/Makefile
@@ -0,0 +1,37 @@
+.DEFAULT_GOAL = all
+
+.PHONY = all install uninstall clean
+
+all: make_host_manager_11ad make_remoteserver make_logcollector make_wiburn make_wlctutils make_wlctpciacss make_flashacss
+
+make_host_manager_11ad:
+	$(MAKE) -C host_manager_11ad CROSS=$(CROSS)
+
+make_remoteserver: make_wlctutils make_wlctpciacss
+	$(MAKE) -C remoteserver CROSS=$(CROSS)
+
+make_logcollector: make_wlctutils make_wlctpciacss
+	$(MAKE) -C LogCollector CROSS=$(CROSS)
+
+make_wiburn: make_wlctutils make_wlctpciacss make_flashacss
+	$(MAKE) -C wiburn CROSS=$(CROSS)
+
+make_wlctutils:
+	$(MAKE) -C lib/utils CROSS=$(CROSS)
+
+make_wlctpciacss:
+	$(MAKE) -C lib/WlctPciAcss CROSS=$(CROSS)
+
+make_flashacss:
+	$(MAKE) -C lib/FlashAcss CROSS=$(CROSS)
+
+clean:
+	echo "Cleaning up wigig debug tools"
+	$(MAKE) -C host_manager_11ad clean
+	$(MAKE) -C remoteserver clean
+	$(MAKE) -C LogCollector clean
+	$(MAKE) -C wiburn clean
+	$(MAKE) -C lib/utils clean
+	$(MAKE) -C lib/WlctPciAcss clean
+	$(MAKE) -C lib/FlashAcss clean
+
diff --git a/debug-tools/host_manager_11ad/Android.mk b/debug-tools/host_manager_11ad/Android.mk
new file mode 100644
index 0000000..8a96497
--- /dev/null
+++ b/debug-tools/host_manager_11ad/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := host_manager_11ad
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPPFLAGS := -Wall -lpthread -fexceptions
+
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH)/access_layer_11ad \
+	$(LOCAL_PATH)/access_layer_11ad/Unix \
+
+LOCAL_SRC_FILES := $(shell find $(LOCAL_PATH) -name '*.cpp' | sed s:^$(LOCAL_PATH)::g )
+
+include $(BUILD_EXECUTABLE)
diff --git a/debug-tools/host_manager_11ad/ArgumentsParser.cpp b/debug-tools/host_manager_11ad/ArgumentsParser.cpp
new file mode 100644
index 0000000..49e6fbf
--- /dev/null
+++ b/debug-tools/host_manager_11ad/ArgumentsParser.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+
+#include "ArgumentsParser.h"
+
+#include <cstdio>
+#include <vector>
+#include <string>
+#include <algorithm>
+
+#define HOST_MANAGER_VERSION 0x0100
+
+using namespace std;
+// *************************************************************************************************
+
+int ArgumentsParser::ParseAndHandleArguments(int argc, char * argv[], unsigned int &commandsTcpPort)
+{
+
+    //do something with params
+    (void)commandsTcpPort;
+
+    for (int i = 0; i < argc; i++)
+    {
+        m_arguments.push_back(string(argv[i]));
+    }
+    if (DoesArgumentExist("-v"))
+    { //Argument for the version of host_manager_11ad
+        printf("Host Manager 11ad v%d.%d\n", HOST_MANAGER_VERSION >> 8, HOST_MANAGER_VERSION & 0xff);
+    }
+    if (DoesArgumentExist("-p"))
+    { //Argument for setting the port of the commands TCP port
+
+    }
+
+    unsigned val;
+    if (GetArgumentValue("-d", val))
+    { //Argument for setting verbosity level
+        g_LogConfig.SetMaxSeverity(val);
+    }
+
+    return 0;
+}
+
+bool ArgumentsParser::DoesArgumentExist(string option)
+{
+    bool doesArgumentExist = find(m_arguments.begin(), m_arguments.end(), option) != m_arguments.end();
+    return doesArgumentExist;
+}
+
+bool ArgumentsParser::GetArgumentValue(string option, unsigned& val)
+{
+    auto argumentIter = find(m_arguments.begin(), m_arguments.end(), option);
+    if (argumentIter != m_arguments.end())
+    {
+        auto valueIter = ++argumentIter;
+        if (valueIter != m_arguments.end())
+        {
+            string valStr = *valueIter;
+            try
+            {
+                val = strtoul(valStr.c_str(), NULL, 10);
+                return true;
+            }
+            catch (...)
+            {
+                printf("Error in setting verbosity level\n");
+            }
+        }
+    }
+    return false;
+}
diff --git a/debug-tools/host_manager_11ad/ArgumentsParser.h b/debug-tools/host_manager_11ad/ArgumentsParser.h
new file mode 100644
index 0000000..a9caa0f
--- /dev/null
+++ b/debug-tools/host_manager_11ad/ArgumentsParser.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _ARGUMENTSPARSER_H_
+#define _ARGUMENTSPARSER_H_
+
+#include "DebugLogger.h"
+
+#include <string>
+#include <vector>
+
+using namespace std;
+
+// *************************************************************************************************
+/*
+ * Class for parsing the arguments given in the command line
+ */
+class ArgumentsParser
+{
+public:
+    int ParseAndHandleArguments(int argc, char* argv[], unsigned int &commandsTcpPort);
+
+private:
+    vector<string> m_arguments; //Vector that holds each one of the arguments that was given in the command line
+	bool DoesArgumentExist(string option);
+	bool GetArgumentValue(string option, unsigned& val); // returns true iff the argument exists in the srguments list and its value was extracted correctly
+};
+
+#endif // !_ARGUMENTSPARSER_H_
diff --git a/debug-tools/host_manager_11ad/CommandsHandler.cpp b/debug-tools/host_manager_11ad/CommandsHandler.cpp
new file mode 100644
index 0000000..e02617b
--- /dev/null
+++ b/debug-tools/host_manager_11ad/CommandsHandler.cpp
@@ -0,0 +1,742 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "CommandsHandler.h"
+#include "Host.h"
+#include <sstream>
+#include <string>
+#include "HostDefinitions.h"
+#include "pmc_file.h"
+#include "FileReader.h"
+
+string CommandsHandler::DecorateResponseMessage(bool successStatus, string message)
+{
+    string status = successStatus ? "Success" : "Fail";
+    string decoratedResponse = Utils::GetCurrentLocalTime() + m_reply_feilds_delimiter + status;
+    if (message != "")
+    {
+        decoratedResponse += m_reply_feilds_delimiter + message;
+    }
+    return decoratedResponse;
+}
+
+// **************************************TCP commands handlers*********************************************************** //
+ResponseMessage CommandsHandler::GetInterfaces(vector<string> arguments, unsigned int numberOfArguments)
+{
+    //do something with params
+    (void)arguments;
+
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 0, response.message))
+    {
+        set<string> devices;
+        DeviceManagerOperationStatus status = m_host.GetDeviceManager().GetDevices(devices);
+
+        if (dmosSuccess != status)
+        {
+            LOG_ERROR << "Error while trying to get interfaces. Error: " + m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+            response.message = (dmosNoSuchConnectedDevice == status)? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+        }
+        else
+        {
+            // create one string that contains all connected devices
+            stringstream devicesSs;
+            bool firstTime = true;
+            for (auto device : devices)
+            {
+                if (firstTime)
+                {
+                    devicesSs << device;
+                    firstTime = false;
+                    continue;
+                }
+                devicesSs << m_device_delimiter << device;
+            }
+            response.message = DecorateResponseMessage(true, devicesSs.str());
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::OpenInterface(vector<string> arguments, unsigned int numberOfArguments)
+{
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 1, response.message))
+    {
+        DeviceManagerOperationStatus status = m_host.GetDeviceManager().OpenInterface(arguments[0]);
+
+        if (dmosSuccess != status)
+        {
+            LOG_ERROR << "Error while trying to open interface " + arguments[0] + ". Error: " + m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+            response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+        }
+        else
+        {
+            response.message = DecorateResponseMessage(true, arguments[0]); // backward compatibility
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::CloseInterface(vector<string> arguments, unsigned int numberOfArguments)
+{
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 1, response.message))
+    {
+        DeviceManagerOperationStatus status = m_host.GetDeviceManager().CloseInterface(arguments[0]);
+
+        if (dmosSuccess != status)
+        {
+            LOG_ERROR << "Error while trying to close interface " + arguments[0] + ". Error: " + m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+            response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+        }
+        else
+        {
+            response.message = DecorateResponseMessage(true); // backward compatibility
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::Read(vector<string> arguments, unsigned int numberOfArguments)
+{
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 2, response.message))
+    {
+        DWORD address;
+        if (!Utils::ConvertHexStringToDword(arguments[1], address))
+        {
+            LOG_WARNING << "Error in Read arguments: given address isn't starting with 0x" << endl;
+            response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsInvalidArgument));
+        }
+        else
+        {
+            DWORD value;
+            DeviceManagerOperationStatus status = m_host.GetDeviceManager().Read(arguments[0], address, value);
+            if (dmosSuccess != status)
+            {
+                LOG_ERROR << "Error while trying to read address " + arguments[1] + " from " + arguments[0] + ". Error: " + m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+                response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                    DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+            }
+            else
+            {
+                stringstream message;
+                message << "0x" << hex << value;
+                response.message = DecorateResponseMessage(true, message.str());
+            }
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::Write(vector<string> arguments, unsigned int numberOfArguments)
+{
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 3, response.message))
+    {
+        DWORD address, value;
+        if (!Utils::ConvertHexStringToDword(arguments[1], address) || !Utils::ConvertHexStringToDword(arguments[2], value))
+        {
+            response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsInvalidArgument));
+        }
+        else
+        {
+            DeviceManagerOperationStatus status = m_host.GetDeviceManager().Write(arguments[0], address, value);
+            if (dmosSuccess != status)
+            {
+                LOG_ERROR << "Error while trying to write value " + arguments[2] +" to " + arguments[1] + " on " + arguments[0] + ". Error: " + m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+                response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                    DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+            }
+            else
+            {
+                response.message = DecorateResponseMessage(true);
+            }
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::ReadBlock(vector<string> arguments, unsigned int numberOfArguments)
+{
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 3, response.message))
+    {
+        DWORD address, blockSize;
+        if (!Utils::ConvertHexStringToDword(arguments[1], address) || !Utils::ConvertHexStringToDword(arguments[2], blockSize))
+        {
+            response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsInvalidArgument));
+        }
+        else
+        {
+            vector<DWORD> values;
+            DeviceManagerOperationStatus status = m_host.GetDeviceManager().ReadBlock(arguments[0], address, blockSize, values);
+            if (dmosSuccess != status)
+            {
+                LOG_ERROR << "Error while trying to read " + arguments[2] + " addresses starting at address " + arguments[1] + " from " + arguments[0] + ". Error: " + m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+                response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                    DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+            }
+            else
+            {
+                stringstream responseSs;
+                auto it = values.begin();
+                if (it != values.end())
+                {
+                    responseSs << "0x" << hex << *it;
+                    ++it;
+                }
+                for (; it != values.end(); ++it)
+                {
+                    responseSs << m_array_delimiter << "0x" << hex << *it;
+                }
+                response.message = DecorateResponseMessage(true, responseSs.str());
+            }
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::WriteBlock(vector<string> arguments, unsigned int numberOfArguments)
+{
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 3, response.message))
+    {
+        DWORD address;
+        vector<DWORD> values;
+        if (!Utils::ConvertHexStringToDword(arguments[1], address) || !Utils::ConvertHexStringToDwordVector(arguments[2], m_array_delimiter, values))
+        {
+            response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsInvalidArgument));
+        }
+        else
+        {
+            // perform write block
+            DeviceManagerOperationStatus status = m_host.GetDeviceManager().WriteBlock(arguments[0], address, values);
+            if (dmosSuccess != status)
+            {
+                LOG_ERROR << "Error in write blocks. arguments are:\nDevice name - " + arguments[0] + "\nStart address - " + arguments[1] +
+                    "\nValues - " + arguments[2];
+                response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                    DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+            }
+            else
+            {
+                response.message = DecorateResponseMessage(true);
+            }
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::InterfaceReset(vector<string> arguments, unsigned int numberOfArguments)
+{
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 1, response.message))
+    {
+        DeviceManagerOperationStatus status = m_host.GetDeviceManager().InterfaceReset(arguments[0]);
+        if (dmosSuccess != status)
+        {
+            LOG_ERROR << "Failed to perform interface reset on " + arguments[0] + ". Error: " + m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+            response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+        }
+        else
+        {
+            response.message = DecorateResponseMessage(true);
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::SwReset(vector<string> arguments, unsigned int numberOfArguments)
+{
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 1, response.message))
+    {
+        DeviceManagerOperationStatus status = m_host.GetDeviceManager().SwReset(arguments[0]);
+        if (dmosSuccess != status)
+        {
+            LOG_ERROR << "Failed to perform sw reset on " + arguments[0] + ". Error: " + m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+            response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+        }
+        else
+        {
+            response.message = DecorateResponseMessage(true);
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::AllocPmc(vector<string> arguments, unsigned int numberOfArguments)
+{
+    //do something with params
+    (void)numberOfArguments;
+    LOG_VERBOSE << __FUNCTION__;
+    for (auto& s : arguments)
+    {
+        LOG_VERBOSE << "," << s;
+    }
+    LOG_VERBOSE << endl;
+
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, arguments.size(), 3, response.message))
+    {
+        unsigned descSize;
+        unsigned descNum;
+        if (!Utils::ConvertDecimalStringToUnsignedInt(arguments[1], descSize) || !Utils::ConvertDecimalStringToUnsignedInt(arguments[2], descNum))
+        {
+            stringstream error;
+            response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsInvalidArgument));
+        }
+        else
+        {
+            DeviceManagerOperationStatus status = m_host.GetDeviceManager().AllocPmc(arguments[0], descSize, descNum);
+            if (dmosSuccess != status)
+            {
+                stringstream error;
+                LOG_ERROR << __FUNCTION__ << ":" << m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+                response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                    DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+            }
+            else
+            {
+                response.message = DecorateResponseMessage(true);
+            }
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::DeallocPmc(vector<string> arguments, unsigned int numberOfArguments)
+{
+    //do something with params
+    (void)numberOfArguments;
+    LOG_VERBOSE << __FUNCTION__;
+    for (auto& s : arguments)
+    {
+        LOG_VERBOSE << "," << s;
+    }
+    LOG_VERBOSE << endl;
+
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, arguments.size(), 1, response.message))
+    {
+        DeviceManagerOperationStatus status = m_host.GetDeviceManager().DeallocPmc(arguments[0]);
+        if (dmosSuccess != status)
+        {
+            stringstream error;
+            LOG_ERROR << __FUNCTION__ << ":" << m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+            response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+        }
+        else
+        {
+            response.message = DecorateResponseMessage(true);
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::CreatePmcFile(vector<string> arguments, unsigned int numberOfArguments)
+{
+    //do something with params
+    (void)numberOfArguments;
+    LOG_VERBOSE << __FUNCTION__;
+    for (auto& s : arguments)
+    {
+        LOG_VERBOSE << "," << s;
+    }
+    LOG_VERBOSE << endl;
+
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, arguments.size(), 2, response.message))
+    {
+        unsigned refNumber;
+        if (!Utils::ConvertDecimalStringToUnsignedInt(arguments[1], refNumber))
+        {
+            response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsInvalidArgument));
+        }
+        else
+        {
+            DeviceManagerOperationStatus status = m_host.GetDeviceManager().CreatePmcFile(arguments[0], refNumber);
+            if (dmosSuccess != status)
+            {
+                stringstream error;
+                LOG_ERROR << __FUNCTION__ << ":" << m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+                response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                    DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+            }
+            else
+            {
+                response.message = DecorateResponseMessage(true);
+            }
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::ReadPmcFile(vector<string> arguments, unsigned int numberOfArguments)
+{
+    //do something with params
+    (void)numberOfArguments;
+    LOG_VERBOSE << __FUNCTION__;
+    for (auto& s : arguments)
+    {
+        LOG_VERBOSE << "," << s;
+    }
+    LOG_VERBOSE << endl;
+
+    ResponseMessage response;
+    response.type = REPLY_TYPE_BUFFER;
+
+#ifdef _WINDOWS
+    response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsLinuxSupportOnly));
+#else
+    if (ValidArgumentsNumber(__FUNCTION__, arguments.size(), 1, response.message))
+    {
+        unsigned refNumber;
+        if (!Utils::ConvertDecimalStringToUnsignedInt(arguments[0], refNumber))
+        {
+            response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsInvalidArgument));
+        }
+        else
+        {
+            LOG_DEBUG << "Reading PMC File #" << refNumber << endl;
+            PmcFile pmcFile(refNumber);
+
+            if (NULL == pmcFile.GetFileName())
+            {
+                response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+            }
+            else
+            {
+                // Note: Nthe file name won't be sent to a clientls
+                response.message = pmcFile.GetFileName();
+                response.type = REPLY_TYPE_FILE;
+            }
+        }
+    }
+#endif // _WINDOWS
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::SendWmi(vector<string> arguments, unsigned int numberOfArguments)
+{
+    //do something with params
+    (void)numberOfArguments;
+    LOG_VERBOSE << __FUNCTION__;
+    for (auto& s : arguments)
+    {
+        LOG_VERBOSE << "," << s;
+    }
+    LOG_VERBOSE << endl;
+
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, arguments.size(), 3, response.message))
+    {
+        DWORD command;
+        vector<DWORD> payload;
+        if (!Utils::ConvertHexStringToDword(arguments[1], command) || !Utils::ConvertHexStringToDwordVector(arguments[2], m_array_delimiter, payload))
+        {
+            response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsInvalidArgument));
+        }
+        DeviceManagerOperationStatus status = m_host.GetDeviceManager().SendWmi(arguments[0], command, payload);
+        if (dmosSuccess != status)
+        {
+            LOG_ERROR << __FUNCTION__ << ":" << m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+            response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+        }
+        else
+        {
+            response.message = DecorateResponseMessage(true);
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::SetHostAlias(vector<string> arguments, unsigned int numberOfArguments)
+{
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 1, response.message))
+    {
+        if (m_host.GetHostInfo().SaveAliasToFile(arguments[0]))
+        {
+            response.message = DecorateResponseMessage(true);
+        }
+        else
+        {
+            response.message = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+ResponseMessage CommandsHandler::GetTime(vector<string> arguments, unsigned int numberOfArguments)
+{
+    //do something with params
+    (void)arguments;
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 0, response.message))
+    {
+        response.message = DecorateResponseMessage(true);
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+// *************************************************************************************************
+ResponseMessage CommandsHandler::SetDriverMode(vector<string> arguments, unsigned int numberOfArguments)
+{
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+    if (ValidArgumentsNumber(__FUNCTION__, numberOfArguments, 2, response.message))
+    {
+        int newMode;
+        int oldMode;
+
+        if ("WBE_MODE" == arguments[1])
+        {
+            newMode = IOCTL_WBE_MODE;
+        }
+        else if ("WIFI_STA_MODE" == arguments[1])
+        {
+            newMode = IOCTL_WIFI_STA_MODE;
+        }
+        else if ("WIFI_SOFTAP_MODE" == arguments[1])
+        {
+            newMode = IOCTL_WIFI_SOFTAP_MODE;
+        }
+        else if ("CONCURRENT_MODE" == arguments[1])
+        {
+            newMode = IOCTL_CONCURRENT_MODE;
+        }
+        else if ("SAFE_MODE" == arguments[1])
+        {
+            newMode = IOCTL_SAFE_MODE;
+        }
+        else
+        {
+            // TODO
+            response.message = dmosFail;
+            response.type = REPLY_TYPE_BUFFER;
+            response.length = response.message.size();
+            return response;
+        }
+
+        DeviceManagerOperationStatus status = m_host.GetDeviceManager().SetDriverMode(arguments[0], newMode, oldMode);
+        if (dmosSuccess != status)
+        {
+            LOG_ERROR << "Failed to set driver mode on " + arguments[0] + ". Error: " + m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status);
+            response.message = (dmosNoSuchConnectedDevice == status) ? DecorateResponseMessage(false, m_host.GetDeviceManager().GetDeviceManagerOperationStatusString(status)) :
+                DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsOperationFailure));
+        }
+        else
+        {
+            string message;
+
+            switch (oldMode)
+            {
+            case IOCTL_WBE_MODE:
+                message = "WBE_MODE";
+                break;
+            case IOCTL_WIFI_STA_MODE:
+                message = "WIFI_STA_MODE";
+                break;
+            case IOCTL_WIFI_SOFTAP_MODE:
+                message = "WIFI_SOFTAP_MODE";
+                break;
+            case IOCTL_CONCURRENT_MODE:
+                message = "CONCURRENT_MODE";
+                break;
+            case IOCTL_SAFE_MODE:
+                message = "SAFE_MODE";
+                break;
+            default:
+                break;
+            }
+
+            response.message = DecorateResponseMessage(true, message);
+        }
+    }
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+// **************************************UDP commands handlers*********************************************************** //
+ResponseMessage CommandsHandler::GetHostNetworkInfo(vector<string> arguments, unsigned int numberOfArguments)
+{
+    //do something with params
+    (void)numberOfArguments;
+    LOG_VERBOSE << __FUNCTION__ << endl;
+    ResponseMessage response;
+
+    if (arguments.size() != 0)
+    {
+        response.message = DecorateResponseMessage(false, "Failed to get host's info: expected zero argument");
+    }
+    else
+    {
+        response.message = "GetHostIdentity;" + m_host.GetHostInfo().GetIps().m_ip + ";" + m_host.GetHostInfo().GetAlias();
+    }
+
+    response.type = REPLY_TYPE_BUFFER;
+    response.length = response.message.size();
+    return response;
+}
+// *************************************************************************************************
+
+CommandsHandler::CommandsHandler(ServerType type, Host& host) :
+    m_host(host)
+{
+    if (stTcp == type) // TCP server
+    {
+        m_functionHandler.insert(make_pair("get_interfaces", &CommandsHandler::GetInterfaces));
+        m_functionHandler.insert(make_pair("open_interface", &CommandsHandler::OpenInterface));
+        m_functionHandler.insert(make_pair("close_interface", &CommandsHandler::CloseInterface));
+        m_functionHandler.insert(make_pair("r", &CommandsHandler::Read));
+        m_functionHandler.insert(make_pair("rb", &CommandsHandler::ReadBlock));
+        m_functionHandler.insert(make_pair("w", &CommandsHandler::Write));
+        m_functionHandler.insert(make_pair("wb", &CommandsHandler::WriteBlock));
+        m_functionHandler.insert(make_pair("interface_reset", &CommandsHandler::InterfaceReset));
+        m_functionHandler.insert(make_pair("sw_reset", &CommandsHandler::SwReset));
+        m_functionHandler.insert(make_pair("alloc_pmc", &CommandsHandler::AllocPmc));
+        m_functionHandler.insert(make_pair("dealloc_pmc", &CommandsHandler::DeallocPmc));
+        m_functionHandler.insert(make_pair("create_pmc_file", &CommandsHandler::CreatePmcFile));
+        m_functionHandler.insert(make_pair("read_pmc_file", &CommandsHandler::ReadPmcFile));
+        m_functionHandler.insert(make_pair("send_wmi", &CommandsHandler::SendWmi));
+        m_functionHandler.insert(make_pair("set_host_alias", &CommandsHandler::SetHostAlias));
+        m_functionHandler.insert(make_pair("get_time", &CommandsHandler::GetTime));
+        m_functionHandler.insert(make_pair("set_local_driver_mode", &CommandsHandler::SetDriverMode));
+    }
+    else // UDP server
+    {
+        m_functionHandler.insert(make_pair(/*"get_host_network_info"*/"GetHostIdentity", &CommandsHandler::GetHostNetworkInfo));
+    }
+}
+
+// *************************************************************************************************
+
+ConnectionStatus CommandsHandler::ExecuteCommand(string message, ResponseMessage &referencedResponse)
+{
+    m_pMessageParser.reset(new MessageParser(message));
+
+    string commandName = m_pMessageParser->GetCommandFromMessage();
+
+    LOG_DEBUG << "command name: " << commandName << endl; //TODO - remove after test
+
+    if (m_functionHandler.find(commandName) == m_functionHandler.end())
+    { //There's no such a command, the return value from the map would be null
+        LOG_WARNING << "Unknown command from client: " << commandName << endl;
+        referencedResponse.message = "Unknown command: " + commandName;
+        referencedResponse.length = referencedResponse.message.size();
+        referencedResponse.type = REPLY_TYPE_BUFFER;
+        return KEEP_CONNECTION_ALIVE;
+    }
+    referencedResponse = (this->*m_functionHandler[commandName])(m_pMessageParser->GetArgsFromMessage(), m_pMessageParser->GetNumberOfArgs()); //call the function that fits commandName
+
+
+
+    /* For testing while developing: */
+    vector<string> vec = m_pMessageParser->GetArgsFromMessage(); //TODO - remove after test
+    for (auto i: vec) //TODO - remove after test - print the given arguments
+    {
+        LOG_DEBUG << "argument is: " << i << endl;
+    }
+    /* End of testing for developing */
+
+    return KEEP_CONNECTION_ALIVE;
+}
diff --git a/debug-tools/host_manager_11ad/CommandsHandler.h b/debug-tools/host_manager_11ad/CommandsHandler.h
new file mode 100644
index 0000000..b2ae6c8
--- /dev/null
+++ b/debug-tools/host_manager_11ad/CommandsHandler.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _COMMANDSHANDLER_H_
+#define _COMMANDSHANDLER_H_
+
+#include <iostream>
+#include <memory>
+#include <map>
+#include "MessageParser.h"
+#include "HostDefinitions.h"
+#include <sstream>
+
+class Host;
+
+using namespace std;
+
+
+// *************************************************************************************************
+
+class CommandsHandler
+{
+public:
+    /*
+    * pCommandFunction is used for the functions map - each function gets two arguments:
+    * vector of strings which holds the arguments and the number of arguments in that vector
+    */
+    typedef ResponseMessage(CommandsHandler::*pCommandFunction)(vector<string>, unsigned int);
+
+    /*
+    * The constructor inserts each one of the available functions into the map - m_functionHandler - according to server type (TCP/UDP)
+    */
+    CommandsHandler(ServerType type, Host& host);
+
+    ConnectionStatus ExecuteCommand(string message, ResponseMessage &referencedResponse);
+
+
+private:
+    shared_ptr<MessageParser> m_pMessageParser;
+    //m_functionHandler is a map that maps a string = command name, to a function
+    map<string, pCommandFunction> m_functionHandler;
+    Host& m_host; // a refernce to the host (enables access to deviceManager and hostInfo)
+
+    enum CommandsHandlerResponseStatus
+    {
+        chrsInvalidNumberOfArguments,
+        chrsInvalidArgument,
+        chrsOperationFailure,
+        chrsLinuxSupportOnly,
+        chrsSuccess
+    };
+
+    string GetCommandsHandlerResponseStatusString(CommandsHandlerResponseStatus status)
+    {
+        switch (status)
+        {
+        case chrsInvalidNumberOfArguments:
+            return "Invalid arguments number";
+        case chrsInvalidArgument:
+            return "Invaild argument type";
+        case chrsOperationFailure:
+            return "Operation failure";
+        case chrsLinuxSupportOnly:
+            return "Linux support only";
+        case chrsSuccess:
+            return "Success";
+        default:
+            return "CommandsHandlerResponseStatus is unknown";
+        }
+    }
+
+    /*
+    FormatResponseMessage
+    Decorate the response message with time stamp and a success status
+    @param: successStatus - true for a successful operation, false otherwise
+    @param: message - the content of the response
+    @return: the decorated response
+    */
+    string DecorateResponseMessage(bool successStatus, string message = "");
+
+    // **********************************Commands Functions:****************************************
+    ResponseMessage GetInterfaces(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage OpenInterface(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage CloseInterface(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage Read(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage Write(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage ReadBlock(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage WriteBlock(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage InterfaceReset(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage SwReset(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage AllocPmc(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage DeallocPmc(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage CreatePmcFile(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage ReadPmcFile(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage SendWmi(vector<string> arguments, unsigned int numberOfArguments);
+
+    ResponseMessage GetTime(vector<string> arguments, unsigned int numberOfArguments);
+
+	ResponseMessage SetDriverMode(vector<string> arguments, unsigned int numberOfArguments);
+
+
+    bool ValidArgumentsNumber(string functionName, size_t numberOfArguments, size_t expectedNumOfArguments, string& responseMessage)
+    {
+        if (expectedNumOfArguments != numberOfArguments)
+        {
+            stringstream error;
+            LOG_WARNING << "Mismatching number of arguments in " << functionName << ": expected " << expectedNumOfArguments << " but got "<< numberOfArguments << endl;
+            responseMessage = DecorateResponseMessage(false, GetCommandsHandlerResponseStatusString(chrsInvalidNumberOfArguments));
+            return false;
+        }
+        return true;
+    }
+
+    /*
+    GetHostNetworkInfo
+    Return host's IP and host's alias as the Response
+    @param: an empty vector
+    @return: a response with a string that contains both  host's IP and host's alias
+    */
+    ResponseMessage GetHostNetworkInfo(vector<string> arguments, unsigned int numberOfArguments);
+
+    /*
+    SetHostAlias
+    Get a new alias and define it as the new host's alias
+    @param: a vector with one string representing the new alias
+    @return: a response with feedback about the operation status (success/failure)
+    */
+    ResponseMessage SetHostAlias(vector<string> arguments, unsigned int numberOfArguments);
+
+    const char m_device_delimiter = ' ';
+
+    const char m_array_delimiter = ' ';
+
+    const char m_reply_feilds_delimiter = '|';
+};
+
+
+#endif // !_COMMANDSHANDLER_H_
diff --git a/debug-tools/host_manager_11ad/CommandsTcpServer.cpp b/debug-tools/host_manager_11ad/CommandsTcpServer.cpp
new file mode 100644
index 0000000..cdfe62f
--- /dev/null
+++ b/debug-tools/host_manager_11ad/CommandsTcpServer.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "CommandsTcpServer.h"
+#include <thread>
+#include "NetworkInterface.h"
+#include "FileReader.h"
+#include "Host.h"
+
+using namespace std;
+
+// *************************************************************************************************
+
+CommandsTcpServer::CommandsTcpServer(unsigned int commandsTcpPort, Host& host)
+    :m_port(commandsTcpPort),m_pSocket(new NetworkInterfaces::NetworkInterface()), m_host(host)
+{
+}
+
+// *************************************************************************************************
+
+void CommandsTcpServer::Start()
+{
+    LOG_INFO << "Starting commands TCP server on port " << m_port << endl;
+    m_pSocket->Bind(m_port);
+    m_pSocket->Listen();
+
+    //Infinite loop that waits for clients to connect to the commands TCP server - there's no reason to stop this loop,
+    //should run forever unless there is a problem
+    while (true)
+    {
+        try
+        {
+            //thread serverThread = thread(&ServerThread, m_pServer->accept());
+            thread serverThread(&CommandsTcpServer::ServerThread, this, m_pSocket->Accept()); //open a new thread for each client
+            serverThread.detach();
+        }
+        catch (exception e)
+        {
+            LOG_ERROR << "Couldn't make a new connection or starting a new thread in Commands TCP server for a new client " << e.what() << endl;
+        }
+
+    }
+}
+
+void CommandsTcpServer::Stop()
+{
+    LOG_INFO << "Stopping the commands TCP server" << endl;
+    m_pSocket->Shutdown(2); //type 2 -> Acts like the close(), shutting down both input and output
+}
+
+// *************************************************************************************************
+//A thread function to handle each client that connects to the server
+void CommandsTcpServer::ServerThread(NetworkInterfaces::NetworkInterface client)
+{
+    unique_ptr<CommandsHandler> pCommandsHandler(new CommandsHandler(stTcp, m_host));
+    ConnectionStatus keepConnectionAliveFromCommand = KEEP_CONNECTION_ALIVE; //A flag for the content of the command - says if the client wants to close connection
+    ConnectionStatus keepConnectionAliveFromReply = KEEP_CONNECTION_ALIVE; //A flag for the reply status, for problems in sending reply etc..
+    m_host.GetHostInfo().AddNewConnectedUser(client.GetPeerName()); // add the user's to the host's connected users
+
+    do
+    {
+        string messages;
+        messages.empty();
+
+        try
+        {
+            messages = client.Receive();
+            vector<string> splitMessages = Utils::Split(messages, '\r');
+
+            for (auto& message : splitMessages)
+            {
+                ResponseMessage referencedResponse = { "", REPLY_TYPE_NONE, 0 };
+                if (message.empty())
+                { //message back from the client is "", means the connection is closed
+                    break;
+                }
+
+                //Try to execute the command from the client, get back from function if to keep the connection with the client alive or not
+                keepConnectionAliveFromCommand = pCommandsHandler->ExecuteCommand(message, referencedResponse);
+
+                //Reply back to the client an answer for his command. If it wasn't successful - close the connection
+                keepConnectionAliveFromReply = CommandsTcpServer::Reply(client, referencedResponse);
+            }
+            //LOG_INFO << "Message from Client to commands TCP server: " << message << endl;
+        }
+        catch (exception e)
+        {
+            LOG_ERROR << "Couldn't get the message from the client" << e.what() << endl;
+            break;
+        }
+
+    } while (keepConnectionAliveFromCommand != CLOSE_CONNECTION && keepConnectionAliveFromReply != CLOSE_CONNECTION);
+
+    //client.shutdown(0); //TODO - check how to do it correctly (without exception)
+    //client.shutdown(1); //TODO - check how to do it correctly (without exception)
+    //client.close(); //TODO - check how to do it correctly (without exception)
+    LOG_INFO << "Closed connection with the client: " << client.GetPeerName() << endl;
+    m_host.GetHostInfo().RemoveNewConnectedUser(client.GetPeerName());
+}
+
+// *************************************************************************************************
+
+ConnectionStatus CommandsTcpServer::Reply(NetworkInterfaces::NetworkInterface &client, ResponseMessage &responseMessage)
+{
+    LOG_DEBUG << "Reply is: " << responseMessage.message << endl;
+
+    switch (responseMessage.type)
+    {
+    case REPLY_TYPE_BUFFER:
+        return ReplyBuffer(client, responseMessage);
+    case REPLY_TYPE_FILE:
+        return ReplyFile(client, responseMessage);
+    default:
+        //LOG_ERROR << "Unknown reply type" << endl;
+        break;
+    }
+    return CLOSE_CONNECTION;
+}
+
+
+// *************************************************************************************************
+
+ConnectionStatus CommandsTcpServer::ReplyBuffer(NetworkInterfaces::NetworkInterface &client, ResponseMessage &responseMessage)
+{
+    LOG_DEBUG << "Replying from a buffer (" << responseMessage.length << "B) Content: " << responseMessage.message << endl;
+
+    if (0 == responseMessage.length)
+    {
+        LOG_ERROR << "No reply generated by a command handler - connection will be closed" << endl;
+        return CLOSE_CONNECTION;
+    }
+
+    try
+    {
+        client.Send((responseMessage.message + "\r").c_str()); //TODO - maybe the sending format is ending with "\n\r"
+    }
+    catch (const exception& e)
+    {
+        LOG_ERROR << "couldn't send the message to the client, closing connection: " << e.what() << endl;
+        return CLOSE_CONNECTION;
+    }
+    catch (int e) // TODO: check if we can remove the previous catch
+    {
+        LOG_ERROR << "couldn't send the message to the client, closing connection: " << e << endl;
+        return CLOSE_CONNECTION;
+    }
+
+
+    return KEEP_CONNECTION_ALIVE;
+}
+
+
+//TODO - reply file had been copied from old "wilserver" almost without touching it.
+//It has to be checked and also modified to fit the new "host_server_11ad"
+//The same applies to "FileReader.h" and "FileReader.cpp"
+ConnectionStatus CommandsTcpServer::ReplyFile(NetworkInterfaces::NetworkInterface & client, ResponseMessage & fileName)
+{
+    LOG_DEBUG << "Replying from a file: " << fileName.message << std::endl;
+    FileReader fileReader(fileName.message.c_str());
+    size_t fileSize = fileReader.GetFileSize();
+
+    if (0 == fileSize)
+    {
+        LOG_ERROR << "No file content is available for reply" << std::endl;
+        return CLOSE_CONNECTION;
+    }
+
+    static const size_t BUF_LEN = 64 * 1024;
+
+    char* pBuf = new char[BUF_LEN];
+    size_t chunkSize = 0;
+    bool isError = false;
+
+    do
+    {
+        LOG_VERBOSE << "Requesting for a file chunk" << std::endl;
+
+        chunkSize = fileReader.ReadChunk(pBuf, BUF_LEN);
+        if (chunkSize > 0)
+        {
+            //if (false == send_buffer(sock, pBuf, chunkSize)) //TODO - was in the old "wilserver" changed to the next line (with client.send(pBuf))
+            if (0 == client.Send(pBuf))
+            {
+                LOG_ERROR << "Send error detected" << std::endl;
+                isError = true;
+                break;
+            }
+        }
+
+        // Error/Completion may occur with non-zero chunk as well
+        if (fileReader.IsError())
+        {
+            LOG_ERROR << "File read error detected" << std::endl;
+            isError = true;
+            break;
+        }
+
+        if (fileReader.IsCompleted())
+        {
+            LOG_DEBUG << "File completion detected" << std::endl;
+            break;
+        }
+
+        LOG_DEBUG << "File Chunk Delivered: " << chunkSize << "B" << std::endl;
+    } while (chunkSize > 0);
+
+    delete[] pBuf;
+
+    if (isError)
+    {
+        LOG_ERROR << "Error occurred while replying file content" << std::endl;
+        return CLOSE_CONNECTION;
+    }
+    else
+    {
+        LOG_DEBUG << "File Content successfully delivered" << std::endl;
+        return KEEP_CONNECTION_ALIVE;
+    }
+}
diff --git a/debug-tools/host_manager_11ad/CommandsTcpServer.h b/debug-tools/host_manager_11ad/CommandsTcpServer.h
new file mode 100644
index 0000000..fa6d8dc
--- /dev/null
+++ b/debug-tools/host_manager_11ad/CommandsTcpServer.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _COMMANDSTCPSERVER_H_
+#define _COMMANDSTCPSERVER_H_
+
+#include "NetworkInterface.h"
+#include <memory>
+#include "HostDefinitions.h"
+#include "CommandsHandler.h"
+
+using namespace std;
+
+class Host;
+
+/*
+* Commands TCP Server is a synchronous server that handles each client separately.
+* When a client sends a new command to the Commands TCP Server, the host processes it and sends back to the client an answer.
+*/
+class CommandsTcpServer
+{
+public:
+
+    /*
+    * Commands TCP server constructor gets the port to start in. It also initializes new Socket object.
+    */
+    CommandsTcpServer(unsigned int commandsTcpPort, Host& host);
+
+    /*
+    * Start the commands TCP server at the given port (given in the constructor).
+    * For each new client that is connecting to the server it opens a new thread and
+    * continue to listen on the port for more clients.
+    */
+    void Start();
+
+    /*
+    * Stop the commands TCP server by doing some clean ups for the sockets.
+    */
+    void Stop();
+
+private:
+
+    unsigned int m_port; //The port in which the commands TCP server is working on
+    shared_ptr<NetworkInterfaces::NetworkInterface> m_pSocket; //an object that holds the connection with each client
+    Host& m_host; // refernce to the host object (that is passed to commandsHandler each time a new TCP connection is created)
+
+    void ServerThread(NetworkInterfaces::NetworkInterface client);
+    ConnectionStatus Reply(NetworkInterfaces::NetworkInterface &client, ResponseMessage &responseMessage);
+    ConnectionStatus ReplyBuffer(NetworkInterfaces::NetworkInterface &client, ResponseMessage &responseMessage);
+    ConnectionStatus ReplyFile(NetworkInterfaces::NetworkInterface &client, ResponseMessage &fileName);
+};
+
+
+#endif // !_COMMANDSTCPSERVER_H_
+
diff --git a/debug-tools/host_manager_11ad/DebugLogger.cpp b/debug-tools/host_manager_11ad/DebugLogger.cpp
new file mode 100644
index 0000000..cf3ae90
--- /dev/null
+++ b/debug-tools/host_manager_11ad/DebugLogger.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "DebugLogger.h"
+#include <stdio.h>
+
+// *************************************************************************************************
+
+LogConfig g_LogConfig(LOG_SEV_INFO, false);
+
+// *************************************************************************************************
+
+LogConfig::LogConfig(LogSeverity maxSeverity, bool bPrintLocation)
+	: m_MaxSeverity(maxSeverity), m_PrintLocation(bPrintLocation)
+{
+}
+
+void LogConfig::SetMaxSeverity(int traceLevel)
+{
+	if (traceLevel > LOG_SEV_VERBOSE)
+	{
+		fprintf(stderr, "Invalid trace level, setting %d\n", LOG_SEV_VERBOSE);
+		m_MaxSeverity = LOG_SEV_VERBOSE;
+	}
+	else
+	{
+		m_MaxSeverity = static_cast<LogSeverity>(traceLevel);
+		fprintf(stdout, "Setting trace level to %d\n", m_MaxSeverity);
+	}
+}
+
+// *************************************************************************************************
+
+const char* LogMsgPrefix::SeverityToString(LogSeverity sev)
+{
+	static const char* const pSeverityToString[] = { "ERR", "WRN", "INF", "DBG", "VRB" };
+
+	size_t index = static_cast<size_t>(sev);
+	if (index >= sizeof(pSeverityToString) / sizeof(pSeverityToString[0]))
+	{
+		return "---";
+	}
+
+	return pSeverityToString[index];
+}
+
+std::ostream& operator<<(std::ostream& os, const LogMsgPrefix& prefix)
+{
+	os << '[' << LogMsgPrefix::SeverityToString(prefix.Severity) << "] ";
+	if (!g_LogConfig.ShouldPrintLocation()) return os;
+	return os << "(" << prefix.File << ':' << prefix.Line << ") ";
+}
diff --git a/debug-tools/host_manager_11ad/DebugLogger.h b/debug-tools/host_manager_11ad/DebugLogger.h
new file mode 100644
index 0000000..20160e6
--- /dev/null
+++ b/debug-tools/host_manager_11ad/DebugLogger.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef  _DEBUGLOGGER_H_
+#define _DEBUGLOGGER_H_
+
+#include <iostream>
+
+// Severity values are expected to raise from zero
+enum LogSeverity
+{
+    LOG_SEV_ERROR   = 0,   // Unexpected input/events that may cause server misbehavior
+    LOG_SEV_WARNING = 1,   // Suspicious events
+    LOG_SEV_INFO    = 2,   // Events like command/response
+    LOG_SEV_DEBUG   = 3,   // Detailed functionality
+    LOG_SEV_VERBOSE = 4    // Excessive debug
+};
+
+#define TRACE_WITH_PREFIX(SEV)    \
+    g_LogConfig.ShouldPrint(SEV) && std::cout << LogMsgPrefix(SEV, __FILE__, __LINE__)
+
+#define LOG_ERROR   TRACE_WITH_PREFIX(LOG_SEV_ERROR)
+#define LOG_WARNING TRACE_WITH_PREFIX(LOG_SEV_WARNING)
+#define LOG_INFO    TRACE_WITH_PREFIX(LOG_SEV_INFO)
+#define LOG_DEBUG   TRACE_WITH_PREFIX(LOG_SEV_DEBUG)
+#define LOG_VERBOSE TRACE_WITH_PREFIX(LOG_SEV_VERBOSE)
+
+// *************************************************************************************************
+
+struct LogConfig
+{
+public:
+    LogConfig(LogSeverity maxSeverity, bool bPrintLocation);
+    void SetMaxSeverity(int traceLevel);
+
+    bool ShouldPrint(LogSeverity sev) const { return sev <= m_MaxSeverity; }
+    bool ShouldPrintLocation() const { return m_PrintLocation; }
+
+private:
+
+    LogSeverity m_MaxSeverity;
+    const bool m_PrintLocation;
+
+};
+
+// *************************************************************************************************
+
+extern LogConfig g_LogConfig;
+
+// *************************************************************************************************
+
+class LogMsgPrefix
+{
+    friend std::ostream& operator<<(std::ostream& os, const LogMsgPrefix& prefix);
+
+public:
+
+    LogMsgPrefix(LogSeverity severity, const char* pFile, int line)
+        : Severity(severity), File(pFile), Line(line) {}
+
+private:
+
+    static const char* SeverityToString(LogSeverity sev);
+
+    const LogSeverity Severity;
+    const char* const File;
+    const int Line;
+};
+
+
+// *************************************************************************************************
+// Stream Formatters
+// *************************************************************************************************
+
+// Print a boolean value as a string
+struct BoolStr
+{
+    explicit BoolStr(bool value): Value(value) {}
+    const bool Value;
+};
+
+inline std::ostream& operator<<(std::ostream& os, const BoolStr& boolStr)
+{
+    return os << std::boolalpha << boolStr.Value << std::noboolalpha;
+}
+
+// *************************************************************************************************
+
+// Print a string while displaying newline characters
+struct PlainStr
+{
+    explicit PlainStr(const std::string& value): Value(value) {}
+    const std::string& Value;
+};
+
+inline std::ostream& operator<<(std::ostream& os, const PlainStr& plainStr)
+{
+    for (std::string::const_iterator it = plainStr.Value.begin(); it != plainStr.Value.end(); ++it)
+    {
+        switch (*it)
+        {
+        case '\r': os << "\\r"; break;
+        case '\n': os << "\\n"; break;
+        case '\t': os << "\\t"; break;
+        default:   os << *it; break;
+        }
+    }
+
+    return os;
+}
+
+
+#endif // ! _DEBUGLOGGER_H_
diff --git a/debug-tools/host_manager_11ad/DeviceManager.cpp b/debug-tools/host_manager_11ad/DeviceManager.cpp
new file mode 100644
index 0000000..debba4b
--- /dev/null
+++ b/debug-tools/host_manager_11ad/DeviceManager.cpp
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <chrono>
+#include <thread>
+#include <future>
+
+#include "DeviceManager.h"
+#include "Utils.h"
+#include "AccessLayerAPI.h"
+
+DeviceManager::DeviceManager() :
+    m_deviceManagerRestDurationMs(500),
+    m_terminate(false)
+{
+    m_deviceManager = thread(&DeviceManager::PeriodicTasks, this);
+}
+
+DeviceManager::~DeviceManager()
+{
+    m_terminate = true;
+    m_deviceManager.join();
+}
+
+string DeviceManager::GetDeviceManagerOperationStatusString(DeviceManagerOperationStatus status)
+{
+    switch (status)
+    {
+    case dmosSuccess:
+        return "Successful operation";
+    case dmosNoSuchConnectedDevice:
+        return "Unknown device";
+    case dmosFailedToReadFromDevice:
+        return "Read failure";
+    case dmosFailedToWriteToDevice:
+        return "Write failure";
+    case dmosFailedToResetInterface:
+        return "Reset interface failure";
+    case dmosFailedToResetSw:
+        return "SW reset failure";
+    case dmosFailedToAllocatePmc:
+        return "Allocate PMC failure";
+    case dmosFailedToDeallocatePmc:
+        return "Deallocate PMC failure";
+    case dmosFailedToCreatePmcFile:
+        return "Create PMC file failure";
+    case dmosFailedToSendWmi:
+        return "Send WMI failure";
+    case dmosFail:
+        return "Operation failure";
+    default:
+        return "DeviceManagerOperationStatus is unknown ";
+    }
+}
+
+DeviceManagerOperationStatus DeviceManager::GetDevices(set<string>& devicesNames)
+{
+    devicesNames.clear();
+    for (auto& device : m_connectedDevices)
+    {
+        devicesNames.insert(device.first);
+    }
+    return dmosSuccess;
+}
+
+DeviceManagerOperationStatus DeviceManager::OpenInterface(string deviceName)
+{
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        return dmosSuccess;
+    }
+    return dmosNoSuchConnectedDevice;
+}
+
+DeviceManagerOperationStatus DeviceManager::CloseInterface(string deviceName)
+{
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        return dmosSuccess;
+    }
+    return dmosNoSuchConnectedDevice;
+}
+
+DeviceManagerOperationStatus DeviceManager::Read(string deviceName, DWORD address, DWORD& value)
+{
+	if ((0 == address) || (0 != address % 4) || (0xFFFFFFFF == address))
+	{
+		return dmosInvalidAddress;
+	}
+
+    DeviceManagerOperationStatus status;
+    m_connectedDevicesMutex.lock();
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        m_connectedDevices[deviceName]->m_mutex.lock();
+        m_connectedDevicesMutex.unlock();
+        bool success = m_connectedDevices[deviceName]->m_device->Read(address, value);
+        if (success)
+        {
+            status = dmosSuccess;
+        }
+        else
+        {
+            value = Device::GetRegisterDefaultValue();
+            status = dmosFailedToReadFromDevice;
+        }
+        m_connectedDevices[deviceName]->m_mutex.unlock();
+        return status;
+    }
+    else
+    {
+        m_connectedDevicesMutex.unlock();
+        value = Device::GetRegisterDefaultValue();
+        return dmosNoSuchConnectedDevice;
+    }
+}
+
+DeviceManagerOperationStatus DeviceManager::Write(string deviceName, DWORD address, DWORD value)
+{
+	if ((0 == address) || (0 != address % 4) || (0xFFFFFFFF == address))
+	{
+		return dmosInvalidAddress;
+	}
+
+    DeviceManagerOperationStatus status;
+    m_connectedDevicesMutex.lock();
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        m_connectedDevices[deviceName]->m_mutex.lock();
+        m_connectedDevicesMutex.unlock();
+        bool success = m_connectedDevices[deviceName]->m_device->Write(address, value);
+        if (success)
+        {
+            status = dmosSuccess;
+        }
+        else
+        {
+            status = dmosFailedToWriteToDevice;
+        }
+        m_connectedDevices[deviceName]->m_mutex.unlock();
+        return status;
+    }
+    else
+    {
+        m_connectedDevicesMutex.unlock();
+        return dmosNoSuchConnectedDevice;
+    }
+}
+
+DeviceManagerOperationStatus DeviceManager::ReadBlock(string deviceName, DWORD address, DWORD blockSize, vector<DWORD>& values)
+{
+	if ((0 == address) || (0 != address % 4) || (0xFFFFFFFF == address))
+	{
+		return dmosInvalidAddress;
+	}
+
+    DeviceManagerOperationStatus status;
+    m_connectedDevicesMutex.lock();
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        m_connectedDevices[deviceName]->m_mutex.lock();
+        m_connectedDevicesMutex.unlock();
+        bool success = m_connectedDevices[deviceName]->m_device->ReadBlock(address, blockSize, values);
+        if (success)
+        {
+            status = dmosSuccess;
+        }
+        else
+        {
+            vector<DWORD> defaultValues(blockSize, Device::GetRegisterDefaultValue());
+            status = dmosFailedToReadFromDevice;
+        }
+        m_connectedDevices[deviceName]->m_mutex.unlock();
+        return status;
+    }
+    else
+    {
+        m_connectedDevicesMutex.unlock();
+        vector<DWORD> defaultValues(blockSize, Device::GetRegisterDefaultValue());
+        return dmosNoSuchConnectedDevice;
+    }
+}
+
+DeviceManagerOperationStatus DeviceManager::WriteBlock(string deviceName, DWORD address, const vector<DWORD>& values)
+{
+	if ((0 == address) || (0 != address % 4) || (0xFFFFFFFF == address))
+	{
+		return dmosInvalidAddress;
+	}
+
+    DeviceManagerOperationStatus status;
+    m_connectedDevicesMutex.lock();
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        m_connectedDevices[deviceName]->m_mutex.lock();
+        m_connectedDevicesMutex.unlock();
+        bool success = m_connectedDevices[deviceName]->m_device->WriteBlock(address, values);
+        if (success)
+        {
+            status = dmosSuccess;
+        }
+        else
+        {
+            status = dmosFailedToWriteToDevice;
+        }
+        m_connectedDevices[deviceName]->m_mutex.unlock();
+        return status;
+    }
+    else
+    {
+        m_connectedDevicesMutex.unlock();
+        return dmosNoSuchConnectedDevice;
+    }
+}
+
+DeviceManagerOperationStatus DeviceManager::InterfaceReset(string deviceName)
+{
+    DeviceManagerOperationStatus status;
+    m_connectedDevicesMutex.lock();
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        m_connectedDevices[deviceName]->m_mutex.lock();
+        m_connectedDevicesMutex.unlock();
+        m_connectedDevices[deviceName]->m_device->InterfaceReset();
+        status = dmosSuccess;
+        m_connectedDevices[deviceName]->m_mutex.unlock();
+        return status;
+    }
+    else
+    {
+        m_connectedDevicesMutex.unlock();
+        return dmosNoSuchConnectedDevice;
+    }
+}
+
+DeviceManagerOperationStatus DeviceManager::SwReset(string deviceName)
+{
+    DeviceManagerOperationStatus status;
+    m_connectedDevicesMutex.lock();
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        m_connectedDevices[deviceName]->m_mutex.lock();
+        m_connectedDevicesMutex.unlock();
+        bool success = m_connectedDevices[deviceName]->m_device->SwReset();
+        if (success)
+        {
+            status = dmosSuccess;
+        }
+        else
+        {
+            status = dmosFailedToResetSw;
+        }
+        m_connectedDevices[deviceName]->m_mutex.unlock();
+        return status;
+    }
+    else
+    {
+        m_connectedDevicesMutex.unlock();
+        return dmosNoSuchConnectedDevice;
+    }
+}
+
+DeviceManagerOperationStatus DeviceManager::SetDriverMode(string deviceName, int newMode, int& oldMode)
+{
+	DeviceManagerOperationStatus status;
+	m_connectedDevicesMutex.lock();
+	if (m_connectedDevices.count(deviceName) > 0)
+	{
+		m_connectedDevices[deviceName]->m_mutex.lock();
+		m_connectedDevicesMutex.unlock();
+		bool success = m_connectedDevices[deviceName]->m_device->SetDriverMode(newMode, oldMode);
+		if (success)
+		{
+			status = dmosSuccess;
+		}
+		else
+		{
+			status = dmosFailedToResetSw;
+		}
+		m_connectedDevices[deviceName]->m_mutex.unlock();
+		return status;
+	}
+	else
+	{
+		m_connectedDevicesMutex.unlock();
+		return dmosNoSuchConnectedDevice;
+	}
+}
+
+DeviceManagerOperationStatus DeviceManager::AllocPmc(string deviceName, unsigned descSize, unsigned descNum)
+{
+    DeviceManagerOperationStatus status;
+    m_connectedDevicesMutex.lock();
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        m_connectedDevices[deviceName]->m_mutex.lock();
+        m_connectedDevicesMutex.unlock();
+        bool success = m_connectedDevices[deviceName]->m_device->AllocPmc(descSize, descNum);
+        if (success)
+        {
+            status = dmosSuccess;
+        }
+        else
+        {
+            status = dmosFailedToAllocatePmc;
+        }
+        m_connectedDevices[deviceName]->m_mutex.unlock();
+        return status;
+    }
+    else
+    {
+        m_connectedDevicesMutex.unlock();
+        return dmosNoSuchConnectedDevice;
+    }
+}
+
+DeviceManagerOperationStatus DeviceManager::DeallocPmc(string deviceName)
+{
+    DeviceManagerOperationStatus status;
+    m_connectedDevicesMutex.lock();
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        m_connectedDevices[deviceName]->m_mutex.lock();
+        m_connectedDevicesMutex.unlock();
+        bool success = m_connectedDevices[deviceName]->m_device->DeallocPmc();
+        if (success)
+        {
+            status = dmosSuccess;
+        }
+        else
+        {
+            status = dmosFailedToDeallocatePmc;
+        }
+        m_connectedDevices[deviceName]->m_mutex.unlock();
+        return status;
+    }
+    else
+    {
+        m_connectedDevicesMutex.unlock();
+        return dmosNoSuchConnectedDevice;
+    }
+}
+
+DeviceManagerOperationStatus DeviceManager::CreatePmcFile(string deviceName, unsigned refNumber)
+{
+    DeviceManagerOperationStatus status;
+    m_connectedDevicesMutex.lock();
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        m_connectedDevices[deviceName]->m_mutex.lock();
+        m_connectedDevicesMutex.unlock();
+        bool success = m_connectedDevices[deviceName]->m_device->CreatePmcFile(refNumber);
+        if (success)
+        {
+            status = dmosSuccess;
+        }
+        else
+        {
+            status = dmosFailedToCreatePmcFile;
+        }
+        m_connectedDevices[deviceName]->m_mutex.unlock();
+        return status;
+    }
+    else
+    {
+        m_connectedDevicesMutex.unlock();
+        return dmosNoSuchConnectedDevice;
+    }
+}
+
+DeviceManagerOperationStatus DeviceManager::SendWmi(string deviceName, DWORD command, const vector<DWORD>& payload)
+{
+    DeviceManagerOperationStatus status;
+    m_connectedDevicesMutex.lock();
+    if (m_connectedDevices.count(deviceName) > 0)
+    {
+        m_connectedDevices[deviceName]->m_mutex.lock();
+        m_connectedDevicesMutex.unlock();
+        bool success = m_connectedDevices[deviceName]->m_device->SendWmi(command, payload);
+        if (success)
+        {
+            status = dmosSuccess;
+        }
+        else
+        {
+            status = dmosFailedToSendWmi;
+        }
+        m_connectedDevices[deviceName]->m_mutex.unlock();
+        return status;
+    }
+    else
+    {
+        m_connectedDevicesMutex.unlock();
+        return dmosNoSuchConnectedDevice;
+    }
+}
+
+void DeviceManager::CreateDevice(string deviceName)
+{
+    m_connectedDevicesMutex.lock();
+    shared_ptr<ConnectedDevice> connectedDevice(new ConnectedDevice(AccessLayer::OpenDevice(deviceName)));
+    m_connectedDevices.insert(make_pair(deviceName, connectedDevice));
+    m_connectedDevicesMutex.unlock();
+}
+
+void DeviceManager::DeleteDevice(string deviceName)
+{
+    m_connectedDevicesMutex.lock();
+    // make sure that no client is using this object
+    m_connectedDevices[deviceName]->m_mutex.lock();
+    // no need that the mutex will be still locked since new clients have to get m_connectedDevicesMutex before they try to get m_mutex
+    m_connectedDevices[deviceName]->m_mutex.unlock();
+    AccessLayer::CloseDevice(deviceName);
+    m_connectedDevices.erase(deviceName);
+    m_connectedDevicesMutex.unlock();
+}
+
+void DeviceManager::UpdateConnectedDevices()
+{
+    set<string> currentlyConnectedDevices = AccessLayer::GetDevices();
+
+    // delete devices that arn't connected anymore
+    vector<string> devicesForRemove;
+    for (auto& connectedDevice : m_connectedDevices)
+    {
+        if (0 == currentlyConnectedDevices.count(connectedDevice.first))
+        {
+            devicesForRemove.push_back(connectedDevice.first);
+        }
+    }
+    for (auto& device : devicesForRemove)
+    {
+        DeleteDevice(device);
+    }
+
+    // add new connected devices
+    vector<string> newDevices;
+    for (auto& currentlyConnectedDevice : currentlyConnectedDevices)
+    {
+        if (0 == m_connectedDevices.count(currentlyConnectedDevice))
+        {
+            newDevices.push_back(currentlyConnectedDevice);
+        }
+    }
+    for (auto& device : newDevices)
+    {
+        CreateDevice(device);
+    }
+}
+
+void DeviceManager::PeriodicTasks()
+{
+    while (!m_terminate)
+    {
+        UpdateConnectedDevices();
+        for (auto& connectedDevice : m_connectedDevices)
+        {
+            connectedDevice.second->m_mutex.lock();
+            connectedDevice.second->m_device->Poll();
+            connectedDevice.second->m_mutex.unlock();
+        }
+        this_thread::sleep_for(std::chrono::milliseconds(m_deviceManagerRestDurationMs));
+    }
+}
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/DeviceManager.h b/debug-tools/host_manager_11ad/DeviceManager.h
new file mode 100644
index 0000000..6cd8596
--- /dev/null
+++ b/debug-tools/host_manager_11ad/DeviceManager.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _DEVICEMANAGER_H_
+#define _DEVICEMANAGER_H_
+
+#include <string>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+#include <thread>
+#include <mutex>
+#include <atomic>
+
+#include "HostDefinitions.h"
+#include "Device.h"
+
+using namespace std;
+
+struct ConnectedDevice
+{
+    ConnectedDevice(unique_ptr<Device> device) :
+        m_device(move(device))
+    { }
+
+    shared_ptr<Device> m_device;
+    mutex m_mutex;
+};
+
+enum DeviceManagerOperationStatus
+{
+    dmosSuccess,
+    dmosNoSuchConnectedDevice, // the given device name is not part of m_conncectedDevices
+    dmosFailedToReadFromDevice,
+    dmosFailedToWriteToDevice,
+    dmosFailedToResetInterface,
+    dmosFailedToResetSw,
+    dmosFailedToAllocatePmc,
+    dmosFailedToDeallocatePmc,
+    dmosFailedToCreatePmcFile,
+    dmosFailedToSendWmi,
+	dmosInvalidAddress,
+    dmosFail // general failure. try to avoid using it
+};
+
+class DeviceManager
+{
+public:
+    DeviceManager();
+    ~DeviceManager();
+    string GetDeviceManagerOperationStatusString(DeviceManagerOperationStatus status);
+
+    DeviceManagerOperationStatus GetDevices(set<string>&);
+    DeviceManagerOperationStatus Read(string deviceName, DWORD address, DWORD& value);
+    DeviceManagerOperationStatus Write(string deviceName, DWORD address, DWORD value);
+    DeviceManagerOperationStatus ReadBlock(string deviceName, DWORD address, DWORD blockSize, vector<DWORD>& values);
+    DeviceManagerOperationStatus WriteBlock(string deviceName, DWORD address, const vector<DWORD>& values);
+    DeviceManagerOperationStatus InterfaceReset(string deviceName);
+    DeviceManagerOperationStatus SwReset(string deviceName);
+    DeviceManagerOperationStatus AllocPmc(string deviceName, unsigned descSize, unsigned descNum);
+    DeviceManagerOperationStatus DeallocPmc(string deviceName);
+    DeviceManagerOperationStatus CreatePmcFile(string deviceName, unsigned refNumber);
+    DeviceManagerOperationStatus SendWmi(string deviceName, DWORD command, const vector<DWORD>& payload);
+    DeviceManagerOperationStatus OpenInterface(string deviceName); // for backward compatibility
+    DeviceManagerOperationStatus CloseInterface(string deviceName);
+    DeviceManagerOperationStatus SetDriverMode(string deviceName, int newMode, int& oldMode);
+
+private:
+    void PeriodicTasks();
+    void UpdateConnectedDevices();
+    void CreateDevice(string deviceName);
+    void DeleteDevice(string deviceName);
+
+    unordered_map<string, shared_ptr<ConnectedDevice>> m_connectedDevices; // map from unique string (unique inside a host) to a connected device
+    unsigned const m_deviceManagerRestDurationMs;
+    thread m_deviceManager;
+    mutex m_connectedDevicesMutex;
+    atomic<bool> m_terminate;
+};
+
+#endif // !_DEVICEMANAGER_H_
diff --git a/debug-tools/host_manager_11ad/EventsTcpServer.cpp b/debug-tools/host_manager_11ad/EventsTcpServer.cpp
new file mode 100644
index 0000000..6bed5ce
--- /dev/null
+++ b/debug-tools/host_manager_11ad/EventsTcpServer.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "EventsTcpServer.h"
+
+EventsTcpServer::EventsTcpServer(unsigned int eventsTcpPort)
+    :m_port(eventsTcpPort), m_pSocket(new NetworkInterfaces::NetworkInterface())
+{
+}
+
+void EventsTcpServer::Start()
+{
+    LOG_INFO << "Starting events TCP server on port " << m_port << endl;
+    m_pSocket->Bind(m_port);
+    m_pSocket->Listen();
+
+    //Infinite loop because it has to wait for clients to connect to it forever, there's no reason to stop it
+    //unless there is a problem.
+    while (true)
+    {
+        try
+        {
+			NetworkInterfaces::NetworkInterface newClient = m_pSocket->Accept();
+            //LOG_INFO << "Adding a new client to the Events TCP Server: " << newClient.getPeerName() << endl;
+            //using unique_lock promises that in case of exception the mutex is unlocked:
+            unique_lock<mutex> clientsVectorLock(clientsVectorMutex);
+            clientsVector.push_back(newClient);
+            clientsVectorLock.unlock();
+        }
+        catch (exception e)
+        {
+            LOG_ERROR << "Couldn't start a new connection with a new client on events TCP server" << e.what() << endl;
+        }
+    }
+}
+
+bool EventsTcpServer::SendToAllConnectedClients(string message)
+{
+    try
+    {
+        //using unique_lock promises that in case of exception the mutex is unlocked:
+        unique_lock<mutex> clientsVectorLock(clientsVectorMutex); //locks the mutex in for loop because it iterates on clientsVector
+        for (auto client = clientsVector.begin(); client != clientsVector.end(); )
+        {
+            try
+            {
+                int bytesSent = (*client).Send(message);
+                if (bytesSent == 0)
+                { //it means the client had disconnected, remove the client from the clients list
+                    LOG_WARNING << "Client: " << (*client).GetPeerName() << " has disconnected, removing from the clients list" << endl;
+                    client = clientsVector.erase(client);
+                }
+                else
+                {
+                    ++client;
+                }
+            }
+            catch (exception e)
+            {
+                string peerName = "Unknown client";
+                if (client != clientsVector.end())
+                {
+                    peerName = (*client).GetPeerName();
+                }
+                LOG_WARNING << "Couldn't send the event to the client: " << peerName << " " << e.what() << endl;
+
+            }
+        }
+        clientsVectorLock.unlock(); //unlock the mutex on the for loop
+    }
+    catch (exception e)
+    {
+        LOG_WARNING << "Couldn't send the event to all the clients" << e.what() << endl;
+        return false;
+    }
+
+    return true;
+}
+
+void EventsTcpServer::Stop()
+{
+    LOG_INFO << "Stopping the events TCP server" << endl;
+    m_pSocket->Shutdown(2); //type 2 -> Acts like the close(), shutting down both input and output
+}
diff --git a/debug-tools/host_manager_11ad/EventsTcpServer.h b/debug-tools/host_manager_11ad/EventsTcpServer.h
new file mode 100644
index 0000000..9527cee
--- /dev/null
+++ b/debug-tools/host_manager_11ad/EventsTcpServer.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _EVENTSTCPSERVER_H_
+#define _EVENTSTCPSERVER_H_
+
+#include "NetworkInterface.h"
+#include <memory>
+#include <mutex>
+#include "HostDefinitions.h"
+#include "CommandsHandler.h"
+
+/*
+ *TODO - add a function to the events TCP server: when some client connects to the host server, the host server informs every client
+ *(include the one that just connected) that another client had connected to the host
+ */
+
+/*
+* Events TCP server is a asynchronous server that broadcasts events that come from the device or the host to all connected clients.
+* If a client wants to get events he has to connect this server (separately from the Commands TCP server).
+* This server doesn't get any messages from clients.
+*/
+class EventsTcpServer
+{
+public:
+    /*
+    * Events TCP server constructor gets the port to start in. It also initializes new Socket object.
+    */
+    EventsTcpServer(unsigned int eventsTcpPort);
+
+    /*
+    * Start the events TCP server at the given port (given in the constructor).
+    * For each new client that is connecting to the server, it adds it to a clients list.
+    */
+    void Start();
+
+    /*
+    * Send an event to all registered clients (clients that exist in the list).
+    * If the connection is lost, remove the client from the list (it is the client's responsibility
+    * to renew the connection with this server).
+    */
+    bool SendToAllConnectedClients(string message);
+
+    /*
+    * Stop the events TCP server by doing some clean ups for the sockets.
+    */
+    void Stop();
+
+private:
+    unsigned int m_port; //The port in which the events TCP server is working on
+    shared_ptr<NetworkInterfaces::NetworkInterface> m_pSocket;
+    // clientsVector is a vector that keeps all the clients that are connected to the server and want to get events from the device or the host
+    vector<NetworkInterfaces::NetworkInterface> clientsVector;
+    mutex clientsVectorMutex; //Two different (or more) threads can access the clients vector - a mutex is needed
+
+};
+
+
+
+#endif // !_EVENTSTCPSERVER_H_
diff --git a/debug-tools/host_manager_11ad/FileReader.cpp b/debug-tools/host_manager_11ad/FileReader.cpp
new file mode 100644
index 0000000..a5cc951
--- /dev/null
+++ b/debug-tools/host_manager_11ad/FileReader.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "FileReader.h"
+//#include "DebugLogger.h"
+
+#include <cstring>
+#include <cerrno>
+#include <stdio.h>
+
+// *************************************************************************************************
+
+FileReader::FileReader(const char* pFileName)
+    : m_FileName(pFileName)
+    , m_pFile(NULL)
+    , m_FileSize(0)
+    , m_ReadTillNow(0)
+    , m_IsCompleted(false)
+    , m_IsError(false)
+{
+    if (NULL == pFileName)
+    {
+        //LOG_ERROR << "No file name provided" << std::endl;
+        return;
+    }
+
+    //LOG_DEBUG << "Opening file reader for: " << m_FileName << std::endl;
+    m_pFile = fopen(pFileName, "rb");
+
+    if (NULL == m_pFile)
+    {
+        //int lastErrno = errno;
+        //LOG_ERROR << "Error opening file."
+            //<< " Name: " << pFileName
+            //<< " Error: " << lastErrno
+            //<< " Message: " << strerror(lastErrno)
+            //<< std::endl;
+        return;
+    }
+
+    fseek(m_pFile, 0, SEEK_END);
+    m_FileSize = ftell(m_pFile);
+    rewind(m_pFile);
+
+    //LOG_DEBUG << "Get file size for " << pFileName << ": " << m_FileSize << "B" << std::endl;
+}
+
+// *************************************************************************************************
+
+FileReader::~FileReader()
+{
+    if (m_pFile)
+    {
+        //LOG_DEBUG << "Closing the file: " << m_FileName << std::endl;
+        fclose(m_pFile);
+        m_pFile = NULL;
+    }
+}
+
+// *************************************************************************************************
+
+bool FileReader::CanReadFromFile(char* pBuf, size_t availableSpace)
+{
+    if (!pBuf)
+    {
+        //LOG_ERROR << "Cannot read from file " << m_FileName << ": "
+            //<< "No buffer is provided" << std::endl;
+        return false;
+    }
+
+    if (0 == availableSpace)
+    {
+        //LOG_ERROR << "Cannot read from file " << m_FileName << ": "
+            //<< "No buffer space is provided" << std::endl;
+        return false;
+    }
+
+    if (NULL == m_pFile)
+    {
+        //LOG_ERROR << "Cannot read from file " << m_FileName << ": "
+            //<< "No file handle is available" << std::endl;
+        return false;
+    }
+
+    if (m_IsCompleted)
+    {
+        //LOG_ERROR << "Unexpected read from file " << m_FileName << ": "
+            //<< "EoF is reached" << std::endl;
+        return false;
+    }
+
+    if (m_IsError)
+    {
+        //LOG_ERROR << "Unexpected read from file " << m_FileName << ": "
+            //<< "Error occured" << std::endl;
+        return false;
+    }
+
+    return true;
+
+}
+
+// *************************************************************************************************
+
+size_t FileReader::ReadChunk(char* pBuf, size_t availableSpace)
+{
+    //LOG_DEBUG << "Reading a chunk."
+        //<< " File Name: " << m_FileName
+        //<< " File Size: " << m_FileSize << "B"
+        //<< " Read till now: " << m_ReadTillNow << "B"
+        //<< " Buffer: " << availableSpace << "B"
+        //<< " Completed: " << BoolStr(m_IsCompleted)
+        //<< " Error: " << BoolStr(m_IsError)
+        //<< std::endl;
+
+    if (false == CanReadFromFile(pBuf, availableSpace))
+    {
+        //LOG_ERROR << "Cannot read from file: " << m_FileName
+            //<< " Check previous errors/status" << std::endl;
+        m_IsError = true;
+        return 0;
+    }
+
+    // Read up to availableSpace. Reading less means either EoF is reached or read error occured
+    size_t readBytes = fread(pBuf, 1, availableSpace, m_pFile);
+    m_ReadTillNow += readBytes;
+
+    if (feof(m_pFile))
+    {
+        //LOG_DEBUG << "EOF reached" << std::endl;
+        m_IsCompleted = true;
+    }
+
+    if (ferror(m_pFile))
+    {
+        //int lastErrno = errno;
+        m_IsError = true;
+        //LOG_ERROR << "Cannot read file"
+            //<< " Name: " << m_FileName
+            //<< " Error: " << lastErrno
+            //<< " Message:" << strerror(lastErrno)
+            //<< std::endl;
+    }
+
+    //LOG_VERBOSE << "Got a chunk."
+        //<< " File Name: " << m_FileName
+        //<< " File Size: " << m_FileSize << "B"
+        //<< " Read till now: " << m_ReadTillNow << "B"
+        //<< " Buffer: " << availableSpace << "B"
+        //<< " Completed: " << BoolStr(m_IsCompleted)
+        //<< " Error: " << BoolStr(m_IsError)
+        //<< std::endl;
+
+    return readBytes;
+
+}
diff --git a/debug-tools/host_manager_11ad/FileReader.h b/debug-tools/host_manager_11ad/FileReader.h
new file mode 100644
index 0000000..2b7b12f
--- /dev/null
+++ b/debug-tools/host_manager_11ad/FileReader.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _FILE_READER_H_
+#define _FILE_READER_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+
+// *************************************************************************************************
+
+// Reads a file from the file system and exports its content to a buffer provided by the caller.
+// If the file is larger than a provide bugffer, it is delivered by chunks of the buffer size.
+// The last chunk may occupy less than the whole buffer. It's a caller's responsibility to allocate
+// the buffer and call the FileReader API untill the file is fully exported.
+
+class FileReader
+{
+public:
+
+    explicit FileReader(const char* pFileName);
+    ~FileReader();
+
+    size_t ReadChunk(char* pBuf, size_t availableSpace);
+
+    bool IsCompleted() const { return m_ReadTillNow == m_FileSize; }
+    bool IsError() const { return m_IsError; }
+
+    size_t ReadTillNow() const { return m_ReadTillNow; }
+    size_t GetFileSize() const { return m_FileSize; }
+
+private:
+
+    bool CanReadFromFile(char* pBuf, size_t availableSpace);
+
+    const std::string m_FileName;        // File name - cached for tracing
+    FILE* m_pFile;                       // File Handler - open for read
+    size_t m_FileSize;                   // File Size
+    size_t m_ReadTillNow;                // Bytes read till now
+    bool m_IsCompleted;                  // Set to true when OEF is reached
+    bool m_IsError;                      // Error flag
+
+};
+
+
+#endif    // _FILE_READER_H_
diff --git a/debug-tools/host_manager_11ad/Host.cpp b/debug-tools/host_manager_11ad/Host.cpp
new file mode 100644
index 0000000..46a9450
--- /dev/null
+++ b/debug-tools/host_manager_11ad/Host.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "Host.h"
+#include "DebugLogger.h"
+#include <iostream>
+#include <thread>
+#include <functional> //Included for the "ref" in events TCP server thread
+#include "Utils.h"
+
+using namespace std;
+
+void Host::StartHost(unsigned int commandsTcpPort, unsigned int eventsTcpPort, unsigned int udpPortIn, unsigned int udpPortOut)
+{
+    m_pCommandsTcpServer.reset(new CommandsTcpServer(commandsTcpPort, *this));
+
+    if (!m_pCommandsTcpServer)
+    { //m_pCommandsTcpServer is NULL, couldn't set Socket
+        LOG_ERROR << "Couldn't set new socket for the commands TCP server" << endl;
+        throw "Couldn't set new socket for the commands TCP server";
+    }
+    thread threadCommandsTcpServer;
+    try
+    {
+        //threadCommandsTcpServer = thread(&CommandsTcpServer::Start, m_pCommandsTcpServer);
+        threadCommandsTcpServer = thread(&CommandsTcpServer::Start, m_pCommandsTcpServer.get());
+    }
+    catch (exception e)
+    {
+        LOG_ERROR << "Couldn't start commands TCP server" << endl;
+        throw "Couldn't start commands TCP server";
+    }
+
+    m_pEventsTcpServer.reset(new EventsTcpServer(eventsTcpPort));
+
+    if (!m_pEventsTcpServer)
+    { //m_pEventsTcpServer is NULL, couldn't set Socket
+        LOG_ERROR << "Couldn't set new socket for the events TCP server" << endl;
+        throw "Couldn't set new socket for the events TCP server";
+    }
+
+    thread threadEventsTcpServer;
+    try
+    {
+        //threadEventsTcpServer = thread(&EventsTcpServer::Start, m_pEventsTcpServer);
+        threadEventsTcpServer = thread(&EventsTcpServer::Start, m_pEventsTcpServer.get());
+    }
+    catch (exception e)
+    {
+        LOG_ERROR << "Couldn't start events TCP server" << endl;
+        throw "Couldn't start commands TCP server";
+    }
+
+    LOG_INFO << "Starting UDP server at port in: " << udpPortIn << ", and port out: " << udpPortOut << endl;
+
+    m_pUdpServer.reset(new UdpServer(udpPortIn, udpPortOut, *this));
+    if (!m_pUdpServer)
+    { //m_pUdpServer is NULL, couldn't set Socket
+        LOG_ERROR << "Couldn't set new socket for the UDP server" << endl;
+        throw "Couldn't set new socket for the UDP server";
+    }
+
+    thread threadUdpServer;
+    try
+    {
+        threadUdpServer = thread(&UdpServer::StartServer, m_pUdpServer);
+    }
+    catch (exception e)
+    {
+        LOG_ERROR << "Couldn't start UDP server thread" << e.what() << endl;
+        throw "Couldn't start UDP server thread";
+    }
+
+    threadCommandsTcpServer.join();
+    threadEventsTcpServer.join();
+    threadUdpServer.join();
+
+}
+
+void Host::StopHost()
+{
+    m_pCommandsTcpServer->Stop();
+    m_pEventsTcpServer->Stop();
+    m_pUdpServer->Stop();
+}
diff --git a/debug-tools/host_manager_11ad/Host.h b/debug-tools/host_manager_11ad/Host.h
new file mode 100644
index 0000000..e899259
--- /dev/null
+++ b/debug-tools/host_manager_11ad/Host.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _HOST_H_
+#define _HOST_H_
+
+//#include "Server.h"
+#include "CommandsTcpServer.h"
+#include "EventsTcpServer.h"
+#include "CommandsHandler.h"
+#include "UdpServer.h"
+#include "HostInfo.h"
+#include "DeviceManager.h"
+
+/*
+ * Host is a class that holds the TCP and UDP server.
+ * It also holds the Device Manager.
+ */
+class Host
+{
+public:
+
+    /*
+    * Host is s singletone due to HandleOsSignals - signal is a global function that can't get a pointer to the host as an argument
+    */
+    static Host& GetHost()
+    {
+        static Host host;
+        return host;
+    }
+
+
+    /*
+     * StratHost starts each one of the servers it holds
+     */
+    void StartHost(unsigned int commandsTcpPort, unsigned int eventsTcpPort, unsigned int udpPortIn, unsigned int udpPortOut);
+
+    /*
+     * StopHost stops each one of the servers it holds
+     */
+    void StopHost();
+
+    HostInfo& GetHostInfo() { return m_hostInfo; }
+
+    DeviceManager& GetDeviceManager() { return m_deviceManager;  }
+
+
+private:
+    shared_ptr<CommandsTcpServer> m_pCommandsTcpServer;
+    shared_ptr<EventsTcpServer> m_pEventsTcpServer;
+    shared_ptr<UdpServer> m_pUdpServer;
+    HostInfo m_hostInfo;
+    DeviceManager m_deviceManager;
+};
+
+
+#endif // ! _HOST_H_
diff --git a/debug-tools/host_manager_11ad/HostDefinitions.h b/debug-tools/host_manager_11ad/HostDefinitions.h
new file mode 100644
index 0000000..1db346a
--- /dev/null
+++ b/debug-tools/host_manager_11ad/HostDefinitions.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _DEFINITIONS_H_
+#define _DEFINITIONS_H_
+
+#include <string>
+#include <cstdint>
+#include "Utils.h"
+
+
+// *************************************************************************************************
+/*
+    * The reply data may be generated in several ways, the data is expected to be obtained according to this type
+    */
+enum REPLY_TYPE
+{
+    REPLY_TYPE_NONE,
+    REPLY_TYPE_BUFFER,
+    REPLY_TYPE_FILE
+};
+
+// *************************************************************************************************
+/*
+    * A response to the client, through the servers
+    */
+typedef struct
+{
+    std::string message;
+    REPLY_TYPE type;
+    unsigned int length;
+} ResponseMessage;
+
+// *************************************************************************************************
+/*
+    * ConnectionStatus indicates whether to close a connection with a client or not.
+    */
+enum ConnectionStatus
+{
+    CLOSE_CONNECTION,
+    KEEP_CONNECTION_ALIVE
+};
+
+// **************************** Events Structures and Enum Types **************************************
+/*
+    * Define an event struct which would be sent as bytes in packed mode.
+    * The concept is to send the smallest message we can as it being sent many times and to multiple clients.
+    * NOTE that the __exactly__ same struct is defined in the side that gets this struct.
+    * The structures sent in packed mode (by using "#pragma pack(push, 1)")
+    */
+
+#pragma pack(push, 1) //following structures would be in packed mode
+
+enum HOST_EVENT_TYPE : uint8_t
+{
+    VERSION_CHANGED,
+    CONNECTED_USERS_CHANGED,
+    DEVICES_LIST_CHANGED,
+    DEVICE_EVENT
+};
+
+struct HostEvent
+{
+    HostEvent(HOST_EVENT_TYPE hostEventType) :
+        m_marker("TheUtopicHostManager11ad"),
+        m_currentTime(Utils::GetCurrentLocalTime()),
+        m_eventType(hostEventType)
+    { }
+
+    const string m_marker; // for stream synchronization in DmTools
+    string m_currentTime; // event's genaration time, in YYYY-MM-DD HH:mm:ss.<ms><ms><ms> format
+    HOST_EVENT_TYPE m_eventType; //Value size is uint8_t
+    uint32_t m_payloadSize;
+    uint8_t *payLoad; //The size of the payload (which is the raw data from the device) is given in "payloadSize"
+};
+
+//The type of the event coming from the device - as the device aware of it
+enum DEVICE_EVENT_TYPE : uint8_t
+{
+    WMI_EVENT,
+    LOG_EVENT,
+    POLLER_EVENT
+};
+
+typedef enum _DRIVER_MODE {
+	IOCTL_WBE_MODE,
+	IOCTL_WIFI_STA_MODE,
+	IOCTL_WIFI_SOFTAP_MODE,
+	IOCTL_CONCURRENT_MODE,    // This mode is for a full concurrent implementation  (not required mode switch between WBE/WIFI/SOFTAP)
+	IOCTL_SAFE_MODE,          // A safe mode required for driver for protected flows like upgrade and crash dump...
+} DRIVER_MODE;
+
+struct DeviceEvent : public HostEvent
+{
+    DeviceEvent(DEVICE_EVENT_TYPE deviceEventType) :
+        HostEvent(DEVICE_EVENT),
+        m_deviceEventType(deviceEventType)
+        {}
+
+    DEVICE_EVENT_TYPE m_deviceEventType; //This value size is uint8_t
+    uint16_t m_deviceNameSize; //This value would be sent with the package
+    uint8_t* m_deviceName; //The size of the device name is in "deviceNameSize"
+    uint32_t m_payloadSize;
+    uint8_t* m_payLoad; //The size of the payload (which is the raw data from the device) is given in "payloadSize"
+};
+
+
+//Example for another host event
+//typedef struct _DevicesChangedEvent : HostEvent
+//{
+//
+//} DevicesChangedEvent;
+
+#pragma pack(pop) //stop using packed mode
+
+// *************************************************************************************************
+
+#define MAX_REGS_LEN    (256* 1024)    // Max registers to read/write at once //TODO - is it needed? maybe read until line terminator?
+
+// Max buffer size for a command and a reply. We should consider the longest command/data sequence to fit in a buffer.
+// rb reading 1024 (MAX_REGS_LEN) registers: rb HHHHHHHH HHHH 1024*(0xHHHHHHHH) = 17 + 1024*10 = 10257 bytes
+// wb writing 1024 (MAX_REGS_LEN) hex values: wb HHHHHHHH "1024*HH" = 14+1024*2 = 2062 bytes
+#define MAX_INPUT_BUF (11*MAX_REGS_LEN) //TODO - is it needed? maybe read until line terminator?
+
+// *************************************************************************************************
+
+struct HostIps
+{
+    HostIps() :
+        m_ip(""),
+        m_broadcastIp("")
+    {}
+
+    std::string m_ip; // host's IP address
+    std::string m_broadcastIp; // host's broadcast IP address (derivated by subnet mask)
+};
+
+// *************************************************************************************************
+
+enum ServerType
+{
+    stTcp,
+    stUdp
+};
+
+#endif // !_DEFINITIONS_H_
diff --git a/debug-tools/host_manager_11ad/HostInfo.cpp b/debug-tools/host_manager_11ad/HostInfo.cpp
new file mode 100644
index 0000000..735ce31
--- /dev/null
+++ b/debug-tools/host_manager_11ad/HostInfo.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "HostInfo.h"
+#include "DebugLogger.h"
+#include "UdpTempOsAbstruction.h"
+#include <iostream>
+
+HostInfo::HostInfo() :
+    m_alias(""),
+    m_persistencyPath(UdpTempOsAbstruction::GetPersistencyLocation() + "host_manager_11ad"),
+    m_aliasFileName(UdpTempOsAbstruction::GetDirectoriesDilimeter() + "host_alias"),
+    m_oldHostAliasFile(UdpTempOsAbstruction::GetPersistencyLocation() + "wigig_remoteserver_details"),
+    m_isAliasFileChanged(false)
+{
+    LoadHostInfo();
+}
+
+const HostIps& HostInfo::GetIps()
+{
+    return m_ips;
+}
+
+string HostInfo::GetAlias()
+{
+    if (m_isAliasFileChanged)
+    {
+        UpdateAliasFromFile();
+    }
+    return m_alias;
+}
+
+bool HostInfo::SaveAliasToFile(string newAlias)
+{
+    m_persistencyLock.lock();
+    if (!UdpTempOsAbstruction::WriteFile(m_persistencyPath + m_aliasFileName, newAlias))
+    {
+        LOG_WARNING << "Failed to write new alias to configuration file " << m_persistencyPath << m_aliasFileName << endl;
+        return false;
+    }
+    m_isAliasFileChanged = true;
+    m_persistencyLock.unlock();
+    return true;
+}
+
+bool HostInfo::UpdateAliasFromFile()
+{
+    m_persistencyLock.lock();
+    if (!UdpTempOsAbstruction::ReadFile(m_persistencyPath + m_aliasFileName, m_alias))
+    {
+        LOG_WARNING << "Failed to write new alias to configuration file " << m_persistencyPath << m_aliasFileName << endl;
+        return false;
+    }
+    m_isAliasFileChanged = false;
+    m_persistencyLock.unlock();
+    return true;
+}
+
+
+//void HostInfo::LoadHostInfo()
+//{
+//    m_ips = UdpTempOsAbstruction::GetHostIps();
+//
+//    bool res = UdpTempOsAbstruction::ReadFile(m_persistencyPath, m_alias);
+//    if (!res) // file doesn't exist
+//    {
+//        /*
+//        res = UdpTempOsAbstruction::CreateFile(m_persistencyPath)
+//        if (!res)
+//        {
+//            cout << "Failed to create persistency file" << endl;
+//            m_alias = "";
+//            return;
+//        }
+//        */
+//        res = UdpTempOsAbstruction::ReadHostOsAlias(m_alias);
+//        if (!res)
+//        {
+//            cout << "Failed to read OS host name" << endl;
+//            m_alias = "";
+//        }
+//        res = UdpTempOsAbstruction::WriteFile(m_persistencyPath, m_alias);
+//        if (!res)
+//        {
+//            cout << "Failed to write host alias to persistency" << endl;
+//        }
+//    }
+//}
+
+void HostInfo::LoadHostInfo()
+{
+    m_ips = UdpTempOsAbstruction::GetHostIps();
+
+    // create host manager directory if doesn't exist
+    bool res = UdpTempOsAbstruction::IsFolderExists(m_persistencyPath);
+    if (!res)
+    {
+        res = UdpTempOsAbstruction::CreateFolder(m_persistencyPath);
+        if (!res)
+        {
+            LOG_WARNING << "Failed to create " << m_persistencyPath << " directory" << endl;
+            return;
+        }
+        // backward compatibility - copy the alias that the user already given to its new place
+        if (UdpTempOsAbstruction::IsFileExists(m_oldHostAliasFile))
+        {
+            UdpTempOsAbstruction::MoveFileToNewLocation(m_oldHostAliasFile, m_persistencyPath + m_aliasFileName);
+        }
+    }
+
+    res = UdpTempOsAbstruction::ReadFile(m_persistencyPath + m_aliasFileName, m_alias);
+    if (!res) // file doesn't exist
+    {
+        res = UdpTempOsAbstruction::ReadHostOsAlias(m_alias);
+        if (!res)
+        {
+            LOG_WARNING << "Failed to read OS host name" << endl;
+            m_alias = "";
+        }
+        res = UdpTempOsAbstruction::WriteFile(m_persistencyPath + m_aliasFileName, m_alias);
+        if (!res)
+        {
+            LOG_WARNING << "Failed to write host alias to persistency" << endl;
+        }
+    }
+}
diff --git a/debug-tools/host_manager_11ad/HostInfo.h b/debug-tools/host_manager_11ad/HostInfo.h
new file mode 100644
index 0000000..98acbe5
--- /dev/null
+++ b/debug-tools/host_manager_11ad/HostInfo.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _HOSTINFO_H_
+#define _HOSTINFO_H_
+
+#include <string>
+#include <memory>
+#include <atomic>
+#include <mutex>
+#include <set>
+
+#include "HostDefinitions.h"
+
+using namespace std;
+
+class HostInfo
+{
+
+public:
+
+    /*
+    HostInfo
+    Initializes all hostInfo members (ips and alias)
+    */
+    HostInfo();
+
+    /*
+    GetIps
+    Returns host's Ips (private and broadcast)
+    @param: none
+    @return: host's ips
+    */
+    const HostIps& GetIps();
+
+    /*
+    GetHostAlias
+    Returns host's alias (if one was given by the user)
+    @param: none
+    @return: host's alias if exists, otherwise empty string
+    */
+    string GetAlias();
+
+    /*
+    SaveAliasToFile
+    Gets a new alias for the host and saves it to a configuration file.
+    This function is called from CommandsTcpServer only. It turns on a flag so that the UDP server (that is on a different thread) will check for the new alias
+    @param: string - the new alias
+    @return: bool - operation status - true for success, false otherwise
+    */
+    bool SaveAliasToFile(string newAlias);
+
+    /*
+    UpdateAliasFromFile
+    Updates the m_alias member with the host's alias from 11ad's persistency
+    @param: none
+    @return: bool - operation status - true for success, false otherwise
+    */
+    bool UpdateAliasFromFile();
+
+    /*
+    GetConnectedUsers
+    Returns a set of all the users that are connected to this host
+    @param: none
+    @return: set<string> of all connected users
+    */
+    const set<string>& GetConnectedUsers() { return m_connectedUsers;  }
+
+    /*
+    AddNewConnectedUser
+    Adds a user to the connected user's list
+    @param: string - a new user (currently the user's DmTools's IP. TODO: change to the user's personal host's name or user's DmTools username)
+    @return: none
+    */
+    void AddNewConnectedUser(string user) { m_connectedUsers.insert(user); }
+
+    /*
+    RemoveConnectedUser
+    Removes a user from the connected user's list
+    @param: string - a user (currently the user's DmTools's IP. TODO: change to the user's personal host's name or user's DmTools username)
+    @return: none
+    */
+    void RemoveNewConnectedUser(string user) { m_connectedUsers.erase(user); }
+
+    string GetVersion() { return m_version;  }
+
+
+private:
+    HostIps m_ips; // host's network details // assumption: each host has only one IP address for ethernet interfaces
+    string m_alias; // host's alias (given by user)
+    const string m_persistencyPath; // host server's files location
+    const string m_aliasFileName; // host's alias file
+    const string m_oldHostAliasFile; // old location of the host alias
+    set<string> m_connectedUsers; // list of users IPs that have a connection to the commandsTcpServer // TODO: change to the user's personal host's name or user's DmTools username
+    string m_version; // host_manager_11ad version // TODO: update m_version
+    atomic<bool> m_isAliasFileChanged; // when turned on indicates that m_alias contains stale information, so we need to update it from persistency
+    mutex m_persistencyLock; // only one thread is allowed to change persistency at a time
+
+    // load host's info from persistency and ioctls
+    void LoadHostInfo();
+};
+
+
+#endif
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/Makefile b/debug-tools/host_manager_11ad/Makefile
new file mode 100644
index 0000000..3c39b3c
--- /dev/null
+++ b/debug-tools/host_manager_11ad/Makefile
@@ -0,0 +1,39 @@
+-include $(TOPDIR)/rules.mk
+
+CPPFLAGS := -Wall -g -MMD -std=c++0x -fPIE
+LDFLAGS := -pthread -fPIE -pie
+
+ifneq ($(CONFIG_TARGET_ipq)$(CONFIG_TARGET_ipq806x),)
+is_ipq806x = 1
+endif
+
+ifeq ($(is_ipq806x), 1)
+ifneq ($(strip $(TOOLPREFIX)),)
+CROSS:=$(TOOLPREFIX)
+endif
+endif
+
+CXX := $(CROSS)g++
+
+.DEFAULT_GOAL = all
+PROG = host_manager_11ad
+
+INCLUDE_CFLAGS += -I access_layer_11ad \
+                  -I access_layer_11ad/Unix \
+
+all: $(PROG)
+
+CPP_FILES = $(shell find . -type f -name '*.cpp')
+OBJ_FILES=  $(CPP_FILES:.cpp=.o)
+
+$(PROG): $(OBJ_FILES) $(LIBS)
+	$(CXX) -o $@ $^ $(LDFLAGS) $(LIBS)
+
+%.o : %.cpp
+	$(CXX) $(CPPFLAGS) $(INCLUDE_CFLAGS) -o $@ -c $<
+
+clean:
+	rm -rf $(PROG)
+	find . -type f \( -name "*.d" -o -name "*.o" \) -delete
+
+-include $(OBJ_FILES:%.o=%.d)
diff --git a/debug-tools/host_manager_11ad/MessageParser.cpp b/debug-tools/host_manager_11ad/MessageParser.cpp
new file mode 100644
index 0000000..ede3ba1
--- /dev/null
+++ b/debug-tools/host_manager_11ad/MessageParser.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "MessageParser.h"
+//#include <regex>
+#include <sstream>
+
+// *************************************************************************************************
+
+MessageParser::MessageParser(string message)
+    :m_message(message)
+{
+    char delimeter = '|'; //The new separator in a message is: "|", the old one is " ", keep the old one for backward compatibility
+    if (message.find_first_of(delimeter) == string::npos)
+    { //The new separator is *not* in the message, that means that the message is in the old format
+        delimeter = ' ';
+    }
+    m_splitMessage = m_SplitMessageByDelim(m_message, delimeter);
+}
+
+// *************************************************************************************************
+vector<string> MessageParser::m_SplitMessageByDelim(const string &message, char delim)
+{
+    vector<string> splitMessage;
+    stringstream sstream(message);
+    string word;
+    while (getline(sstream, word, delim))
+    {
+        if (word.empty())
+        { //don't push whitespace
+            continue;
+        }
+        splitMessage.push_back(word);
+    }
+    return splitMessage;
+}
+
+// *************************************************************************************************
+
+string MessageParser::GetCommandFromMessage()
+{
+    return string(m_splitMessage.front());
+
+}
+
+
+// *************************************************************************************************
+
+vector<string> MessageParser::GetArgsFromMessage()
+{
+    vector<string> temp = m_splitMessage;
+    temp.erase(temp.begin());
+    return temp;
+}
+
+// *************************************************************************************************
+
+unsigned int MessageParser::GetNumberOfArgs()
+{
+    return (m_splitMessage.size()-1); //(-1) because the function name is in also in the message
+}
diff --git a/debug-tools/host_manager_11ad/MessageParser.h b/debug-tools/host_manager_11ad/MessageParser.h
new file mode 100644
index 0000000..07c31b2
--- /dev/null
+++ b/debug-tools/host_manager_11ad/MessageParser.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _MESSAGEPARSER_H
+#define _MESSAGEPARSER_H
+
+#include <iostream>
+#include "DebugLogger.h"
+#include <vector>
+
+using namespace std;
+
+// *************************************************************************************************
+
+class MessageParser
+{
+public:
+
+    MessageParser(string message);
+
+    /*
+     * Returns the command name from the message. Command name should be the first parameter in the message.
+     */
+    string GetCommandFromMessage();
+
+    vector<string> GetArgsFromMessage();
+
+    unsigned int GetNumberOfArgs();
+
+private:
+    string m_message; //holds the initial message - before was being parsed
+    vector<string> m_splitMessage;
+
+    vector<string> m_SplitMessageByDelim(const string &message, char delim);
+
+};
+
+#endif // !_MESSAGEPARSER_H
diff --git a/debug-tools/host_manager_11ad/NetworkInterface.cpp b/debug-tools/host_manager_11ad/NetworkInterface.cpp
new file mode 100644
index 0000000..ac9884b
--- /dev/null
+++ b/debug-tools/host_manager_11ad/NetworkInterface.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "NetworkInterface.h"
+#include "DebugLogger.h"
+
+#include <cerrno>
+
+using namespace NetworkInterfaces;
+
+NetworkInterface::NetworkInterface()
+{
+#ifdef _WINDOWS
+    WSADATA wsa;
+
+    if (-1 == WSAStartup(MAKEWORD(2, 0), &wsa))
+    {
+        LOG_ERROR << "Cannot initialize network library" << std::endl;
+        exit(1);
+    }
+#endif
+
+    m_fileDescriptor = socket(AF_INET, SOCK_STREAM, 0);
+    if (m_fileDescriptor < 0)
+    {
+        LOG_ERROR << "Cannot create socket file descriptor: " << strerror(errno) << std::endl;
+        exit(1);
+    }
+
+    char optval = 1;
+    setsockopt(m_fileDescriptor, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+
+    m_localAddress.sin_family = AF_INET;
+    m_bufferSize = 0;
+    m_buffer = NULL;
+}
+
+NetworkInterface::NetworkInterface(int fileDescriptor)
+    : m_fileDescriptor(fileDescriptor)
+    , m_buffer(NULL)
+    , m_bufferSize(0)
+{
+}
+
+// Establish Connections
+void NetworkInterface::Bind(int port)
+{
+    m_localAddress.sin_port = htons(port);
+    m_localAddress.sin_addr.s_addr = INADDR_ANY;
+    memset(m_localAddress.sin_zero, '\0', sizeof m_localAddress.sin_zero);
+
+    if (-1 == bind(m_fileDescriptor, (struct sockaddr*)&m_localAddress, sizeof(m_localAddress)))
+    {
+        LOG_ERROR << "Cannot bind listener to port " << port << ": " << strerror(errno) << std::endl;
+        LOG_ERROR << "Please verify if another application instance is running" << std::endl;
+        exit(1);
+    }
+}
+
+void NetworkInterface::Listen(int backlog)
+{
+    if (-1 == listen(m_fileDescriptor, backlog))
+    {
+        LOG_ERROR << "Cannot listen to the socket: " << strerror(errno) << std::endl;
+        LOG_ERROR << "Please verify if another application instance is running" << std::endl;
+        exit(1);
+    }
+}
+
+NetworkInterface NetworkInterface::Accept()
+{
+    struct sockaddr_in remoteAddress;
+    socklen_t size = sizeof(remoteAddress);
+
+    int fileDescriptor = accept(m_fileDescriptor, (struct sockaddr*)&remoteAddress, &size);
+    if (fileDescriptor <= 0)
+    {
+        LOG_ERROR << "Cannot accept incoming connection: " << strerror(errno) << std::endl;
+        exit(1);
+    }
+
+    return NetworkInterface(fileDescriptor);
+}
+
+// Send and Receive
+int NetworkInterface::Send(const std::string& data)
+{
+    return send(m_fileDescriptor, data.c_str(), data.size(), 0);
+}
+
+int NetworkInterface::Send(const char* data)
+{
+    return send(m_fileDescriptor, data, strlen(data), 0);
+}
+
+const char* NetworkInterface::Receive(int size, int flags)
+{
+    if (m_bufferSize <= size + 1)
+    {
+        m_buffer = (char*)(realloc(m_buffer, sizeof(char) * (size + 1)));
+        m_bufferSize = size;
+    }
+
+    int bytesReceived = recv(m_fileDescriptor, m_buffer, size, flags);
+    m_buffer[bytesReceived] = '\0';
+
+    return m_buffer;
+}
+
+// Socket Closing Functions
+void NetworkInterface::Close()
+{
+#ifdef _WINDOWS
+    WSACleanup();
+    closesocket(m_fileDescriptor);
+#else
+    close(m_fileDescriptor);
+#endif
+}
+
+void NetworkInterface::Shutdown(int type)
+{
+#ifdef _WINDOWS
+    WSACleanup();
+#endif
+
+    shutdown(m_fileDescriptor, type);
+}
+
+const char* NetworkInterface::GetPeerName() const
+{
+    struct sockaddr_in remoteAddress;
+    socklen_t size = sizeof(remoteAddress);
+
+    if (-1 == getpeername(m_fileDescriptor, (struct sockaddr*)&remoteAddress, &size))
+    {
+        LOG_ERROR << "Failure in getpeername" << std::endl;
+        exit(1);
+    }
+
+    return inet_ntoa(remoteAddress.sin_addr);
+}
diff --git a/debug-tools/host_manager_11ad/NetworkInterface.h b/debug-tools/host_manager_11ad/NetworkInterface.h
new file mode 100644
index 0000000..7f1c40e
--- /dev/null
+++ b/debug-tools/host_manager_11ad/NetworkInterface.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _SOCKET_H_
+#define _SOCKET_H_
+
+#ifdef _WINDOWS
+#pragma comment(lib, "Ws2_32.lib")
+#endif
+
+#include <cstdlib>
+#include <cstdio>
+#include <cerrno>
+#include <cstring>
+#include <string>
+
+#ifdef _WINDOWS
+#include <winsock.h>
+#elif __linux
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+#else
+
+#endif
+
+#ifdef _WINDOWS
+typedef int socklen_t;
+#endif
+
+
+namespace NetworkInterfaces
+{
+    class NetworkInterface
+    {
+    private:
+
+        int m_fileDescriptor;
+        struct sockaddr_in m_localAddress;
+        char* m_buffer;
+        int m_bufferSize;
+
+    public:
+
+        NetworkInterface();
+        explicit NetworkInterface(int sockfd);
+
+        // Establish Connection
+        void Bind(int portNumber);
+        void Listen(int backlog = 5);
+        NetworkInterface Accept();
+
+        // Send and Receive
+        int Send(const char* data);
+        int Send(const std::string& data);
+        const char* Receive(int size = 1024, int flags = 0);
+
+        // Terminate Connection
+        void Close();
+        void Shutdown(int type);
+
+        // Addresses
+        const char* GetPeerName() const;
+    };
+
+}
+
+#endif // !_NETWORK_INTERFACE_H_
diff --git a/debug-tools/host_manager_11ad/OsHandler.cpp b/debug-tools/host_manager_11ad/OsHandler.cpp
new file mode 100644
index 0000000..324d8c5
--- /dev/null
+++ b/debug-tools/host_manager_11ad/OsHandler.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "OsHandler.h"
+#include <memory>
+#include <iostream> //TODO - maybe to remove
+#include "Host.h"
+using namespace std; //TODO - maybe to remove
+
+#ifdef __linux
+void sig_quit_handler(int signum)
+{
+    if (signum == SIGQUIT)
+    {
+        printf("Exiting host_manager_11ad as per user request\n");
+        Host::GetHost().StopHost();
+        exit(signum);
+    }
+    else if (signum == SIGPIPE)
+    {
+        //printf("Connection lost\n");
+    }
+}
+#endif // __linux
+
+
+// *************************************************************************************************
+
+void OsHandler::HandleOsSignals()
+{
+#ifdef __linux
+    //LOG_INFO << "Handle linux SIQQUIT signal" << endl;
+    signal(SIGQUIT, sig_quit_handler);
+    signal(SIGPIPE, sig_quit_handler);
+#endif // __linux
+
+}
diff --git a/debug-tools/host_manager_11ad/OsHandler.h b/debug-tools/host_manager_11ad/OsHandler.h
new file mode 100644
index 0000000..8c4eb90
--- /dev/null
+++ b/debug-tools/host_manager_11ad/OsHandler.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _OSHANDLER_H_
+#define _OSHANDLER_H_
+
+
+
+// *************************************************************************************************
+
+/*
+* Class handling specific OS implementations
+*/
+class OsHandler
+{
+public:
+
+    /*
+    * Function to handle os signals - mostly relevant for linux os.
+    */
+    void HandleOsSignals();
+};
+
+#endif // _OSHANDLER_H_
+
diff --git a/debug-tools/host_manager_11ad/UdpServer.cpp b/debug-tools/host_manager_11ad/UdpServer.cpp
new file mode 100644
index 0000000..af08c25
--- /dev/null
+++ b/debug-tools/host_manager_11ad/UdpServer.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "UdpServer.h"
+#include "UdpTempOsAbstruction.h"
+#include "CommandsHandler.h"
+#include "Host.h"
+
+const int UdpServer::m_maxMessageLength = 1024;
+
+UdpServer::UdpServer(unsigned int udpPortIn, unsigned int udpPortOut, Host& host) :
+    m_udpPortIn(udpPortIn),
+    m_udpPortOut(udpPortOut),
+    m_broadcastIp(host.GetHostInfo().GetIps().m_broadcastIp),
+    m_CommandHandler(stUdp, host)
+{
+    try
+    {
+        m_pSocket.reset(new UdpSocket(m_broadcastIp, udpPortIn, udpPortOut));
+    }
+    catch (string error)
+    {
+        LOG_WARNING << "Failed to open UDP socket: " << error << endl;
+        m_pSocket.reset();
+    }
+}
+
+void UdpServer::StartServer()
+{
+    if (UdpTempOsAbstruction::LOCAL_HOST_IP == m_broadcastIp)
+    {
+        LOG_WARNING << "Can't start UDP server due to invalid host's IP/ broadcast IP";
+        return;
+    }
+
+    if (m_pSocket)
+    {
+        LOG_DEBUG << "Start UDP server on local port " << m_udpPortIn << std::endl;
+        LOG_DEBUG << "Broadcast messages are sent to port " << m_udpPortOut << std::endl;
+        BlockingReceive();
+    }
+}
+
+void UdpServer::Stop()
+{
+    m_pSocket.reset();
+}
+
+void UdpServer::BlockingReceive()
+{
+    do
+    {
+        const char* incomingMessage = m_pSocket->Receive(m_maxMessageLength);
+        LOG_VERBOSE << "Got Udp message: " << incomingMessage << endl;
+        ResponseMessage referencedResponse = { "", REPLY_TYPE_NONE, 0 };
+        m_CommandHandler.ExecuteCommand(incomingMessage, referencedResponse);
+        if (referencedResponse.length > 0)
+        {
+            LOG_VERBOSE << "Send broadcast message" << endl;
+            SendBroadcastMessage(referencedResponse);
+        }
+
+    } while (true);
+}
+
+void UdpServer::SendBroadcastMessage(ResponseMessage responseMessage)
+{
+    m_pSocket->Send(responseMessage.message);
+}
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/UdpServer.h b/debug-tools/host_manager_11ad/UdpServer.h
new file mode 100644
index 0000000..f9324f7
--- /dev/null
+++ b/debug-tools/host_manager_11ad/UdpServer.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _UDPSERVER_H_
+#define _UDPSERVER_H_
+
+#include <string>
+#include <thread>
+#include "HostDefinitions.h"
+#include "CommandsHandler.h"
+#include "UdpTempOsAbstruction.h"
+
+class Host;
+
+class UdpServer
+{
+public:
+    /*
+    UdpServer
+    Creates a UDP socket which receives messages from the network and can response using a broadcast option
+    */
+    UdpServer(unsigned int udpPortIn, unsigned int udpPortOut, Host& host);
+
+    /*
+    StartServer
+    Starts to receive messages, Handles the message and continue to the receive
+    @param: none
+    @return: none
+    */
+    void StartServer();
+
+    /*
+    StopServer
+    Stops receiving messages
+    @param: none
+    @return: none
+    */
+    void Stop();
+
+private:
+    /*
+    BlockingReceive
+    Waits for a UDP message and handles it
+    Assumption: m_pSocket is valid
+    @param: none
+    @return: none
+    */
+    void BlockingReceive();
+
+    /*
+    SendBroadcastMessage
+    Sends a message to all hosts in the subnet
+    Assumption: m_pSocket is valid
+    @param: responseMessage - the message to send
+    @return: none
+    */
+    void SendBroadcastMessage(ResponseMessage responseMessage);
+
+    unsigned int m_udpPortIn; // the local host port
+    unsigned int m_udpPortOut; // the remote host port
+    string m_broadcastIp;
+    unique_ptr<UdpSocket> m_pSocket;
+    CommandsHandler m_CommandHandler;
+    static const int m_maxMessageLength;
+};
+
+
+#endif // !_UDPSERVER_H_
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/UdpTempOsAbstruction.cpp b/debug-tools/host_manager_11ad/UdpTempOsAbstruction.cpp
new file mode 100644
index 0000000..dc951f0
--- /dev/null
+++ b/debug-tools/host_manager_11ad/UdpTempOsAbstruction.cpp
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifdef __linux
+#include <sys/ioctl.h> // for struct ifreq
+#include <net/if.h> // for struct ifreq
+
+#include <stdlib.h>
+#include <string.h>
+#include <cerrno>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdio.h>
+
+#else
+#include <windows.h>
+#endif
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include "DebugLogger.h"
+#include "UdpTempOsAbstruction.h"
+
+const std::string UdpTempOsAbstruction::LOCAL_HOST_IP = "127.0.0.1";
+
+bool UdpTempOsAbstruction::FindEthernetInterface(struct ifreq& ifr, int& fd)
+{
+#ifdef __linux
+    fd = socket(AF_INET, SOCK_DGRAM, 0);
+    if (fd < 0)
+    {
+        LOG_WARNING << "Failed to get host's IP address and broadcast IP address" << std::endl;
+        return false;
+    }
+
+    for (int i = 0; i < 100; i++)
+    {
+        snprintf(ifr.ifr_name, IFNAMSIZ - 1, "eth%d", i);
+
+        if (ioctl(fd, SIOCGIFADDR, &ifr) >= 0)
+        {
+            return true;
+        }
+    }
+#endif
+    return false;
+}
+
+HostIps UdpTempOsAbstruction::GetHostIps()
+{
+#ifdef __linux
+    HostIps hostIps;
+    int fd;
+    struct ifreq ifr;
+
+    ifr.ifr_addr.sa_family = AF_INET; // IP4V
+
+    // Get IP address according to OS
+    if (FindEthernetInterface(ifr, fd))
+    {
+        LOG_INFO << "Linux OS" << std::endl;
+    }
+    else
+    {
+        strncpy(ifr.ifr_name, "br-lan", IFNAMSIZ - 1);
+        if (ioctl(fd, SIOCGIFADDR, &ifr) >= 0)
+        {
+            LOG_INFO << "OpenWRT OS" << std::endl;
+        }
+        else
+        {
+            // Probably Android OS
+            LOG_INFO << "Android OS (no external IP Adress)" << std::endl;
+            hostIps.m_ip = UdpTempOsAbstruction::LOCAL_HOST_IP;
+            hostIps.m_broadcastIp = UdpTempOsAbstruction::LOCAL_HOST_IP;
+            return hostIps;
+        }
+    }
+
+    hostIps.m_ip = inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr);
+
+    if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
+    {
+        LOG_WARNING << "Failed to get broadcast IP" << std::endl;
+        return hostIps;
+    }
+    hostIps.m_broadcastIp = inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr);
+    LOG_DEBUG << "Host's IP address is " << hostIps.m_ip << std::endl;
+    LOG_DEBUG << "Broadcast IP address is " << hostIps.m_broadcastIp << std::endl;
+
+    close(fd);
+    return hostIps;
+#else
+    HostIps empty;
+    empty.m_broadcastIp = "10.18.172.155";
+    return empty;
+#endif
+}
+
+bool UdpTempOsAbstruction::ReadFile(string fileName, string& data)
+{
+    ifstream fd(fileName.c_str());
+    if (!fd.good()) // file doesn't exist
+    {
+        data = "";
+        return false;
+    }
+
+    fd.open(fileName.c_str());
+    stringstream content;
+    content << fd.rdbuf();
+    fd.close();
+    data = content.str();
+    return true;
+}
+
+bool UdpTempOsAbstruction::WriteFile(string fileName, string content)
+{
+    std::ofstream fd(fileName.c_str());
+    if (!fd.is_open())
+    {
+        LOG_WARNING << "Failed to open file: " << fileName << std::endl;
+        return false;
+    }
+    fd << content;
+    if (fd.bad())
+    {
+        LOG_WARNING << "Failed to write to file: " << fileName << std::endl;
+        fd.close();
+        return false;
+    }
+    fd.close();
+    return true;
+}
+
+string UdpTempOsAbstruction::GetPersistencyLocation()
+{
+#ifdef __linux
+    return "/etc/";
+#else
+    return "C:\\Temp\\"; // TODO: change
+#endif // __linux
+}
+
+string UdpTempOsAbstruction::GetDirectoriesDilimeter()
+{
+#ifdef __linux
+    return "/";
+#else
+    return "\\";
+#endif
+}
+
+bool UdpTempOsAbstruction::ReadHostOsAlias(string& alias)
+{
+#ifdef __linux
+    if (!ReadFile("/etc/hostname", alias))
+    {
+        alias = "";
+        return false;
+    }
+    return true;
+#else
+    alias = "";
+    return false;
+#endif // __linux
+}
+
+bool UdpTempOsAbstruction::IsFolderExists(string path)
+{
+#ifdef __linux
+    DIR* pDir = opendir(path.c_str());
+    if (pDir != NULL)
+    {
+        (void)closedir(pDir);
+        return true;
+    }
+    return false;
+#else
+    DWORD fileAttributes = GetFileAttributesA(path.c_str());
+    if (INVALID_FILE_ATTRIBUTES == fileAttributes) // no such path
+    {
+        return false;
+    }
+    if (fileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+    {
+        return true;   // given path is a directory
+    }
+    return false;    // given path isn't a directory
+#endif
+}
+
+bool UdpTempOsAbstruction::IsFileExists(string path)
+{
+    ifstream f(path.c_str());
+    return f.good();
+}
+
+bool UdpTempOsAbstruction::CreateFolder(string path)
+{
+#ifdef __linux
+    system(("mkdir " + path).c_str());
+    return true;
+#else
+    // not Implemented yet
+    return false;
+#endif
+}
+
+void UdpTempOsAbstruction::MoveFileToNewLocation(string oldFileLocation, string newFileLocation)
+{
+#ifdef __linux
+    system(("mv " + oldFileLocation + " " + newFileLocation).c_str());
+#else
+    // not Implemented yet
+#endif
+}
+
+UdpSocket::UdpSocket(string broadcastIp, int portIn, int portOut)
+{
+    m_portIn = portIn;
+    m_portOut = portOut;
+    m_broadcastIp = broadcastIp;
+#ifdef __linux
+
+    // create UDP socket
+    m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (m_socket < 0)
+    {
+        string error = "Can't open UDP socket";
+        LOG_WARNING << error << endl;
+        throw error;
+    }
+
+    // set broadcast flag on
+    int enabled = 1;
+    if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (char*)&enabled, sizeof(enabled)) < 0)
+    {
+        string error = "Can't set broadcast option for udp socket, error: ";
+        error += strerror(errno);
+
+        LOG_WARNING << error << endl;
+        shutdown(m_socket, SHUT_RDWR);
+        throw error;
+    }
+
+    // bind socket to portIn
+    struct sockaddr_in address;
+    address.sin_family = AF_INET;
+    address.sin_addr.s_addr = INADDR_ANY;
+    address.sin_port = htons(m_portIn);
+    if (::bind(m_socket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0)
+    {
+        string error = "Can't bind socket to port, error: ";
+        error += strerror(errno);
+
+        LOG_WARNING << error << std::endl;
+        throw error;
+    }
+#else
+    string error = "UDP socket is supported on linux OS only";
+    throw error;
+#endif
+}
+
+int UdpSocket::Send(string message)
+{
+#ifdef __linux
+    struct sockaddr_in dstAddress;
+    dstAddress.sin_family = AF_INET;
+    inet_pton(AF_INET, m_broadcastIp.c_str(), &dstAddress.sin_addr.s_addr);
+    dstAddress.sin_port = htons(m_portOut);
+    int messageSize = message.length() * sizeof(char);
+    int result = sendto(m_socket, message.c_str(), messageSize, 0, (sockaddr*)&dstAddress, sizeof(dstAddress));
+    LOG_VERBOSE << "INFO : sendto with sock_out=" << m_socket << ", message=" << message << " messageSize=" << messageSize << " returned with " << result << std::endl;
+    if (result < 0)
+    {
+        LOG_WARNING << "ERROR : Cannot send udp broadcast message, error " << ": " << strerror(errno) << std::endl;
+        return 0;
+    }
+    return messageSize;
+#else
+    return 0;
+#endif
+}
+
+const char* UdpSocket::Receive(int len)
+{
+#ifdef __linux
+    char* buf = new char[len];
+    if (recvfrom(m_socket, buf, len, 0, NULL, 0) < 0)
+    {
+        LOG_WARNING << "Can't receive from port " << m_portIn << std::endl;
+        return "";
+    }
+    return buf;
+#else
+    return "";
+#endif
+}
+
+void UdpSocket::Close()
+{
+#ifdef __linux
+    shutdown(m_socket, SHUT_RDWR);
+#else
+#endif
+}
diff --git a/debug-tools/host_manager_11ad/UdpTempOsAbstruction.h b/debug-tools/host_manager_11ad/UdpTempOsAbstruction.h
new file mode 100644
index 0000000..836bd1f
--- /dev/null
+++ b/debug-tools/host_manager_11ad/UdpTempOsAbstruction.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _UDPTEMPOSABSTRUCTION_H_
+#define _UDPTEMPOSABSTRUCTION_H_
+
+#include <string>
+#include <memory>
+#include "HostDefinitions.h"
+
+using namespace std;
+
+class UdpTempOsAbstruction
+{
+public:
+
+    /*
+    GetHostIps
+    Returns host's personal IP and broadcat IP
+    @param: none
+    @return: HostIps - host's personal IP and broadcat IP
+    */
+    static HostIps GetHostIps();
+
+    /*
+    ReadFile
+    Gets a file name and reads its context.
+    @param: fileName - full file name
+    @return: file's content
+    */
+    static bool ReadFile(string fileName, string& data);
+
+    /*
+    WriteFile
+    Gets a file name and the required content, and write the content to the file (overrides the old content if exists)
+    @param: fileName - full file name
+    @param: content - the new file's content
+    @return: true for successful write operation, false otherwise
+    */
+    static bool WriteFile(string fileName, string content);
+
+    /*
+    GetPersistencyLocation
+    Returns the host persistency location prefix accurding to the OS
+    @param: none
+    @return: host persistency location prefix accurding to the OS
+    */
+    static string GetPersistencyLocation();
+
+    /*
+    ReadHostOsAlias
+    Returns the host's alias as defined in persistency
+    @param: a reference to a string that will be updated with the host's alias
+    @return: bool - status - true for successful operation, false otherwise
+    */
+    static bool ReadHostOsAlias(string& alias);
+
+    static bool IsFolderExists(string path);
+
+    static bool CreateFolder(string path);
+
+    static void MoveFileToNewLocation(string oldFileLocation, string newFileLocation);
+
+    static string GetDirectoriesDilimeter();
+
+    static bool IsFileExists(string path);
+
+    static const string LOCAL_HOST_IP; // default IP address
+
+private:
+    static bool FindEthernetInterface(struct ifreq& ifr, int& fd);
+
+};
+
+class UdpSocket
+{
+public:
+
+    UdpSocket(string broadcastIp, int portIn, int portOut);
+
+    ~UdpSocket() { Close(); }
+
+    int Send(string message);
+
+    const char* Receive(int len);
+
+    void Close();
+
+private:
+
+    int m_portIn;
+    int m_portOut;
+    int m_socket;
+    string m_broadcastIp;
+};
+
+#endif
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/Utils.cpp b/debug-tools/host_manager_11ad/Utils.cpp
new file mode 100644
index 0000000..9047d89
--- /dev/null
+++ b/debug-tools/host_manager_11ad/Utils.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "Utils.h"
+#include <sstream>
+#include <iomanip>
+#include <stdexcept>
+#include <cstdlib>
+
+#ifdef __linux
+#else
+#define localtime_r(_Time, _Tm) localtime_s(_Tm, _Time)
+#endif
+
+using namespace std;
+
+// *************************************************************************************************
+vector<string> Utils::Split(string str, char delimiter)
+{
+    vector<string> splitStr;
+    size_t nextSpacePosition = str.find_first_of(delimiter);
+    while (string::npos != nextSpacePosition)
+    {
+        splitStr.push_back(str.substr(0, nextSpacePosition));
+        str = str.substr(nextSpacePosition + 1);
+        nextSpacePosition = str.find_first_of(delimiter);
+    }
+
+    if ("" != str)
+    {
+        splitStr.push_back(str);
+    }
+    return splitStr;
+    /*
+    vector<string> splitMessage;
+    stringstream sstream(message);
+    string word;
+    while (getline(sstream, word, delim))
+    {
+        if (word.empty())
+        { //don't push whitespace
+            continue;
+        }
+        splitMessage.push_back(word);
+    }
+    return splitMessage;
+    */
+}
+
+// *************************************************************************************************
+string Utils::GetCurrentLocalTime()
+{
+        chrono::system_clock::time_point nowTimePoint = chrono::system_clock::now(); // get current time
+
+        // convert epoch time to struct with year, month, day, hour, minute, second fields
+        time_t now = chrono::system_clock::to_time_t(nowTimePoint);
+        tm localTime;
+        localtime_r(&now, &localTime);
+
+        // get milliseconds field
+        const chrono::duration<double> tse = nowTimePoint.time_since_epoch();
+        chrono::seconds::rep milliseconds = chrono::duration_cast<std::chrono::milliseconds>(tse).count() % 1000;
+
+
+        ostringstream currentTime;
+        currentTime << (1900 + localTime.tm_year) << '-'
+            << std::setfill('0') << std::setw(2) << (localTime.tm_mon + 1) << '-'
+            << std::setfill('0') << std::setw(2) << localTime.tm_mday << ' '
+            << std::setfill('0') << std::setw(2) << localTime.tm_hour << ':'
+            << std::setfill('0') << std::setw(2) << localTime.tm_min << ':'
+            << std::setfill('0') << std::setw(2) << localTime.tm_sec << '.'
+            << std::setfill('0') << std::setw(3) << milliseconds;
+
+        string currentTimeStr(currentTime.str());
+        return currentTimeStr;
+}
+
+// *************************************************************************************************
+bool Utils::ConvertHexStringToDword(string str, DWORD& word)
+{
+    if (str.find_first_of("0x") != 0) //The parameter is a hex string (assuming that a string starting with 0x must be hex)
+    {
+        return false;
+    }
+    istringstream s(str);
+    s >> hex >> word;
+    return true;
+}
+
+// *************************************************************************************************
+bool Utils::ConvertHexStringToDwordVector(string str, char delimiter, vector<DWORD>& values)
+{
+    vector<string> strValues = Utils::Split(str, delimiter);
+    values.reserve(strValues.size());
+    for (auto& strValue : strValues)
+    {
+        DWORD word;
+        if (Utils::ConvertHexStringToDword(strValue, word))
+        {
+            values.push_back(word);
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// *************************************************************************************************
+bool Utils::ConvertDecimalStringToUnsignedInt(string str, unsigned int& ui)
+{
+    unsigned long l;
+    try
+    {
+        l = strtoul(str.c_str(), nullptr, 10); // 10 for decimal base
+    }
+    catch (...)
+    {
+        return false;
+    }
+
+    ui = l;
+    return true;
+}
diff --git a/debug-tools/host_manager_11ad/Utils.h b/debug-tools/host_manager_11ad/Utils.h
new file mode 100644
index 0000000..716e6fb
--- /dev/null
+++ b/debug-tools/host_manager_11ad/Utils.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+#include <vector>
+#include <string>
+#include <chrono>
+
+#ifdef _WINDOWS
+typedef unsigned long DWORD;
+#else
+typedef uint32_t    DWORD;
+#endif
+
+using namespace std;
+
+class Utils
+{
+public:
+
+    static vector<string> Split(string str, char delimiter);
+
+    static string GetCurrentLocalTime();
+
+    static bool ConvertHexStringToDword(string str, DWORD& word);
+
+    static bool ConvertHexStringToDwordVector(string str, char delimiter, vector<DWORD>& values);
+
+    static bool ConvertDecimalStringToUnsignedInt(string str, unsigned int& ui);
+};
+
+#endif // !_UTILS_H_
+
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/AccessLayerAPI.cpp b/debug-tools/host_manager_11ad/access_layer_11ad/AccessLayerAPI.cpp
new file mode 100644
index 0000000..9c55094
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/AccessLayerAPI.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <sstream>
+
+#include "AccessLayerAPI.h"
+
+#ifdef _WINDOWS
+//#include "JTagDevice.h"
+#include "SerialDevice.h"
+#endif
+#include "TestDevice.h"
+
+#include "PciDevice.h"
+#include "../Utils.h"
+
+using namespace std;
+
+set<string> AccessLayer::GetDevices()
+{
+    set<string> enumeratedDevices;
+
+    // Enumerate
+    set<string> pciDevices = PciDevice::Enumerate();
+
+#ifdef _WINDOWS
+    //set<string> jtagDevices = JTagDevice::Enumerate();
+    //set<string> serialDevices = SerialDevice::Enumerate();
+    //enumeratedDevices.insert(serialDevices.begin(), serialDevices.end());
+#endif
+
+    enumeratedDevices.insert(pciDevices.begin(), pciDevices.end());
+#ifdef _UseTestDevice
+    set<string> testDevices = TestDevice::Enumerate();
+    enumeratedDevices.insert(testDevices.begin(), testDevices.end());
+#endif // _UseTestDevice
+
+    return enumeratedDevices;
+}
+
+unique_ptr<Device> AccessLayer::OpenDevice(string deviceName)
+{
+    vector<string> tokens = Utils::Split(deviceName, DEVICE_NAME_DELIMITER);
+
+    // Device name consists of exactly 3 elements:
+    // 1. Baseband Type (SPARROW, TALYN...)
+    // 2. Transport Type (PCI, JTAG, Serial...)
+    // 3. Interface name (wMp, wPci, wlan0, wigig0...)
+    if (tokens.size() != 2)
+    {
+        // LOG_MESSAGE_ERROR
+        return NULL;
+    }
+
+    // Transport type
+    unique_ptr<Device> pDevice;
+
+    if ("PCI" == tokens[0])
+    {
+        pDevice.reset(new PciDevice(deviceName, tokens[1]));
+    }
+
+#ifdef _WINDOWS
+    if ("SERIAL" == tokens[0])
+    {
+        pDevice.reset(new SerialDevice(deviceName, tokens[1]));
+    }
+#endif
+
+#ifdef _UseTestDevice
+    if ("TEST" == tokens[0])
+    {
+        pDevice.reset(new TestDevice(deviceName, tokens[1]));
+    }
+#endif // _UseOnlyTestDevice
+
+
+    return pDevice;
+}
+
+void AccessLayer::CloseDevice(string deviceName)
+{
+    //do something with params
+    (void)deviceName;
+}
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/AccessLayerAPI.h b/debug-tools/host_manager_11ad/access_layer_11ad/AccessLayerAPI.h
new file mode 100644
index 0000000..3461b4c
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/AccessLayerAPI.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <set>
+#include "Device.h"
+
+class AccessLayer
+{
+public:
+    //static void GetVersion(WLCT_DLL_VERSION *pVer);
+    static set<string> GetDevices();
+    static unique_ptr<Device> OpenDevice(string deviceName);
+    static void CloseDevice(string deviceName);
+
+    static set<string> GetTestDevices();
+
+private:
+    static vector<string> Split(const string &message, char delim);
+};
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/Definitions.h b/debug-tools/host_manager_11ad/access_layer_11ad/Definitions.h
new file mode 100644
index 0000000..e127218
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/Definitions.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _11AD_ACCESS_LAYER_DEFINITIONS_H_
+#define _11AD_ACCESS_LAYER_DEFINITIONS_H_
+
+#define BAUD_RATE_REGISTER 0x880050
+
+typedef enum BasebandTypeEnum
+{
+    BASEBAND_TYPE_NONE,
+    BASEBAND_TYPE_SPARROW,   // added here to keep backward compatibility. some tools assume MARLON == 2, we don't brake this assumption
+    BASEBAND_TYPE_MARLON,
+    BASEBAND_TYPE_TALYN,
+    BASEBAND_TYPE_LAST
+} BasebandType;
+
+#define EMPTY_ARRAY_SIZE
+
+#define DEVICE_NAME_DELIMITER '!'
+
+#endif //_11AD_ACCESS_LAYER_DEFINITIONS_H_
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/Device.h b/debug-tools/host_manager_11ad/access_layer_11ad/Device.h
new file mode 100644
index 0000000..9d166c5
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/Device.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _11AD_DEVICE_H_
+#define _11AD_DEVICE_H_
+
+#include <string>
+#include <vector>
+#include <set>
+#include <iostream>
+#include "OperatingSystemConstants.h"
+#include "Definitions.h"
+#include "../DebugLogger.h"
+
+using namespace std;
+
+class Device
+{
+public:
+    Device(string deviceName, string interfaceName)
+    {
+        m_deviceName = deviceName;
+        m_interfaceName = interfaceName;
+        m_initialized = false;
+
+        m_basebandType = BASEBAND_TYPE_NONE;
+    }
+
+    // ************************** Device API ****************************//
+    // Device Management
+    virtual bool Open() { return false; };
+    virtual void Close() {};
+
+    // Base access functions (to be implemented by specific device)
+    virtual bool Read(DWORD address, DWORD& value)
+    {
+        //do something with params
+        (void)address;
+        (void)value;
+        return false;
+    };
+    virtual bool ReadBlock(DWORD address, DWORD blockSize, vector<DWORD>& values)
+    {
+        //do something with params
+        (void)address;
+        (void)blockSize;
+        (void)values;
+        return false;
+    };
+
+    virtual bool Write(DWORD address, DWORD value)
+    {
+        //do something with params
+        (void)address;
+        (void)value;
+        return false; };
+    virtual bool WriteBlock(DWORD address, vector<DWORD> values)
+    {
+        //do something with params
+        (void)address;
+        (void)values;
+        return false; };
+
+    // Polling function
+    //vector<DeviceEvent> DoPoll();
+
+    // Functionality common to all devices
+    bool SwReset() { return false; }
+
+    virtual bool AllocPmc(unsigned descSize, unsigned descNum)
+    {
+        //do something with params
+        (void)descSize;
+        (void)descNum;
+        return false;
+    } // TODO: implement
+
+    virtual bool DeallocPmc() { return false; } // TODO: implement
+
+    virtual bool CreatePmcFile(unsigned refNumber)
+    {
+        //do something with params
+        (void)refNumber;
+        return false;
+    } // TODO: implement
+
+    virtual void InterfaceReset() {};
+
+    virtual bool SetDriverMode(int newMode, int& oldMode)
+    {
+        //do something with params
+        (void)newMode;
+        (void)oldMode;
+        return false;
+    }
+
+    bool SendWmi(DWORD command, vector<DWORD> payload)
+    {
+        //do something with params
+        (void)command;
+        (void)payload;
+        return false;
+
+    }
+    vector<DWORD> GetWmiEvent()
+    {
+
+        vector<DWORD> ret;
+        return ret;
+    }
+
+    bool IsOpen()
+    {
+        return m_initialized;
+    }
+
+    void Poll()
+    {
+        // TODO: implement polling: MB, logs, rgf
+    }
+
+    static unsigned int GetRegisterDefaultValue()
+    {
+        return 0xDEADDEAD;
+    }
+    // ************************** [END] Device API **********************//
+
+    string GetDeviceName()
+    {
+        return m_deviceName;
+    }
+
+    string GetInterfaceName()
+    {
+        return m_interfaceName;
+    }
+
+    BasebandType GetBasebandType()
+    {
+        if (m_basebandType == BASEBAND_TYPE_NONE)
+        {
+            m_basebandType = ReadBasebandType();
+        }
+
+        return m_basebandType;
+    }
+    virtual ~Device(){};
+protected:
+    DWORD m_deviceHandle;
+    bool m_initialized;
+private:
+    string m_deviceName;
+    string m_interfaceName;
+    BasebandType m_basebandType;
+
+    BasebandType ReadBasebandType()
+    {
+        DWORD jtagVersion;
+        const int rev_id_address = 0x880B34; //USER.JTAG.USER_USER_JTAG_1.dft_idcode_dev_id
+        const int device_id_mask = 0x0fffffff; //take the first 28 bits from the Jtag Id
+        BasebandType res = BASEBAND_TYPE_NONE;
+
+        if (!Read(rev_id_address, jtagVersion))
+        {
+            LOG_ERROR << "Failed to read baseband type" << "\n";
+        }
+
+        LOG_INFO << "JTAG rev ID = " << hex << jtagVersion << "\n";
+
+        switch (jtagVersion & device_id_mask)
+        {
+        case 0x612072F:
+            res = BASEBAND_TYPE_MARLON;
+            break;
+        case 0x632072F:
+            res = BASEBAND_TYPE_SPARROW;
+            break;
+        case 0x642072F:
+        case 0x007E0E1:
+            res = BASEBAND_TYPE_TALYN;
+            break;
+        default:
+            ////LOG_MESSAGE_WARN("Invalid device type - assuming Sparrow");
+            res = BASEBAND_TYPE_SPARROW;
+            break;
+        }
+
+        return res;
+    }
+};
+
+#endif // !_11AD_DEVICE_H_
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/DriverAPI.h b/debug-tools/host_manager_11ad/access_layer_11ad/DriverAPI.h
new file mode 100644
index 0000000..11bb3bf
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/DriverAPI.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _11AD_PCI_DRIVER_API_H_
+#define _11AD_PCI_DRIVER_API_H_
+
+#include <string>
+#include <set>
+
+#include "OperatingSystemConstants.h"
+
+using namespace std;
+
+class DriverAPI
+{
+public:
+    DriverAPI(string interfaceName)
+    {
+        m_interfaceName = interfaceName;
+    }
+    virtual ~DriverAPI() {};
+
+    // Base access functions (to be implemented by specific device)
+    virtual bool Read(DWORD address, DWORD& value) = 0;
+    virtual bool ReadBlock(DWORD addr, DWORD blockSize, char *arrBlock) = 0;
+    virtual bool Write(DWORD address, DWORD value) = 0;
+    virtual bool WriteBlock(DWORD addr, DWORD blockSize, const char *arrBlock) = 0;
+
+    virtual bool IsOpened(void) = 0;
+
+    virtual bool Open() = 0;
+    virtual bool ReOpen() = 0;
+    virtual bool Ioctl(uint32_t Id,
+                       const void *inBuf, uint32_t inBufSize,
+                       void *outBuf, uint32_t outBufSize) = 0;
+    virtual DWORD DebugFS(char *FileName, void *dataBuf, DWORD dataBufLen, DWORD DebugFSFlags)
+    {
+        //do something with params
+        (void)FileName;
+        (void)dataBuf;
+        (void)dataBufLen;
+        (void)DebugFSFlags;
+        return -1;
+    }
+    virtual void          Close() = 0;
+
+    virtual int GetDriverMode(int &currentState) = 0;
+    virtual bool SetDriverMode(int newState, int &oldState) = 0;
+
+    virtual void Reset() = 0;
+
+protected:
+    string m_interfaceName;
+    void* m_deviceHandle;
+
+private:
+};
+
+
+#endif //_11AD_PCI_DRIVER_API_H_
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/OperatingSystemConstants.h b/debug-tools/host_manager_11ad/access_layer_11ad/OperatingSystemConstants.h
new file mode 100644
index 0000000..3b866b1
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/OperatingSystemConstants.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#ifdef _WINDOWS
+
+#include <windows.h>
+#include <atlbase.h>
+#include <atlstr.h>
+#include <assert.h>
+
+typedef unsigned __int8 u_int8_t;
+typedef unsigned __int16 u_int16_t;
+typedef unsigned __int32 u_int32_t;
+typedef unsigned __int64 u_int64_t;
+#if (defined(_MSC_VER) && (_MSC_VER < 1900))
+//typedef __int8 int8_t;
+#endif
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+
+#define WLCT_OS_ERROR_SUCCESS              ERROR_SUCCESS
+#define WLCT_OS_ERROR_NOT_SUPPORTED        ERROR_NOT_SUPPORTED
+#define WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED ERROR_CALL_NOT_IMPLEMENTED
+#define WLCT_OS_ERROR_GEN_FAILURE          ERROR_GEN_FAILURE
+#define WLCT_OS_ERROR_NOT_ENOUGH_MEMORY    ERROR_NOT_ENOUGH_MEMORY
+#define WLCT_OS_ERROR_NO_SUCH_ENTRY        ERROR_FILE_NOT_FOUND
+#define WLCT_OS_ERROR_OPEN_FAILED          ERROR_OPEN_FAILED
+
+#define WLCT_ASSERT assert
+
+#define __TRY __try
+
+#define __EXCEPT __except
+
+#define sleep_ms Sleep
+
+#define WlctGetLastError GetLastError
+
+#else
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <string>
+
+#define WLCT_ASSERT assert
+
+#define __INLINE   __inline
+
+typedef uint8_t         BYTE;
+typedef uint16_t        WORD;
+typedef uint32_t        DWORD;
+
+typedef unsigned char   UCHAR;
+typedef unsigned int    UINT;
+typedef char            CHAR;
+typedef long            LONG;
+typedef unsigned short  USHORT;
+typedef unsigned long   ULONG;
+typedef ULONG*          ULONG_PTR;
+
+typedef char            TCHAR;
+
+typedef uint8_t         u_int8_t;
+typedef uint16_t        u_int16_t;
+typedef uint32_t        u_int32_t;
+typedef uint64_t        u_int64_t;
+
+typedef const TCHAR     *LPCTSTR;
+typedef TCHAR           *LPTSTR;
+typedef CHAR            *LPSTR;
+typedef const CHAR      *LPCSTR;
+
+typedef DWORD           HANDLE;
+
+typedef int             BOOL;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <strings.h>
+
+typedef int wlct_os_err_t;
+
+#define WLCT_OS_ERROR_SUCCESS              0
+#define WLCT_OS_ERROR_NOT_SUPPORTED        -ENOTSUP
+#define WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED -ENOSYS
+#define WLCT_OS_ERROR_GEN_FAILURE          -EINVAL
+#define WLCT_OS_ERROR_NOT_ENOUGH_MEMORY    -ENOMEM
+#define WLCT_OS_ERROR_NO_SUCH_ENTRY        -ENOENT
+#define WLCT_OS_ERROR_OPEN_FAILED          -EBADF
+
+#define _T(x) (x)
+
+#define __TRY if (1)
+#define __EXCEPT(ignore) else if (0)
+
+#define WLCT_MSEC_IN_SEC 1000
+
+#define sleep_ms(msec) usleep(msec * WLCT_MSEC_IN_SEC)
+
+#define USES_CONVERSION
+
+#define T2A(x) (x)
+
+#define _tcscpy_s(x, y, z) snprintf((x), (y), "%s", (z))
+#define _tcslen            strlen
+#define _stprintf_s        snprintf
+#define _snprintf          snprintf
+//#define sprintf_s          sprintf
+//#define _stprintf          sprintf
+#define sscanf_s           sscanf
+#define _tcstok_s          strtok_r
+#define _tcsstr            strstr
+#define _tcsicmp           strcasecmp
+#define _vsntprintf        vsnprintf
+#define _tfopen            fopen
+
+#define WlctGetLastError() errno
+
+#endif
+
+#define WLCT_UNREFERENCED_PARAM(x)  ((x) = (x))
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/PciDevice.cpp b/debug-tools/host_manager_11ad/access_layer_11ad/PciDevice.cpp
new file mode 100644
index 0000000..93b7f01
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/PciDevice.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "OperatingSystemConstants.h"
+#include "../DebugLogger.h"
+#ifdef _WINDOWS
+#include "WindowsDriverAPI.h"
+#else
+#include "UnixDriverAPI.h"
+#endif
+
+#include "PciDevice.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+// PCI interface
+
+PciDevice::PciDevice(string deviceName, string interfaceName) : Device(deviceName, interfaceName)
+{
+    //LOG_MESSAGE_INFO(_T("Create PCI device access for: %s"), interfaceName.c_str());
+    m_initialized = false;
+
+#ifdef _WINDOWS
+    m_pDriverApi.reset(new WindowsDriverAPI(interfaceName));
+#else
+    m_pDriverApi.reset(new UnixDriverAPI(interfaceName));
+#endif
+
+    if (m_pDriverApi->Open())
+    {
+        m_initialized = true;
+    }
+    else
+    {
+        m_initialized = false;
+    }
+}
+PciDevice::~PciDevice()
+{
+    Close();
+}
+
+// Virtual access functions for device
+bool PciDevice::Read(DWORD address, DWORD& value)
+{
+    return (m_pDriverApi->Read(address, value));
+}
+bool PciDevice::ReadBlock(DWORD address, DWORD blockSize, vector<DWORD>& values)
+{
+    bool success = false;
+
+    DWORD* arrBlock = NULL;
+    try
+    {
+        arrBlock = new DWORD[blockSize];
+
+        // blockSize is in bytes, need to be multiplied by 4 for DWORDS
+        success = (m_pDriverApi->ReadBlock(address, blockSize * 4, (char*)arrBlock));
+
+        values = std::vector<DWORD>(arrBlock, arrBlock + (blockSize));
+
+        LOG_DEBUG << "Read: " << values.size() << " Values \n";
+    }
+    catch (...)
+    {
+        LOG_ERROR << "Exception when trying to read block\n";
+        delete[] arrBlock;
+        return false;
+    }
+
+    delete[] arrBlock;
+    return success;
+}
+bool PciDevice::Write(DWORD address, DWORD value)
+{
+    return (m_pDriverApi->Write(address, value));
+}
+bool PciDevice::WriteBlock(DWORD address, vector<DWORD> values)
+{
+    char* valuesToWrite = (char*)&values[0];
+
+    return (m_pDriverApi->WriteBlock(address, values.size() * 4, valuesToWrite));
+}
+
+bool PciDevice::Open()
+{
+    return m_pDriverApi->Open();
+}
+void PciDevice::Close()
+{
+    return m_pDriverApi->Close();
+}
+bool PciDevice::ReOpen()
+{
+    return m_pDriverApi->ReOpen();
+}
+
+bool PciDevice::SetDriverMode(int newState, int &oldState)
+{
+    return m_pDriverApi->SetDriverMode(newState, oldState);
+}
+int PciDevice::GetDriverMode(int &currentState)
+{
+    return m_pDriverApi->GetDriverMode(currentState);
+}
+
+static string NameDevice(string interfaceName)
+{
+    return std::string("PCI") + DEVICE_NAME_DELIMITER + interfaceName;
+}
+
+void PciDevice::InterfaceReset()
+{
+    m_pDriverApi->Reset();
+    return;
+}
+
+set<string> PciDevice::Enumerate()
+{
+    // Hold all discovered hosts
+    set<string> discoveredDevices;
+
+#ifdef _WINDOWS
+    set<string> enumeratedDevices = WindowsDriverAPI::Enumerate();
+#else
+    set<string> enumeratedDevices = UnixDriverAPI::Enumerate();
+#endif
+
+    set<string>::iterator it;
+    for (it = enumeratedDevices.begin(); it != enumeratedDevices.end(); ++it)
+    {
+        string interfaceName = *it;
+
+        PciDevice device("Enum", interfaceName);
+
+        if (device.IsOpen())
+        {
+            discoveredDevices.insert(NameDevice(interfaceName));
+            device.Close();
+        }
+    }
+
+    return discoveredDevices;
+}
+
+bool PciDevice::try2open(int timeout)
+{
+    do
+    {
+        Open();
+        if (m_pDriverApi->IsOpened())
+            break;
+        sleep_ms(100);
+        timeout -= 100;
+    } while (timeout > 0);
+
+    if (!m_pDriverApi->IsOpened())
+        return false;
+    return true;
+}
+void PciDevice::rr32(DWORD addr, DWORD num_repeat, DWORD *arrBlock)
+{
+    //do something with params
+    (void)addr;
+    (void)num_repeat;
+    (void)arrBlock;
+    WLCT_ASSERT(0);
+}
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/PciDevice.h b/debug-tools/host_manager_11ad/access_layer_11ad/PciDevice.h
new file mode 100644
index 0000000..06f49b3
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/PciDevice.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _11AD_PCI_DEVICE_H_
+#define _11AD_PCI_DEVICE_H_
+
+#ifdef _WINDOWS
+//#include "ioctl_if.h"
+#else
+// some definitions from ioctl_if.h
+#define WILOCITY_IOCTL_INDIRECT_READ IOCTL_INDIRECT_READ_OLD
+#define WILOCITY_IOCTL_INDIRECT_WRITE IOCTL_INDIRECT_WRITE_OLD
+#define WILOCITY_IOCTL_INDIRECT_READ_BLOCK IOCTL_INDIRECT_READ_BLOCK
+#define WILOCITY_IOCTL_INDIRECT_WRITE_BLOCK IOCTL_INDIRECT_WRITE_BLOCK
+#endif
+
+#include <memory>
+#include "Device.h"
+#include "DriverAPI.h"
+
+using namespace std;
+
+class PciDevice : public Device
+{
+public:
+    PciDevice(string deviceName, string interfaceName);
+    ~PciDevice();
+
+    // Device Management
+    bool Open();
+    void Close();
+
+    // Virtual access functions for device
+    bool Read(DWORD address, DWORD& value);
+    bool ReadBlock(DWORD address, DWORD blockSize, vector<DWORD>& values);
+    bool Write(DWORD address, DWORD value);
+    bool WriteBlock(DWORD address, vector<DWORD> values);
+
+    virtual void InterfaceReset();
+
+    virtual bool SetDriverMode(int newState, int &oldState);
+    virtual int GetDriverMode(int &currentState);
+
+    static set<string> Enumerate();
+
+private:
+    void rr32(DWORD addr, DWORD num_repeat, DWORD *arrBlock);
+    bool ReOpen();
+    bool try2open(int timeout);
+
+    static void SamplingThreadProc(void *pDeviceAccss);
+    static void PciPluginThreadProc(void *pDeviceAccss);
+
+    // The driver API for the PCI access (OS specific)
+    unique_ptr<DriverAPI> m_pDriverApi;
+};
+
+#endif //_11AD_PCI_DEVICE_H_
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/TestDevice.cpp b/debug-tools/host_manager_11ad/access_layer_11ad/TestDevice.cpp
new file mode 100644
index 0000000..2641d0d
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/TestDevice.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <sstream>
+#include "TestDevice.h"
+
+//////////////////////////////////////////////////////////////////////////
+// Test Device interface
+
+TestDevice::TestDevice(string deviceName, string interfaceName) : Device(deviceName, interfaceName)
+{
+    //LOG_MESSAGE_INFO(_T("Create test device access for: %s"), interfaceName.c_str());
+    m_registersAddressToValue.insert(make_pair(0x880050, 0x12345678));
+
+    unsigned baseAddress = 0x880100;
+    unsigned numOfAddresses = 40;
+    unsigned numOfAddressesInRegister = 4;
+    unsigned value = 0x0;
+    for (unsigned i = 0; i < numOfAddresses * numOfAddressesInRegister; i += numOfAddressesInRegister)
+    {
+        m_registersAddressToValue.insert(make_pair(baseAddress + i, value++));
+    }
+}
+
+TestDevice::~TestDevice()
+{
+    Close();
+}
+
+// Virtual access functions for device
+bool TestDevice::Read(DWORD address, DWORD& value)
+{
+    auto registerElement = m_registersAddressToValue.find(address);
+    if (registerElement != m_registersAddressToValue.end())
+    {
+        value = registerElement->second;
+        return true;
+
+    }
+    value = Device::GetRegisterDefaultValue();
+    return false;
+}
+
+bool TestDevice::ReadBlock(DWORD address, DWORD blockSize, vector<DWORD>& values)
+{
+    auto registerElement = m_registersAddressToValue.find(address);
+    if (registerElement != m_registersAddressToValue.end())
+    {
+        for (DWORD v = 0x0; v < blockSize; ++v)
+        {
+            values.push_back(registerElement->second + v);
+        }
+        return true;
+    }
+    return false;
+}
+
+bool TestDevice::Write(DWORD address, DWORD value)
+{
+    auto registerElement = m_registersAddressToValue.find(address);
+    if (registerElement != m_registersAddressToValue.end())
+    {
+        registerElement->second = value;
+        return true;
+    }
+    return false;
+}
+
+bool TestDevice::WriteBlock(DWORD address, vector<DWORD> values)
+{
+    auto registerElement = m_registersAddressToValue.find(address);
+    if (registerElement != m_registersAddressToValue.end())
+    {
+        unsigned i = 0;
+        for (auto v = values.begin(); v != values.end(); ++v)
+        {
+            m_registersAddressToValue[address + i] = *v;
+            ++i;
+        }
+        return true;
+    }
+    return false;
+}
+
+bool TestDevice::Open()
+{
+    return true;
+}
+
+void TestDevice::Close()
+{
+    return;
+}
+
+void TestDevice::InterfaceReset()
+{
+    return;
+}
+
+bool TestDevice::SwReset()
+{
+    return true;
+}
+
+set<string> TestDevice::Enumerate()
+{
+    stringstream deviceNameDelimiter;
+    deviceNameDelimiter << DEVICE_NAME_DELIMITER;
+    set<string> discoveredDevices;
+
+    // add first device
+    string deviceName = std::string("TEST") + deviceNameDelimiter.str() + "wTest0";
+    discoveredDevices.insert(deviceName);
+
+    // add second device
+    deviceName = std::string("TEST") + deviceNameDelimiter.str() + "wTest1";
+    discoveredDevices.insert(deviceName);
+
+    return discoveredDevices;
+}
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/TestDevice.h b/debug-tools/host_manager_11ad/access_layer_11ad/TestDevice.h
new file mode 100644
index 0000000..4ede6b4
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/TestDevice.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _11AD_TEST_DEVICE_H_
+#define _11AD_TEST_DEVICE_H_
+
+#include <map>
+#include "Device.h"
+
+using namespace std;
+
+class TestDevice : public Device
+{
+public:
+    TestDevice(string deviceName, string interfaceName);
+    ~TestDevice();
+
+    // Device Management
+    bool Open();
+    void Close();
+
+    // Virtual access functions for device
+    bool Read(DWORD address, DWORD& value);
+    bool ReadBlock(DWORD address, DWORD blockSize, vector<DWORD>& values);
+    bool Write(DWORD address, DWORD value);
+    bool WriteBlock(DWORD address, vector<DWORD> values);
+
+    virtual void InterfaceReset();
+    bool SwReset();
+
+    static set<string> Enumerate();
+
+private:
+    map<DWORD, DWORD> m_registersAddressToValue;
+};
+#endif //_11AD_TEST_DEVICE_H_
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/Unix/UnixDriverAPI.cpp b/debug-tools/host_manager_11ad/access_layer_11ad/Unix/UnixDriverAPI.cpp
new file mode 100644
index 0000000..751f224
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/Unix/UnixDriverAPI.cpp
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _WINDOWS
+
+#include <iostream>
+
+#include "UnixDriverAPI.h"
+
+#include <net/if.h> // for struct ifreq
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/ioctl.h> // for struct ifreq
+
+#define END_POINT_RESULT_MAX_SIZE 256
+#define NETWORK_INTERFACE_RESULT_MAX_SIZE 256
+
+using namespace std;
+
+UnixDriverAPI::~UnixDriverAPI()
+{
+    Close();
+}
+
+// Base access functions (to be implemented by specific device)
+bool UnixDriverAPI::Read(DWORD address, DWORD& value)
+{
+    IoctlIO io;
+
+    io.addr = address;
+    io.val = 0;
+    io.op = EP_OPERATION_READ;
+    if (!SendRWIoctl(io, m_fileDescriptor, m_interfaceName.c_str()))
+    {
+        return false;
+    }
+
+    value = io.val;
+
+    return true;
+}
+bool UnixDriverAPI::ReadBlock(DWORD addr, DWORD blockSize, char *arrBlock)
+{
+    IoctlIO io;
+
+    // cout << "Read block addr = " << addr << ". block size = " << blockSize << "\n";
+
+    //blocks must be 32bit alligned!
+    int numReads = blockSize / 4;
+    io.op = EP_OPERATION_READ;
+    io.addr = addr;
+    for (int i = 0; i < numReads; i++)
+    {
+        if (!SendRWIoctl(io, m_fileDescriptor, m_interfaceName.c_str()))
+        {
+            // cout << "Failed to Read in ReadBlock";
+            return false;
+        }
+
+        // Copy the read 32 bits into the arrBlock
+        memcpy(&arrBlock[(i * 4)], &io.val, sizeof(int32_t));
+        // cout << "Read block " << i << " out of " << numReads << ". val = " << io.val << "\n";
+
+        io.addr += sizeof(int32_t);
+    }
+
+    return true;
+}
+bool UnixDriverAPI::Write(DWORD address, DWORD value)
+{
+    IoctlIO io;
+
+    io.addr = address;
+    io.val = value;
+    io.op = EP_OPERATION_WRITE;
+
+    if (!SendRWIoctl(io, m_fileDescriptor, m_interfaceName.c_str()))
+    {
+        return false;
+    }
+
+    return true;
+}
+bool UnixDriverAPI::WriteBlock(DWORD addr, DWORD blockSize, const char *arrBlock)
+{
+    // cout << "Write Block addr = " << addr << ". block size = " << blockSize << "\n";
+
+    IoctlIO io;
+
+    io.addr = addr;
+
+    //blocks must be 32bit alligned!
+    int sizeToWrite = blockSize / 4;
+    io.op = EP_OPERATION_WRITE;
+    for (int i = 0; i < sizeToWrite; i++)
+    {
+        io.val = *((int*)&(arrBlock[i * 4]));
+
+        // cout << "Writing " << io.val << " to address " << io.addr << "\n";
+
+        Write(io.addr, io.val);
+
+        io.addr += sizeof(int32_t);
+    }
+
+    return true;
+}
+
+bool UnixDriverAPI::IsOpened(void)
+{
+    return m_initialized;
+}
+
+string GetInterfaceNameFromEP(string pciEndPoint)
+{
+    char szInterfaceCmdPattern[END_POINT_RESULT_MAX_SIZE];
+
+    // This command translates the End Point to the interface name
+    snprintf(szInterfaceCmdPattern, END_POINT_RESULT_MAX_SIZE, "ls /sys/module/wil6210/drivers/pci:wil6210/%s/net", pciEndPoint.c_str());
+
+    FILE* pIoStream = popen(szInterfaceCmdPattern, "r");
+    if (!pIoStream)
+    {
+        // cout << "Failed to run command to detect End Points" << "\n";
+        //LOG_MESSAGE_ERROR("Failed to run command to detect End Points\n" );
+        return "Invalid";
+    }
+
+    char foundInterfaceName[NETWORK_INTERFACE_RESULT_MAX_SIZE];
+
+    while (fgets(foundInterfaceName, END_POINT_RESULT_MAX_SIZE, pIoStream) != NULL)
+    {
+        // The command output contains a newline character that should be removed
+        foundInterfaceName[strcspn(foundInterfaceName, "\r\n")] = '\0';
+
+        string interfaceName(foundInterfaceName);
+
+        // cout << "PCI interface found: " << interfaceName << "\n";
+        //LOG_MESSAGE_DEBUG("PCI interface found: %s", interfaceName);
+
+        pclose(pIoStream);
+
+        return interfaceName;
+    }
+
+    pclose(pIoStream);
+    return "Invalid";
+}
+
+set<string> GetNetworkInterfaceNames()
+{
+    set<string> networkInterfaces;
+
+    // Holds the console ouput containing the current End Point
+    char pciEndPoints[END_POINT_RESULT_MAX_SIZE];
+
+    // This command retrieves the PCI endpoints enumerated
+    const char* szCmdPattern = "ls /sys/module/wil6210/drivers/pci\\:wil6210 | grep :";
+
+    FILE* pIoStream = popen(szCmdPattern, "r");
+    if (!pIoStream)
+    {
+        // cout << "Failed to run command to detect End Points" << "\n";
+        //LOG_MESSAGE_ERROR("Failed to run command to detect End Points\n" );
+        return networkInterfaces;
+    }
+
+    while (fgets(pciEndPoints, END_POINT_RESULT_MAX_SIZE, pIoStream) != NULL)
+    {
+        // The command output contains a newline character that should be removed
+        pciEndPoints[strcspn(pciEndPoints, "\r\n")] = '\0';
+
+        string pciEndPoint(pciEndPoints);
+        // cout << "PCI End Point Found:" << pciEndPoint << "\n";
+        //LOG_MESSAGE_DEBUG("PCI End Point Found: %s", pciEndPoint.c_str());
+
+        // Get interface name from End Point
+        string networkInterfaceName = GetInterfaceNameFromEP(pciEndPoint);
+
+        if (networkInterfaceName != "Invalid")
+        {
+            networkInterfaces.insert(networkInterfaceName);
+        }
+    }
+
+    pclose(pIoStream);
+    return networkInterfaces;
+}
+
+set<string> UnixDriverAPI::Enumerate()
+{
+    set<string> interfaces = GetNetworkInterfaceNames();
+
+    return interfaces;
+}
+
+bool UnixDriverAPI::Open()
+{
+    if(IsOpened())
+    {
+        return true;
+    }
+
+    // cout << "Trying to open device:" << m_interfaceName << "\n";
+    //LOG_MESSAGE_DEBUG("Trying to open device:", m_interfaceName.c_str());
+
+    m_fileDescriptor = socket(AF_INET, SOCK_DGRAM, 0);
+    if (INVALID_FD == m_fileDescriptor || m_fileDescriptor < 0)
+    {
+        // cout << "Failed to open socket to device:" << m_interfaceName << "\n";
+        //LOG_MESSAGE_ERROR("Failed to open socket to device %s", m_interfaceName.c_str());
+        Close();
+        return false;
+    }
+
+    // Validate interface is 11ad interface
+    if(!ValidateInterface())
+    {
+        // cout << "Failed to query interface:" << m_interfaceName << "\n";
+        //LOG_MESSAGE_ERROR("Failed to query interface %s", m_interfaceName.c_str());
+        Close();
+        return false;
+    }
+
+    // Unix command for getting Debug FS path
+    string debugFsFind = "echo \"/sys/kernel/debug/ieee80211/$(ls $(find /sys/devices -name " + m_interfaceName + ")/../../ieee80211 | grep -Eo \"phy[0-9]*\")/wil6210\"";
+
+    // cout << debugFsFind << "\n";
+
+    FILE* pIoStream = popen(debugFsFind.c_str(), "r");
+    if (!pIoStream)
+    {
+        // cout << "Failed to run command to detect DebugFS" << "\n";
+        //LOG_MESSAGE_ERROR("Failed to run command to detect DebugFS\n" );
+        Close();
+        return false;
+    }
+
+    char debugFSPath[DEBUG_FS_MAX_PATH_LENGTH];
+    while (fgets(debugFSPath, DEBUG_FS_MAX_PATH_LENGTH, pIoStream) != NULL)
+    {
+        // The command output contains a newline character that should be removed
+        debugFSPath[strcspn(debugFSPath, "\r\n")] = '\0';
+        string str = (debugFSPath);
+        m_debugFsPath = str;
+
+        // cout << "Found DebugFS Path:" << m_debugFsPath << "\n";
+        //LOG_MESSAGE_DEBUG("Found DebugFS Path: %s", debugFSPath);
+    }
+
+    pclose(pIoStream);
+    m_initialized = true;
+    return true;
+}
+
+bool UnixDriverAPI::ReOpen()
+{
+    return Open();
+}
+
+bool UnixDriverAPI::InternalOpen()
+{
+    return true;
+}
+
+DWORD UnixDriverAPI::DebugFS(char *FileName, void *dataBuf, DWORD dataBufLen, DWORD DebugFSFlags)
+{
+    //do something with params
+    (void)FileName;
+    (void)dataBuf;
+    (void)dataBufLen;
+    (void)DebugFSFlags;
+    return 0;
+}
+
+void UnixDriverAPI::Close()
+{
+    if (m_fileDescriptor != INVALID_FD)
+    {
+        close(m_fileDescriptor);
+        m_fileDescriptor = INVALID_FD;
+    }
+}
+
+int UnixDriverAPI::GetDriverMode(int &currentState)
+{
+    //do something with params
+    (void)currentState;
+
+    return 0;
+}
+bool UnixDriverAPI::SetDriverMode(int newState, int &oldState)
+{
+    //do something with params
+    (void)newState;
+    (void)oldState;
+    return false;
+}
+
+void UnixDriverAPI::Reset()
+{
+    return;
+}
+
+bool UnixDriverAPI::Ioctl(uint32_t Id,
+                          const void *inBuf, uint32_t inBufSize,
+                          void *outBuf, uint32_t outBufSize)
+{
+    //do something with params
+    (void)Id;
+    (void)inBuf;
+    (void)inBufSize;
+    (void)outBuf;
+    (void)outBufSize;
+    return false;
+}
+
+bool UnixDriverAPI::SendRWIoctl(IoctlIO & io, int fd, const char* interfaceName)
+{
+    int ret;
+    struct ifreq ifr;
+    ifr.ifr_data = (char*)&io;
+
+    // cout << "Address is " << hex << io.addr << "\n";
+    // cout << "fd is " << fd << "\n";
+    // cout << "interfaceName is " << interfaceName << "\n";
+
+    snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interfaceName);
+    ifr.ifr_name[IFNAMSIZ - 1] = 0;
+
+    ret = ioctl(fd, WIL_IOCTL_MEMIO, &ifr);
+    if (ret < 0)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+// Receives interface name (wigig#, wlan#) and checks if it is responding
+bool UnixDriverAPI::ValidateInterface()
+{
+    IoctlIO io;
+    io.addr = 0x880050; //baud rate
+    io.op = EP_OPERATION_READ;
+
+    // cout << "Checking interface name:" << m_interfaceName << "\n";
+    //LOG_MESSAGE_DEBUG("Checking interface name: %s", m_interfaceName.c_str());
+
+    if(SendRWIoctl(io, m_fileDescriptor, m_interfaceName.c_str()))
+    {
+        // cout << "Successfuly set interface name:" << m_interfaceName << "\n";
+        //LOG_MESSAGE_DEBUG("Successfuly set interface name: %s", interfaceName);
+        return true;
+    }
+
+    return false;
+}
+
+#endif // ifndef _WINDOWS
diff --git a/debug-tools/host_manager_11ad/access_layer_11ad/Unix/UnixDriverAPI.h b/debug-tools/host_manager_11ad/access_layer_11ad/Unix/UnixDriverAPI.h
new file mode 100644
index 0000000..fbccaf7
--- /dev/null
+++ b/debug-tools/host_manager_11ad/access_layer_11ad/Unix/UnixDriverAPI.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _11AD_PCI_UNIX_DRIVER_API_H_
+#define _11AD_PCI_UNIX_DRIVER_API_H_
+
+
+#ifndef _WINDOWS
+
+#include "DriverAPI.h"
+
+#define DEBUG_FS_MAX_PATH_LENGTH 1024
+
+using namespace std;
+
+class UnixDriverAPI : public DriverAPI
+{
+    typedef struct
+    {
+        DWORD deviceUID;
+        DWORD commandID;
+        DWORD dataSize; /* inBufSize + outBufSize */
+        DWORD inBufOffset;
+        DWORD inBufSize;
+        DWORD outBufOffset;
+        DWORD outBufSize;
+    } IoctlHeader;
+
+    #define IOCTL_FLAG_SET 0x1
+    #define IOCTL_FLAG_GET 0x2
+
+    #define EP_OPERATION_READ 0
+    #define EP_OPERATION_WRITE 1
+    #define WIL_IOCTL_MEMIO (SIOCDEVPRIVATE + 2)
+
+    #define INVALID_FD -1
+
+    static __INLINE BYTE *
+        IoctlDataIn(IoctlHeader *h)
+    {
+        return ((BYTE*)&h[1]) + h->inBufOffset;
+    }
+
+    static __INLINE BYTE *
+        IoctlDataOut(IoctlHeader *h)
+    {
+        return ((BYTE*)&h[1]) + h->outBufOffset;
+    }
+
+    typedef struct {
+        uint32_t op;
+        uint32_t addr; /* should be 32-bit aligned */
+        uint32_t val;
+    } IoctlIO;
+
+public:
+    UnixDriverAPI(string interfaceName) : DriverAPI(interfaceName)
+    {
+        m_initialized = false;
+    }
+    ~UnixDriverAPI();
+
+    // Base access functions (to be implemented by specific device)
+    bool Read(DWORD address, DWORD& value);
+    bool ReadBlock(DWORD addr, DWORD blockSize, char *arrBlock);
+    bool Write(DWORD address, DWORD value);
+    bool WriteBlock(DWORD addr, DWORD blockSize, const char *arrBlock);
+
+    bool IsOpened(void);
+
+    bool Open();
+    bool ReOpen();
+    bool InternalOpen();
+    bool Ioctl(uint32_t Id,
+        const void *inBuf, uint32_t inBufSize,
+        void *outBuf, uint32_t outBufSize);
+    DWORD DebugFS(char *FileName, void *dataBuf, DWORD dataBufLen, DWORD DebugFSFlags);
+    void Close();
+
+    int GetDriverMode(int &currentState);
+    bool SetDriverMode(int newState, int &oldState);
+
+    void Reset();
+
+    static set<string> Enumerate();
+
+private:
+    bool InternalIoctl(void *dataBuf, DWORD dataBufLen, DWORD ioctlFlags);
+    bool SendRWIoctl(IoctlIO & io, int fd, const char* interfaceName);
+    bool ValidateInterface();
+
+    bool m_initialized;
+
+    int m_fileDescriptor;
+
+    string m_debugFsPath;
+};
+
+#endif // ifndef _WINDOWS
+
+#endif //_11AD_PCI_UNIX_DRIVER_API_H_
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/main.cpp b/debug-tools/host_manager_11ad/main.cpp
new file mode 100644
index 0000000..1c41bad
--- /dev/null
+++ b/debug-tools/host_manager_11ad/main.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "OsHandler.h"
+#include "ArgumentsParser.h"
+#include <memory>
+//#include "Server.h"
+#include "DebugLogger.h"
+#include <iostream> //TODO - maybe remove in final
+#include "Host.h"
+
+using namespace std;
+
+#define DEFAULT_COMMANDS_TCP_SERVER_PORT 12348 //TODO - change back to 12348
+#define DEFAULT_EVENTS_TCP_SERVER_PORT 12339 //TODO - change back to 12347
+#define DEFAULT_UDP_SERVER_PORT_IN_GET_MESSAGE 12349 // This is a UDP port to get messages only from the remote server
+#define DEFAULT_REMOTE_UDP_SERVER_PORT_OUT_SEND_MESSAGE 12350 // This is the UDP port in the remote server to send messages only
+
+// *************************************************************************************************
+
+int main(int argc, char* argv[])
+{
+    try
+    {
+        unsigned int commandsTcpPort = DEFAULT_COMMANDS_TCP_SERVER_PORT;
+        unsigned int eventsTcpPort = DEFAULT_EVENTS_TCP_SERVER_PORT;
+        unsigned int udpPortIn = DEFAULT_UDP_SERVER_PORT_IN_GET_MESSAGE;
+        unsigned int udpPortOut = DEFAULT_REMOTE_UDP_SERVER_PORT_OUT_SEND_MESSAGE;
+
+        unique_ptr<ArgumentsParser> pArgumentsParser(new ArgumentsParser());
+        //support to change by the user the commands TCP port only,events Tcp port UDP ports are not changeable by the user
+        pArgumentsParser->ParseAndHandleArguments(argc, argv, commandsTcpPort);
+
+        //Handle OS specific configurations
+        unique_ptr<OsHandler> pOsHandler(new OsHandler());
+        pOsHandler->HandleOsSignals();
+
+        //Start Host object
+        LOG_INFO << "Starting Host Manager" << endl;
+        Host::GetHost().StartHost(commandsTcpPort, eventsTcpPort, udpPortIn, udpPortOut);
+
+        LOG_INFO << "Stopping host_manager_11ad" << endl;
+    }
+    catch (exception& e)
+    {
+        LOG_ERROR << "Stopping host_manager_11ad due to failure: " << e.what() << endl;
+    }
+
+    return 0;
+
+
+}
\ No newline at end of file
diff --git a/debug-tools/host_manager_11ad/pmc_file.cpp b/debug-tools/host_manager_11ad/pmc_file.cpp
new file mode 100644
index 0000000..a653884
--- /dev/null
+++ b/debug-tools/host_manager_11ad/pmc_file.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "pmc_file.h"
+//#include "debug.h" // TODO: change after fixing log issues
+#include <iostream> // TODO: ...and then, remove this line
+#include "UdpTempOsAbstruction.h" // TODO: fix OS issues
+#include "DebugLogger.h"
+
+#include <cstring>
+#include <cerrno>
+#include <sstream>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+// *************************************************************************************************
+#ifdef __ANDROID__
+#define PMC_DATA_DIRECTORY "/data/pmc"
+#else
+#define PMC_DATA_DIRECTORY "/var/pmc"
+#endif
+
+// PMC directory and file name pattern should be managed separately as directory is required as a
+// separate variable.
+
+const char* const PmcFile::s_pDirectory = PMC_DATA_DIRECTORY;
+const char* const PmcFile::s_pFileNamePrefix = "pmc_data_";
+
+// *************************************************************************************************
+
+PmcFile::PmcFile(int fileId)
+    : m_FileId(fileId)
+{
+    std::stringstream ss;
+    ss << s_pDirectory << '/' << s_pFileNamePrefix << fileId;
+    m_FileName = ss.str();
+
+    LOG_DEBUG << "PMC file name #" << fileId << " generated: " << m_FileName << std::endl;
+}
+
+std::ostream& operator<<(std::ostream& os, const PmcFile& pmcFile)
+{
+    return os << "PMC file #" << pmcFile.GetFileId() << " (" << pmcFile.GetFileName() << ')';
+}
+
+// *************************************************************************************************
+
+PmcFileWriter::PmcFileWriter(const PmcFile& pmcFile)
+    : m_PmcFile(pmcFile)
+{
+}
+
+// *************************************************************************************************
+
+bool PmcFileWriter::CreateDirectoryIfNeeded() const
+{
+    // Create a PMC directory if does not exist
+    struct stat st = {};
+    if (stat(m_PmcFile.GetDirectory(), &st) != -1)
+    {
+        LOG_DEBUG << "PMC directory " << m_PmcFile.GetDirectory()
+                  << " exists for " << m_PmcFile.GetFileName() << std::endl;
+        return true;
+    }
+
+    LOG_DEBUG << "Creating a PMC directory: " << m_PmcFile.GetDirectory() << std::endl;
+
+    int status = UdpTempOsAbstruction::CreateFolder(m_PmcFile.GetDirectory()); // TDOO: original line: int status = mkdir(m_PmcFile.GetDirectory(), 0700);
+    if (0 != status)
+    {
+        LOG_ERROR << "Failed to create PMC directory. Path: " << m_PmcFile.GetDirectory() << endl;
+        /*int lastErrno = errno;
+        LOG_ERROR << "Cannot create PMC directory."
+                  << " Path: "    << m_PmcFile.GetDirectory()
+                  << " Error:"    <<  lastErrno
+                  << " Message: " << strerror(lastErrno)
+                  << std::endl;
+                  */
+        return false;
+    }
+
+    return true;
+}
+
+// *************************************************************************************************
+
+bool PmcFileWriter::WriteFile() const
+{
+    if (false == CreateDirectoryIfNeeded())
+    {
+        LOG_ERROR << "Cannot create a PMC directory for " << m_PmcFile << std::endl;
+        return false;
+    }
+
+    // Create a PMC file
+    const char* pCmdPrefix =
+        "D=$(find /sys/kernel/debug/ieee80211/ -name wil6210); cat $D/pmcdata >> ";
+    std::stringstream ss;
+    ss << pCmdPrefix << m_PmcFile.GetFileName();
+
+    system(ss.str().c_str());
+    return true;
+
+}
+
+// *************************************************************************************************
+
+size_t PmcFileWriter::GetFileSize() const
+{
+    FILE *pFile = fopen(m_PmcFile.GetFileName(), "r");
+
+    if (NULL == pFile)
+    {
+        int lastErrno = errno;
+        LOG_ERROR << "Cannot open " << m_PmcFile << " for writing."
+                  << " Error: "   << lastErrno
+                  << " Message: " << strerror(lastErrno)
+                  << std::endl;
+        return 0;
+    }
+
+    fseek (pFile, 0, SEEK_END);
+    size_t fileSize = ftell(pFile);
+    fclose(pFile);
+
+    LOG_DEBUG << "Get PMC file size for " << m_PmcFile
+              << ": " << fileSize << "B" << std::endl;
+
+    return fileSize;
+}
diff --git a/debug-tools/host_manager_11ad/pmc_file.h b/debug-tools/host_manager_11ad/pmc_file.h
new file mode 100644
index 0000000..b7af0b7
--- /dev/null
+++ b/debug-tools/host_manager_11ad/pmc_file.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _PMC_FILE_H_
+#define _PMC_FILE_H_
+
+#include <stdio.h>
+#include <string>
+
+// *************************************************************************************************
+
+// Generates a PMC file name from its ID.
+class PmcFile
+{
+public:
+
+    explicit PmcFile(int fileId);
+
+    int GetFileId() const { return m_FileId; }
+    const char* GetFileName() const { return m_FileName.c_str(); }
+
+    static const char* GetDirectory() { return s_pDirectory; }
+
+private:
+
+    static const char* const s_pDirectory;
+    static const char* const s_pFileNamePrefix;
+
+    const int m_FileId;        // File ID (expected to be unique)
+    std::string m_FileName;    // File Name Buffer
+
+};
+
+std::ostream& operator<<(std::ostream& os, const PmcFile& pmcFile);
+
+// *************************************************************************************************
+
+// Creates a PMC data file according to a provided ID.
+class PmcFileWriter
+{
+public:
+
+    explicit PmcFileWriter(const PmcFile& pmcFile);
+
+    bool WriteFile() const;
+    size_t GetFileSize() const;
+
+private:
+
+    bool CreateDirectoryIfNeeded() const;
+
+    const PmcFile& m_PmcFile;
+
+};
+
+
+#endif    // PMC_FILE_H_
diff --git a/debug-tools/lib/Android.mk b/debug-tools/lib/Android.mk
new file mode 100644
index 0000000..8e4e086
--- /dev/null
+++ b/debug-tools/lib/Android.mk
@@ -0,0 +1,6 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
+
diff --git a/debug-tools/lib/FlashAcss/Android.mk b/debug-tools/lib/FlashAcss/Android.mk
new file mode 100644
index 0000000..2fdbf9f
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libwigig_flashaccess
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPPFLAGS := -Wall -lpthread
+
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/../inc \
+	$(LOCAL_PATH)/../inc/linux \
+	$(LOCAL_PATH)/../utils \
+	$(LOCAL_PATH)/../utils/linux \
+	$(LOCAL_PATH)/linux \
+	$(LOCAL_PATH)/../WlctPciAcss \
+	$(LOCAL_PATH)/../WlctPciAcss/linux
+
+LOCAL_SRC_FILES := $(shell find $(LOCAL_PATH) -name '*.cpp' | sed s:^$(LOCAL_PATH)::g )
+
+LOCAL_SHARED_LIBRARIES := \
+	libwigig_utils \
+	libwigig_pciaccess
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/debug-tools/lib/FlashAcss/FlashAcss.cpp b/debug-tools/lib/FlashAcss/FlashAcss.cpp
new file mode 100644
index 0000000..47f12f4
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/FlashAcss.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "flashacss.h"
+#include "flash_gateway.h"
+#include "SparrowGateway.h"
+#include "MarlonGateway.h"
+
+FLSHACSS_API int wfa_create_flash_access_handler(DType devType, void* pDeviceAccess, void** pFlashAccess)
+{
+	flash_gateway* p_flash_gateway = NULL;
+	if (devType == MST_TALYN)
+	{
+		p_flash_gateway = new SparrowGateway(pDeviceAccess);
+	}
+	if (devType == MST_SPARROW)
+	{
+		p_flash_gateway = new SparrowGateway(pDeviceAccess);
+	}
+	else if (devType == MST_MARLON)
+	{
+		p_flash_gateway = new MarlonGateway(pDeviceAccess);
+	}
+	else
+	{
+		return WLCT_OS_ERROR_NOT_SUPPORTED;
+	}
+	*pFlashAccess = (void*)p_flash_gateway;
+	return 0;
+}
+
+FLSHACSS_API int wfa_close_flash_access_handler(void* pFlashAccess)
+{
+    int res = 0;
+    flash_gateway* p_flash_gateway = (flash_gateway*)pFlashAccess;
+    if (p_flash_gateway != NULL)
+    {
+        __TRY
+        {
+            delete p_flash_gateway;
+        }
+        __EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+        {
+            res = -1;
+        }
+    }
+    return res;
+}
+
+FLSHACSS_API int wfa_run_command(void* pFlashAccss, UCHAR flash_cmd, FLASH_PHASE phase, bool bWrite, unsigned long addr, unsigned long ulSize)
+{
+    int rc = 0;
+    if (pFlashAccss == NULL)
+        return -1;
+
+    __TRY
+    {
+        rc = ((flash_gateway*)pFlashAccss)->runCommand(flash_cmd, phase, bWrite, addr, ulSize);
+    }
+    __EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+    {
+    }
+    return rc;
+}
+
+FLSHACSS_API int wfa_set_data(void* pFlashAccss, const BYTE *buffer, unsigned long size)
+{
+    int rc = 0;
+    if (pFlashAccss == NULL)
+        return -1;
+
+    __TRY
+    {
+        rc = ((flash_gateway*)pFlashAccss)->setData(buffer, size);
+    }
+    __EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+    {
+    }
+    return rc;
+}
+
+FLSHACSS_API int wfa_get_data(void* pFlashAccss, BYTE *buffer, unsigned long size)
+{
+    int rc = 0;
+    if (pFlashAccss == NULL)
+        return -1;
+
+    __TRY
+    {
+        rc = ((flash_gateway*)pFlashAccss)->getData(buffer, size);
+    }
+    __EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+    {
+    }
+    return rc;
+}
+
+FLSHACSS_API int wfa_wait_done(void* pFlashAccss)
+{
+    int rc = 0;
+    if (pFlashAccss == NULL)
+        return -1;
+
+    __TRY
+    {
+        rc = ((flash_gateway*)pFlashAccss)->wait_done();
+    }
+    __EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+    {
+    }
+    return rc;
+}
+
+FLSHACSS_API int wfa_boot_done(void* pFlashAccss)
+{
+    int rc = 0;
+    if (pFlashAccss == NULL)
+        return -1;
+
+    __TRY
+    {
+        rc = ((flash_gateway*)pFlashAccss)->boot_done();
+    }
+    __EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+    {
+    }
+    return rc;
+}
+
+FLSHACSS_API bool wfa_get_lock (void* pFlashAccss)
+{
+    bool ret = false;
+
+    if (pFlashAccss == NULL)
+        return ret;
+
+    __TRY
+    {
+        ret = ((flash_gateway*)pFlashAccss)->get_lock();
+    }
+    __EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+    {
+    }
+    return ret;
+}
+
+FLSHACSS_API int wfa_force_lock (void* pFlashAccss)
+{
+    int rc = 0;
+    if (pFlashAccss == NULL)
+        return -1;
+
+    __TRY
+    {
+        rc = ((flash_gateway*)pFlashAccss)->force_lock();
+    }
+    __EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+    {
+    }
+    return rc;
+}
+
+FLSHACSS_API int wfa_release_lock(void* pFlashAccss)
+{
+    int rc = 0;
+    if (pFlashAccss == NULL)
+        return -1;
+
+    __TRY
+    {
+        rc = ((flash_gateway*)pFlashAccss)->release_lock();
+    }
+    __EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+    {
+    }
+    return rc;
+}
diff --git a/debug-tools/lib/FlashAcss/Makefile b/debug-tools/lib/FlashAcss/Makefile
new file mode 100644
index 0000000..3189001
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/Makefile
@@ -0,0 +1,46 @@
+-include $(TOPDIR)/rules.mk
+
+CFLAGS := -fPIC -Wall -g -MMD
+LDFLAGS := -shared -fPIC
+
+LIB := libwigig_flashaccess.so
+
+.DEFAULT_GOAL = all
+
+ifneq ($(CONFIG_TARGET_ipq)$(CONFIG_TARGET_ipq806x),)
+is_ipq806x = 1
+endif
+
+ifeq ($(is_ipq806x), 1)
+ifneq ($(strip $(TOOLPREFIX)),)
+CROSS:=$(TOOLPREFIX)
+endif
+endif
+
+CC = $(CROSS)gcc
+CXX = $(CROSS)g++
+
+INCLUDES = -I . \
+		-I ../inc/linux \
+                -I ../inc \
+                -I ../utils/linux \
+                -I ../utils \
+                -I ./linux \
+                -I ../WlctPciAcss \
+
+all: $(LIB)
+
+CPP_FILES := $(shell find . -type f -name '*.cpp')
+OBJ_FILES :=  $(CPP_FILES:.cpp=.o)
+
+$(LIB): $(OBJ_FILES)
+	$(CXX) $(LDFLAGS) -o $(LIB) $(OBJ_FILES)
+
+%.o : %.cpp
+	$(CXX) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+clean:
+	rm -rf $(LIB)
+	find . -type f \( -name "*.d" -o -name "*.o" \) -delete
+
+-include $(OBJ_FILES:%.o=%.d)
diff --git a/debug-tools/lib/FlashAcss/MarlonGateway.cpp b/debug-tools/lib/FlashAcss/MarlonGateway.cpp
new file mode 100644
index 0000000..859b9c8
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/MarlonGateway.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <stdio.h>
+#include "MarlonGateway.h"
+
+#define ONES32(size)                    ((size)?(0xffffffff>>(32-(size))):0)
+#define MASK32(offset,size)             (ONES32(size)<<(offset))
+
+#define EXTRACT_C32(source,offset,size)   ((((unsigned)(source))>>(offset)) & ONES32(size))
+#define EXTRACT32(src,start,len)          (((len)==32)?(src):EXTRACT_C32(src,start,len))
+
+#define MERGE_C32(rsrc1,rsrc2,start,len)  ((((rsrc2)<<(start)) & (MASK32((start),(len)))) | ((rsrc1) & (~MASK32((start),(len)))))
+#define MERGE32(rsrc1,rsrc2,start,len)    (((len)==32)?(rsrc2):MERGE_C32(rsrc1,rsrc2,start,len))
+
+MarlonGateway::MarlonGateway(const char *device_name)
+{
+    m_got_lock = false;
+    int res;
+    res =  CreateDeviceAccessHandler( device_name, MST_MARLON, &m_handler );
+    WLCT_UNREFERENCED_PARAM(res);
+}
+
+MarlonGateway::MarlonGateway(void* flashHandle)
+{
+    m_got_lock = false;
+    m_handler = flashHandle;
+}
+
+MarlonGateway::~MarlonGateway(void)
+{
+    int res = CloseDeviceAccessHandler(m_handler);
+
+    WLCT_UNREFERENCED_PARAM(res);
+//     if (m_got_lock)
+//     {
+//       release_lock();
+//     }
+}
+
+int MarlonGateway::runCommand(UCHAR flash_cmd, FLASH_PHASE phase, bool bWrite, DWORD addr, DWORD ulSize)
+{
+    int rc = 0;
+    // write the address if it needed (according to the instruction phase)
+    switch (phase)
+    {
+    case INSTRUCTION_PHASE:
+        break;
+    case INSTRUCTION_ADDRESS_PHASE:
+        rc = setAddr(addr);
+        break;
+    case INSTRUCTION_DATA_PHASE:
+        break;
+    case INSTRUCTION_ADDRESS_DATA_PHASE:
+        rc = setAddr(addr);
+        break;
+    }
+    if (rc != 0)
+    {
+        return rc;
+    }
+
+    u_int32_t opcode_n_len = 0;
+
+    // write the number of bytes to read or write
+    opcode_n_len = MERGE32(opcode_n_len, ulSize, 0, 16);
+
+    if (bWrite)
+    {
+        opcode_n_len = MERGE32(opcode_n_len, 1, BIT_OFFSET_WRITE_OP, 1);
+    }
+
+    switch (phase)
+    {
+    case INSTRUCTION_PHASE:
+        break;
+    case INSTRUCTION_ADDRESS_PHASE:
+        opcode_n_len = MERGE32(opcode_n_len, 1, BIT_OFFSET_ADDR_PHASE, 1);
+        break;
+    case INSTRUCTION_DATA_PHASE:
+        opcode_n_len = MERGE32(opcode_n_len, 1, BIT_OFFSET_DATA_PHASE, 1);
+        break;
+    case INSTRUCTION_ADDRESS_DATA_PHASE:
+        opcode_n_len = MERGE32(opcode_n_len, 1, BIT_OFFSET_DATA_PHASE, 1);
+        opcode_n_len = MERGE32(opcode_n_len, 1, BIT_OFFSET_ADDR_PHASE, 1);
+        break;
+    }
+    opcode_n_len = MERGE32(opcode_n_len, flash_cmd, BIT_OFFSET_INST, BIT_SIZE_INST);
+
+    rc = w(CR_FLASH_OPCODE, opcode_n_len);
+    if (rc != 0)
+    {
+        return rc;
+    }
+    rc = execute_cmd();
+    return rc;
+}
+
+int MarlonGateway::setAddr(DWORD addr)
+{
+    int rc = 0;
+    rc = w(CR_FLASH_ADDR, addr);
+    return rc;
+}
+
+
+int MarlonGateway::execute_cmd () const
+{
+    int rc = 0;
+    // BIT_GO
+    u_int32_t cmd = 0x40000000;
+    if (m_got_lock)
+    {
+        // BIT_GO & BIT_LOCK
+        cmd = 0xC0000000;
+    }
+
+    rc = w(CR_FLASH_STAT_CTL, cmd);
+    if (rc != 0)
+    {
+        return rc;
+    }
+    rc = wait_done();
+    return rc;
+}
+
+typedef struct _FOUR_BYTES_ {
+    union {
+        struct {
+            u_int8_t b[4];
+        }dummyStrct;
+
+        u_int32_t _dword_;
+    }dummyUnion;
+}FOUR_BYTES;
+
+int MarlonGateway::setData(const BYTE *buffer, DWORD size)
+{
+    int rc = 0;
+    u_int32_t word;
+    if ((size & 0x3) == 0)
+    {    // size is module 4
+        rc = wb(CR_FLASH_DATA, size, buffer);
+    }
+    else
+    {
+        for (u_int32_t i = 0 ; i < size ; i += 4)
+        {
+            // check the case that size is not DWORD align
+            if (i+4 > size)
+            {
+                FOUR_BYTES fb;
+                fb.dummyUnion._dword_ = 0;
+                // copy the entire array (1, 2, or 3 bytes)
+                for (DWORD j = 0; j < (size-i); j++)
+                {
+                    fb.dummyUnion.dummyStrct.b[j] = buffer[i+j];
+                }
+                word = fb.dummyUnion._dword_;
+            }
+            else
+            {
+                word = *((u_int32_t*)(&buffer[i]));
+            }
+            rc = w(CR_FLASH_DATA + i, word );
+            if (rc != 0)
+            {
+                return rc;
+            }
+        }
+    }
+    return rc;
+}
+
+int MarlonGateway::getData(BYTE *buffer, DWORD size)
+{
+    int rc = 0;
+    DWORD val;
+    DWORD size2 = (size >> 2) << 2;
+    DWORD remainder = size - size2;
+    rc = rb(CR_FLASH_DATA, size2, buffer);
+    return rc;
+
+    WLCT_UNREFERENCED_PARAM(val);
+    WLCT_UNREFERENCED_PARAM(remainder);
+}
+
+int MarlonGateway::wait_done (void) const
+{
+    int rc = 0;
+    DWORD val;
+    u_int32_t timeout = 0;
+    do {
+        rc = r(CR_FLASH_STAT_CTL, val);
+        if (rc != 0)
+        {
+            return rc;
+        }
+        if (EXTRACT32(val, BIT_OFFSET_BUSY, 1) == 0) {
+            return rc;
+        }
+        sleep_ms( 10 );
+        timeout+= 10;
+    } while (timeout <= 100);
+
+    ERR("wait_done:: timeout reached\n");
+    return (-1);
+}
+
+int MarlonGateway::boot_done(void) const
+{
+    int rc = 0;
+    return rc;
+}
+
+bool MarlonGateway::get_lock ()
+{
+    if (g_debug) DBG("Trying to get flash lock\n");
+    int rc = 0;
+    u_int32_t timeout = 0;
+    DWORD value;
+
+    do {
+        rc = r(CR_FLASH_STAT_CTL, value);
+        if (rc != 0)
+        {
+            return false;
+        }
+        // bit BIT_LOCK
+        if ( (value & 0x80000000) == 0) {
+            m_got_lock = true;
+            if (g_debug) DBG("Done\n");
+            return true;
+        }
+        sleep_ms( 10 );
+        timeout++;
+    } while (timeout <= 10 );
+
+    if (g_debug) DBG("Failed. Semaphore is 0x%04x\n", (unsigned int)value);
+    return false;
+}
+
+int MarlonGateway::force_lock ()
+{
+    int rc = 0;
+    //w (CR_FLASH_STAT_CTL, 1<<15);
+    m_got_lock = true;
+    if (g_debug) DBG("Forced flash lock\n");
+    return rc;
+}
+
+int MarlonGateway::release_lock()
+{
+    int rc = 0;
+    DWORD val;
+    if ( m_got_lock )
+    {
+        rc = r(CR_FLASH_STAT_CTL, val);
+        if (rc != 0)
+        {
+            return rc;
+        }
+        rc = w(CR_FLASH_STAT_CTL, val & 0x7fffffff);
+        m_got_lock = false;
+        if (g_debug) DBG("Released flash lock\n");
+    }
+    return rc;
+}
+
+int MarlonGateway::w(u_int32_t offset, DWORD val) const
+{
+    int rc = 0;
+    rc = WlctAccssWrite(m_handler, offset, val);
+    if( 0 != rc ) {
+        ERR("Failed writing offset 0x%04x rc=%d\n", offset, rc);
+    }
+    return rc;
+}
+
+int MarlonGateway::r(u_int32_t offset, DWORD & val) const
+{
+    int rc = 0;
+    rc = WlctAccssRead(m_handler, offset, val);
+    if( 0 != rc ) {
+        ERR("Failed reading offset 0x%04x rc=%d\n", offset, rc);
+    }
+    return rc;
+}
+
+int MarlonGateway::wb(u_int32_t offset, DWORD size, const BYTE *buffer)
+{
+    int rc = 0;
+    rc = writeBlock(m_handler, offset, size, (char*)buffer);
+    if( 0 != rc ) {
+        ERR("Failed writing offset 0x%04x rc=%d\n", offset, rc);
+    }
+    return rc;
+}
+
+int MarlonGateway::rb(u_int32_t offset, DWORD size, const BYTE *buffer)
+{
+    int rc = 0;
+    rc = readBlock(m_handler, offset, size, (char*)buffer);
+    if( 0 != rc ) {
+        ERR("Failed reading offset 0x%04x rc=%d\n", offset, rc);
+    }
+    return rc;
+}
+
diff --git a/debug-tools/lib/FlashAcss/MarlonGateway.h b/debug-tools/lib/FlashAcss/MarlonGateway.h
new file mode 100644
index 0000000..6d275b2
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/MarlonGateway.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+#include "flashacss.h"
+
+class MarlonGateway : public flash_gateway
+{
+public:
+    MarlonGateway(const char *device_name);
+    MarlonGateway(void* flashHandle);
+    virtual ~MarlonGateway(void);
+    virtual int runCommand(UCHAR flash_cmd, FLASH_PHASE phase, bool bWrite, DWORD addr, DWORD ulSize);
+    virtual int setData(const BYTE *buffer, DWORD size);
+    virtual int getData(BYTE *buffer, DWORD size);
+    virtual int wait_done (void) const;
+    virtual int boot_done(void) const;
+    virtual bool get_lock ();
+    virtual int force_lock ();
+    virtual int release_lock();
+
+private:
+
+    int setAddr(DWORD addr);
+//    void setSize(DWORD size);
+    int setCommand(UCHAR cmd, FLASH_PHASE phase, bool bWrite);
+
+    int wb(u_int32_t offset, DWORD size, const BYTE *buffer);
+    int rb(u_int32_t offset, DWORD size, const BYTE *buffer);
+    int r(u_int32_t offset, DWORD & val) const;
+    int w(u_int32_t offset, DWORD val) const;
+    int execute_cmd() const;
+
+    bool m_got_lock;
+
+    enum constants{
+        CR_USER                 = 0x880000,
+#ifndef MARLON_B0
+        CR_FLASH_DATA           = CR_USER + 0xA8,
+        CR_FLASH_ADDR           = CR_USER + 0x1B0,
+        CR_FLASH_OPCODE         = CR_USER + 0x1AC,
+        CR_FLASH_STAT_CTL       = CR_USER + 0x1A8,
+#else
+        CR_FLASH_DATA           = CR_USER + 0x5C,
+        CR_FLASH_ADDR           = CR_USER + 0x164,
+        CR_FLASH_OPCODE         = CR_USER + 0x160,
+        CR_FLASH_STAT_CTL       = CR_USER + 0x15C,
+#endif // MARLON_B0
+
+        // CR_FLASH_OPCODE
+        BIT_OFFSET_INST         = 16,
+        BIT_SIZE_INST           = 8,
+        BIT_OFFSET_ADDR_PHASE   = 24,
+        BIT_OFFSET_DATA_PHASE   = 25,
+        BIT_OFFSET_WRITE_OP     = 31,
+
+        BIT_FLASH_STATUS_OFFSET = 0,
+        BIT_FLASH_STATUS_SIZE   = 8,
+        BIT_OFFSET_BUSY         = 29,
+        BIT_GO                  = 30,
+        BIT_LOCK                = 31,
+    };
+
+};
diff --git a/debug-tools/lib/FlashAcss/SparrowGateway.cpp b/debug-tools/lib/FlashAcss/SparrowGateway.cpp
new file mode 100644
index 0000000..2146643
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/SparrowGateway.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <stdio.h>
+#include "SparrowGateway.h"
+
+#define ONES32(size)                    ((size)?(0xffffffff>>(32-(size))):0)
+#define MASK32(offset,size)             (ONES32(size)<<(offset))
+
+#define EXTRACT_C32(source,offset,size)   ((((unsigned)(source))>>(offset)) & ONES32(size))
+#define EXTRACT32(src,start,len)          (((len)==32)?(src):EXTRACT_C32(src,start,len))
+
+#define MERGE_C32(rsrc1,rsrc2,start,len)  ((((rsrc2)<<(start)) & (MASK32((start),(len)))) | ((rsrc1) & (~MASK32((start),(len)))))
+#define MERGE32(rsrc1,rsrc2,start,len)    (((len)==32)?(rsrc2):MERGE_C32(rsrc1,rsrc2,start,len))
+
+SparrowGateway::SparrowGateway(const char *device_name)
+{
+    m_got_lock = false;
+    int res;
+    res =  CreateDeviceAccessHandler( device_name, MST_SPARROW, &m_handler );
+    WLCT_UNREFERENCED_PARAM(res);
+}
+
+SparrowGateway::SparrowGateway(void* flashHandle)
+{
+    m_got_lock = false;
+    m_handler = flashHandle;
+}
+
+SparrowGateway::~SparrowGateway(void)
+{
+    int res = CloseDeviceAccessHandler(m_handler);
+
+    WLCT_UNREFERENCED_PARAM(res);
+//     if (m_got_lock)
+//     {
+//       release_lock();
+//     }
+}
+
+int SparrowGateway::runCommand(UCHAR flash_cmd, FLASH_PHASE phase, bool bWrite, DWORD addr, DWORD ulSize)
+{
+    int rc = 0;
+    // write the address if it needed (according to the instruction phase)
+    switch (phase)
+    {
+    case INSTRUCTION_PHASE:
+        break;
+    case INSTRUCTION_ADDRESS_PHASE:
+        rc = setAddr(addr);
+        break;
+    case INSTRUCTION_DATA_PHASE:
+        break;
+    case INSTRUCTION_ADDRESS_DATA_PHASE:
+        rc = setAddr(addr);
+        break;
+    }
+    if (rc != 0)
+    {
+        return rc;
+    }
+
+    u_int32_t opcode_n_len = 0;
+
+    // write the number of bytes to read or write
+    opcode_n_len = MERGE32(opcode_n_len, ulSize, 0, 16);
+
+    if (bWrite)
+    {
+        opcode_n_len = MERGE32(opcode_n_len, 1, BIT_OFFSET_WRITE_OP, 1);
+    }
+
+    switch (phase)
+    {
+    case INSTRUCTION_PHASE:
+        break;
+    case INSTRUCTION_ADDRESS_PHASE:
+        opcode_n_len = MERGE32(opcode_n_len, 1, BIT_OFFSET_ADDR_PHASE, 1);
+        break;
+    case INSTRUCTION_DATA_PHASE:
+        opcode_n_len = MERGE32(opcode_n_len, 1, BIT_OFFSET_DATA_PHASE, 1);
+        break;
+    case INSTRUCTION_ADDRESS_DATA_PHASE:
+        opcode_n_len = MERGE32(opcode_n_len, 1, BIT_OFFSET_DATA_PHASE, 1);
+        opcode_n_len = MERGE32(opcode_n_len, 1, BIT_OFFSET_ADDR_PHASE, 1);
+        break;
+    }
+    opcode_n_len = MERGE32(opcode_n_len, flash_cmd, BIT_OFFSET_INST, BIT_SIZE_INST);
+
+    rc = w(CR_FLASH_OPCODE, opcode_n_len);
+    if (rc != 0)
+    {
+        return rc;
+    }
+    rc = execute_cmd();
+    return rc;
+}
+
+int SparrowGateway::setAddr(DWORD addr)
+{
+    int rc = 0;
+    rc = w(CR_FLASH_ADDR, addr);
+    return rc;
+}
+
+
+int SparrowGateway::execute_cmd () const
+{
+    int rc = 0;
+    // BIT_GO
+    u_int32_t cmd = 0x40000000;
+    if (m_got_lock)
+    {
+        // BIT_GO & BIT_LOCK
+        cmd = 0xC0000000;
+    }
+
+    rc = w(CR_FLASH_STAT_CTL, cmd);
+    if (rc != 0)
+    {
+        return rc;
+    }
+    rc = wait_done();
+    return rc;
+}
+
+typedef struct _FOUR_BYTES_ {
+    union {
+        struct {
+            u_int8_t b[4];
+        }dummyStrct;
+
+        u_int32_t _dword_;
+    }dummyUnion;
+}FOUR_BYTES;
+
+int SparrowGateway::setData(const BYTE *buffer, DWORD size)
+{
+    int rc = 0;
+    u_int32_t word;
+    if ((size & 0x3) == 0)
+    {    // size is module 4
+        rc = wb(CR_FLASH_DATA, size, buffer);
+    }
+    else
+    {
+        for (u_int32_t i = 0 ; i < size ; i += 4)
+        {
+            // check the case that size is not DWORD align
+            if (i+4 > size)
+            {
+                FOUR_BYTES fb;
+                fb.dummyUnion._dword_ = 0;
+                // copy the entire array (1, 2, or 3 bytes)
+                for (DWORD j = 0; j < (size-i); j++)
+                {
+                    fb.dummyUnion.dummyStrct.b[j] = buffer[i+j];
+                }
+                word = fb.dummyUnion._dword_;
+            }
+            else
+            {
+                word = *((u_int32_t*)(&buffer[i]));
+            }
+            rc = w(CR_FLASH_DATA + i, word );
+            if (rc != 0)
+            {
+                return rc;
+            }
+        }
+    }
+    return rc;
+}
+
+int SparrowGateway::getData(BYTE *buffer, DWORD size)
+{
+    int rc = 0;
+    DWORD val;
+    DWORD size2 = (size >> 2) << 2;
+    DWORD remainder = size - size2;
+    rc = rb(CR_FLASH_DATA, size2, buffer);
+    return rc;
+
+    WLCT_UNREFERENCED_PARAM(val);
+    WLCT_UNREFERENCED_PARAM(remainder);
+}
+
+int SparrowGateway::wait_done (void) const
+{
+    int rc = 0;
+    DWORD val;
+    u_int32_t timeout = 0;
+    do {
+        rc = r(CR_FLASH_STAT_CTL, val);
+        if (rc != 0)
+        {
+            return rc;
+        }
+        if (EXTRACT32(val, BIT_OFFSET_BUSY, 1) == 0) {
+            return rc;
+        }
+        sleep_ms( 10 );
+        timeout+= 10;
+    } while (timeout <= 100);
+
+    ERR("wait_done:: timeout reached\n");
+    return (-1);
+}
+
+int SparrowGateway::boot_done(void) const
+{
+    int rc = 0;
+    return rc;
+}
+
+bool SparrowGateway::get_lock ()
+{
+    if (g_debug) DBG("Trying to get flash lock\n");
+    int rc = 0;
+    u_int32_t timeout = 0;
+    DWORD value;
+
+    do {
+        rc = r(CR_FLASH_STAT_CTL, value);
+        if (rc != 0)
+        {
+            return false;
+        }
+        // bit BIT_LOCK
+        if ( (value & 0x80000000) == 0) {
+            m_got_lock = true;
+            if (g_debug) DBG("Done\n");
+            return true;
+        }
+        sleep_ms( 10 );
+        timeout++;
+    } while (timeout <= 10 );
+
+    if (g_debug) DBG("Failed. Semaphore is 0x%04x\n", (unsigned int)value);
+    return false;
+}
+
+int SparrowGateway::force_lock ()
+{
+    int rc = 0;
+    //w (CR_FLASH_STAT_CTL, 1<<15);
+    m_got_lock = true;
+    if (g_debug) DBG("Forced flash lock\n");
+    return rc;
+}
+
+int SparrowGateway::release_lock()
+{
+    int rc = 0;
+    DWORD val;
+    if ( m_got_lock )
+    {
+        rc = r(CR_FLASH_STAT_CTL, val);
+        if (rc != 0)
+        {
+            return rc;
+        }
+        rc = w(CR_FLASH_STAT_CTL, val & 0x7fffffff);
+        m_got_lock = false;
+        if (g_debug) DBG("Released flash lock\n");
+    }
+    return rc;
+}
+
+int SparrowGateway::w(u_int32_t offset, DWORD val) const
+{
+    int rc = 0;
+    rc = WlctAccssWrite(m_handler, offset, val);
+    if( 0 != rc ) {
+        ERR("Failed writing offset 0x%04x rc=%d\n", offset, rc);
+    }
+    return rc;
+}
+
+int SparrowGateway::r(u_int32_t offset, DWORD & val) const
+{
+    int rc = 0;
+    rc = WlctAccssRead(m_handler, offset, val);
+    if( 0 != rc ) {
+        ERR("Failed reading offset 0x%04x rc=%d\n", offset, rc);
+    }
+    return rc;
+}
+
+int SparrowGateway::wb(u_int32_t offset, DWORD size, const BYTE *buffer)
+{
+    int rc = 0;
+    rc = writeBlock(m_handler, offset, size, (char*)buffer);
+    if( 0 != rc ) {
+        ERR("Failed writing offset 0x%04x rc=%d\n", offset, rc);
+    }
+    return rc;
+}
+
+int SparrowGateway::rb(u_int32_t offset, DWORD size, const BYTE *buffer)
+{
+    int rc = 0;
+    rc = readBlock(m_handler, offset, size, (char*)buffer);
+    if( 0 != rc ) {
+        ERR("Failed reading offset 0x%04x rc=%d\n", offset, rc);
+    }
+    return rc;
+}
+
diff --git a/debug-tools/lib/FlashAcss/SparrowGateway.h b/debug-tools/lib/FlashAcss/SparrowGateway.h
new file mode 100644
index 0000000..1d293ba
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/SparrowGateway.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+#include "flashacss.h"
+
+class SparrowGateway : public flash_gateway
+{
+public:
+    SparrowGateway(const char *device_name);
+    SparrowGateway(void* flashHandle);
+    virtual ~SparrowGateway(void);
+    virtual int runCommand(UCHAR flash_cmd, FLASH_PHASE phase, bool bWrite, DWORD addr, DWORD ulSize);
+    virtual int setData(const BYTE *buffer, DWORD size);
+    virtual int getData(BYTE *buffer, DWORD size);
+    virtual int wait_done (void) const;
+    virtual int boot_done(void) const;
+    virtual bool get_lock ();
+    virtual int force_lock ();
+    virtual int release_lock();
+
+private:
+
+    int setAddr(DWORD addr);
+//    void setSize(DWORD size);
+    int setCommand(UCHAR cmd, FLASH_PHASE phase, bool bWrite);
+
+    int wb(u_int32_t offset, DWORD size, const BYTE *buffer);
+    int rb(u_int32_t offset, DWORD size, const BYTE *buffer);
+    int r(u_int32_t offset, DWORD & val) const;
+    int w(u_int32_t offset, DWORD val) const;
+    int execute_cmd() const;
+
+    bool m_got_lock;
+
+    enum constants{
+        CR_USER                 = 0x880000,
+#ifndef MARLON_B0
+        CR_FLASH_DATA           = CR_USER + 0xA8,
+        CR_FLASH_ADDR           = CR_USER + 0x1B0,
+        CR_FLASH_OPCODE         = CR_USER + 0x1AC,
+        CR_FLASH_STAT_CTL       = CR_USER + 0x1A8,
+#else
+        CR_FLASH_DATA           = CR_USER + 0x5C,
+        CR_FLASH_ADDR           = CR_USER + 0x164,
+        CR_FLASH_OPCODE         = CR_USER + 0x160,
+        CR_FLASH_STAT_CTL       = CR_USER + 0x15C,
+#endif // MARLON_B0
+
+        // CR_FLASH_OPCODE
+        BIT_OFFSET_INST         = 16,
+        BIT_SIZE_INST           = 8,
+        BIT_OFFSET_ADDR_PHASE   = 24,
+        BIT_OFFSET_DATA_PHASE   = 25,
+        BIT_OFFSET_WRITE_OP     = 31,
+
+        BIT_FLASH_STATUS_OFFSET = 0,
+        BIT_FLASH_STATUS_SIZE   = 8,
+        BIT_OFFSET_BUSY         = 29,
+        BIT_GO                  = 30,
+        BIT_LOCK                = 31,
+    };
+
+};
diff --git a/debug-tools/lib/FlashAcss/flash.cpp b/debug-tools/lib/FlashAcss/flash.cpp
new file mode 100644
index 0000000..63c8c79
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/flash.cpp
@@ -0,0 +1,852 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "flash.h"
+#include "wlct_os.h"
+
+bool g_debug = false;
+
+void flash_base::set_exit_flag(bool bExit)
+{
+    m_bExit = bExit;
+}
+
+flash::flash(DType device_type)
+    :flash_base(device_type)
+{
+	m_pDeviceAccss = NULL;
+	m_pFlashAccss = NULL;
+	if (device_type == MST_SPARROW)
+		m_size = FLASH_SIZE_SPARROW;
+	if (device_type == MST_MARLON)
+		m_size = FLASH_SIZE_MARLON;
+	if (device_type == MST_TALYN)
+		m_size = FLASH_SIZE_TALYN;
+	m_hw_read_chunk_size = 256;
+	m_hw_write_chunk_size = 256;
+	m_page_erased = new bool [m_size / FLASH_PAGE_SIZE];
+	memset(m_page_erased, 0, m_size / FLASH_PAGE_SIZE);
+	m_buffer = NULL;
+	update_erased_flash(false);
+
+    flag_reading_not_done = false;
+    m_address = 0;
+    m_length = 0;
+}
+
+flash::~flash(void)
+{
+    if (m_pFlashAccss != NULL)
+    {
+        wfa_release_lock(m_pFlashAccss);
+        close ();
+    }
+
+    free_buffer();
+
+    delete m_page_erased;
+}
+
+void flash::free_buffer ()
+{
+    if (m_buffer != NULL)
+    {
+        delete [] m_buffer;
+    }
+}
+
+#ifdef _WINDOWS
+void readThread(void* pFlashDevice)
+#else
+    void *readThread(void* pFlashDevice)
+#endif
+{
+    flash *pFlash = (flash*)pFlashDevice;
+    pFlash->set_flag_reading_not_done(true);
+
+    u_int32_t address = pFlash->get_address();
+    u_int32_t length = pFlash->get_length();
+    BYTE* buffer = (BYTE*)pFlash->get_buffer_ptr();
+
+    pFlash->read( address , length , buffer);
+
+    pFlash->set_flag_reading_not_done(false);
+#ifndef _WINDOWS
+    return NULL;
+#endif
+}
+
+int flash::read_async( const u_int32_t address, const u_int32_t length )
+{
+    if (flag_reading_not_done)
+    {
+        return BUFFER_NOT_READY;
+    }
+
+    m_address = address;
+    m_length = length;
+
+    free_buffer(); //free memory if already allocated before
+    m_buffer = new BYTE[length];
+
+#ifdef _WINDOWS
+    m_thread = (HANDLE)_beginthread(readThread, 0 , this);
+#else
+    if (0 != pthread_create(&m_thread, NULL, readThread, this))
+    {
+        ERR("Failed to create Read thread\n");
+        free_buffer();
+        return BUFFER_NOT_READY;
+    }
+#endif
+
+    return BUFFER_OK;
+}
+
+int flash::open (const char *device_name, DType dtype, bool ignore_lock)
+{
+    int res = 0;
+    res =  CreateDeviceAccessHandler( device_name, dtype, &m_pDeviceAccss);
+    if (res != 0)
+        return res;
+    deviceType = dtype;
+    res =  wfa_create_flash_access_handler(dtype, m_pDeviceAccss, &m_pFlashAccss);
+    if (res != 0)
+        return res;
+
+    res = wfa_boot_done(m_pFlashAccss);
+    if (res != 0)
+        return res;
+
+    if (ignore_lock) {
+        res = wfa_force_lock(m_pFlashAccss);
+    } else {
+        if (wfa_get_lock(m_pFlashAccss) == false) {
+            ERR("Failed getting Flash lock."
+                "Use -ignore_lock option to ignore locking mechanism\n");
+            return (-1);
+        }
+    }
+
+    res = retrive_info();
+    return res;
+}
+
+int flash::open (void *m_pDeviceAccss, DType dtype, bool ignore_lock)
+{
+    int res = 0;
+    if (m_pDeviceAccss == NULL)
+        return -1;
+    deviceType = dtype;
+    res =  wfa_create_flash_access_handler(dtype, m_pDeviceAccss, &m_pFlashAccss);
+    if (res != 0)
+        return res;
+
+    res = wfa_boot_done(m_pFlashAccss);
+    if (res != 0)
+        return res;
+
+    if (ignore_lock) {
+        res = wfa_force_lock(m_pFlashAccss);
+    } else {
+        if (wfa_get_lock(m_pFlashAccss) == false) {
+            ERR("Failed getting Flash lock."
+                "Use -ignore_lock option to ignore locking mechanism\n");
+            return (-1);
+        }
+    }
+
+    res = retrive_info();
+    return res;
+}
+
+void flash::close ()
+{
+    if (m_pFlashAccss)
+    {
+        wfa_close_flash_access_handler(m_pFlashAccss);
+        m_pFlashAccss = NULL;
+    }
+    int res = CloseDeviceAccessHandler(m_pDeviceAccss);
+
+    WLCT_UNREFERENCED_PARAM(res);
+    if (g_debug ) DBG("Closed device\n");
+}
+
+int flash::retrive_info()
+{
+    int res = 0;
+    res = wfa_run_command(m_pFlashAccss, FC_RDID, INSTRUCTION_DATA_PHASE, false, 0, 20);
+    if (res != 0)
+    {
+#ifdef _WINDOWS /* TODO: Handle error in linux */
+        // 1 - OK
+        // 2 = cancel
+        //int mb = MessageBox(NULL, L"Failed access to flash.\nPress OK to continue or\nCancel to abort.", L"Error", MB_OKCANCEL );
+        //if (mb == 2)
+        {
+            return res;
+        }
+        //res = 0;
+#endif
+    }
+
+    memset((void*)&m_info, 0, sizeof(m_info));
+    res = wfa_get_data(m_pFlashAccss,(BYTE*)&m_info, sizeof(m_info) - 4);
+    if (res != 0)
+        return 0;
+
+    INFO ("Flash Manufactured by ");
+    switch (m_info.manufacturer_id)
+    {
+    case 0x20:
+    {
+        INFO("Numonyx ");
+        switch (m_info.device_id1)
+        {
+        case 0x80 :
+        {
+            INFO("M25PE ");
+            break;
+        }
+        case 0x20 :
+        {
+            INFO("M25P ");
+            break;
+        }
+        default : INFO("Unknown device ID ");
+        }
+
+        switch (m_info.device_id2)
+        {
+        case 0x11 :
+        {
+            INFO("Capacity of 1Mbits ");
+            break;
+        }
+        case 0x12 :
+        {
+            INFO("Capacity of 2Mbits ");
+            break;
+        }
+        case 0x14 :
+        {
+            INFO("Capacity of 8Mbits ");
+            break;
+        }
+        default : INFO("Unknown capacity ");
+        }
+
+        break;
+    }
+
+    case 0xC2:
+    {
+        INFO("Macronix ");
+        switch (m_info.device_id1)
+        {
+        case 0x20 :
+        {
+            INFO("MX25L8006E ");
+            break;
+        }
+        default : INFO("Unknown device ID ");
+        }
+
+        switch (m_info.device_id2)
+        {
+        case 0x11 :
+        {
+            INFO("Capacity of 1Mbits ");
+            break;
+        }
+        case 0x12 :
+        {
+            INFO("Capacity of 2Mbits ");
+            break;
+        }
+        case 0x13 :
+        {
+            INFO("Capacity of 4Mbits ");
+            break;
+        }
+        case 0x14 :
+        {
+            INFO("Capacity of 8Mbits ");
+            break;
+        }
+        default : INFO("Unknown capacity ");
+        }
+
+        break;
+    }
+
+    case 0x1F:
+    {
+        INFO("Atmel ");
+        switch (m_info.device_id1)
+        {
+        case 0x43 :
+        {
+            INFO("AT25DF021 ");
+            break;
+        }
+        default : INFO("Unknown device ID ");
+        }
+        break;
+    }
+    default:
+    {
+        INFO("Unknown manufacturer");
+    }
+    }
+
+    //if (m_info.extended_string_length != 0) {
+    //INFO("Extended INFO %s ", m_info.extended_string);
+    //}
+    INFO("\n --------------------------- \n");
+    return res;
+}
+
+
+int flash::read( const u_int32_t address, const u_int32_t length, BYTE *buffer ) const
+{
+    int res = 0;
+    if (address & 0x1) {
+        ERR("address 0x%04x is not word aligned\n",address);
+        return -1;
+    }
+
+    if (length & 0x1) {
+        ERR("length 0x%04x is not word aligned\n",length);
+        return -1;
+    }
+    if (address + length > this->m_size) {
+        ERR("address 0x%04x + length 0x%04x exceeds flash size of 0x%04x\n",address,length,this->m_size);
+        //return -1;
+    }
+
+    u_int32_t offset = 0;
+    while (!m_bExit && offset < length )
+    {
+        u_int16_t current_size = FLASH_PAGE_SIZE - ((address + offset) & 0xff); // Part of a page
+        if (current_size > length ) {
+            current_size = (u_int16_t)length;
+        }
+
+        if (offset + current_size > length ) {
+            current_size = (u_int16_t)(length - offset);
+        }
+        //while ( offset < length ) {
+        //   if( m_bExit ) {
+        //      reruen(-1);
+        //   }
+
+        //   u_int32_t curr_length = min(m_hw_read_chunk_size, length - offset);
+        u_int32_t curr_address = address + offset;
+        if (g_debug) DBG("Reading 0x%04x bytes from address 0x%04x\n", current_size, curr_address);
+
+        res = wfa_run_command(m_pFlashAccss, FC_READ, INSTRUCTION_ADDRESS_DATA_PHASE, false, curr_address, current_size);
+        if (res != 0)
+            break;
+        res = wfa_get_data(m_pFlashAccss,buffer + offset, current_size);
+        if (res != 0)
+            break;
+        offset += current_size;
+    }
+    return res;
+}
+
+int flash::write( const u_int32_t address, const u_int32_t length, const BYTE *buffer, bool verify )
+{
+
+    //unused param
+    (void)verify;
+    int res = -1;
+
+    res = write_wen();
+    if (res != 0)
+        return res;
+
+    u_int32_t offset = 0;
+    while (!m_bExit && offset < length )
+    {
+        u_int16_t current_size = FLASH_PAGE_SIZE - ((address + offset) & 0xff); // Part of a page
+        if (current_size > length ) {
+            current_size = (u_int16_t)length;
+        }
+
+        if (offset + current_size > length ) {
+            current_size = (u_int16_t)(length - offset);
+        }
+
+        //   u_int32_t curr_length = min(m_hw_read_chunk_size, length - offset);
+        u_int32_t curr_address = address + offset;
+        if (g_debug) DBG("Reading 0x%04x bytes from address 0x%04x\n", current_size, curr_address);
+
+        res = wfa_set_data(m_pFlashAccss,buffer + offset, current_size);
+        if (res != 0)
+            break;
+        res = wfa_run_command(m_pFlashAccss, FC_PW, INSTRUCTION_ADDRESS_DATA_PHASE, true, curr_address, current_size);
+        if (res != 0)
+            break;
+        offset += current_size;
+    }
+    return res;
+}
+
+int flash::program( const u_int32_t address, const u_int32_t length, const BYTE *buffer, bool verify )
+{
+    int res = -1;
+
+    //    u_int8_t type = m_erased ? FC_PP : FC_PW;
+    //    u_int8_t type = FC_PW;
+    u_int8_t type = FC_PP;
+
+    if (address & 0x1) {
+        ERR("address 0x%04x is not word aligned\n",address);
+        return -1;
+    }
+
+    if (length & 0x1) {
+        ERR("length 0x%04x is not word aligned\n",length);
+        return -1;
+    }
+    if (address + length > this->m_size) {
+        ERR("address 0x%04x + length 0x%04x exceeds flash size of 0x%04x\n",address,length,this->m_size);
+        return -1;
+    }
+
+    u_int32_t offset = 0;
+    BYTE *verify_buffer = new BYTE[FLASH_PAGE_SIZE];
+    u_int32_t loop = 0;
+    bool dbg_verify = false;
+    while (!m_bExit && offset < length )
+    {
+        loop++;
+        if (loop%50 == 0 || loop < 10)
+            dbg_verify = true;
+        else
+            dbg_verify = false;
+
+        u_int16_t current_size = FLASH_PAGE_SIZE - ((address + offset) & 0xff); // Part of a page
+        if (current_size > length ) {
+            current_size = (u_int16_t)length;
+        }
+
+        if (offset + current_size > length ) {
+            current_size = (u_int16_t)(length - offset);
+        }
+
+        if (type == FC_PP) {
+            bool all_ff = true;
+            for (u_int32_t i = 0; i < current_size ; i+=2) {
+                if ( (*(u_int16_t*)(buffer + offset + i)) != (u_int16_t)(-1) ) {
+                    all_ff = false;
+                    break;
+                }
+            }
+
+            if (all_ff) {
+                if (g_debug) {
+                    DBG(" - skipped empty page 0x%04x - ", address+offset);
+                } else {
+                    INFO("\rSkip   - ");
+                }
+                offset += current_size;
+                INFO("%03.2f%%", (float)offset / (float)length * 100);
+                if (g_debug) DBG("\n");
+                continue;
+            }
+        }
+
+        INFO("\rWrite  - ");
+        res = page_write_program(address+offset, current_size, &buffer[offset], type);
+        if (res != 0)
+            break;
+
+        if (verify || dbg_verify) {
+            INFO("\rRead   - ");
+            res = read(address+offset, current_size, verify_buffer);
+            if (res != 0)
+                break;
+            INFO("\rVerify - ");
+            if( memcmp(&buffer[offset], verify_buffer, current_size) != 0 ) {
+                ERR("Data verification failed on address 0x%04x length 0x%03x\n", address+offset, current_size);
+                res = -1;
+                break;
+            }
+        }
+
+        offset += current_size;
+        INFO("%03.2f%%", (float)offset / (float)length * 100);
+        if (g_debug) DBG("\n");
+    }
+    delete[] verify_buffer;
+    printf("\n");
+    return res;
+}
+
+int flash::page_write_program( const u_int32_t address, const u_int16_t length, const BYTE *buffer, u_int8_t type )
+{
+    int res = 0;
+    if( m_bExit ) {
+        return (-1);
+    }
+
+    if (type == FC_PP) {
+        if ( !is_erased(address) ) {
+            res = sub_sector_erase( address );
+//            sector_erase( address );
+        }
+        if (g_debug) DBG("Programing page address 0x%04x length 0x%03x\n", address, length);
+    }
+    else {
+        if (g_debug) DBG("Writing page address 0x%04x length 0x%03x\n", address, length);
+    }
+
+    res = write_wen();
+    if (res != 0)
+        return res;
+    res = wfa_set_data(m_pFlashAccss, buffer, length);
+    if (res != 0)
+        return res;
+    res = wfa_run_command(m_pFlashAccss, type, INSTRUCTION_ADDRESS_DATA_PHASE, true, address, length);
+    if (res != 0)
+        return res;
+
+    res = wait_wip();
+    return res;
+}
+
+int flash::write_wen (void) const
+{
+    int res = 0;
+//    execute_cmd(0x0106);
+    res = wfa_run_command(m_pFlashAccss, FC_WREN, INSTRUCTION_PHASE, true, 0, 0);
+    return res;
+}
+
+int flash::erase (void)
+{
+    int res = 0;
+    res = wfa_boot_done(m_pFlashAccss);
+    if (res != 0)
+        return res;
+    res = write_wen();
+    if (res != 0)
+        return res;
+
+    //erase
+    res = wfa_run_command(m_pFlashAccss, FC_BE, INSTRUCTION_PHASE, true, 0, 0);
+    if (res != 0)
+        return res;
+
+    res = wait_wip();
+    if (res != 0)
+        return res;
+    update_erased_flash( true );
+    return res;
+}
+
+int flash::page_erase(u_int32_t address)
+{
+    int res = 0;
+    write_wen();
+    if (res != 0)
+        return res;
+
+    res = wfa_run_command(m_pFlashAccss, FC_PE, INSTRUCTION_ADDRESS_PHASE, true, address, 0);
+    if (res != 0)
+        return res;
+    res = wait_wip();
+    if (res != 0)
+        return res;
+    if (g_debug) DBG("Cmd is 0x%04x, Status is 0x%04x\n",FC_PE, get_status() );
+    if (g_debug) DBG("Erased page address 0x%04x\n", address);
+    update_erased_page(address, true);
+    return res;
+}
+
+int flash::sector_erase(u_int32_t address)
+{
+    int res = 0;
+    res = write_wen();
+    if (res != 0)
+        return res;
+
+    res = wfa_run_command(m_pFlashAccss, FC_SE, INSTRUCTION_ADDRESS_PHASE, true, address, 0);
+    if (res != 0)
+        return res;
+    res = wait_wip();
+    if (res != 0)
+        return res;
+    if (g_debug) DBG("Cmd is 0x%04x, Status is 0x%04x\n",FC_SE, get_status() );
+    if (g_debug) DBG("Erased sector address 0x%04x\n", address);
+    update_erased_sector(address, true);
+    return res;
+}
+
+int flash::sub_sector_erase(u_int32_t address)
+{
+    int res = 0;
+    printf("Erasing sub_sector %d\n", address / SUB_SECTOR_SIZE);
+    res = write_wen();
+    if (res != 0)
+        return res;
+
+    res = wfa_run_command(m_pFlashAccss, FC_SSE, INSTRUCTION_ADDRESS_PHASE, true, address, 0);
+    if (res != 0)
+        return res;
+    res = wait_wip();
+    if (res != 0)
+        return res;
+    if (g_debug) DBG("Cmd is 0x%04x, Status is 0x%04x\n",FC_SSE, get_status() );
+    if (g_debug) {
+        DBG(" - Erased sub_sector address 0x%04x - ", address);
+    } else {
+        INFO("\rErase  - ");
+    }
+    update_erased_sub_sector(address, true);
+    return res;
+}
+
+u_int8_t flash::get_status() const
+{
+    int res = 0;
+    res = wfa_run_command(m_pFlashAccss, FC_RDSR, INSTRUCTION_DATA_PHASE, false, 0, 1);
+
+    u_int32_t value;
+    unsigned long size = sizeof(u_int32_t);
+    res = wfa_get_data(m_pFlashAccss, (BYTE*)&value, size);
+
+    WLCT_UNREFERENCED_PARAM(res);
+    return (u_int8_t)value;
+}
+
+int flash::wait_wip (void) const
+{
+    int res = 0;
+    u_int16_t value;
+    u_int32_t timeout = 0;
+    WLCT_UNREFERENCED_PARAM(res);
+
+    do {
+        value = get_status();
+        if (EXTRACT(value, 0, 1) == 0) {
+            if (EXTRACT(value, 1, 1) == 1 ) {
+                ERR("WIP bit is 0 but WEL bit is 1. Status = 0x%04x\n", value);
+                return (-1);
+            }
+            return 0;
+        }
+        timeout++;
+    } while (timeout <= 1000000 );
+
+    ERR("wait_wip:: timeout reached\n");
+    return -1;
+}
+
+void flash::update_erased_page (u_int32_t offset, bool erased )
+{
+    m_page_erased[offset/FLASH_PAGE_SIZE] = erased;
+}
+
+void flash::update_erased_sub_sector (u_int32_t offset, bool erased )
+{
+    u_int32_t page_offset = offset / SUB_SECTOR_SIZE * SUB_SECTOR_SIZE;
+    for (u_int32_t i =0; i < PAGES_PER_SUB_SECTOR; i++) {
+        update_erased_page( page_offset + i * FLASH_PAGE_SIZE, erased );
+    }
+}
+
+void flash::update_erased_sector (u_int32_t offset, bool erased )
+{
+    u_int32_t page_offset = offset / SECTOR_SIZE * SECTOR_SIZE;
+    for (u_int32_t i =0; i < SUB_SECTORS_PER_SECTOR; i++) {
+        update_erased_sub_sector( page_offset + i * SUB_SECTOR_SIZE, erased );
+    }
+}
+
+void flash::update_erased_flash (bool erased )
+{
+    for (u_int32_t i =0; i < SECTORS_PER_FLASH; i++) {
+        update_erased_sector( i * SECTOR_SIZE, erased );
+    }
+}
+
+bool flash::is_erased( u_int32_t page_offset ) const{
+    u_int32_t page_index = page_offset/FLASH_PAGE_SIZE;
+    bool erased = m_page_erased[page_index];
+    return erased;
+}
+
+void flash::clear_erased( u_int32_t page_offset ) {
+    u_int32_t page_index = page_offset/FLASH_PAGE_SIZE;
+    m_page_erased[page_index] = false;
+}
+
+int flash_file::open (const char *device_name, DType dtype, bool ignore_lock = true)
+{
+    //unused param
+    (void)ignore_lock;
+
+//    m_device_name = device_name;
+    m_handler = fopen( device_name, "rb+");
+    m_buffer = new char [m_size];
+    if (0 == m_handler) { // File doesn't exist
+        if (g_debug) DBG("file %s type %d does not exist. Creating...\n", device_name, dtype);
+        m_handler = fopen( device_name, "wb");
+        if (0 == m_handler) {
+            ERR("Failed creating file %s type %d\n", device_name, dtype);
+            return (-1);
+        }
+        memset(m_buffer, 0, m_size);
+    } else {
+        int res = fread(m_buffer, 1, m_size, (FILE*)m_handler);
+        if( (u_int32_t)res != m_size ) {
+            ERR("Expected %d bytes and read %d bytes\n", m_size, res);
+            return (-1);
+        }
+        rewind((FILE*)m_handler);
+        //res = fclose((FILE*)m_handler);
+        //if (0 != res) {
+        //   ERR("Failed closing file\n");
+        //   return (-1);
+        //}
+        if (g_debug) DBG("Opened file %s type %d\n", device_name, dtype);
+    }
+    return 0;
+}
+
+void flash_file::close ()
+{
+    //m_handler = fopen( this->m_device_name.c_str(), "w");
+    //if (0 == m_handler) {
+    //   ERR("Failed opening file for writing\n");
+    //   return (-1);
+    //}
+
+
+    int res = fwrite(m_buffer, 1, m_size, (FILE*)m_handler);
+    if( (u_int32_t)res != m_size ) {
+        ERR("Expected %d bytes and wrote %d bytes\n", m_size, res);
+        return;
+    }
+
+    res = fclose((FILE*)m_handler);
+
+    if (0 != res) {
+        ERR("Failed closing device\n");
+        return;
+    }
+
+    if (g_debug ) DBG("Closed device\n");
+}
+
+int flash_file::erase (void)
+{
+    memset(m_buffer, 0xff, m_size);
+    this->update_erased_flash( true );
+    return 0;
+}
+
+flash_file::flash_file(DType device_type)
+    :flash(device_type)
+{
+    m_buffer = 0;
+}
+
+flash_file::~flash_file(void)
+{
+    if (0 != m_handler) {
+        close ();
+        m_handler = 0;
+    }
+    if (0 != m_buffer) {
+        delete m_buffer;
+        m_buffer = 0;
+    }
+}
+
+int flash_file::page_write_program( const u_int32_t address, const u_int16_t length, const BYTE *buffer, u_int8_t type )
+{
+    if( m_bExit ) {
+        return(-1);
+    }
+
+    if (type == FC_PP) {
+        if ( !this->is_erased(address) ) {
+            sub_sector_erase( address );
+            //         sector_erase( address );
+        }
+        if (g_debug) DBG("Programing page address 0x%04x length 0x%03x\n", address, length);
+    }
+    else {
+        if (g_debug) DBG("Writing page address 0x%04x length 0x%03x\n", address, length);
+    }
+
+    memcpy(m_buffer+address, buffer, length);
+    return 0;
+}
+
+int flash_file::sub_sector_erase(u_int32_t address)
+{
+    printf("Erasing sub_sector %d\n", address / SUB_SECTOR_SIZE);
+
+    memset(m_buffer+address, 0xff, SUB_SECTOR_SIZE);
+    if (g_debug) {
+        DBG(" - Erased sub_sector address 0x%04x - ", address);
+    } else {
+        INFO("\rErase  - ");
+    }
+    this->update_erased_sub_sector(address, true);
+    return 0;
+}
+
+int flash_file::read( const u_int32_t address, const u_int32_t length, BYTE *buffer ) const
+{
+    if (address & 0x1) {
+        ERR("address 0x%04x is not word aligned\n",address);
+        return(-1);
+    }
+
+    if (length & 0x1) {
+        ERR("length 0x%04x is not word aligned\n",length);
+        return(-1);
+    }
+
+    if (address + length > this->m_size) {
+        ERR("address 0x%04x + length 0x%04x exceeds flash size of 0x%04x\n",address,length,this->m_size);
+        return(-1);
+    }
+
+    memcpy(buffer, m_buffer+address, length);
+    return 0;
+}
diff --git a/debug-tools/lib/FlashAcss/flash.h b/debug-tools/lib/FlashAcss/flash.h
new file mode 100644
index 0000000..9625baf
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/flash.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+#include "WlctPciAcss.h"
+#include "flashacss.h"
+
+#ifdef _WINDOWS
+#ifdef FLSHACSS_EXPORTS
+#define FLSHACSS_CPP_API __declspec(dllexport)
+#else
+#define FLSHACSS_CPP_API __declspec(dllimport)
+#endif
+#else //#ifdef _WINDOWS
+#define FLSHACSS_CPP_API
+#endif //#ifdef _WINDOWS
+
+#define BUFFER_NOT_READY -1
+#define BUFFER_OK 0
+
+extern "C"
+{
+class FLSHACSS_CPP_API flash_base
+{
+public:
+	enum {
+		//FLASH_SIZE_SWIFT = 256*1024,
+		FLASH_SIZE_SPARROW = 1024*512,
+		//FLASH_SIZE_MARLON = 1024*1024,
+		FLASH_SIZE_MARLON = 1024*512,
+		FLASH_SIZE_TALYN = 1024*512*4
+	};
+	flash_base(DType device_type)
+	{
+		m_bExit = false;
+		if (device_type == MST_SPARROW)
+			m_size = FLASH_SIZE_SPARROW;
+		if (device_type == MST_MARLON)
+			m_size = FLASH_SIZE_MARLON;
+		if (device_type == MST_TALYN)
+			m_size = FLASH_SIZE_TALYN;
+	};
+	virtual ~flash_base(void) {};
+	virtual int open (const char *device_name, DType dtype, bool ignore_lock) = 0;
+	virtual int open (void *m_pDeviceAccss, DType dtype, bool ignore_lock) = 0;
+	virtual void close () = 0;
+	virtual int read( const u_int32_t address, const u_int32_t length, BYTE *buffer ) const = 0;
+	virtual int write( const u_int32_t address, const u_int32_t length, const BYTE *buffer, bool verify ) = 0;
+	virtual int program( const u_int32_t address, const u_int32_t length, const BYTE *buffer, bool verify ) = 0;
+	virtual int erase (void) = 0;
+	virtual void clear_erased( u_int32_t page_offset ) = 0;
+
+        void set_exit_flag(bool bExit);
+        DType GetDeviceType()
+        {
+            return deviceType;
+        }
+
+    protected:
+        bool m_bExit;
+        DType deviceType;
+        u_int32_t m_size;
+    };
+
+    class FLSHACSS_CPP_API flash: public flash_base
+    {
+    public:
+        flash(DType device_type);
+        virtual ~flash(void);
+        virtual int open (const char *device_name, DType dtype, bool ignore_lock);
+        virtual int open (void *m_pDeviceAccss, DType dtype, bool ignore_lock);
+        virtual void close ();
+        virtual int read( const u_int32_t address, const u_int32_t length, BYTE *buffer ) const;
+        virtual int read_async( const u_int32_t address, const u_int32_t length);
+        int write( const u_int32_t address, const u_int32_t length, const BYTE *buffer, bool verify );
+        int program( const u_int32_t address, const u_int32_t length, const BYTE *buffer, bool verify );
+        virtual int erase (void);
+        bool get_flag_reading_not_done () {return flag_reading_not_done; };
+        void set_flag_reading_not_done (bool new_val) {flag_reading_not_done = new_val;};
+        void* get_buffer_ptr () {return m_buffer; };
+        void free_buffer ();
+
+        u_int32_t get_address () {return m_address; };
+        u_int32_t get_length () {return m_length; };
+
+
+    public:
+        enum {
+            FLASH_PAGE_SIZE = 256,
+            PAGES_PER_SUB_SECTOR = 16,
+            SUB_SECTOR_SIZE = PAGES_PER_SUB_SECTOR * FLASH_PAGE_SIZE,
+            SUB_SECTORS_PER_SECTOR = 16,
+            SECTOR_SIZE = SUB_SECTORS_PER_SECTOR * SUB_SECTOR_SIZE,
+#ifdef FLASH_256KB
+            SECTORS_PER_FLASH = 4, // support 1MB flash
+#else
+            //SECTORS_PER_FLASH = 16, // support 1MB flash
+            SECTORS_PER_FLASH = 8, // support 0.5MB flash
+#endif
+        };
+
+    public:
+        struct {
+            BYTE manufacturer_id;
+            BYTE device_id1;
+            BYTE device_id2;
+            BYTE extended_string_length;
+            char extended_string [256]; // maximal size
+        } m_info; // according to JEDEC standard
+
+    protected:
+        int page_erase(u_int32_t offset);
+        int sector_erase(u_int32_t address);
+        virtual int sub_sector_erase(u_int32_t address);
+        virtual int page_write_program( const u_int32_t address, const u_int16_t length, const BYTE *buffer, u_int8_t type );
+        int wait_wip (void) const;
+        int write_wen (void) const;
+        u_int8_t get_status(void) const;
+        void update_erased_page (u_int32_t offset, bool erased );
+        void update_erased_sub_sector (u_int32_t offset, bool erased );
+        void update_erased_sector (u_int32_t offset, bool erased );
+        void update_erased_flash ( bool erased );
+        bool is_erased( u_int32_t page_offset ) const;
+        void clear_erased( u_int32_t page_offset );
+        int retrive_info();
+
+    protected:
+        bool *m_page_erased;
+        u_int32_t m_hw_read_chunk_size;
+        u_int32_t m_hw_write_chunk_size;
+
+#if _WINDOWS
+        HANDLE m_thread;
+#else
+        pthread_t m_thread;
+#endif
+
+    protected:
+//    string m_device_name;
+
+    protected:
+        enum FlashCommand {
+            FC_WREN         = 0x06,
+            FC_WRDI         = 0x04,
+            FC_RDID         = 0x9F,
+            FC_RDSR         = 0x05,
+            FC_WRLR         = 0xE5,
+            FC_WRSR         = 0x01,
+            FC_RDLR         = 0xE8,
+            FC_READ         = 0x03,
+            FC_FAST_READ    = 0x0B,
+            FC_PW           = 0x0A,
+            FC_PP           = 0x02,
+            FC_PE           = 0xDB,
+            FC_SSE          = 0x20,
+            FC_SE           = 0xD8,
+            FC_BE           = 0xC7,
+            FC_DP           = 0xB9,
+            FC_RDP          = 0xAB
+        };
+    private:
+//    flash_gateway* m_flash_gateway;
+        void* m_pDeviceAccss;
+        void* m_pFlashAccss;
+
+        bool flag_reading_not_done;
+        u_int32_t m_address;
+        u_int32_t m_length;
+        BYTE* m_buffer;
+    };
+
+
+    class FLSHACSS_CPP_API flash_file: public flash
+    {
+    public:
+        flash_file(DType device_type);
+        ~flash_file(void);
+        virtual int read( const u_int32_t address, const u_int32_t length, BYTE *buffer ) const;
+        virtual int erase ();
+        virtual int open (const char *device_name, DType dtype, bool ignore_lock);
+        virtual int open (void *m_pDeviceAccss, DType dtype, bool ignore_lock)
+        {
+            //do something with params
+		    (void)m_pDeviceAccss;
+		    (void)dtype;
+		    (void)ignore_lock;
+            return -1;
+        }
+        virtual void close ();
+
+    private:
+        virtual int page_write_program( const u_int32_t address, const u_int16_t length, const BYTE *buffer, u_int8_t type );
+        virtual int sub_sector_erase(u_int32_t address);
+    private:
+        mutable char *m_buffer;
+        void *m_handler;
+    };
+};
diff --git a/debug-tools/lib/FlashAcss/flash_gateway.h b/debug-tools/lib/FlashAcss/flash_gateway.h
new file mode 100644
index 0000000..ee86d7a
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/flash_gateway.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+#include "flashacss.h"
+#include "WlctPciAcss.h"
+
+//using namespace std;
+
+#define ONES16(size)                    ((size)?(0xffff>>(16-(size))):0)
+#define MASK16(offset,size)             (ONES16(size)<<(offset))
+
+#define EXTRACT_C(source,offset,size)   ((((unsigned)(source))>>(offset)) & ONES16(size))
+#define EXTRACT(src,start,len)          (((len)==16)?(src):EXTRACT_C(src,start,len))
+
+#define MERGE_C(rsrc1,rsrc2,start,len)  ((((rsrc2)<<(start)) & (MASK16((start),(len)))) | ((rsrc1) & (~MASK16((start),(len)))))
+#define MERGE(rsrc1,rsrc2,start,len)    (((len)==16)?(rsrc2):MERGE_C(rsrc1,rsrc2,start,len))
+
+typedef enum _FlashGatewayType
+{
+    FPT_SPARROW,
+    FPT_MARLON
+
+}FlashGatewayType;
+
+typedef enum _FLASH_PHASE
+{
+    INSTRUCTION_PHASE                = 0,
+    INSTRUCTION_ADDRESS_PHASE        = 1,
+    INSTRUCTION_DATA_PHASE           = 2,
+    INSTRUCTION_ADDRESS_DATA_PHASE   = 3
+}FLASH_PHASE;
+
+class flash_gateway
+{
+protected:
+
+public:
+    flash_gateway(const char *device_name);
+    flash_gateway(void* flashHandle);
+    flash_gateway(){}
+    virtual ~flash_gateway(){};
+    virtual int runCommand(UCHAR flash_cmd, FLASH_PHASE phase, bool bWrite, DWORD addr, DWORD ulSize) = 0;
+    virtual int setData(const BYTE *buffer, DWORD size) = 0;
+    virtual int getData(BYTE *buffer, DWORD size) = 0;
+    virtual int wait_done (void) const = 0;
+    virtual int boot_done(void) const = 0;
+    virtual bool get_lock () = 0;
+    virtual int force_lock () = 0;
+    virtual int release_lock() = 0;
+
+protected:
+    void *m_handler;
+};
diff --git a/debug-tools/lib/FlashAcss/flashacss.h b/debug-tools/lib/FlashAcss/flashacss.h
new file mode 100644
index 0000000..f56f290
--- /dev/null
+++ b/debug-tools/lib/FlashAcss/flashacss.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "flash_gateway.h"
+
+#define ERR printf
+#define DBG printf
+#define INFO printf
+//#define _EXIT_(val) {exit (val);}
+
+extern bool g_debug;
+
+
+typedef struct _FLSH_ACCSS_DLL_VERSION
+{
+    int major;
+    int minor;
+    int maintenance;
+    int build;
+    char fullFilePath[256];
+
+}FLSH_ACCSS_DLL_VERSION;
+
+
+// The following ifdef block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the WLCTPCIACSS_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// WLCTPCIACSS_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+
+#ifdef _WINDOWS
+#ifdef FLSHACSS_EXPORTS
+#define FLSHACSS_API __declspec(dllexport)
+#else
+#define FLSHACSS_API __declspec(dllimport)
+#endif
+#endif   // _WINDOWS
+
+#if defined(__GNUC__)
+#if defined(__i386)
+#define FLSHACSS_API extern "C" __attribute__((cdecl))
+#else
+#define FLSHACSS_API extern "C"
+#endif
+#endif   // __GNUC__
+
+
+FLSHACSS_API int wfa_create_flash_access_handler(DType devType, void* pDeviceAccess, void** pFlashAccess);
+FLSHACSS_API int wfa_close_flash_access_handler(void* pFlashAccess);
+FLSHACSS_API int wfa_read(void* pFlashAccess, BYTE *buffer, unsigned long offset, unsigned long size);
+FLSHACSS_API int wfa_write(void* pFlashAccess, const BYTE *buffer, unsigned long offset, unsigned long size);
+FLSHACSS_API int wfa_program(void* pFlashAccess);
+FLSHACSS_API int wfa_erase(void* pFlashAccess);
+
+FLSHACSS_API int wfa_run_command(void* pFlashAccss, UCHAR flash_cmd, FLASH_PHASE phase, bool bWrite, unsigned long addr, unsigned long ulSize);
+FLSHACSS_API int wfa_set_data(void* pFlashAccss, const BYTE *buffer, unsigned long size);
+FLSHACSS_API int wfa_get_data(void* pFlashAccss, BYTE *buffer, unsigned long size);
+FLSHACSS_API int wfa_wait_done(void* pFlashAccss);
+FLSHACSS_API int wfa_boot_done(void* pFlashAccss);
+FLSHACSS_API bool wfa_get_lock(void* pFlashAccss);
+FLSHACSS_API int wfa_force_lock(void* pFlashAccss);
+FLSHACSS_API int wfa_release_lock(void* pFlashAccss);
+
diff --git a/debug-tools/lib/WlctPciAcss/Android.mk b/debug-tools/lib/WlctPciAcss/Android.mk
new file mode 100644
index 0000000..65b6c68
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libwigig_pciaccess
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPPFLAGS := -Wall -lpthread
+
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/../inc \
+	$(LOCAL_PATH)/../inc/linux \
+	$(LOCAL_PATH)/../utils \
+	$(LOCAL_PATH)/../utils/linux \
+	$(LOCAL_PATH)/linux
+
+LOCAL_SRC_FILES := $(shell find $(LOCAL_PATH) -name '*.cpp' | sed s:^$(LOCAL_PATH)::g )
+
+LOCAL_SHARED_LIBRARIES := \
+	libwigig_utils \
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/debug-tools/lib/WlctPciAcss/DeviceAccess.h b/debug-tools/lib/WlctPciAcss/DeviceAccess.h
new file mode 100644
index 0000000..34b7640
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/DeviceAccess.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "wlct_os.h"
+#include "WlctPciAcss.h"
+#include "LoggerSupport.h"
+
+#define _DeviceTypeCOM		1
+#define _DeviceTypePCI		2
+#define _DeviceTypeJTAG	        3
+#define _DeviceTypeMEMORY	4
+
+#define MAX_DEVICE_NAME_LEN 256
+
+class IDeviceAccess
+{
+public:
+    typedef enum
+    {
+        ETypeUnknown = -1,			// Unknown
+        ETypeCOM	= _DeviceTypeCOM,
+        ETypePCI	= _DeviceTypePCI,
+        ETypeJTAG	= _DeviceTypeJTAG,
+        ETypeMEMORY	= _DeviceTypeMEMORY,
+    }
+    EType;
+
+    IDeviceAccess(const TCHAR* tchDeviceName, DType devType);
+    IDeviceAccess(){deviceType = MST_NONE;}
+    virtual ~IDeviceAccess(void){}
+    virtual int CloseDevice() = 0;
+    virtual int GetType() = 0;
+
+    virtual int r32(DWORD addr, DWORD & val) = 0;
+    virtual int w32(DWORD addr, DWORD val) = 0;
+
+    // read block
+    virtual int rb(DWORD addr, DWORD blockSize, char *arrBlock) = 0;
+    // write block
+    virtual int wb(DWORD addr, DWORD blockSize, const char *arrBlock) = 0;
+    // read repeat
+    virtual int rr(DWORD addr, DWORD num_repeat, DWORD *arrBlock) = 0;
+
+    virtual int getFwDbgMsg(FW_DBG_MSG** pMsg) = 0;
+    virtual int clearAllFwDbgMsg() = 0;
+    virtual int do_reset(BOOL bFirstTime = TRUE) = 0;
+    virtual int do_sw_reset() = 0;
+    virtual int do_interface_reset() = 0;
+
+    virtual int startSampling(
+        DWORD* pRegsArr,
+        DWORD regArrSize,
+        DWORD interval,
+        DWORD maxSampling,
+        DWORD transferMethod)
+    {
+        //do something with params
+        (void)pRegsArr;
+        (void)regArrSize;
+        (void)interval;
+        (void)maxSampling;
+        (void)transferMethod;
+
+        LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+        return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+    }
+    virtual int stopSampling()
+    {
+        LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+        return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+    }
+    virtual int getSamplingData(DWORD** pDataSamples)
+    {
+        //do something with params
+    	(void)pDataSamples;
+        LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+        return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+    }
+    virtual int alloc_pmc(int num_of_descriptors, int size_of_descriptor)
+    {
+        //do something with params
+        (void)num_of_descriptors;
+        (void)size_of_descriptor;
+        LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+        return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+    }
+
+    bool isInitialized()
+    {
+        return bInitialized;
+    }
+    wlct_os_err_t GetLastError()
+    {
+        return lastError;
+    }
+    void SetLastError(wlct_os_err_t err)
+    {
+        lastError = err;
+    }
+    TCHAR* GetInterfaceName()
+    {
+        return szInterfaceName;
+    }
+    DType GetDeviceType()
+    {
+        return deviceType;
+    }
+    DEVICE_STEP GetDeviceStep()
+    {
+        return deviceStep;
+    }
+    void SetDeviceStep(DEVICE_STEP devStep)
+    {
+        deviceStep = devStep;
+    }
+
+    //virtual int alloc_pmc(){
+    //	return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+    //}
+protected:
+    bool bInitialized;
+    DType deviceType;
+    DEVICE_STEP deviceStep;
+    TCHAR szInterfaceName[MAX_DEVICE_NAME_LEN];
+    std::deque<FW_DBG_MSG*> m_dbgMsgsList;
+
+public:
+    // Sampling
+    DWORD	m_no_sampling_regs;
+    DWORD	m_interval;
+    DWORD	m_maxSampling;
+    DWORD*	m_pRegsArr;
+    DWORD	m_sampling_head;
+    DWORD	m_sampling_tail;
+    DWORD	m_loops;
+    DWORD	oneSamplingSize;
+    // cyclic buffer that hold the sampling
+    DWORD*	m_sampling_arr;
+    // I'm using this buffer for optimizations
+    // when getSamplingData will called, we will copy the data that was capture
+    // till now to this buffer.
+    // We do not need to allocate it each time and not release it.
+    DWORD*	m_get_sampling_arr;
+    DWORD	m_transferMethod; // 1-save to file 2-save to buffer
+
+    LONG m_flag_busy;
+    wlct_os_err_t lastError;
+};
+
+
diff --git a/debug-tools/lib/WlctPciAcss/IoctlDevXFace.h b/debug-tools/lib/WlctPciAcss/IoctlDevXFace.h
new file mode 100644
index 0000000..ae37ca4
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/IoctlDevXFace.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "wlct_os.h"
+
+class IIoctlDev
+{
+public:
+  IIoctlDev(const TCHAR* tchDeviceName)
+  {
+    WLCT_ASSERT(tchDeviceName != NULL);
+    WLCT_ASSERT(sizeof(szInterfaceName) > _tcslen(tchDeviceName));
+    _tcscpy_s(szInterfaceName, INTERFACE_NAME_LENGTH, tchDeviceName);
+  }
+
+  virtual ~IIoctlDev()
+  {
+
+  }
+
+  virtual bool          IsOpened(void) = 0;
+
+  virtual wlct_os_err_t Open() = 0;
+  virtual wlct_os_err_t Ioctl(uint32_t Id,
+                              const void *inBuf, uint32_t inBufSize,
+                              void *outBuf, uint32_t outBufSize) = 0;
+  virtual wlct_os_err_t DebugFS(char *FileName, void *dataBuf, DWORD dataBufLen, DWORD DebugFSFlags){
+	  //do something with params
+    (void)FileName;
+    (void)dataBuf;
+    (void)dataBufLen;
+    (void)DebugFSFlags;
+    return -1;
+  }
+  virtual void          Close() = 0;
+
+protected:
+  static const size_t INTERFACE_NAME_LENGTH = 256;
+  TCHAR szInterfaceName[INTERFACE_NAME_LENGTH];
+};
diff --git a/debug-tools/lib/WlctPciAcss/Makefile b/debug-tools/lib/WlctPciAcss/Makefile
new file mode 100644
index 0000000..2e5ef56
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/Makefile
@@ -0,0 +1,52 @@
+-include $(TOPDIR)/rules.mk
+
+CFLAGS := -fPIC -Wall -g -MMD
+LDFLAGS := -shared -fPIC
+
+LIB := libwigig_pciaccess.so
+
+.DEFAULT_GOAL = all
+
+ifneq ($(CONFIG_TARGET_ipq)$(CONFIG_TARGET_ipq806x),)
+is_ipq806x = 1
+endif
+
+ifeq ($(is_ipq806x), 1)
+ifneq ($(strip $(TOOLPREFIX)),)
+CROSS:=$(TOOLPREFIX)
+endif
+endif
+
+CC = $(CROSS)gcc
+CXX = $(CROSS)g++
+
+INCLUDES = -I . \
+	   -I ../inc/linux \
+           -I ../inc \
+           -I ../utils/linux \
+           -I ../utils \
+           -I ./linux \
+
+all: $(LIB)
+
+CPP_FILES := $(shell find . -type f -name '*.cpp')
+C_FILES := $(shell find . -type f -name '*.c')
+
+OBJ_FILES :=  $(CPP_FILES:.cpp=.o)
+OBJ_FILES +=  $(C_FILES:.c=.o)
+
+$(LIB): $(OBJ_FILES)
+	$(CXX) $(LDFLAGS) -o $(LIB) $(OBJ_FILES)
+
+%.o : %.cpp
+	$(CXX) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+%.o : %.c
+	$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+clean:
+	rm -rf $(LIB)
+	find . -type f \( -name "*.d" -o -name "*.o" \) -delete
+
+
+-include $(OBJ_FILES:%.o=%.d)
diff --git a/debug-tools/lib/WlctPciAcss/MemoryAccess.cpp b/debug-tools/lib/WlctPciAcss/MemoryAccess.cpp
new file mode 100644
index 0000000..758c4cb
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/MemoryAccess.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "MemoryAccess.h"
+
+CMemoryAccess::CMemoryAccess(const TCHAR* tchDeviceName, DType devType)
+{
+	//do something with params
+	(void)tchDeviceName;
+	//if (devType == MST_MARLON)
+	//{
+	m_size = WLCT_DEV_MEMORY_SIZE;
+	m_baseAddress = 0x800000;
+	//}
+
+	deviceType = devType;
+	m_pMem = new char[m_size];
+	memset(m_pMem, 0, m_size);
+}
+
+CMemoryAccess::~CMemoryAccess(void)
+{
+	CloseDevice();
+}
+
+int CMemoryAccess::GetType()
+{
+	return IDeviceAccess::ETypeMEMORY;
+}
+
+int CMemoryAccess::CloseDevice()
+{
+	if (m_pMem != NULL)
+	{
+		delete []m_pMem;
+		m_pMem = NULL;
+	}
+	return 0;
+}
+
+int CMemoryAccess::r32(DWORD addr, DWORD & val)
+{
+	DWORD	actualAddr = addr - m_baseAddress;
+
+	if (actualAddr >= m_size)
+		return -1;
+
+	actualAddr = actualAddr >> 2;
+	val = ((DWORD*)m_pMem)[actualAddr];
+	LOG_MESSAGE_DEBUG(_T("ADDR(in bytes): %04X Value: 0x%08X"), addr, val);
+	return 0;
+}
+
+int CMemoryAccess::w32(DWORD addr, DWORD val)
+{
+	DWORD	actualAddr = addr - m_baseAddress;
+	if (actualAddr >= m_size)
+		return -1;
+
+	actualAddr = actualAddr >> 2;
+	((DWORD*)m_pMem)[actualAddr] = val;
+	LOG_MESSAGE_DEBUG(_T("ADDR: %04X Value: 0x%04X"),addr, val);
+	return 0;
+}
+
+int CMemoryAccess::rb(DWORD addr, DWORD blockSize, char *arrBlock)
+{
+	DWORD	actualAddr = addr;
+//	DWORD	val;
+
+	//if (GetDeviceType() == MST_MARLON)
+	//{
+	actualAddr = addr - m_baseAddress;
+	//}
+
+	if ((actualAddr+blockSize) >= m_size)
+		return -1;
+
+	memcpy(arrBlock, &(m_pMem[actualAddr]), blockSize);
+
+// 	for (int inx = 0; inx < blockSize; inx++)
+// 	{
+// 		// wait between each loop
+// 		DWORD readFromIndex = actualAddr+inx;
+//
+// 		if (GetDeviceType() == MST_SWIFT)
+// 		{
+// 			val = ((USHORT*)m_pMem)[readFromIndex];
+// 		}
+//
+// 		if (GetDeviceType() == MST_MARLON)
+// 		{
+// 			val = ((DWORD*)m_pMem)[actualAddr];
+// 		}
+//
+// 		arrBlock[inx] = val;
+// 	}
+
+	return 0;
+}
+
+int CMemoryAccess::wb(DWORD addr, DWORD blockSize, const char *arrBlock)
+{
+	//do something with params
+	(void)addr;
+	(void)blockSize;
+	(void)arrBlock;
+
+	return 0;
+}
+
+void CMemoryAccess::rr32(DWORD addr, DWORD num_repeat, DWORD *arrBlock)
+{
+	DWORD* pFrom = &((DWORD*)m_pMem)[addr>>2];
+	for (DWORD loop = 0; loop < num_repeat; loop++)
+	{
+		// wait between each loop
+
+		arrBlock[loop] = *pFrom;
+	}
+}
+
+int CMemoryAccess::rr(DWORD addr, DWORD num_repeat, DWORD *arrBlock)
+{
+	if (!isInitialized())
+		return -1;
+
+	DWORD	actualAddr = addr;
+
+	//if (GetDeviceType() == MST_MARLON)
+	//{
+	actualAddr = addr - m_baseAddress;
+	//}
+
+	if (actualAddr >= m_size)
+		return -1;
+
+	//if (GetDeviceType() == MST_MARLON)
+	//{
+	rr32(actualAddr, num_repeat, arrBlock);
+	//}
+	return 0;
+}
+
+int CMemoryAccess::getFwDbgMsg(FW_DBG_MSG** pMsg)
+{
+	//do something with params
+	(void)pMsg;
+
+//	LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+	return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+int CMemoryAccess::clearAllFwDbgMsg()
+{
+	LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+	return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+int CMemoryAccess::do_reset(BOOL bFirstTime)
+{
+	//do something with params
+	(void)bFirstTime;
+	LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+	return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+int CMemoryAccess::do_sw_reset()
+{
+	LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+	return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+int CMemoryAccess::do_interface_reset()
+{
+	LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+	return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+}
diff --git a/debug-tools/lib/WlctPciAcss/MemoryAccess.h b/debug-tools/lib/WlctPciAcss/MemoryAccess.h
new file mode 100644
index 0000000..3240327
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/MemoryAccess.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+#include "DeviceAccess.h"
+
+#define WLCT_DEV_MEMORY_SIZE	(0x129000)
+
+
+extern "C" class CMemoryAccess : public IDeviceAccess
+{
+public:
+	CMemoryAccess(const TCHAR* tchDeviceName, DType devType);
+	virtual ~CMemoryAccess(void);
+	virtual int CloseDevice();
+	virtual int GetType();
+	virtual int r32(DWORD addr, DWORD & val);
+	virtual int w32(DWORD addr, DWORD val);
+	virtual int rb(DWORD addr, DWORD blockSize, char *arrBlock);
+	virtual int wb(DWORD addr, DWORD blockSize, const char *arrBlock);
+	virtual int rr(DWORD addr, DWORD num_repeat, DWORD *arrBlock);
+	virtual int getFwDbgMsg(FW_DBG_MSG** pMsg);
+	virtual int clearAllFwDbgMsg();
+	virtual int do_reset(BOOL bFirstTime = TRUE);
+	virtual int do_sw_reset();
+	virtual int do_interface_reset();
+
+private:
+	void rr32(DWORD addr, DWORD num_repeat, DWORD *arrBlock);
+
+private:
+	char*	m_pMem;
+	DWORD	m_size;
+	DWORD	m_baseAddress;
+};
diff --git a/debug-tools/lib/WlctPciAcss/PciDeviceAccess.cpp b/debug-tools/lib/WlctPciAcss/PciDeviceAccess.cpp
new file mode 100644
index 0000000..343a650
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/PciDeviceAccess.cpp
@@ -0,0 +1,1265 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "wlct_os.h"
+
+#include "PciDeviceAccess.h"
+#include "WlctPciAcssHelper.h"
+#include "DeviceAccess.h"
+#include <ctime>
+#include "Util.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+// PCI interface
+
+CPciDeviceAccess::CPciDeviceAccess(const TCHAR* tchDeviceName, DType devType)
+    : IoctlDev(tchDeviceName)/*, SamplingThread(SamplingThreadProc, this),
+                               PciPluginThread(this)*/
+{
+    LOG_MESSAGE_INFO(_T("Create PCI device access for: %s"), tchDeviceName);
+    _tcscpy_s(szInterfaceName, MAX_DEVICE_NAME_LEN, tchDeviceName);
+    deviceType = devType;
+    m_close_state = 2;
+    m_open_state = 0;
+    //LOG_MESSAGE_INFO(_T("[close %d] [open %d]"), m_close_state, m_open_state);
+    bInitialized = false;
+    Open();
+    if (bInitialized)
+    {
+//		PciPluginThread.Start();
+    }
+    return;
+}
+
+void CPciDeviceAccess::Open()
+{
+    if (IoctlDev.IsOpened())
+    {
+        LOG_MESSAGE_INFO(_T("Already open. changing m_close_state = 0 and m_open_state = 2 [close %d] [open %d]"), m_close_state, m_open_state);
+        bInitialized = true;
+        m_close_state = 0;
+        m_open_state = 2;
+        return;
+    }
+
+    m_sampling_arr = NULL;
+    m_get_sampling_arr = NULL;
+//	m_hMonitorwPciPluginThread = NULL;
+    lastError = WLCT_OS_ERROR_SUCCESS;
+    dwBaseAddress = 0x880000;
+
+    bIsLocal = true;
+    TCHAR LorR = szInterfaceName[_tcslen(szInterfaceName) - 1];
+    if (LorR == _T('R') || LorR == _T('r'))
+    {
+        bIsLocal = false;
+        dwBaseAddress += 0x100000;
+    }
+
+    lastError = IoctlDev.Open();
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        //LOG_MESSAGE_ERROR(_T("PCIdeviceAccess: failed to open driver wPci. ERROR_FILE_NOT_FOUND = %d"), lastError);
+        return;
+    }
+
+//	ReOpen();
+
+    bInitialized = true;
+//	LOG_MESSAGE_INFO(_T("changing m_close_state to 0 and m_open_state to 2 [close %d] [open %d]"), m_close_state, m_open_state);
+    m_close_state = 0;
+    m_open_state = 2;
+
+    m_flag_busy = false;
+}
+
+CPciDeviceAccess::~CPciDeviceAccess()
+{
+    CloseDevice();
+}
+
+int CPciDeviceAccess::ReOpen()
+{
+    LOG_MESSAGE_INFO(_T("Sending ioctl IOCTL_FILTER_OPEN_DEVICE"));
+
+    FILTER_OPEN_DEVICE openDevice;
+
+    lastError = IoctlDev.Ioctl(bIsLocal?IOCTL_FILTER_OPEN_LOCAL_DEVICE:IOCTL_FILTER_OPEN_REMOTE_DEVICE,
+                               NULL, 0, &openDevice, sizeof(openDevice));
+    if ( lastError != WLCT_OS_ERROR_SUCCESS )
+    {
+        LOG_MESSAGE_ERROR(_T("Error in DeviceIoControl: IOCTL_FILTER_OPEN_DEVICE [err %d]"), lastError);
+        return -1;
+    }
+
+    LOG_MESSAGE_INFO(_T("Successfully sent ioctl IOCTL_FILTER_OPEN_DEVICE"));
+
+    return 0;
+}
+
+int CPciDeviceAccess::GetType()
+{
+    return IDeviceAccess::ETypePCI;
+}
+
+int CPciDeviceAccess::InternalCloseDevice()
+{
+//	DWORD bytesReturned = 0;
+
+//	sleep_ms(100);
+
+// 	if (bIsLocal)
+// 	{
+// 		bRc = DeviceIoControl (hPciCtrlDevice, IOCTL_FILTER_CLOSE_LOCAL_DEVICE, NULL, 0, NULL, 0, &bytesReturned, NULL);
+// 	}
+// 	else
+// 	{
+// 		bRc = DeviceIoControl (hPciCtrlDevice, IOCTL_FILTER_CLOSE_REMOTE_DEVICE, NULL, 0, NULL, 0, &bytesReturned, NULL);
+// 	}
+// 	lastError = ::GetLastError();
+// 	if ( !bRc || bytesReturned != 0)
+// 	{
+// 		LOG_MESSAGE_WARN(_T("Error in DeviceIoControl : %d"), lastError);
+// 	}
+// 	else
+// 	{
+// 		LOG_MESSAGE_INFO(_T("Successfully sent ioctl IOCTL_FILTER_CLOSE_DEVICE"))
+// 	}
+
+    IoctlDev.Close();
+//	LOG_MESSAGE_INFO(_T("changing m_close_state to 2 [close %d] [open %d]"), m_close_state, m_open_state);
+    m_close_state = 2;
+
+    return 0;
+}
+
+int CPciDeviceAccess::CloseDevice()
+{
+    //PciPluginThread.Stop();
+    if (InternalCloseDevice() == 0)
+    {
+        bInitialized = false;
+        //LOG_MESSAGE_INFO(_T("changing m_open_state to 0 and bInitialized to false [close %d] [open %d]"), m_close_state, m_open_state);
+        m_open_state = 0;
+    }
+    return 0;
+}
+
+#ifdef _WINDOWS
+int CPciDeviceAccess::SetDriverMode(int newState, int &oldState, int &payloadResult)
+{
+    if(!isInitialized()){
+        return -1;
+    }
+    if (m_close_state == 2)
+        Open();
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+    SET_MODE_CMD_INPUT inBuffer;
+    SET_MODE_CMD_OUTPUT outBuffer;
+
+    memset(&inBuffer, 0, sizeof(SET_MODE_CMD_INPUT));
+    memset(&outBuffer, 0, sizeof(SET_MODE_CMD_OUTPUT));
+
+    inBuffer.mode = (DRIVER_MODE)newState;
+
+    lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_SET_MODE_NEW, &inBuffer, sizeof(inBuffer), &outBuffer, sizeof(outBuffer));
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_SET_MODE_NEW failed. %X"), lastError);
+        oldState = -1;
+        return -1;
+        payloadResult = -1;
+    }
+    if(!outBuffer.result){
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_SET_MODE_NEW did not change the mode"));
+    }
+    payloadResult = outBuffer.result;
+    oldState = outBuffer.previousMode;
+    return 0;
+}
+
+
+int CPciDeviceAccess::GetDriverMode(int &currentState){
+    if(!isInitialized()){
+        return false;
+    }
+    if (m_close_state == 2)
+        Open();
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+    GET_MODE_CMD_OUTPUT currentModeBuffer;
+    memset(&currentModeBuffer, 0, sizeof(GET_MODE_CMD_OUTPUT));
+
+
+    lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_GET_MODE_NEW, NULL, 0, &currentModeBuffer, sizeof(currentModeBuffer));
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_GET_MODE_NEW failed. %X"), lastError);
+        return -1;
+    }
+
+    currentState = currentModeBuffer.currentMode;
+    return 0;
+}
+#endif //_WINDOWS
+
+// MARLON
+int CPciDeviceAccess::r32(DWORD addr, DWORD & val)
+{
+    if (!isInitialized())
+        return -1;
+    if (m_close_state == 2)
+        Open();
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+    FILTER_1_ULONG_PARAM	inParams;
+    FILTER_1_ULONG_PARAM	outParams;
+
+    inParams.param = addr;
+
+    if (!bIsLocal)
+    {
+        inParams.param += 0x100000;
+    }
+
+    if (IoctlDev.bOldIoctls)
+        lastError = IoctlDev.Ioctl(IOCTL_INDIRECT_READ_OLD, &inParams, sizeof(inParams), &outParams, sizeof(outParams));
+    else
+        lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_INDIRECT_READ, &inParams, sizeof(inParams), &outParams, sizeof(outParams));
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_INDIRECT_READ failed. %X"), lastError);
+        return -1;
+    }
+
+    val = outParams.param;
+    LOG_MESSAGE_DEBUG(_T("ADDR(in bytes): 0x%X Value: 0x%X"), addr, val);
+    return 0;
+}
+
+bool CPciDeviceAccess::try2open(int timeout)
+{
+    do
+    {
+        Open();
+        if (IoctlDev.IsOpened())
+            break;
+        sleep_ms(100);
+        timeout -= 100;
+    } while (timeout > 0);
+
+    if (!IoctlDev.IsOpened())
+        return false;
+    return true;
+}
+
+
+int CPciDeviceAccess::do_interface_reset()
+{
+    if (!isInitialized())
+        return -1;
+    if (m_close_state == 2)
+        Open();
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+    FILTER_1_ULONG_PARAM	inParams;
+    FILTER_1_ULONG_PARAM	outParams;
+
+    /*inParams.param = addr;
+
+      if (!bIsLocal)
+      {
+      inParams.param += 0x100000;
+      }*/
+
+    lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_DEVICE_SW_RESET, &inParams, sizeof(inParams), &outParams, sizeof(outParams));
+
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_DEVICE_SW_RESET failed. %X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+
+    //val = outParams.param;
+    LOG_MESSAGE_INFO(_T("Pci Interface Reset using IOCTL"));
+    return 0;
+}
+
+int CPciDeviceAccess::do_sw_reset()
+{
+    LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+    return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+#define USING_RESET_FUNCTION 0
+int CPciDeviceAccess::do_reset(BOOL bFirstTime)
+{
+    if (USING_RESET_FUNCTION == 0)
+    {
+        LOG_MESSAGE_WARN(_T("reset was not done because USING_RESET_FUNCTION == 0"));
+        return -1;
+    }
+
+    if (!isInitialized())
+        return -1;
+    if (m_close_state == 2)
+        Open();
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+    DWORD addr;
+    if (deviceStep == STEP_NONE)
+        addr = 0x880AE0;
+    else if (deviceStep == MARLON_STEP_B0 || deviceStep == SPARROW_STEP_A0 || deviceStep == SPARROW_STEP_B0)
+        addr = 0x880B04;
+    else // default
+    {
+        addr = 0x880B04;
+    }
+
+    DWORD val;
+    bool bres;
+
+    // check if there is an access to the board
+    int ret = r32(BAUD_RATE_REGISTER, val);
+    if (ret != 0 || val == 0 || val == 0xFFFFFFFF)
+    {
+        // access failed.
+        if (bFirstTime == FALSE)
+            return -1;
+
+        // do disable enable
+        InternalCloseDevice();
+        sleep_ms(500);
+        bres = Util::ICHDisableEnable();
+        if (!bres)
+            sleep_ms(1000);
+        Open();
+        do_reset(FALSE);
+    }
+
+    w32(addr, 1);
+    InternalCloseDevice();
+    sleep_ms(500);
+    bres = Util::ICHDisableEnable();
+
+    bres = try2open(2000);
+    if (!bres)
+    {
+        LOG_MESSAGE_INFO(_T("do_reset: failed to open the device after reset"));
+        return -1;
+    }
+
+
+    int timeout = 2000;
+    bres = false;
+    do
+    {
+        ret = r32(BAUD_RATE_REGISTER, val);
+        if (ret == 0 && val > 0 && val < 0xFFFFFFFF)
+        {
+            bres = true;
+            break;
+        }
+        sleep_ms(100);
+        timeout -= 100;
+    } while (timeout > 0);
+    if (!bres)
+    {
+        LOG_MESSAGE_ERROR(_T("ERROR: failed to read the baudrate after reset."));
+        return -1;
+    }
+    return 0;
+}
+
+int CPciDeviceAccess::reset_complete()
+{
+    DWORD val;
+    bool bres;
+    int ret;
+
+    InternalCloseDevice();
+    sleep_ms(500);
+    Util::ICHDisableEnable();
+
+    bres = try2open(2000);
+    if (!bres)
+    {
+        LOG_MESSAGE_INFO(_T("failed to open the device after reset"));
+        return -1;
+    }
+
+    int timeout = 2000;
+    bres = false;
+    do
+    {
+        ret = r32(BAUD_RATE_REGISTER, val);
+        if (ret == 0 && val > 0 && val < 0xFFFFFFFF)
+        {
+            bres = true;
+            break;
+        }
+        sleep_ms(100);
+        timeout -= 100;
+    } while (timeout > 0);
+    if (!bres)
+    {
+        LOG_MESSAGE_ERROR(_T("ERROR: failed to read the baudrate after reset."));
+        return -1;
+    }
+    return 0;
+}
+
+// marlon
+int CPciDeviceAccess::w32(DWORD addr, DWORD val)
+{
+    if (!isInitialized())
+        return -1;
+    if (m_close_state == 2)
+        Open();
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+
+    FILTER_2_ULONG_PARAM	inParams;
+
+    inParams.param1 = addr;
+
+    if (!bIsLocal)
+    {
+        inParams.param1 += 0x100000;
+    }
+
+    inParams.param2 = val;
+
+
+    if (IoctlDev.bOldIoctls)
+        lastError = IoctlDev.Ioctl(IOCTL_INDIRECT_WRITE_OLD, &inParams, sizeof(inParams), NULL, 0);
+    else
+        lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_INDIRECT_WRITE, &inParams, sizeof(inParams), NULL, 0);
+
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("IOCTL_INDIRECT_WRITE failed. %X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+
+    if (USING_RESET_FUNCTION == 0)
+    {
+        if (((deviceStep == STEP_NONE) && (addr == 0x880AE0)) || ((deviceStep == MARLON_STEP_B0 || deviceStep == SPARROW_STEP_A0 || deviceStep == SPARROW_STEP_B0) && (addr == 0x880B04)))
+        {
+            if (val & 0x1)
+            {
+                LOG_MESSAGE_WARN(_T("Calling reset from write command instead of calling reset directly!!!!!!!!!!!!!!!!!!!!!!!!!!"));
+                reset_complete();
+            }
+        }
+    }
+
+    LOG_MESSAGE_DEBUG(_T("ADDR: 0x%X Value: 0x%X"),addr, val);
+    return 0;
+}
+
+// addr is in bytes.
+// block size for SWITH is number of 16 bits and MARLON is number of bytes
+// In MARLON the block size should be align to 32 bits (otherwise it will be
+// truncated by the hardware)
+//
+int CPciDeviceAccess::rb(DWORD addr, DWORD blockSize, char *arrBlock)
+{
+    if (!isInitialized())
+        return -1;
+// 	if (m_close_state == 1)
+// 		InternalCloseDevice();
+// 	if (m_open_state == 1)
+// 		Open();
+// 	if (m_close_state == 2)
+// 		return -1;
+    if (m_close_state == 2)
+        Open();
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+
+    //if (GetDeviceType() == MST_MARLON)
+    //{
+    FILTER_1_ULONG_PARAM	inParams;
+
+    inParams.param = addr;
+
+    if (!bIsLocal)
+    {
+        inParams.param += 0x100000;
+    }
+
+
+    if (IoctlDev.bOldIoctls)
+        lastError = IoctlDev.Ioctl(IOCTL_INDIRECT_READ_BLOCK, &inParams, sizeof(inParams), arrBlock, blockSize);
+    else
+        lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_INDIRECT_READ_BLOCK, &inParams, sizeof(inParams), arrBlock, blockSize);
+
+    //	DWORD le = GetLastError();
+    //	LOG_MESSAGE_WARN(_T("IOCTL_INDIRECT_READ return %d [lastError 0x%X]"), bRc, le);
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("IOCTL_INDIRECT_READ failed. %X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+    //}
+
+    return 0;
+}
+
+int CPciDeviceAccess::wb(DWORD addr, DWORD blockSize, const char *arrBlock)
+{
+    if (!isInitialized())
+        return -1;
+    if (m_close_state == 2)
+        Open();
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+    PFILTER_WRITE_BLOCK	pinParams;
+    char* p = new char[2*sizeof(ULONG) + blockSize];
+    pinParams = (PFILTER_WRITE_BLOCK)p;
+    pinParams->address = addr;
+
+    if (!bIsLocal)
+    {
+        pinParams->address += 0x100000;
+    }
+
+    pinParams->size = blockSize;
+    memcpy(pinParams->buffer, arrBlock, blockSize);
+
+
+    if (IoctlDev.bOldIoctls)
+        lastError = IoctlDev.Ioctl(IOCTL_INDIRECT_WRITE_BLOCK, pinParams, 2*sizeof(ULONG) + blockSize, NULL, 0);
+    else
+        lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_INDIRECT_WRITE_BLOCK, pinParams, 2*sizeof(ULONG) + blockSize, NULL, 0);
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_INDIRECT_WRITE_BLOCK failed. %X"), lastError);
+        InternalCloseDevice();
+        delete [] p;
+        return -1;
+    }
+
+    delete [] p;
+    return 0;
+}
+
+void CPciDeviceAccess::rr32(DWORD addr, DWORD num_repeat, DWORD *arrBlock)
+{
+    WLCT_UNREFERENCED_PARAM(addr);
+    WLCT_UNREFERENCED_PARAM(num_repeat);
+    WLCT_UNREFERENCED_PARAM(arrBlock);
+    WLCT_ASSERT(0);
+}
+
+int CPciDeviceAccess::rr(DWORD addr, DWORD num_repeat, DWORD *arrBlock)
+{
+    if (!isInitialized())
+        return -1;
+    if (m_close_state == 2)
+        Open();
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+    //if (GetDeviceType() == MST_MARLON)
+    //{
+    FILTER_1_ULONG_PARAM	inParams;
+    inParams.param = addr;
+    if (!bIsLocal)
+    {
+        inParams.param += 0x100000;
+    }
+
+    lastError = IoctlDev.Ioctl(IOCTL_INDIRECT_READ_REPEAT, &inParams, sizeof(inParams), arrBlock, num_repeat*sizeof(DWORD));
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("IOCTL_INDIRECT_READ failed. %X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+
+
+// 		actualAddr = addr - dwBaseAddress;
+// 		if (actualAddr >= CRSsize)
+// 			return -1;
+//
+// 		rr32(actualAddr>>2, num_repeat, arrBlock);
+    //}
+    return 0;
+}
+
+int CPciDeviceAccess::getFwDbgMsg(FW_DBG_MSG** pMsg)
+{
+    (void)pMsg;
+    //	LOG_MESSAGE_DEBUG(_T("NOT IMPLEMENTED"));
+    return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+int CPciDeviceAccess::clearAllFwDbgMsg()
+{
+    LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
+    return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+/*
+  void CPciDeviceAccess::SamplingThreadProc(void *pDeviceAccss)
+  {
+  LOG_MESSAGE_DEBUG(_T("start running"));
+  CPciDeviceAccess *pDevice = (CPciDeviceAccess*)pDeviceAccss;
+  #ifdef WCLT_SAMPLING_TO_FILE_IS_SUPPORTED
+  HANDLE            hSamplingFile = INVALID_HANDLE_VALUE;
+  #endif
+  uint64_t          startTS;
+
+  pDevice->m_sampling_head = 0;
+  pDevice->m_sampling_tail = 0;
+  pDevice->m_loops = 0;
+
+  startTS = GetTimeStampMs();
+
+  WLCT_UNREFERENCED_PARAM(startTS);
+
+  SAMPLING_REGS* currEntry;
+
+  #ifdef WCLT_SAMPLING_TO_FILE_IS_SUPPORTED
+  DWORD written = 0;
+  if (pDevice->m_transferMethod == 1)
+  {	// saving to file
+  TCHAR file_name[256];
+  _stprintf (file_name, _T("c:\\sampling_%X.bin"), GetTickCount());
+  hSamplingFile = CreateFile(file_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+  if (hSamplingFile == INVALID_HANDLE_VALUE)
+  {
+  return;
+  }
+  // first data in the file is the number of registers in each sampling
+  WriteFile(hSamplingFile, &pDevice->m_no_sampling_regs, sizeof(pDevice->m_no_sampling_regs), &written, NULL);
+  // then write the registers address
+  WriteFile(hSamplingFile, pDevice->m_pRegsArr, sizeof(DWORD)* pDevice->m_no_sampling_regs, &written, NULL);
+  }
+  #endif
+
+  uint64_t last_timeStamp = 0;
+  do
+  {
+  //sleep_ms(pDevice->m_interval);
+  do
+  {
+  sleep_ms(0);
+  } while ( (GetTimeStampMs() - last_timeStamp) <  pDevice->m_interval);
+  last_timeStamp = GetTimeStampMs();
+
+  currEntry = (SAMPLING_REGS*)(pDevice->m_sampling_arr + pDevice->m_sampling_head * (pDevice->m_no_sampling_regs + 1));
+  currEntry->timeStamp = (DWORD)last_timeStamp;
+  for (DWORD i = 0; i < pDevice->m_no_sampling_regs; i++)
+  {
+  DWORD val;
+  if (pDevice->GetDeviceType() == MST_SWIFT)
+  {
+  pDevice->r2(pDevice->m_pRegsArr[i], val);
+  currEntry->regArr[i] = val;
+  }
+  else if (pDevice->GetDeviceType() == MST_MARLON)
+  {
+  pDevice->r32(pDevice->m_pRegsArr[i], currEntry->regArr[i]);
+  }
+  }
+
+  pDevice->m_sampling_head++;
+  if (pDevice->m_sampling_head >= pDevice->m_maxSampling)
+  {
+  pDevice->m_sampling_head = 0;
+  #ifdef WCLT_SAMPLING_TO_FILE_IS_SUPPORTED
+  if (pDevice->m_transferMethod == 1)
+  {
+  // save the buffer to the disk;
+  WriteFile(hSamplingFile, pDevice->m_sampling_arr, pDevice->oneSamplingSize * pDevice->m_maxSampling, &written, NULL);
+  }
+  #endif
+  if (pDevice->m_transferMethod == 2)
+  {
+  pDevice->m_loops++;
+  }
+
+  }
+
+  } while (!pDevice->SamplingThread.ShouldStop());
+  #ifdef WCLT_SAMPLING_TO_FILE_IS_SUPPORTED
+  if (pDevice->m_transferMethod == 1)
+  {
+  CloseHandle(hSamplingFile);
+  }
+  #endif
+  LOG_MESSAGE_DEBUG(_T("Leaving"));
+  }
+
+  int CPciDeviceAccess::startSampling(
+  DWORD* pRegsArr,
+  DWORD regArrSize,
+  DWORD interval,
+  DWORD maxSampling,
+  DWORD transferMethod)
+  {
+  m_no_sampling_regs = regArrSize;
+  m_pRegsArr = new DWORD[regArrSize];
+  memcpy(m_pRegsArr, pRegsArr, sizeof(DWORD)*regArrSize);
+  m_interval = interval;
+  m_maxSampling = maxSampling;
+  m_transferMethod = transferMethod;
+
+  // allocate the sampling buffer
+  // each sampling required:
+  // m_no_sampling_regs * sizeof(DWORD) + timestamp
+  oneSamplingSize = m_no_sampling_regs * sizeof(DWORD) + sizeof(DWORD);
+  m_sampling_arr = new DWORD[oneSamplingSize * m_maxSampling];
+  m_get_sampling_arr = new DWORD[oneSamplingSize * m_maxSampling];
+
+  // start the read tread
+  SamplingThread.Start();
+  sleep_ms(100);
+
+  return 0;
+  }
+
+  int CPciDeviceAccess::stopSampling()
+  {
+  SamplingThread.Stop();
+
+  // free the sampling buffers
+  delete [] m_pRegsArr;
+  delete [] m_sampling_arr;
+  delete [] m_get_sampling_arr;
+  return 0;
+  }
+
+  int CPciDeviceAccess::getSamplingData(DWORD** pDataSamples)
+  {
+  DWORD total_copy = 0;
+
+  // get the head and tail position
+  DWORD head = m_sampling_head;
+  DWORD tail = m_sampling_tail;
+
+  LOG_MESSAGE_DEBUG(_T("[head %X] [tail %X] [loops %d]"), head, tail, m_loops);
+
+  memset(m_get_sampling_arr, 0, oneSamplingSize * m_maxSampling);
+
+  // 0 - no new data. nothing to copy
+  // -1 - error
+  // 1 - copy from tail to head
+  // 2 - copy from tail to end buffer and then from start buffer to head
+  // 3 - overlapped. copy from head to head.
+  //
+  DWORD copy_type = 0;
+  if (m_loops == 0)
+  {
+  if (head == tail)
+  {
+  // no new data
+  copy_type = 0;
+  }
+  else if (head > tail)
+  {
+  // new data. copy from tail to head
+  copy_type = 1;
+  }
+  else if (head < tail)
+  {
+  // error
+  LOG_MESSAGE_ERROR(_T("ERROR: !!!!!!!! loop is ZERO [head %X] [tail %X]"), head, tail);
+  copy_type = -1;
+  }
+  }
+  else if (m_loops == 1)
+  {
+  if (head == tail)
+  {
+  // overlapped. copy head to head
+  copy_type = 3;
+  }
+  else if (head > tail)
+  {
+  // overlapped. copy head to head
+  copy_type = 3;
+  }
+  else if (head < tail)
+  {
+  // copy from tail to end buffer and then from start buffer to head
+  copy_type = 2;
+  }
+  }
+  else if (m_loops > 1)
+  {
+  // overlapped. copy head to head
+  copy_type = 3;
+  }
+
+  DWORD srcPos;
+  switch (copy_type)
+  {
+  case 1:
+  {
+  srcPos = oneSamplingSize * tail / sizeof(DWORD);
+  memcpy(m_get_sampling_arr, &(m_sampling_arr[srcPos]), oneSamplingSize * (head - tail));
+  total_copy = oneSamplingSize * (head - tail);
+  }
+  break;
+  case 2:
+  {
+  // copy from tail to the end of the buffer
+  srcPos = oneSamplingSize * tail / sizeof(DWORD);
+  memcpy(m_get_sampling_arr, &(m_sampling_arr[srcPos]), oneSamplingSize * (m_maxSampling - tail));
+  //
+  DWORD nextIndex = (oneSamplingSize * (m_maxSampling - tail))/sizeof(DWORD);
+  memcpy(&(m_get_sampling_arr[nextIndex]), m_sampling_arr, oneSamplingSize * head);
+  total_copy = oneSamplingSize * (m_maxSampling - tail) + oneSamplingSize * head;
+  }
+  break;
+  case 3:
+  {
+  // copy all the cyclic buffer, starting from the head
+  // the head is pointing to the next place to put there new sample.
+  // there is a racing condition because it is possible that just before
+  // we will start coping a context switch will happened and the read
+  // sampling thread will overwrite this area.
+  // we are not locking this sharing resource for now
+  memcpy(m_get_sampling_arr, &(m_sampling_arr[head]), oneSamplingSize * (m_maxSampling - head));
+  // copy from the beginning till the head
+  DWORD nextIndex = (oneSamplingSize * (m_maxSampling - head))/sizeof(DWORD);
+  memcpy(&(m_get_sampling_arr[nextIndex]), &(m_sampling_arr[0]), oneSamplingSize * head);
+  total_copy = oneSamplingSize * m_maxSampling;
+
+  LOG_MESSAGE_WARN(_T("detect a loop [%d]. samples lost."), m_loops);
+  }
+  break;
+  }
+
+  m_loops = 0;
+  m_sampling_tail = head;
+  LOG_MESSAGE_DEBUG(_T("[m_sampling_tail %X] [total_copy %d]"), m_sampling_tail, total_copy);
+
+  *pDataSamples = m_get_sampling_arr;
+  return total_copy;
+  }
+*/
+int CPciDeviceAccess::alloc_pmc(int num_of_descriptors, int size_of_descriptor){
+    if (!isInitialized())
+    {
+        LOG_MESSAGE_ERROR(_T("alloc_pmc - Not initialized"));
+        return -1;
+    }
+    if (m_close_state == 2)
+    {
+        Open();
+    }
+    if (!IoctlDev.IsOpened())
+    {
+        LOG_MESSAGE_ERROR(_T("alloc_pmc - Not opened"));
+        return -1;
+    }
+
+    int data[2] = {num_of_descriptors, size_of_descriptor};
+    int res = IoctlDev.DebugFS((char*)"pmccfg", data, 8, 0);
+
+    if (res != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_ERROR(_T("Cannot open DebugFS for pmccfg: 0x%X"), res);
+    }
+
+    return res;
+}
+#ifdef _WINDOWS
+int CPciDeviceAccess::send_wmi_cmd(SEND_RECEIVE_WMI* wmi)
+{
+    LOG_MESSAGE_INFO(_T("send_wmi_cmd: 0x%X"),  wmi->uCmdId);
+
+    if (!isInitialized())
+        return -1;
+
+
+    lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_SEND_WMI, wmi, sizeof(SEND_RECEIVE_WMI), NULL, 0);
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_SEND_WMI failed. %X"), lastError);
+        return lastError;
+    }
+
+
+    return 0;
+}
+
+int CPciDeviceAccess::recieve_wmi_event(SEND_RECEIVE_WMI* evt)
+{
+    LOG_MESSAGE_INFO(_T("recieve_wmi_event"));
+
+    if (!isInitialized())
+        return -1;
+
+
+    lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_RECEIVE_WMI, NULL, 0, evt, sizeof(SEND_RECEIVE_WMI));
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_RECEIVE_WMI failed. %X"), lastError);
+        return lastError;
+    }
+
+    return 0;
+}
+#endif //_WINDOWS
+
+int CPciDeviceAccess::register_driver_mailbox_event(HANDLE* pMailboxEventHandle )
+{
+    LOG_MESSAGE_INFO(_T("register_driver_mailbox_event"));
+
+    if (!isInitialized())
+        return -1;
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+    REGISTER_EVENT req;
+    memset(&req, 0, sizeof(REGISTER_EVENT));
+
+    req.hEvent = *pMailboxEventHandle;
+
+    lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_REGISTER_WMI_RX_EVENT, &req, sizeof(REGISTER_EVENT), NULL, 0);
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_REGISTER_WMI_RX_EVENT failed. 0x%X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+
+    return ERROR_SUCCESS;
+}
+
+int CPciDeviceAccess::register_device_unplug2(INT_PTR hEvent){
+    LOG_MESSAGE_INFO(_T("register_device_unplug2"));
+
+    WLCT_UNREFERENCED_PARAM(hEvent);
+
+    if (!isInitialized())
+        return -1;
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+
+#ifdef _WINDOWS
+    DRIVER_REGISTER_EVENT req;
+    memset(&req, 0, sizeof(DRIVER_REGISTER_EVENT));
+    LOG_MESSAGE_INFO(_T("register_device_unplug2: <Event Pointer=0x%p>"), hEvent);
+    req.UserEventHandle = hEvent;
+
+    lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_REGISTER_DEVICE, &req, sizeof(req), NULL, 0);
+
+
+#endif //_WINDOWS
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("register_device_unplug2 failed. 0x%X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+
+    return ERROR_SUCCESS;
+}
+
+int CPciDeviceAccess::unregister_device_unplug2(){
+    LOG_MESSAGE_INFO(_T("unregister_device_unplug2"));
+
+    if (!isInitialized())
+        return -1;
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+
+#ifdef _WINDOWS
+    DRIVER_REGISTER_EVENT req;
+    memset(&req, 0, sizeof(DRIVER_REGISTER_EVENT));
+    LONG invalidPointer = -1;
+    LOG_MESSAGE_INFO(_T("register_device_unplug2: <Event Pointer=0x%X>"), invalidPointer);
+    req.UserEventHandle = invalidPointer;
+
+    lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_REGISTER_DEVICE, &req, sizeof(req), NULL, 0);
+
+
+#endif //_WINDOWS
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("register_device_unplug2 failed. 0x%X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+
+    return ERROR_SUCCESS;
+}
+
+
+
+int CPciDeviceAccess::register_driver_device_event(INT_PTR hEvent,int deviceId, int eventId)
+{
+    LOG_MESSAGE_INFO(_T("register_driver_device_event"));
+    WLCT_UNREFERENCED_PARAM(hEvent);
+    WLCT_UNREFERENCED_PARAM(deviceId);
+    WLCT_UNREFERENCED_PARAM(eventId);
+
+    if (!isInitialized())
+        return -1;
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+
+#ifdef _WINDOWS
+
+    LOG_MESSAGE_INFO(_T("register_driver_device_event: <Event Pointer=0x%p> <deviceId=0x%x> <EventId=0x%x>"), hEvent, deviceId, eventId);
+
+    // Our DLL assumed to be always compiled for 32bit application.
+    // Since the driver excpects to recieve HANDLEs of size that IS platform speciefic,
+    // we must dynamically find out if we are running on 64bit OS or now.
+    // for more information, read remarks on WlcyPciAcssWmi.h file
+    if (Util::Is64BitWindows())
+    {
+        LOG_MESSAGE_INFO(_T("register_driver_device_event Driver HANDLE problem WA, using 64bit struct"));
+        EVENT_HANDLE_64BIT req;
+        memset(&req, 0, sizeof(EVENT_HANDLE_64BIT));
+        req.DeviceId = deviceId;
+        req.EventId = eventId;
+        req.hEvent_l = hEvent;
+        req.hEvent_h = 0;
+
+        lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_REGISTER_EVENT, &req, sizeof(req), NULL, 0);
+
+
+    }
+    else
+    {
+        LOG_MESSAGE_INFO(_T("register_driver_device_event Driver HANDLE problem WA, using 32bit struct"));
+        EVENT_HANDLE_32BIT req;
+        memset(&req, 0, sizeof(EVENT_HANDLE_32BIT));
+
+        req.DeviceId = deviceId;
+        req.EventId = eventId;
+        req.hEvent = hEvent;
+
+        lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_REGISTER_EVENT, &req, sizeof(req), NULL, 0);
+    }
+
+#endif //_WINDOWS
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_REGISTER_EVENT failed. 0x%X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+    //do something with params
+    (void)deviceId;
+    (void)eventId;
+    return ERROR_SUCCESS;
+}
+int CPciDeviceAccess::register_driver_device_events(INT_PTR hDnEvent, INT_PTR hUpEvent, INT_PTR hUnplugEvent, INT_PTR hSysAssertEvent)
+{
+    LOG_MESSAGE_INFO(_T("register_driver_device_events"));
+    WLCT_UNREFERENCED_PARAM(hDnEvent);
+    WLCT_UNREFERENCED_PARAM(hUpEvent);
+    WLCT_UNREFERENCED_PARAM(hUnplugEvent);
+    WLCT_UNREFERENCED_PARAM(hSysAssertEvent);
+
+    if (!isInitialized())
+        return -1;
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+
+#ifdef _WINDOWS
+
+    LOG_MESSAGE_INFO(_T("register_driver_device_events: <hDnEvent=0x%p> <hUpEvent=0x%p> <hUnplugEvent=0x%p> <hSysAssertEvent=0x%p>"), hDnEvent, hUpEvent, hUnplugEvent, hSysAssertEvent );
+
+    // Our DLL assumed to be always compiled for 32bit application.
+    // Since the driver excpects to recieve HANDLEs of size that IS platform speciefic,
+    // we must dynamically find out if we are running on 64bit OS or now.
+    // for more information, read remarks on WlcyPciAcssWmi.h file
+    if (Util::Is64BitWindows())
+    {
+        LOG_MESSAGE_INFO(_T("register_driver_device_events Driver HANDLES problem WA, using 64bit struct"));
+        SHARED_EVENT_64BIT req;
+        memset(&req, 0, sizeof(SHARED_EVENT_64BIT));
+
+        req.hDnEvent_l = hDnEvent;
+        req.hDnEvent_h = 0;
+        req.hUpEvent_l = hUpEvent;
+        req.hUpEvent_h = 0;
+        req.unplugEvent_l = hUnplugEvent;
+        req.hUpEvent_h = 0;
+        req.sysAssertEvent_l = hSysAssertEvent;
+        req.sysAssertEvent_h = 0;
+
+        lastError = IoctlDev.Ioctl( IOCTL_OPEN_USER_MODE_EVENT, &req, sizeof(req), NULL, 0);
+
+
+    }
+    else
+    {
+        LOG_MESSAGE_INFO(_T("register_driver_device_events Driver HANDLES problem WA, using 32bit struct"));
+        SHARED_EVENT_32BIT req;
+        memset(&req, 0, sizeof(SHARED_EVENT_32BIT));
+
+        req.hDnEvent = hDnEvent;
+        req.hUpEvent = hUpEvent;
+        req.unplugEvent = hUnplugEvent;
+        req.sysAssertEvent = hSysAssertEvent;
+
+        lastError = IoctlDev.Ioctl( IOCTL_OPEN_USER_MODE_EVENT, &req, sizeof(req), NULL, 0);
+    }
+
+#endif //_WINDOWS
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("IOCTL_OPEN_USER_MODE_EVENT failed. 0x%X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+
+    return ERROR_SUCCESS;
+}
+
+int CPciDeviceAccess::unregister_driver_device_events()
+{
+    LOG_MESSAGE_INFO(_T("unregister_driver_device_events"));
+
+    if (!isInitialized())
+        return -1;
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+
+#ifdef _WINDOWS
+
+    LOG_MESSAGE_INFO(_T("unregister_driver_device_events with invalid handles"));
+
+    // Our DLL assumed to be always compiled for 32bit application.
+    // Since the driver excpects to recieve HANDLEs of size that IS platform speciefic,
+    // we must dynamically find out if we are running on 64bit OS or now.
+    // for more information, read remarks on WlcyPciAcssWmi.h file
+    if (Util::Is64BitWindows())
+    {
+        LOG_MESSAGE_INFO(_T("register_driver_device_events Driver HANDLES problem WA, using 64bit struct"));
+        SHARED_EVENT_64BIT req;
+        memset(&req, 0, sizeof(SHARED_EVENT_64BIT));
+
+        req.hDnEvent_l = -1;
+        req.hDnEvent_h = -1;
+        req.hUpEvent_l = -1;
+        req.hUpEvent_h = -1;
+        req.unplugEvent_l = -1;
+        req.hUpEvent_h = -1;
+        req.sysAssertEvent_l = -1;
+        req.sysAssertEvent_h = -1;
+
+        lastError = IoctlDev.Ioctl( IOCTL_OPEN_USER_MODE_EVENT, &req, sizeof(req), NULL, 0);
+
+
+    }
+    else
+    {
+        LOG_MESSAGE_INFO(_T("register_driver_device_events Driver HANDLES problem WA, using 32bit struct"));
+        SHARED_EVENT_32BIT req;
+        memset(&req, 0, sizeof(SHARED_EVENT_32BIT));
+
+        req.hDnEvent = -1;
+        req.hUpEvent = -1;
+        req.unplugEvent = -1;
+        req.sysAssertEvent = -1;
+
+        lastError = IoctlDev.Ioctl( IOCTL_OPEN_USER_MODE_EVENT, &req, sizeof(req), NULL, 0);
+    }
+
+#endif //_WINDOWS
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("IOCTL_OPEN_USER_MODE_EVENT failed. 0x%X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+
+    return ERROR_SUCCESS;
+}
+
+int CPciDeviceAccess::setMpDriverLogLevels(ULONG logModulesEnableMsk, ULONG logModuleLevelsMsk[WILO_DRV_NUM_LOG_COMPS])
+{
+    LOG_MESSAGE_INFO(_T("setMpDriverLogLevels"));
+
+    if (!isInitialized())
+        return -1;
+    if (!IoctlDev.IsOpened())
+        return -1;
+
+    DRIVER_LOGS_CFG req;
+    memset(&req, 0, sizeof(DRIVER_LOGS_CFG));
+    req.logModulesEnableMsk = logModulesEnableMsk;
+    memcpy( req.logModuleLevelsMsk, logModuleLevelsMsk, (WILO_DRV_NUM_LOG_COMPS*4)) ;
+
+    lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_DRIVER_LOG_LEVELS_CFG, &req, sizeof(req), NULL, 0);
+
+    if (lastError != WLCT_OS_ERROR_SUCCESS)
+    {
+        LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_DRIVER_LOG_LEVELS_CFG failed. 0x%X"), lastError);
+        InternalCloseDevice();
+        return -1;
+    }
+
+    return ERROR_SUCCESS;
+}
diff --git a/debug-tools/lib/WlctPciAcss/PciDeviceAccess.h b/debug-tools/lib/WlctPciAcss/PciDeviceAccess.h
new file mode 100644
index 0000000..8c2d741
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/PciDeviceAccess.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "DeviceAccess.h"
+#include "WlctPciAcss.h"
+#include "IoctlDev.h"
+#include "Thread.h"
+#include "public.h"
+
+#ifdef _WINDOWS
+#include "ioctl_if.h"
+#else
+// some definitions from ioctl_if.h
+#define WILOCITY_IOCTL_INDIRECT_READ IOCTL_INDIRECT_READ_OLD
+#define WILOCITY_IOCTL_INDIRECT_WRITE IOCTL_INDIRECT_WRITE_OLD
+#define WILOCITY_IOCTL_INDIRECT_READ_BLOCK IOCTL_INDIRECT_READ_BLOCK
+#define WILOCITY_IOCTL_INDIRECT_WRITE_BLOCK IOCTL_INDIRECT_WRITE_BLOCK
+#endif
+
+extern "C" class CPciDeviceAccess : public IDeviceAccess
+{
+public:
+    CPciDeviceAccess(const TCHAR* tchDeviceName, DType devType);
+    ~CPciDeviceAccess();
+
+    virtual int CloseDevice();
+    virtual int GetType();
+    virtual int r32(DWORD addr, DWORD & val);
+    virtual int w32(DWORD addr, DWORD val);
+    virtual int rb(DWORD addr, DWORD blockSize, char *arrBlock);
+    virtual int wb(DWORD addr, DWORD blockSize, const char *arrBlock);
+    virtual int rr(DWORD addr, DWORD num_repeat, DWORD *arrBlock);
+    virtual int getFwDbgMsg(FW_DBG_MSG** pMsg);
+    virtual int clearAllFwDbgMsg();
+    virtual int do_reset(BOOL bFirstTime = TRUE);
+    virtual int do_sw_reset();
+    virtual int do_interface_reset();
+#ifdef _WINDOWS
+    virtual int send_wmi_cmd(SEND_RECEIVE_WMI* wmi) ;
+    virtual int recieve_wmi_event(SEND_RECEIVE_WMI* evt) ;
+
+    virtual int SetDriverMode(int newState, int &oldState, int &payload);
+    virtual int GetDriverMode(int &currentState);
+#endif // _WINDOWS
+    virtual int register_driver_mailbox_event(HANDLE* pMailboxEventHandle );
+    virtual int register_driver_device_events(INT_PTR hDnEvent, INT_PTR hUpEvent, INT_PTR hUnplugEvent, INT_PTR hSysAssertEvent);
+    virtual int unregister_driver_device_events();
+    virtual int register_driver_device_event(INT_PTR hEvent, int eventId, int deviceId);
+    virtual int register_device_unplug2(INT_PTR hEvent);
+    virtual int unregister_device_unplug2();
+    virtual int setMpDriverLogLevels(ULONG logModulesEnableMsk, ULONG logModuleLevelsMsk[WILO_DRV_NUM_LOG_COMPS]);
+    virtual int alloc_pmc(int num_of_descriptors, int size_of_descriptor);
+
+    int		reset_complete();
+    void	Open();
+    int		InternalCloseDevice();
+
+    /*virtual int startSampling(
+      DWORD* pRegsArr,
+      DWORD regArrSize,
+      DWORD interval,
+      DWORD maxSampling,
+      DWORD transferMethod);
+      virtual int stopSampling();
+      virtual int getSamplingData(DWORD** pDataSamples);*/
+
+    // 0 - not closed
+    // 1 - need to be close
+    // 2 - close
+    DWORD	m_close_state;
+    // 0 - not opened
+    // 1 - need to be open
+    // 2 - open
+    DWORD	m_open_state;
+
+private:
+    void rr32(DWORD addr, DWORD num_repeat, DWORD *arrBlock);
+    int ReOpen();
+    bool try2open(int timeout);
+
+private:
+    static void SamplingThreadProc(void *pDeviceAccss);
+    static void PciPluginThreadProc(void *pDeviceAccss);
+
+    // handle to the control device in wPci driver
+    CIoctlDev			IoctlDev;
+
+    // true if device is Local (wPciL)
+    // false if device is remote (wPciR)
+    bool		bIsLocal;
+
+    DWORD		dwBaseAddress;
+
+};
diff --git a/debug-tools/lib/WlctPciAcss/PciPluginThreadXFace.h b/debug-tools/lib/WlctPciAcss/PciPluginThreadXFace.h
new file mode 100644
index 0000000..fc5937d
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/PciPluginThreadXFace.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "Thread.h"
+
+class CPciDeviceAccess;
+
+class IWlctPluginThread : public CWlctThread
+{
+public:
+  IWlctPluginThread(CPciDeviceAccess *pciDeviceAccess)
+    : CWlctThread(GlobalPluginThreadMain, this), pAccess(pciDeviceAccess)
+  {
+
+  }
+  virtual ~IWlctPluginThread() {;}
+
+  virtual void PluginThreadMain() = 0;
+
+protected:
+  CPciDeviceAccess *pAccess;
+
+  static void GlobalPluginThreadMain(void *p);
+};
diff --git a/debug-tools/lib/WlctPciAcss/Util.h b/debug-tools/lib/WlctPciAcss/Util.h
new file mode 100644
index 0000000..88a6fa4
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/Util.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "wlct_os.h"
+
+class Util
+{
+public:
+	static bool getFileVersionInfo(const TCHAR *fileNameFillPath, int &mjr, int &mnr, int &mnt, int &build);
+	static BOOL IsNumeric(LPCTSTR pszString, BOOL bIgnoreColon);
+	static DWORD ReadRegistrySettings(LPCTSTR lpszRegistryPath, LPCTSTR valName);
+	static DWORD WriteRegistrySettings(LPCTSTR lpszRegistryPath, LPCTSTR valName, DWORD val);
+	static int   IsWlctDevicePlugin();
+//	static bool Util::GetWlstPluggedInDevice();
+	static bool ICHDisableEnable();
+	static bool GetPciControllerDevicePath(TCHAR* devicePath);
+
+	// perfrom atomic change value, to acquire resource!
+	// if VAR != FLAG_VALUE, then set VAR to FLAG_VALUE.
+	// loop until timeout (milisec). return success in acheiving resource
+	// Assumes that FLAG_VALUE should be diffrent then current value stored in VAR
+	// turn keepWaiting on to wait infinite
+
+	static BOOL timedResourceInterLockExchange ( LONG* var, LONG flag_value, int timeout, bool keepWaiting );
+
+	static BOOL Is64BitWindows();
+
+private:
+	Util(void);
+	~Util(void);
+};
+
+#ifdef _WINDOWS
+#include <setupapi.h>
+#include <cfgmgr32.h>
+
+typedef HKEY (__stdcall SETUPDIOPENDEVREGKEY)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM);
+typedef BOOL (__stdcall SETUPDICLASSGUIDSFROMNAME)(LPCTSTR, LPGUID, DWORD, PDWORD);
+typedef BOOL (__stdcall SETUPDIDESTROYDEVICEINFOLIST)(HDEVINFO);
+typedef BOOL (__stdcall SETUPDIENUMDEVICEINFO)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
+typedef HDEVINFO (__stdcall SETUPDIGETCLASSDEVS)(LPGUID, LPCTSTR, HWND, DWORD);
+typedef BOOL (__stdcall SETUPDIGETDEVICEREGISTRYPROPERTY)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
+typedef DWORD (__stdcall CM_GET_DEVICE_ID)(DEVINST, PTCHAR, ULONG, ULONG);
+#endif
diff --git a/debug-tools/lib/WlctPciAcss/WlctPciAcss.cpp b/debug-tools/lib/WlctPciAcss/WlctPciAcss.cpp
new file mode 100644
index 0000000..49740b3
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/WlctPciAcss.cpp
@@ -0,0 +1,1544 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+
+#include "WlctPciAcss.h"
+#include "WlctPciAcssHelper.h"
+#include "wlct_os.h"
+#include "DeviceAccess.h"
+#include "PciDeviceAccess.h"
+#ifdef _WINDOWS
+#include "JtagDeviceAccess.h"
+#include "SerialDeviceAccess.h"
+#endif
+#include "MemoryAccess.h"
+#include "Util.h"
+
+#ifdef _WINDOWS
+#define WIGIG_REGISTRY_PATH _T("Software\\QualcommAtheros\\WIGIG")
+#endif
+
+using namespace std;
+
+#define WLCT_IFACE_NAME_LEN 256
+#define BL_READY_TIMEOUT_MS 1000
+#define BL_READY_WAIT_INTERVAL_MS 20
+
+WLCTPCIACSS_API int GetMyVersion(WLCT_DLL_VERSION *pVer)
+{
+	return GetPciAcssVersion(pVer);
+}
+
+WLCTPCIACSS_API bool wPciDisableEnable()
+{
+	return Util::ICHDisableEnable();
+}
+
+// return 0 for success
+WLCTPCIACSS_API int GetInterfaces(INTERFACE_LIST* ifList, int* ReturnItems)
+{
+	*ReturnItems = 0;
+//	int ret = 0;
+#ifdef _WINDOWS
+#ifndef NO_JTAG
+	if (!jtagLoaded) {
+		if (!load_jtag_dll()) {
+			printf("jTag DLL were not found, skipping jTag interfaces...\n");
+		}
+	}
+#endif
+#endif
+
+	for (int i = 0; i < MAX_INTERFACES; i++)
+	{
+		memset(ifList->list[i].ifName, 0, MAX_IF_NAME_LENGTH);
+	}
+
+#ifdef _WINDOWS
+	LOG_MESSAGE_INFO(_T("Checking registry for SkipSerialInterfaces register"));
+	DWORD dwSkip = Util::ReadRegistrySettings(WIGIG_REGISTRY_PATH, _T("SkipSerialInterfaces"));
+	if (dwSkip == (DWORD)-1)
+	{
+		LOG_MESSAGE_INFO(_T("SkipSerialInterfaces not found, adding registry key with default set to skip serial interfaces scan"));
+		dwSkip = 0;
+		Util::WriteRegistrySettings(WIGIG_REGISTRY_PATH, _T("SkipSerialInterfaces"), dwSkip);
+	}
+	else if (dwSkip == 0)
+	{
+		LOG_MESSAGE_INFO(_T("Get Interfaces for Serial"));
+		GetSerialInterfaces(ifList, ReturnItems);
+	}
+	else
+	{
+		LOG_MESSAGE_INFO(_T("SkipSerialInterfaces registry key found, skipping serial interface scan"));
+	}
+#endif
+
+	LOG_MESSAGE_INFO(_T("Get Interfaces for PCI"));
+	GetPciInterfaces(ifList, ReturnItems);
+
+#ifdef _WINDOWS
+#ifndef NO_JTAG
+	if (jtagLoaded)
+	{
+		LOG_MESSAGE_INFO(_T("Get Interfaces for jTag"));
+		GetJtagInterfaces(ifList, ReturnItems);
+	}
+#endif
+
+#ifndef NO_SERIAL
+	//GetSerialInterfaces(ifList, ReturnItems);
+#endif
+
+#endif
+
+	printf("Found %d interfaces \n",*ReturnItems);
+
+	return 0;
+}
+
+WLCTPCIACSS_API int StrGetInterfaces(char* ifListStr, int capacity)
+{
+    INTERFACE_LIST ifList;
+    int ReturnItems;
+    int ret = GetInterfaces(&ifList, &ReturnItems);
+    WLCT_UNREFERENCED_PARAM(ret);
+
+    std::ostringstream ifListBuilder;
+
+    for (int item = 0; item < ReturnItems; item++)
+    {
+        ifListBuilder << ifList.list[item].ifName << ' ';
+    }
+
+    int ifListActualLength = _snprintf(ifListStr, capacity, "%s", ifListBuilder.str().c_str());
+    if (ifListActualLength >= capacity)
+    {
+        LOG_MESSAGE_ERROR(
+            _T("Error filling interface list: %S, insufficient buffer capacity: %d\n"),
+            ifListBuilder.str().c_str(), capacity);
+        return 1;
+    }
+
+    LOG_MESSAGE_INFO(_T("Interfaces returned: %S"), ifListStr);
+    return 0;
+}
+
+//	NAME OF FUNCTION: CreateDeviceAccessHandler
+//	CREDIT:
+//	PURPOSE:
+//		The function will create and will initialize an access of read and write
+//		to Wilocity hardware. According to tchDeviceName it will interpret the
+//		access type (COM port, PCIe driver or Jtag)
+//
+//	PARAMETERS:
+//	name				type	value/reference		description
+// ---------------------------------------------------------------------
+//	tchDeviceName    TCHAR*  reference			the name of the access interface
+//	devType			int		value				the hardware type (MARLON)
+//
+//	RETURN VALUE:
+//	name         type	description
+//	handle / pointer to the access object.
+//
+//	NOTE:
+//		After calling this
+// ---------------------------------------------------------------------
+//	func return	void*	the overall total enrollment for the university
+//
+//	CALLS TO: This is a factory method. According to the device name it interprets
+//		the right interface and create a new object.
+//
+// CALLED FROM: main
+//
+// METHOD: The following is a factory.
+
+WLCTPCIACSS_API int CreateDeviceAccessHandler(const char* deviceName, DType devType, void** pDeviceAccess)
+{
+	LOG_STACK_ENTER;
+	IDeviceAccess* pIDeviceAccss = NULL;
+	const TCHAR* const delimit = _T("!");
+
+	TCHAR *tchDeviceName;
+
+	TCHAR *next_token = NULL;
+	DType devTypeFromInterface = devType;
+	TCHAR tchInterfaceName[WLCT_IFACE_NAME_LEN];
+	TCHAR tchOriginalInterfaceName[WLCT_IFACE_NAME_LEN];
+
+    // tchInterfaceName may be not null-terminated after calling _tcscpy_s()
+	_tcscpy_s(tchInterfaceName, WLCT_IFACE_NAME_LEN, TSTR_ARG(deviceName));
+	tchInterfaceName[WLCT_IFACE_NAME_LEN - 1] = '\0';
+
+	_tcscpy_s(tchOriginalInterfaceName, WLCT_IFACE_NAME_LEN, TSTR_ARG(deviceName));
+	//tchOriginalInterfaceName[WLCT_IFACE_NAME_LEN - 1] = '\0';
+
+	LOG_MESSAGE_INFO(_T("CreateDeviceAccessHandler for interface named: %s"), tchInterfaceName);
+
+	tchDeviceName = _tcstok_s( tchInterfaceName, delimit, &next_token);
+
+	if (!tchDeviceName)
+	{
+		LOG_MESSAGE_ERROR(_T("No device name found"));
+		return WLCT_OS_ERROR_NOT_SUPPORTED;
+	}
+
+	if (_tcsstr(tchDeviceName, _T("wPci")) == tchDeviceName ||
+            _tcsstr(tchDeviceName, _T("wpci")) == tchDeviceName)
+	{
+            if (devTypeFromInterface != devType)
+            {
+                return WLCT_OS_ERROR_NOT_SUPPORTED;
+            }
+			LOG_MESSAGE_INFO(_T("wPci Interface detected"));
+            pIDeviceAccss = new CPciDeviceAccess(tchDeviceName, devType);
+	}
+	else if (_tcsstr(tchDeviceName, _T("wMp")) == tchDeviceName ||
+            _tcsstr(tchDeviceName, _T("wmp")) == tchDeviceName)
+	{
+            if (devTypeFromInterface != devType)
+            {
+                return WLCT_OS_ERROR_NOT_SUPPORTED;
+            }
+			LOG_MESSAGE_INFO(_T("wMp Interface detected"));
+            pIDeviceAccss = new CPciDeviceAccess(tchDeviceName, devType);
+	}
+	else if (_tcsstr(tchDeviceName, _T("wEP")) == tchDeviceName ||
+            _tcsstr(tchDeviceName, _T("wep")) == tchDeviceName)
+	{
+			LOG_MESSAGE_INFO(_T("wEP Interface detected"));
+            pIDeviceAccss = new CPciDeviceAccess(tchOriginalInterfaceName, devType);
+	}
+	else if (_tcsstr(tchDeviceName, _T("wController")) == tchDeviceName ||
+            _tcsstr(tchDeviceName, _T("wcontroller")) == tchDeviceName)
+	{
+            if (devTypeFromInterface != devType)
+            {
+                return WLCT_OS_ERROR_NOT_SUPPORTED;
+            }
+			LOG_MESSAGE_INFO(_T("wController Interface detected"));
+            pIDeviceAccss = new CPciDeviceAccess(tchDeviceName, devType);
+	}	// acceptable format is: com3, COM3
+	else if (_tcsstr(tchDeviceName, _T("COM")) == tchDeviceName ||
+            _tcsstr(tchDeviceName, _T("com")) == tchDeviceName)
+	{
+		if (devTypeFromInterface != devType)
+		{
+			return WLCT_OS_ERROR_NOT_SUPPORTED;
+		}
+
+#ifdef _WINDOWS
+		pIDeviceAccss = new CSerialDeviceAccess(tchDeviceName, devType);
+		pIDeviceAccss->SetLastError(0);
+#else
+                return WLCT_OS_ERROR_NOT_SUPPORTED;
+#endif
+	}
+	else /*if (_tcsicmp(tchDeviceName, _T("wjtag")) == 0)*/
+	{
+            if (devTypeFromInterface != devType)
+            {
+                return WLCT_OS_ERROR_NOT_SUPPORTED;
+            }
+#ifdef _WINDOWS
+#ifndef NO_JTAG
+            pIDeviceAccss = new CJtagDeviceAccess(tchDeviceName, devType);
+            if (pIDeviceAccss->lastError == WLCT_OS_ERROR_OPEN_FAILED)
+            {
+                printf("JTAG CJtagDeviceAccess creation failed!\n");
+                return WLCT_OS_ERROR_NOT_SUPPORTED;
+            }
+#endif
+#else
+            return WLCT_OS_ERROR_NOT_SUPPORTED;
+#endif
+	}
+
+        // Sanity check - pIDeviceAccss should be set according to the access type in the above block
+        if (!pIDeviceAccss)
+        {
+            LOG_MESSAGE_ERROR(_T("No device access handler is set"));
+            return WLCT_OS_ERROR_NOT_SUPPORTED;
+        }
+
+	// assume device type = unknown and search for correct device type
+	pIDeviceAccss->SetDeviceStep(STEP_NONE);
+
+	DWORD rev_id_address = 0x880B34;
+	DWORD dft_signature_address = 0x800C;
+	DWORD val = 0;
+
+	int ret = WlctAccssRead(pIDeviceAccss, rev_id_address, val);
+	LOG_MESSAGE_INFO(_T("RevID on [%S] is [0x%X]"),deviceName,val);
+	if (ret == 0 && val != 0xFFFFFFFF)
+	{
+		if (devType == MST_MARLON)
+		{
+			if (val == 0x612072F)
+			{
+				pIDeviceAccss->SetDeviceStep(MARLON_STEP_B0);
+				LOG_MESSAGE_INFO(_T("MARLON STEP B0"));
+			}
+
+			/* This is not really Marlon, it is a DFT device and it should have
+				been a different gateway (not a step inside Marlon) */
+			else if (val == 0x0) // DFT
+			{
+				int ret = WlctAccssRead(pIDeviceAccss, dft_signature_address, val);
+				if (ret == 0 && val == 0xCE4)
+				{
+					pIDeviceAccss->SetDeviceStep(DFT_STEP);
+					LOG_MESSAGE_INFO(_T("DFT STEP"));
+				}
+			}
+			else
+			{
+
+				//for now always use marlon as B0
+
+				// Device doesn't match the device type MST_MARLON
+				LOG_MESSAGE_INFO(_T("NOT Marlon, RevID = [0x%X], closing handler.."),val);
+				pIDeviceAccss->CloseDevice();
+				return WLCT_OS_ERROR_NOT_SUPPORTED;
+			}
+		}
+		else if (devType == MST_SPARROW)
+		{
+			if (val == 0x0632072F)
+			{
+				pIDeviceAccss->SetDeviceStep(SPARROW_STEP_A0);
+				LOG_MESSAGE_INFO(_T("SPARROW STEP A0"));
+			}
+			else if(val == 0x1632072F)
+			{
+				pIDeviceAccss->SetDeviceStep(SPARROW_STEP_A1);
+				LOG_MESSAGE_INFO(_T("SPARROW STEP A1"));
+			}
+			else if (val == 0x2632072F)
+			{
+				pIDeviceAccss->SetDeviceStep(SPARROW_STEP_B0);
+				LOG_MESSAGE_INFO(_T("SPARROW STEP B0"));
+			}
+			else
+			{
+				LOG_MESSAGE_INFO(_T("Unknown RevID = [0x%X] "),val);
+				// This case is for future unrecognized devices, for example, MST_NONE
+				pIDeviceAccss->SetDeviceStep(STEP_NONE);
+				LOG_MESSAGE_INFO(_T("UNKNOWN DEVICE found, assuming it is Sparrow's next step"));
+				//pIDeviceAccss->CloseDevice();
+				//return WLCT_OS_ERROR_NOT_SUPPORTED;
+			}
+		}
+	}
+	else
+	{
+		pIDeviceAccss->SetLastError(-1);
+	}
+
+	*pDeviceAccess = (void*)pIDeviceAccss;
+	return pIDeviceAccss->GetLastError();
+}
+
+WLCTPCIACSS_API int CloseDeviceAccessHandler(void* pDeviceAccss)
+{
+	int res = 0;
+	IDeviceAccess* pIDevice = (IDeviceAccess*)pDeviceAccss;
+	if (pIDevice != NULL)
+	{
+		__TRY
+		{
+			pIDevice->CloseDevice();
+            #ifdef _WINDOWS
+            delete pIDevice;
+            #else
+			pIDevice = NULL;
+            #endif
+		}
+		__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+		{
+			LOG_MESSAGE_ERROR(_T("got exception"));
+			res = -1;
+		}
+	}
+	return res;
+}
+
+#ifdef _WINDOWS
+WLCTPCIACSS_API int WlctAccssSetDriverMode(void* pDeviceAccss, int newState, int & oldState, int &payloadResult){
+	if(pDeviceAccss == NULL){
+		return -1;
+	}
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		LOG_MESSAGE_ERROR(_T("Could not get lock for PCI access"));
+		return -1;
+	}
+
+	__TRY
+	{
+		if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypePCI)
+			res = ((CPciDeviceAccess*)pDeviceAccss)->SetDriverMode(newState, oldState, payloadResult);
+		else
+			res = -1;
+
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception on Mode Change"));
+		res = -1;
+		oldState = -1;
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+		return res;
+}
+
+WLCTPCIACSS_API int WlctAccssGetDriverMode(void* pDeviceAccss, int & oldState){
+	if(pDeviceAccss == NULL){
+		return -1;
+	}
+	int res = 0;
+	int got_resource;
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		LOG_MESSAGE_ERROR(_T("Could not get lock for PCI access"));
+		return -1;
+	}
+	__TRY
+	{
+		if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypePCI)
+			res = ((CPciDeviceAccess*)pDeviceAccss)->GetDriverMode(oldState);
+		else
+			res = -1;
+
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception on Mode Change"));
+		res = -1;
+		oldState = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+#endif //_WINDOWS
+
+WLCTPCIACSS_API int WlctAccssRead(void* pDeviceAccss, DWORD addr, DWORD & val)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	if (addr == BAUD_RATE_REGISTER)
+		if (((IDeviceAccess*)pDeviceAccss)->GetDeviceStep() == DFT_STEP)
+		{
+			DWORD baud_rate = 350; // expected baud rate value from DFT
+			val = baud_rate;
+			return 0;
+		}
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		res = accssRead(pDeviceAccss, addr, val);
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	LOG_MESSAGE_DEBUG(_T("%S [addr 0x%X] [val %d]"), __FUNCTION__, addr, val);
+	return res;
+}
+
+WLCTPCIACSS_API int accssRead(void* pDeviceAccss, DWORD addr, DWORD & val) {
+
+	return ((IDeviceAccess*)pDeviceAccss)->r32(addr, val);
+}
+
+
+WLCTPCIACSS_API int WlctAccssAllocPmc(void* pDeviceAccss, DWORD size, DWORD numOfDescriptors)
+{
+	if (pDeviceAccss == NULL)
+        {
+            LOG_MESSAGE_ERROR(_T("Cannot allocate PMC descriptors - No device access handler"));
+            return -1;
+        }
+
+	// Get Resource
+	int got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+            LOG_MESSAGE_ERROR(_T("Cannot allocated PMC descriptors - Cannot obtain a lock"));
+            return -1;
+	}
+
+        int res = 0;
+	__TRY
+	{
+		res = ((IDeviceAccess*)pDeviceAccss)->alloc_pmc(size, numOfDescriptors);
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+            LOG_MESSAGE_ERROR(_T("Cannot allocated PMC descriptors - Got exception"));
+            res = -1;
+            ((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	LOG_MESSAGE_DEBUG(_T("Allocated PMC descriptors. status: %d"), res);
+	return res;
+}
+
+WLCTPCIACSS_API int SwReset(void* pDeviceAccss)
+{
+	UINT32 bootLoadReady;
+	UINT i, maxIterations;
+	USER_RGF_BL_INFO_VER_0 blInfo;
+
+	DWORD readVal;
+	int res = 0;
+
+	LOG_MESSAGE_INFO(_T("SwReset Initiated..."));
+
+	/* Clear MAC link up */
+	accssSet32(pDeviceAccss, USER_RGF_HP_CTRL, BIT(15));
+	accssSet32(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_MASK_0, BIT(6));	/* hpal_perst_from_pad_src_n_mask */
+	accssSet32(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_MASK_0, BIT(7));	/* car_perst_rst_src_n_mask */
+
+	/* Halt CPU */
+	accssWrite(pDeviceAccss, USER_RGF_USER_CPU_0, BIT(1));
+	accssWrite(pDeviceAccss, USER_RGF_MAC_CPU_0, BIT(1));
+
+
+	/* clear all boot loader "ready" bits */
+	accssWrite(pDeviceAccss, USER_RGF_BL_READY, 0); //USER_RGF_BL_READY
+
+	/* Clear Fw Download notification */
+	accssClear32(pDeviceAccss, USER_RGF_USAGE_6, BIT(0)); //USER_RGF_USAGE_6)
+
+	// Sparrow only register configuration
+	accssSet32(pDeviceAccss, USER_RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN); //USER_RGF_CAF_OSC_CONTROL
+
+
+
+	LOG_MESSAGE_INFO(_T("Sleep: waiting for XTAL stabilization..."));
+	/* XTAL stabilization should take about 3ms */
+	sleep_ms(XTAL_STABLE_WAIT_MS);
+	LOG_MESSAGE_INFO(_T("Sleep done: Checking XTAL stabilization..."));
+	res = accssRead(pDeviceAccss, USER_RGF_CAF_PLL_LOCK_STATUS, readVal);	//USER_RGF_CAF_PLL_LOCK_STATUS
+
+	if (!(readVal & BIT_CAF_OSC_DIG_XTAL_STABLE)) {	//BIT_CAF_OSC_DIG_XTAL_STABLE
+            LOG_MESSAGE_ERROR(_T("%s: BIT_CAF_OSC_DIG_XTAL_STABLE=0x%x\n"), __FUNCTION__, BIT_CAF_OSC_DIG_XTAL_STABLE);
+            LOG_MESSAGE_ERROR(_T("%s: Xtal stabilization timeout USER_RGF_CAF_PLL_LOCK_STATUS val=0x%x\n"), __FUNCTION__, readVal);
+            return -1;
+	}
+
+	/* switch 10k to XTAL*/
+	accssClear32(pDeviceAccss, USER_RGF_SPARROW_M_4, BIT_SPARROW_M_4_SEL_SLEEP_OR_REF); //USER_RGF_SPARROW_M_4
+
+	/* 40 MHz */
+	accssClear32(pDeviceAccss, USER_RGF_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL);  //USER_RGF_CLKS_CTL_0
+
+
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f); //USER_RGF_CLKS_CTL_EXT_SW_RST_VEC_0
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);	//USER_RGF_CLKS_CTL_EXT_SW_RST_VEC_1
+
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);	//USER_RGF_CLKS_CTL_SW_RST_VEC_2
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); //USER_RGF_CLKS_CTL_SW_RST_VEC_1
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_3, 0x000000f0); //USER_RGF_CLKS_CTL_SW_RST_VEC_3
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00);	//USER_RGF_CLKS_CTL_SW_RST_VEC_0
+
+	/* Sparrow Exit SW Reset */
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);	//USER_RGF_CLKS_CTL_EXT_SW_RST_VEC_0
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0);	//USER_RGF_CLKS_CTL_EXT_SW_RST_VEC_1
+
+
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_2, 0);	//USER_RGF_CLKS_CTL_SW_RST_VEC_2
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_1, 0); //USER_RGF_CLKS_CTL_SW_RST_VEC_1
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_3, 0); //USER_RGF_CLKS_CTL_SW_RST_VEC_3
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_0, 0);	//USER_RGF_CLKS_CTL_SW_RST_VEC_0
+
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_3, 0x00000003); //USER_RGF_CLKS_CTL_SW_RST_VEC_3
+	/* reset A2 PCIE AHB */
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_2, 0x00008000);	//USER_RGF_CLKS_CTL_SW_RST_VEC_2
+
+	/* TODO: check order here!!! Erez code is different */
+	accssWrite(pDeviceAccss, USER_RGF_CLKS_CTL_SW_RST_VEC_0, 0x0);	//USER_RGF_CLKS_CTL_SW_RST_VEC_0
+
+	// Now wait for device ready, use HW_MACHINE register for this
+	maxIterations = BL_READY_TIMEOUT_MS / BL_READY_WAIT_INTERVAL_MS;
+
+
+	LOG_MESSAGE_INFO(_T("Checking bootloader..."));
+
+	for (i = maxIterations; i; --i)
+	{
+
+		//First wait to let the register have the stabilization time it needs
+		sleep_ms(BL_READY_WAIT_INTERVAL_MS);
+
+		bootLoadReady = accssRead(pDeviceAccss, USER_RGF_BL_READY, readVal);	//USER_RGF_BL_READY
+		(void)bootLoadReady;
+
+		if (readVal == BL_BIT_READY)//BL_BIT_READY
+		{
+			break;
+		}
+	}
+
+	LOG_MESSAGE_INFO(_T("Wait on register USER_RGF_BL_READY for %d msec\n"), (maxIterations - i)*BL_READY_WAIT_INTERVAL_MS);
+
+	// check for long wait
+	if (0 == i)
+	{
+            LOG_MESSAGE_ERROR(_T("%s: timeout on register USER_RGF_BL_READY\n"), __FUNCTION__);
+            return -1;
+	}
+
+	// read info from BL
+        hwCopyFromIO(&blInfo, pDeviceAccss, USER_RGF_BL_START_OFFSET, sizeof(USER_RGF_BL_INFO_VER_0));
+
+
+        LOG_MESSAGE_INFO(_T("Boot loader information: Ready=0x%x, StructVersion=0x%x, RfType=0x%x BaseBandType=0x%x\n"),
+            blInfo.Ready, blInfo.StructVersion, blInfo.RfType, blInfo.BaseBandType);
+
+        LOG_MESSAGE_INFO(_T("Boot loader macaddr=%02x:%02x:%02x:%02x:%02x:%02x\n"),
+            blInfo.MacAddr[0], blInfo.MacAddr[1], blInfo.MacAddr[2],
+            blInfo.MacAddr[3], blInfo.MacAddr[4], blInfo.MacAddr[5]);
+
+	accssClear32(pDeviceAccss, USER_RGF_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); //USER_RGF_CLKS_CTL_0
+
+
+	if (blInfo.StructVersion > 0)
+	{
+		USER_RGF_BL_INFO_VER_1 blInfoVer1;
+		// print the BL version
+		hwCopyFromIO(&blInfoVer1, pDeviceAccss, USER_RGF_BL_START_OFFSET, sizeof(USER_RGF_BL_INFO_VER_1));
+
+		LOG_MESSAGE_INFO(_T("Boot Loader build %d.%d.%d.%d\n"),
+			blInfoVer1.VersionMajor, blInfoVer1.VersionMinor,
+			blInfoVer1.VersionSubminor, blInfoVer1.VersionBuild);
+	}
+
+	LOG_MESSAGE_INFO(_T("SwReset Done..."));
+
+	return res;
+}
+
+WLCTPCIACSS_API int InterfaceReset(void* pDeviceAccss)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		res = ((IDeviceAccess*)pDeviceAccss)->do_interface_reset();
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	LOG_MESSAGE_DEBUG(_T("Interface Reset flow end"));
+	return res;
+}
+
+/* helper function copied and modified from the driver
+	we can use this to read info from the boot loader
+*/
+WLCTPCIACSS_API void hwCopyFromIO( void* dst, void* pDeviceAccss, DWORD src, UINT32 len)
+{
+	UINT32 i, regCount;
+	DWORD readVal;
+
+	regCount = (UINT64)(ALIGN_UP_BY(len, 4)) / 4;
+
+	for (i = 0; i < regCount; ++i)
+	{
+		//*((PUINT32)dst + i) = READ32((PUINT32)src + i);
+		int res = ((IDeviceAccess*)pDeviceAccss)->r32(src + i, readVal);
+                (void)res;
+		*((PUINT32)dst + i) = readVal;
+	}
+}
+
+WLCTPCIACSS_API int WlctAccssWrite(void* pDeviceAccss, DWORD addr, DWORD val)
+{
+	int res = 0;
+	int got_resource;
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return -1;
+	}
+
+	__TRY
+	{
+		res = accssWrite(pDeviceAccss,addr,val);
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	LOG_MESSAGE_DEBUG(_T("%S [addr 0x%X] [val %d]"), __FUNCTION__, addr, val);
+	return res;
+}
+
+WLCTPCIACSS_API int accssWrite(void* pDeviceAccss, DWORD addr, DWORD val)
+{
+
+	return ((IDeviceAccess*)pDeviceAccss)->w32((addr), val);
+
+}
+
+/* accssSet32 is a modifiled write function based on logic from the driver
+	First read from the addr
+	Set  the readVal to the desired val with |= val
+	Write readVal back into addr
+*/
+WLCTPCIACSS_API int accssSet32(void* pDeviceAccss, DWORD addr, DWORD val) {
+	int res = 0;
+	DWORD readVal;
+
+	res = accssRead(pDeviceAccss, addr, readVal);
+	readVal |= val;
+	res = accssWrite(pDeviceAccss, addr, readVal);
+
+	return res;
+}
+
+/* accssClear32 is a modifiled write function based on logic from the driver
+	First read from the addr
+	Clear the readVal to the desired val with &= ~val
+	Write readVal back into addr
+*/
+WLCTPCIACSS_API int accssClear32(void* pDeviceAccss, DWORD addr, DWORD val) {
+	int res = 0;
+	DWORD readVal;
+
+	res = accssRead(pDeviceAccss, addr, readVal);
+	readVal &= ~val;
+	res = accssWrite(pDeviceAccss, addr, readVal);
+
+	return res;
+}
+
+WLCTPCIACSS_API bool isInit(void* pDeviceAccss)
+{
+	if (pDeviceAccss == NULL)
+		return false;
+
+	bool res = 0;
+	__TRY
+	{
+		res = ((IDeviceAccess*)pDeviceAccss)->isInitialized();
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = false;
+	}
+	return res;
+}
+
+WLCTPCIACSS_API int writeBlock(void* pDeviceAccss, DWORD addr, DWORD blockSize, const char *arrBlock)
+{
+	int got_resource;
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return -1;
+	}
+
+
+	int res = 0;
+	__TRY
+	{
+		LOG_MESSAGE_DEBUG(_T("start running"));
+		res = ((IDeviceAccess*)pDeviceAccss)->wb(addr, blockSize, arrBlock);
+		LOG_MESSAGE_DEBUG(_T("Leaving"));
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+
+WLCTPCIACSS_API int readBlock(void* pDeviceAccss, DWORD addr, DWORD blockSize, char *arrBlock)
+{
+	int got_resource;
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return -1;
+	}
+
+
+	int res = 0;
+	__TRY
+	{
+
+		LOG_MESSAGE_DEBUG(_T("start running"));
+
+		res = ((IDeviceAccess*)pDeviceAccss)->rb(addr, blockSize, arrBlock);
+		LOG_MESSAGE_DEBUG(_T("Leaving"));
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+
+//
+// read repeat - will read from the same address num_repeat times
+// the result will store in arrBlock. arrBlock is an array of shorts with at least num_repeat entries.
+//
+WLCTPCIACSS_API int readRepeat(void* pDeviceAccss, DWORD addr, DWORD num_repeat, DWORD *arrBlock)
+{
+	int got_resource;
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return -1;
+	}
+
+
+	int res = 0;
+	__TRY
+	{
+		LOG_MESSAGE_DEBUG(_T("start running"));
+		res = ((IDeviceAccess*)pDeviceAccss)->rr(addr, USHORT(num_repeat), arrBlock);
+		LOG_MESSAGE_DEBUG(_T("Leaving"));
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+
+WLCTPCIACSS_API DType getDeviceType(void* pDeviceAccss)
+{
+	return ((IDeviceAccess*)pDeviceAccss)->GetDeviceType();
+}
+
+WLCTPCIACSS_API int getDbgMsg(void* pDeviceAccss, FW_DBG_MSG** pMsg)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	__TRY
+	{
+		res = ((IDeviceAccess*)pDeviceAccss)->getFwDbgMsg(pMsg);
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+	}
+	return res;
+}
+
+WLCTPCIACSS_API int clearAllFwDbgMsg(void* pDeviceAccss)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	__TRY
+	{
+		((IDeviceAccess*)pDeviceAccss)->clearAllFwDbgMsg();
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+	}
+	return res;
+}
+
+WLCTPCIACSS_API int card_reset(void* pDeviceAccss)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	__TRY
+	{
+		((IDeviceAccess*)pDeviceAccss)->do_reset();
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+	}
+	return res;
+}
+
+WLCTPCIACSS_API int startSampling(void* pDeviceAccss, DWORD* pRegsArr, DWORD regArrSize, DWORD interval, DWORD maxSampling, DWORD transferMethod)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	__TRY
+	{
+		((IDeviceAccess*)pDeviceAccss)->startSampling(pRegsArr, regArrSize, interval, maxSampling, transferMethod);
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+	}
+	return res;
+}
+
+WLCTPCIACSS_API int stopSampling(void* pDeviceAccss)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	__TRY
+	{
+		((IDeviceAccess*)pDeviceAccss)->stopSampling();
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+	}
+	return res;
+}
+
+WLCTPCIACSS_API int getSamplingData(void* pDeviceAccss, DWORD** pDataSamples)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	__TRY
+	{
+		res = ((IDeviceAccess*)pDeviceAccss)->getSamplingData(pDataSamples);
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+	}
+	return res;
+}
+
+WLCTPCIACSS_API TCHAR* getInterfaceName(void* pDeviceAccss)
+{
+	if (pDeviceAccss == NULL)
+		return NULL;
+
+	TCHAR* szInfName = NULL;
+	__TRY
+	{
+		szInfName = ((IDeviceAccess*)pDeviceAccss)->GetInterfaceName();
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+	}
+	return szInfName;
+}
+
+#ifdef _WINDOWS
+#ifndef NO_JTAG
+WLCTPCIACSS_API int WlctAccssJtagSendDR(void* pDeviceAccss, DWORD num_bits, BYTE *arr_in, BYTE *arr_out)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		if (isInit(pDeviceAccss))
+		{
+			if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypeJTAG)
+			{
+				if (((IDeviceAccess*)pDeviceAccss)->GetDeviceType() == MST_MARLON)
+				{
+					res = ((CJtagDeviceAccess*)pDeviceAccss)->jtag_set_dr(arr_in, arr_out, num_bits);
+				}
+			}
+		}
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	//	LOG_MESSAGE_DEBUG(_T("%S [addr 0x%X] [val %d]"), __FUNCTION__, addr, val);
+	return res;
+}
+
+WLCTPCIACSS_API int WlctAccssJtagSendIR(void* pDeviceAccss, DWORD num_bits, BYTE *arr_in)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		if (isInit(pDeviceAccss))
+		{
+			if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypeJTAG)
+			{
+				if (((IDeviceAccess*)pDeviceAccss)->GetDeviceType() == MST_MARLON)
+				{
+					res = ((CJtagDeviceAccess*)pDeviceAccss)->jtag_set_ir(num_bits, arr_in);
+				}
+			}
+		}
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+//	LOG_MESSAGE_DEBUG(_T("%S [addr 0x%X] [val %d]"), __FUNCTION__, addr, val);
+	return res;
+}
+
+WLCTPCIACSS_API int JtagSetClockSpeed(void* pDeviceAccss, DWORD requestedFreq, DWORD* frqSet)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	__TRY
+	{
+		((CJtagDeviceAccess*)pDeviceAccss)->set_speed(requestedFreq, frqSet);
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+	}
+	return res;
+}
+
+WLCTPCIACSS_API int JtagPutTmsTdiBits(void* pDeviceAccss, BYTE *tms, BYTE *tdi, BYTE* tdo, UINT length)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	__TRY
+	{
+		((CJtagDeviceAccess*)pDeviceAccss)->direct_control(tms, tdi, tdo, length);
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+	}
+	return res;
+}
+
+WLCTPCIACSS_API int JtagTmsShiftToReset(void* pDeviceAccss)
+{
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		if (isInit(pDeviceAccss))
+		{
+			if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypeJTAG)
+			{
+				if (((IDeviceAccess*)pDeviceAccss)->GetDeviceType() == MST_MARLON)
+				{
+					res = ((CJtagDeviceAccess*)pDeviceAccss)->jtag_reset();
+				}
+
+				if (((IDeviceAccess*)pDeviceAccss)->GetDeviceType() == MST_SPARROW)
+				{
+					res = ((CJtagDeviceAccess*)pDeviceAccss)->jtag_reset();
+				}
+			}
+		}
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	//	LOG_MESSAGE_DEBUG(_T("%S [addr 0x%X] [val %d]"), __FUNCTION__, addr, val);
+	return res;
+}
+#else // JTAG
+
+WLCTPCIACSS_API int JtagSetClockSpeed(void* pDeviceAccss, DWORD requestedFreq, DWORD* frqSet)
+{
+	return -1;
+}
+
+WLCTPCIACSS_API int JtagPutTmsTdiBits(void* pDeviceAccss, BYTE *tms, BYTE *tdi, BYTE* tdo, UINT length)
+{
+	return -1;
+}
+
+WLCTPCIACSS_API int JtagTmsShiftToReset(void* pDeviceAccss)
+{
+	return -1;
+}
+
+#endif // ifndef NO_JTAG
+#endif /* _WINDOWS */
+
+#ifdef _WINDOWS
+WLCTPCIACSS_API int WlctAccssSendWmiCmd(void* pDeviceAccss, SEND_RECEIVE_WMI* wmi)
+{
+	LOG_MESSAGE_INFO(_T("WlctAccssSendWmiCmd: 0x%X"),  (*wmi).uCmdId);
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypePCI)
+			res = ((CPciDeviceAccess*)pDeviceAccss)->send_wmi_cmd(wmi);
+		else
+			res = -1;
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+
+WLCTPCIACSS_API int WlctAccssRecieveWmiEvent(void* pDeviceAccss, SEND_RECEIVE_WMI* evt)
+{
+	LOG_MESSAGE_INFO(_T("WlctAccssRecieveWmiEvent"));
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypePCI)
+			res = ((CPciDeviceAccess*)pDeviceAccss)->recieve_wmi_event(evt);
+		else
+			res = -1;
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+
+WLCTPCIACSS_API int WlctAccssMpSetDriverLogLevels(void* pDeviceAccss, ULONG logModulesEnableMsk, ULONG logModuleLevelsMsk[WILO_DRV_NUM_LOG_COMPS])
+{
+	LOG_MESSAGE_INFO(_T("WlctAccssMpDriverLogLevels"));
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypePCI)
+			res = ((CPciDeviceAccess*)pDeviceAccss)->setMpDriverLogLevels(logModulesEnableMsk, logModuleLevelsMsk);
+		else
+			res = -1;
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+
+#endif
+
+WLCTPCIACSS_API int WlctAccssRegisterDriverMailboxEvents(void* pDeviceAccss, HANDLE* pMailboxEventHandle )
+{
+	LOG_MESSAGE_INFO(_T("WlctAccssRegisterDriverMailboxEvents"));
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypePCI)
+			res = ((CPciDeviceAccess*)pDeviceAccss)->register_driver_mailbox_event(pMailboxEventHandle);
+		else
+			res = -1;
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+
+
+
+WLCTPCIACSS_API int WlctAccssRegisterDriverDeviceEvents(void* pDeviceAccss, INT_PTR hDnEvent, INT_PTR hUpEvent, INT_PTR hUnplugEvent, INT_PTR hSysAssertEvent )
+{
+	LOG_MESSAGE_INFO(_T("WlctAccssRegisterDriverDeviceEvents"));
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypePCI)
+			res = ((CPciDeviceAccess*)pDeviceAccss)->register_driver_device_events (hDnEvent, hUpEvent, hUnplugEvent, hSysAssertEvent);
+		else
+			res = -1;
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+
+WLCTPCIACSS_API int WlctAccssUnregisterDriverDeviceEvents(void* pDeviceAccss){
+	LOG_MESSAGE_INFO(_T("WlctAccssUnregisterDriverDeviceEvents"));
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypePCI)
+			res = ((CPciDeviceAccess*)pDeviceAccss)->unregister_driver_device_events();
+		else
+			res = -1;
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+WLCTPCIACSS_API int WlctAccssRegisterDriverEvent(void* pDeviceAccss, INT_PTR event_ptr, int eventId, int appId)
+{
+	LOG_MESSAGE_INFO(_T("WlctAccssRegisterDriverDeviceEvent"));
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		if (((IDeviceAccess*)pDeviceAccss)->GetType() == IDeviceAccess::ETypePCI)
+			res = ((CPciDeviceAccess*)pDeviceAccss)->register_driver_device_event (event_ptr, appId, eventId);
+		else
+			res = -1;
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+
+}
+
+
+WLCTPCIACSS_API int WlctAccssRegisterDeviceForUnplug2Event(void* pDeviceAccss, INT_PTR event_ptr)
+{
+
+	LOG_MESSAGE_INFO(_T("WlctAccssRegisterDeviceForUnplug2Event"));
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+			res = ((CPciDeviceAccess*)pDeviceAccss)->register_device_unplug2 (event_ptr);
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+
+WLCTPCIACSS_API int WlctAccssUnregisterDeviceForUnplug2Event(void* pDeviceAccss)
+{
+
+	LOG_MESSAGE_INFO(_T("WlctAccssUnregisterDeviceForUnplug2Event"));
+
+	if (pDeviceAccss == NULL)
+		return -1;
+
+	int res = 0;
+	int got_resource;
+
+	// Get Resource
+	got_resource = Util::timedResourceInterLockExchange(  &((((IDeviceAccess*)pDeviceAccss)->m_flag_busy)), true, 1000, false);
+	if (!got_resource)
+	{
+		return res;
+	}
+
+	__TRY
+	{
+		res = ((CPciDeviceAccess*)pDeviceAccss)->unregister_device_unplug2 ();
+	}
+	__EXCEPT(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+	{
+		LOG_MESSAGE_ERROR(_T("got exception"));
+		res = -1;
+		((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	}
+
+	((IDeviceAccess*)pDeviceAccss)->m_flag_busy = false;
+	return res;
+}
+
diff --git a/debug-tools/lib/WlctPciAcss/WlctPciAcss.h b/debug-tools/lib/WlctPciAcss/WlctPciAcss.h
new file mode 100644
index 0000000..f25467a
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/WlctPciAcss.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include <list>
+#include <queue>
+#include "wlct_os.h"
+#include "WlctPciAcssWmi.h"
+#include "public.h"
+
+#ifdef _WINDOWS
+#include "ioctl_if.h"
+typedef struct _FW_DBG_MSG
+{
+	std::string	msg;
+	SYSTEMTIME	timeStamp;
+}FW_DBG_MSG;
+#else
+#define FW_DBG_MSG int
+#endif
+
+typedef struct _SAMPLING_REGS
+{
+	DWORD		timeStamp; // GetTickCount
+	DWORD		regArr[0];
+}SAMPLING_REGS;
+
+#define MAX_DEVICE_TYPE_SUPPORTED 2
+typedef enum DType_t
+{
+	MST_NONE,
+	MST_SPARROW,   // added here to keep backward compatibility. some tools assume MARLON == 2, we don't brake this assumption
+	MST_MARLON,
+	MST_TALYN,
+	MST_LAST
+} DType;
+
+typedef enum DEVICE_STEP_t
+{
+	STEP_NONE,
+	MARLON_STEP_A0,
+	MARLON_STEP_B0,
+	SPARROW_STEP_A0,
+	SPARROW_STEP_A1,
+	SPARROW_STEP_B0,
+	DFT_STEP,
+	STEP_LAST
+} DEVICE_STEP;
+
+#define BAUD_RATE_REGISTER 0x880050
+
+#define MAX_IF_NAME_LENGTH 32
+typedef struct _INTERFACE_NAME
+{
+	char	ifName[MAX_IF_NAME_LENGTH];
+}INTERFACE_NAME;
+
+
+#define  MAX_INTERFACES 32
+typedef struct _INTERFACE_LIST
+{
+	INTERFACE_NAME	list[MAX_INTERFACES];
+}INTERFACE_LIST;
+
+typedef struct _WLCT_DLL_VERSION
+{
+	int major;
+	int minor;
+	int maintenance;
+	int build;
+
+}WLCT_DLL_VERSION;
+
+// The following ifdef block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the WLCTPCIACSS_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// WLCTPCIACSS_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+
+#ifdef _WINDOWS
+#ifdef WLCTPCIACSS_EXPORTS
+#define WLCTPCIACSS_API __declspec(dllexport)
+#else
+#define WLCTPCIACSS_API __declspec(dllimport)
+#endif
+#endif
+
+#if defined(__GNUC__)
+#if defined(__i386)
+#define WLCTPCIACSS_API extern "C" __attribute__((cdecl))
+#else
+#define WLCTPCIACSS_API extern "C"
+#endif
+#endif
+
+// These are needed for wlanapi.h for pre-vista targets
+
+typedef UCHAR DOT11_MAC_ADDRESS[6];
+typedef DOT11_MAC_ADDRESS * PDOT11_MAC_ADDRESS;
+
+typedef struct
+{
+	UINT32 Ready;
+	UINT32 StructVersion;
+	UINT32 RfType;
+	UINT32 BaseBandType;
+	DOT11_MAC_ADDRESS MacAddr;
+	UINT8  Padding[2];
+}USER_RGF_BL_INFO_VER_0;
+
+typedef struct
+{
+	UINT32 Ready;
+	UINT32 StructVersion;
+	UINT32 RfType;
+	UINT32 BaseBandType;
+	DOT11_MAC_ADDRESS MacAddr;
+	UINT8	VersionMajor;       // 0x880A52 BL ver. major
+	UINT8	VersionMinor;       // 0x880A53 BL ver. minor
+	UINT16	VersionSubminor;    // 0x880A54 BL ver. subminor
+	UINT16	VersionBuild;		// 0x880A56 BL ver. build
+								// valid only for version 2 and above
+	UINT16  AssertCode;         // 0x880A58 BL Assert code
+	UINT16  AssertBlink;        // 0x880A5C BL Assert Branch
+	UINT16  Reserved[22];        // 0x880A60 - 0x880AB4
+	UINT16  MagicNumber;        // 0x880AB8 BL Magic number
+}USER_RGF_BL_INFO_VER_1;
+
+#define BIT(x) (1 << (x))
+
+// Register definitions - taken from the REG files. addresses are from FW point of view
+#define USER_RGF_USAGE_6		            0x880018
+
+// Boot loader registers
+#define USER_RGF_BL_START_OFFSET            0x880A3C
+#define USER_RGF_BL_READY		            USER_RGF_BL_START_OFFSET
+#define BL_BIT_READY                    BIT(0)
+
+// reset sequence related
+#define USER_RGF_HP_CTRL			        0x88265c
+#define USER_RGF_FW_DEDICATED_REG_REV_ID    0x880a8c
+#define PCIE_RGF_MAC_HW_ID_DB1          0x1
+#define PCIE_RGF_MAC_HW_ID_DB2          0x2
+#define USER_RGF_CLKS_CTL_SW_RST_MASK_0     0x880b14
+#define USER_RGF_MAC_CPU_0                  0x8801fc
+#define USER_RGF_USER_CPU_0                 0x8801e0
+#define USER_RGF_CLKS_CTL_SW_RST_VEC_0      0x880b04
+#define USER_RGF_CLKS_CTL_SW_RST_VEC_1      0x880b08
+#define USER_RGF_CLKS_CTL_SW_RST_VEC_2      0x880b0c
+#define USER_RGF_CLKS_CTL_SW_RST_VEC_3      0x880b10
+#define USER_RGF_LOS_COUNTER_CTL            0x882dc4
+#define USER_RGF_SERIAL_BAUD_RATE           0x880050
+#define USER_RGF_SERIAL_BAUD_RATE_READY 0x15e
+#define USER_RGF_PLL_CLR_LOS_COUNTER_CTL    0x882dc4
+#define USER_RGF_HW_MACHINE_STATE           0x8801dc
+#define HW_MACHINE_BOOT_DONE                0x3FFFFFD
+#define USER_RGF_CLKS_CTL_0                 0x880abc
+#define BIT_USER_CLKS_CAR_AHB_SW_SEL	    BIT(1) /* ref clk/PLL */
+#define BIT_USER_CLKS_RST_PWGD              BIT(11)
+
+#define USER_RGF_JTAG_DEVICE_TYPE           0x880B34
+#define USER_RGF_JTAG_DEVICE_SPARROW_A0				0x0632072F
+#define USER_RGF_JTAG_DEVICE_SPARROW_A1				0x1632072F
+#define USER_RGF_JTAG_DEVICE_SPARROW_B0				0x2632072F
+#define USER_RGF_CLKS_CTL_EXT_SW_RST_VEC_0	(0x880c18)
+#define USER_RGF_CLKS_CTL_EXT_SW_RST_VEC_1	(0x880c2c)
+#define USER_RGF_SPARROW_M_4			(0x880c50) /* Sparrow */
+#define BIT_SPARROW_M_4_SEL_SLEEP_OR_REF	BIT(2)
+
+#define USER_RGF_CAF_ICR			            0x88946c /* struct RGF_ICR */
+#define RGF_CAF_ICR_ICR                         (USER_RGF_CAF_ICR+4)
+#define RGF_CAF_ICR_IMV                         (USER_RGF_CAF_ICR+16)
+#define USER_RGF_CAF_OSC_CONTROL		        0x88afa4
+#define BIT_CAF_OSC_XTAL_EN		BIT(0)
+#define USER_RGF_CAF_PLL_LOCK_STATUS		0x88afec
+#define BIT_CAF_OSC_DIG_XTAL_STABLE	BIT(0)
+
+#define XTAL_STABLE_WAIT_MS     0x7
+
+#define ALIGN_DOWN_BY(length, alignment) \
+    (length & ~(alignment - 1))
+
+#define ALIGN_UP_BY(length, alignment) \
+    (ALIGN_DOWN_BY((length + alignment - 1), alignment))
+
+WLCTPCIACSS_API int GetMyVersion(WLCT_DLL_VERSION *pVer);
+WLCTPCIACSS_API bool wPciDisableEnable();
+WLCTPCIACSS_API int GetInterfaces(INTERFACE_LIST* ifList, int* ReturnItems);
+WLCTPCIACSS_API int StrGetInterfaces(char* ifListStr, int capacity);
+WLCTPCIACSS_API int CreateDeviceAccessHandler(const char* deviceName, DType devType, void** pDeviceAccess);
+WLCTPCIACSS_API int CloseDeviceAccessHandler(void* pDeviceAccss);
+WLCTPCIACSS_API int SwReset(void* pDeviceAccss);
+WLCTPCIACSS_API int InterfaceReset(void* pDeviceAccss);
+WLCTPCIACSS_API int WlctAccssRead(void* pDeviceAccss, DWORD addr, DWORD & val);
+WLCTPCIACSS_API int WlctAccssWrite(void* pDeviceAccss, DWORD addr, DWORD val);
+WLCTPCIACSS_API bool isInit(void* pDeviceAccss);
+WLCTPCIACSS_API int writeBlock(void* pDeviceAccss, DWORD addr, DWORD blockSize, const char *arrBlock);
+WLCTPCIACSS_API int readBlock(void* pDeviceAccss, DWORD addr, DWORD blockSize, char *arrBlock);
+WLCTPCIACSS_API int readRepeat(void* pDeviceAccss, DWORD addr, DWORD num_repeat, DWORD *arrBlock);
+WLCTPCIACSS_API int getDbgMsg(void* pDeviceAccss, FW_DBG_MSG** pMsg);
+WLCTPCIACSS_API int clearAllFwDbgMsg(void* pDeviceAccss);
+WLCTPCIACSS_API int card_reset(void* pDeviceAccss);
+WLCTPCIACSS_API TCHAR* getInterfaceName(void* pDeviceAccss);
+WLCTPCIACSS_API DType getDeviceType(void* pDeviceAccss);
+WLCTPCIACSS_API int startSampling(void* pDeviceAccss, DWORD* pRegsArr, DWORD regArrSize, DWORD interval, DWORD maxSampling, DWORD transferMethod);
+WLCTPCIACSS_API int stopSampling(void* pDeviceAccss);
+WLCTPCIACSS_API int getSamplingData(void* pDeviceAccss, DWORD** pDataSamples);
+WLCTPCIACSS_API int SetMachineSpeed(void* pComDeviceAccss, DWORD baud_rate_target);
+#ifndef _ANDROID
+WLCTPCIACSS_API int WlctAccssJtagSendDR(void* pDeviceAccss, DWORD num_bits, BYTE *arr_in, BYTE *arr_out);
+WLCTPCIACSS_API int WlctAccssJtagSendIR(void* pDeviceAccss, DWORD num_bits, BYTE *arr_in);
+WLCTPCIACSS_API int JtagTmsShiftToReset(void* pDeviceAccss);
+WLCTPCIACSS_API int JtagPutTmsTdiBits(void* pDeviceAccss, BYTE *tms, BYTE *tdi, BYTE* tdo, UINT length);
+WLCTPCIACSS_API int JtagSetClockSpeed(void* pDeviceAccss, DWORD requestedFreq, DWORD* frqSet);
+#endif
+#ifdef _WINDOWS
+WLCTPCIACSS_API int WlctAccssSendWmiCmd(void* pDeviceAccss, SEND_RECEIVE_WMI* wmi);
+WLCTPCIACSS_API int WlctAccssRecieveWmiEvent(void* pDeviceAccss, SEND_RECEIVE_WMI* evt);
+WLCTPCIACSS_API int WlctAccssMpSetDriverLogLevels(void* pDeviceAccss, ULONG logModulesEnableMsk, ULONG logModuleLevelsMsk[WILO_DRV_NUM_LOG_COMPS]);
+#endif
+WLCTPCIACSS_API int WlctAccssRegisterDriverMailboxEvents(void* pDeviceAccss, HANDLE* pMailboxEventHandle );
+WLCTPCIACSS_API int WlctAccssUnregisterDriverMailboxEvents(void* pDeviceAccss);
+WLCTPCIACSS_API int WlctAccssRegisterDriverEvent(void* pDeviceAccss, INT_PTR event_ptr, int eventId, int appId);
+WLCTPCIACSS_API int WlctAccssRegisterDeviceForUnplug2Event(void* pDeviceAccss, INT_PTR event_ptr);
+
+WLCTPCIACSS_API int WlctAccssAllocPmc(void* pDeviceAccss, DWORD size, DWORD numOfDescriptors);
+WLCTPCIACSS_API int WlctAccssRegisterDriverDeviceEvents(void* pDeviceAccss, INT_PTR hDnEvent, INT_PTR hUpEvent, INT_PTR hUnplugEvent, INT_PTR hSysAssertEvent );
+
+
+WLCTPCIACSS_API	int accssRead(void* pDeviceAccss, DWORD addr, DWORD & val);
+WLCTPCIACSS_API	int accssWrite(void* pDeviceAccss, DWORD addr, DWORD val);
+WLCTPCIACSS_API int accssClear32(void* pDeviceAccss, DWORD addr, DWORD val);
+WLCTPCIACSS_API int accssSet32(void* pDeviceAccss, DWORD addr, DWORD val);
+
+WLCTPCIACSS_API void hwCopyFromIO(void* dst, void* pDeviceAccss, DWORD src, UINT32 len);
diff --git a/debug-tools/lib/WlctPciAcss/WlctPciAcssHelper.h b/debug-tools/lib/WlctPciAcss/WlctPciAcssHelper.h
new file mode 100644
index 0000000..163d76c
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/WlctPciAcssHelper.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "WlctPciAcss.h"
+
+int GetSimulatorInterfaces(INTERFACE_LIST* ifList, int* ReturnItems);
+int GetPciInterfaces(INTERFACE_LIST* ifList, int* ReturnItems);
+#ifndef _ANDROID_
+int GetJtagInterfaces(INTERFACE_LIST* ifList, int* ReturnItems);
+int GetSerialInterfaces(INTERFACE_LIST* ifList, int* ReturnItems);
+#endif
+
+class CComPortDeviceAccess;
+
+void ComSetParameters(CComPortDeviceAccess* pComDeviceAccss, DType devType);
+int SetMachineSpeed(void* pDeviceAccss, DWORD baud_rate_target);
+
+uint64_t GetTimeStampMs();
+
+int GetPciAcssVersion(WLCT_DLL_VERSION *pVer);
diff --git a/debug-tools/lib/WlctPciAcss/WlctPciAcssWmi.h b/debug-tools/lib/WlctPciAcss/WlctPciAcssWmi.h
new file mode 100644
index 0000000..0ed10b7
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/WlctPciAcssWmi.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#define PREPACK
+#define POSTPACK
+#pragma pack(1)
+#include "wmi.h" // definition of all WMI command structures
+#pragma pack()
+
+
+/* used by IOCTL_REGISTER_WMI_RX_EVENT and IOCTL_REGISTER_DEVICE_EVENT */
+typedef struct
+{
+    HANDLE hEvent; /* use INVALID_HANDLE_VALUE to de-register */
+} REGISTER_EVENT;
+
+
+/* used by IOCTL_OPEN_USER_MODE_EVENT  */
+/*
+	original structure inside the driver is as follows:
+			typedef struct _SHARED_EVENT
+			{
+				HANDLE  hDnEvent;
+				HANDLE  hUpEvent;
+				HANDLE  unplugEvent;
+				HANDLE  sysAssertEvent;
+
+			} SHARED_EVENT, *PSHARED_EVENT;
+
+	The HANDLE type inside the driver is platform speciefic, and
+	can be either 32bit or 64bit!
+	Since our DLL is assumed to be always compiled for 32bit platforms,
+	it is a problem.
+
+	Until the HANDLE types in the driver are changed to ULONG,
+	or until this DLL will have two diffrent barnches for 32bit and 64bit platforms,
+	the following Workarround is implemented:
+	1. Diffrent structs for 32bit and 64bit platforms.
+	2. when sending the IOCTL_OPEN_USER_MODE_EVENT, dynamically descide which struct to use.
+*/
+
+
+//those structs are deprecated
+typedef struct _SHARED_EVENT_64BIT
+{
+	INT_PTR hDnEvent_l;
+	INT_PTR hDnEvent_h;
+
+	INT_PTR hUpEvent_l;
+	INT_PTR hUpEvent_h;
+
+	INT_PTR unplugEvent_l;
+	INT_PTR unplugEvent_h;
+
+	INT_PTR sysAssertEvent_l;
+	INT_PTR sysAssertEvent_h;
+
+} SHARED_EVENT_64BIT, *PSHARED_EVENT_64BIT;
+
+typedef struct _SHARED_EVENT_32BIT
+{
+	INT_PTR hDnEvent;
+	INT_PTR hUpEvent;
+	INT_PTR unplugEvent;
+	INT_PTR sysAssertEvent;
+
+} SHARED_EVENT_32BIT, *PSHARED_EVENT_32BIT;
\ No newline at end of file
diff --git a/debug-tools/lib/WlctPciAcss/linux/CommDeviceAccess.cpp b/debug-tools/lib/WlctPciAcss/linux/CommDeviceAccess.cpp
new file mode 100644
index 0000000..d92ebc7
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/linux/CommDeviceAccess.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "CommDeviceAccess.h"
+
+CComPortDeviceAccess::CComPortDeviceAccess(const TCHAR* tchDeviceName, DType devType)
+{
+  //do something with params
+	(void)tchDeviceName;
+	(void)devType;
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+}
+
+int CComPortDeviceAccess::InitDevice()
+{
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+CComPortDeviceAccess::~CComPortDeviceAccess()
+{
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+}
+
+int CComPortDeviceAccess::GetType()
+{
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::CloseDevice()
+{
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::r2(DWORD addr, DWORD & val)
+{
+  //do something with params
+	(void)addr;
+	(void)val;
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::w2(DWORD addr, DWORD val)
+{
+  //do something with params
+	(void)addr;
+	(void)val;
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::w32(DWORD addr, DWORD val)
+{
+  //do something with params
+	(void)addr;
+	(void)val;
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::rb(DWORD addr, DWORD blockSize, char *arrBlock)
+{
+  //do something with params
+	(void)addr;
+	(void)blockSize;
+	(void)arrBlock;
+
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::wb(DWORD addr, DWORD blockSize, const char *arrBlock)
+{
+  //do something with params
+	(void)addr;
+	(void)blockSize;
+	(void)arrBlock;
+
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::rr(DWORD addr, DWORD num_repeat, DWORD *arrBlock)
+{
+  //do something with params
+	(void)addr;
+	(void)num_repeat;
+	(void)arrBlock;
+
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::getFwDbgMsg(FW_DBG_MSG** pMsg)
+{
+  //do something with params
+	(void)pMsg;
+
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::clearAllFwDbgMsg()
+{
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::do_reset(BOOL bFirstTime)
+{
+  //do something with params
+	(void)bFirstTime;
+
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::do_sw_reset()
+{
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+
+int CComPortDeviceAccess::r32(DWORD addr, DWORD & val)
+{
+  //do something with params
+	(void)addr;
+	(void)val;
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+int CComPortDeviceAccess::r4(DWORD addr, DWORD & val)
+{
+  //do something with params
+	(void)addr;
+	(void)val;
+  LOG_MESSAGE_ERROR(_T("Not Supported\n"));
+  return 0;
+}
+
+
+
diff --git a/debug-tools/lib/WlctPciAcss/linux/CommDeviceAccess.h b/debug-tools/lib/WlctPciAcss/linux/CommDeviceAccess.h
new file mode 100644
index 0000000..cd804f1
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/linux/CommDeviceAccess.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+//using namespace std;
+
+#include "DeviceAccess.h"
+
+class CComPortDeviceAccess : public IDeviceAccess
+{
+public:
+  CComPortDeviceAccess(const TCHAR* tchDeviceName, DType devType);
+  ~CComPortDeviceAccess(void);
+
+  virtual int CloseDevice();
+  virtual int GetType();
+  virtual int r2(DWORD addr, DWORD & val);
+  virtual int r4(DWORD addr, DWORD & val);
+  virtual int w2(DWORD addr, DWORD val);
+
+  virtual int r32(DWORD addr, DWORD & val);
+  virtual int w32(DWORD addr, DWORD val);
+
+  // read block
+  virtual int rb(DWORD addr, DWORD blockSize, char *arrBlock);
+  // write block
+  virtual int wb(DWORD addr, DWORD blockSize, const char *arrBlock);
+  // read repeat
+  virtual int rr(DWORD addr, DWORD num_repeat, DWORD *arrBlock);
+
+  virtual int getFwDbgMsg(FW_DBG_MSG** pMsg);
+  virtual int clearAllFwDbgMsg();
+  virtual int do_reset(BOOL bFirstTime = TRUE);
+  virtual int do_sw_reset();
+
+  int InitDevice();
+};
diff --git a/debug-tools/lib/WlctPciAcss/linux/IoctlDev.cpp b/debug-tools/lib/WlctPciAcss/linux/IoctlDev.cpp
new file mode 100644
index 0000000..4473315
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/linux/IoctlDev.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "IoctlDev.h"
+#include "wlct_procfs.h"
+#include "public.h"
+#include "LoggerSupport.h"
+#include <iostream>
+#include <fstream>
+
+#include <algorithm>
+
+#define PROC_MODULES_PATH "/proc/modules"
+#define DRIVER_KEYWORD "wil6210"
+
+void CIoctlDev::FormatCDevFName(void)
+{
+    int sres = snprintf(cdevFileName, sizeof(cdevFileName),
+                        "/tmp/%s", WLCT_CDEV_NAME);
+
+    WLCT_ASSERT((size_t)sres < sizeof(cdevFileName));
+    (void)sres;
+}
+
+CIoctlDev::CIoctlDev(const TCHAR *tchDeviceName)
+    : IIoctlDev(tchDeviceName)
+{
+    if( strstr(szInterfaceName, "wEP") != NULL || strstr(szInterfaceName, "wep") != NULL ){
+	cdevFile = new CWlctCDevSocket();
+    }  else{
+        cdevFile = new CWlctCDevFile();
+    }
+    // Name in format WLCT_PCI_LDEVNAME_FMT/WLCT_PCI_RDEVNAME_FMT
+    FormatCDevFName();
+}
+
+CIoctlDev::~CIoctlDev()
+{
+    delete cdevFile;
+    Close();
+}
+
+bool CIoctlDev::IsOpened(void)
+{
+    return cdevFile->IsOpened();
+}
+
+wlct_os_err_t CIoctlDev::DebugFS(char *FileName, void *dataBuf, DWORD dataBufLen, DWORD DebugFSFlags)
+{
+    return cdevFile->DebugFS(FileName, dataBuf, dataBufLen, DebugFSFlags);
+}
+
+bool WilDriverExistForEP(TCHAR *szInterfaceName)
+{
+
+    if( strstr(szInterfaceName, "wEP") != NULL || strstr(szInterfaceName, "wep") != NULL ){
+        ifstream ifs(PROC_MODULES_PATH);
+        string DriverKey = DRIVER_KEYWORD;
+        string line;
+        while(getline(ifs, line)) {
+            if (line.find(DriverKey, 0) != string::npos) {
+                LOG_MESSAGE_INFO(_T("Found WIGIG interface [wEP0!MARLON]"));
+                return true;
+            }
+        }
+    }
+    return false;
+}
+wlct_os_err_t CIoctlDev::Open()
+{
+    wlct_os_err_t res = WLCT_OS_ERROR_GEN_FAILURE;
+
+    WLCT_ASSERT(!IsOpened());
+
+    bOldIoctls = TRUE;
+
+    if (WilDriverExistForEP(szInterfaceName))
+    {
+        // Bug fix
+        char tempInterfaceName[INTERFACE_NAME_LENGTH];
+        snprintf(tempInterfaceName, INTERFACE_NAME_LENGTH, "%s", szInterfaceName);
+
+        LOG_MESSAGE_DEBUG("Tokenizing: %s\n", tempInterfaceName);
+
+        res = cdevFile->Open(cdevFileName, tempInterfaceName);
+        if (res == WLCT_OS_ERROR_SUCCESS)
+        {
+            LOG_MESSAGE_DEBUG("Cdev file '%s' opened (uid=%u)",
+                              cdevFileName, uID);
+        }
+        else
+        {
+            LOG_MESSAGE_ERROR("Cdev file '%s' (uid=%u) opening failed (%d)",
+                              cdevFileName, uID, res);
+        }
+    }
+    else
+    {
+        LOG_MESSAGE_ERROR("Cannot get UID by PciDevName (%s)",
+                          szInterfaceName);
+        res = WLCT_OS_ERROR_NO_SUCH_ENTRY;
+    }
+
+    return res;
+}
+
+void CIoctlDev::Close()
+{
+    if (IsOpened())
+    {
+        cdevFile->Close();
+    }
+}
+
+wlct_os_err_t CIoctlDev::Ioctl(uint32_t Id,
+                               const void *inBuf, uint32_t inBufSize,
+                               void *outBuf, uint32_t outBufSize)
+{
+    wlct_os_err_t     res = WLCT_OS_ERROR_GEN_FAILURE;
+    wlct_ioctl_hdr_t *ioctlHdr = NULL;
+    uint32_t          ioctlBufSize = 0;
+
+    WLCT_ASSERT(IsOpened());
+
+    if (!inBuf || !inBufSize)
+    {
+        inBuf     = NULL;
+        inBufSize = 0;
+    }
+
+    if (!outBuf || !outBufSize)
+    {
+        outBuf     = NULL;
+        outBufSize = 0;
+    }
+
+    ioctlBufSize = sizeof(wlct_ioctl_hdr_t) + inBufSize + outBufSize;
+
+    ioctlHdr = (wlct_ioctl_hdr_t *)malloc(ioctlBufSize);
+    if (ioctlHdr)
+    {
+        uint32_t offset     = 0;
+        uint32_t ioctlFlags = 0;
+
+        memset(ioctlHdr, 0, ioctlBufSize);
+
+        ioctlHdr->deviceUID    = uID;
+        ioctlHdr->commandID    = Id;
+        ioctlHdr->dataSize     = inBufSize + outBufSize;
+        if (inBufSize)
+        {
+            ioctlHdr->inBufOffset  = offset;
+            ioctlHdr->inBufSize    = inBufSize;
+            ioctlFlags            |= WLCT_IOCTL_FLAG_SET;
+
+            memcpy(wlct_ioctl_data_in(ioctlHdr), inBuf, inBufSize);
+
+            offset += inBufSize;
+        }
+
+        if (outBufSize)
+        {
+            ioctlHdr->outBufOffset  = offset;
+            ioctlHdr->outBufSize    = outBufSize;
+            ioctlFlags             |= WLCT_IOCTL_FLAG_GET;
+
+            offset += outBufSize;
+        }
+
+        res = cdevFile->Ioctl(ioctlHdr, ioctlBufSize, ioctlFlags);
+
+        if (res != WLCT_OS_ERROR_SUCCESS)
+        {
+            LOG_MESSAGE_ERROR("IOCTL failed with error %u (id=%u)",
+                              res, Id);
+        }
+        else if (outBufSize)
+        {
+            memcpy(outBuf, wlct_ioctl_data_out(ioctlHdr), outBufSize);
+        }
+
+        free(ioctlHdr);
+    }
+    else
+    {
+        LOG_MESSAGE_ERROR("Cannot allocate IOCTL buffer of %u bytes (id=%u)",
+                          ioctlBufSize, Id);
+
+        res = WLCT_OS_ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+
+    return res;
+}
diff --git a/debug-tools/lib/WlctPciAcss/linux/IoctlDev.h b/debug-tools/lib/WlctPciAcss/linux/IoctlDev.h
new file mode 100644
index 0000000..98c5ac5
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/linux/IoctlDev.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "IoctlDevXFace.h"
+#include "WlctCDevFile.h"
+#include "WlctCDevSocket.h"
+
+using namespace std;
+#include <string>
+
+typedef enum{
+  local = 0,
+  remote,
+  endPoint,
+}DEVICE_TYPES;
+
+class CIoctlDev : public IIoctlDev
+{
+public:
+  CIoctlDev(const TCHAR *tchDeviceName);
+  virtual ~CIoctlDev();
+
+  virtual bool          IsOpened(void);
+  virtual wlct_os_err_t	DebugFS(char *FileName, void *dataBuf, DWORD dataBufLen, DWORD DebugFSFlags);
+
+  virtual wlct_os_err_t Open();
+  virtual wlct_os_err_t Ioctl(uint32_t Id,
+                              const void *inBuf, uint32_t inBufSize,
+                              void *outBuf, uint32_t outBufSize);
+  virtual void          Close();
+
+  bool bOldIoctls;
+
+protected:
+  void                  FormatCDevFName(void);
+
+  char                 cdevFileName[128];
+  CWlctCDevFile*        cdevFile;
+  uint32_t             uID;
+};
diff --git a/debug-tools/lib/WlctPciAcss/linux/Util.cpp b/debug-tools/lib/WlctPciAcss/linux/Util.cpp
new file mode 100644
index 0000000..4ad5d69
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/linux/Util.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "Util.h"
+
+#ifdef NO_GCC_ATOMIC
+#error "Platform doesn't support GCC atomic built-ins"
+#endif
+
+#define InterlockedExchange __sync_lock_test_and_set
+
+BOOL Util::timedResourceInterLockExchange ( LONG* var, LONG flag_value, int timeout, bool keepWaiting )
+{
+  // perform atomic change value, to acquire resource!
+  // if VAR != FLAG_VALUE, then set VAR to FLAG_VALUE.
+  // loop until timeout (millisecond). return success in achieving resource
+  // Assumes that FLAG_VALUE should be different then current value stored in VAR
+  // turn keepWaiting on to wait infinite
+
+  LONG original_value;
+
+  int i = 0;
+  do
+  {
+    original_value = InterlockedExchange(var, flag_value);
+    if (original_value != flag_value)
+    {
+      return true;
+    }
+    if (timeout > 0 )
+    {
+      sleep_ms(1);
+    }
+    i++;
+  } while ((i < timeout) || (keepWaiting));
+
+  return false;
+}
+
+bool Util::ICHDisableEnable()
+{
+  return false;
+}
+
+DWORD Util::ReadRegistrySettings(LPCTSTR lpszRegistryPath, LPCTSTR valName)
+{
+  //do something with params
+  (void)lpszRegistryPath;
+  (void)valName;
+
+  return -1;
+}
+
+DWORD Util::WriteRegistrySettings(LPCTSTR lpszRegistryPath, LPCTSTR valName, DWORD val)
+{
+  //do something with params
+  (void)lpszRegistryPath;
+  (void)valName;
+  (void)val;
+
+  return -1;
+}
diff --git a/debug-tools/lib/WlctPciAcss/linux/WlctPciAcssHelper.cpp b/debug-tools/lib/WlctPciAcss/linux/WlctPciAcssHelper.cpp
new file mode 100644
index 0000000..646be85
--- /dev/null
+++ b/debug-tools/lib/WlctPciAcss/linux/WlctPciAcssHelper.cpp
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "WlctPciAcssHelper.h"
+#include "PciDeviceAccess.h"
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#ifdef _WINDOWS
+#include "JtagDeviceAccess.h"
+#endif
+
+#include <sys/time.h>
+
+#define WLCT_MS_PER_S  1000
+#define WLCT_US_PER_MS 1000
+#define PROC_MODULES_PATH "/proc/modules"
+#define DRIVER_KEYWORD "wil6210"
+
+#define END_POINT_RESULT_MAX_SIZE 1000
+
+using namespace std;
+
+void CreatePciInterface(const char* interfaceName, DType devType, INTERFACE_LIST* ifList, int* ReturnItems);
+void CreateMultipleInterfaces(const char* interfaceName, DType devType, INTERFACE_LIST* ifList, int* ReturnItems);
+bool GetInterfaceNameFromEP(const char* pciEndPoint, char* interfaceName);
+int GetNumberOfInterfaces();
+
+int GetSimulatorInterfaces(INTERFACE_LIST* ifList, int* ReturnItems)
+{
+    // Not supported in Linux
+    WLCT_UNREFERENCED_PARAM(ifList);
+
+    return *ReturnItems;
+}
+bool WilDriverExist()
+{
+    ifstream ifs(PROC_MODULES_PATH);
+    string DriverKey = DRIVER_KEYWORD;
+    string line;
+    while(getline(ifs, line)) {
+        if (line.find(DriverKey, 0) != string::npos) {
+            LOG_MESSAGE_INFO(_T("Found WIGIG interface [wEP0!MARLON]"));
+            return true;
+        }
+    }
+
+    return false;
+}
+
+int GetPciInterfaces(INTERFACE_LIST* ifList, int* ReturnItems)
+{
+    CreateMultipleInterfaces("wEP0L!SPARROW", MST_SPARROW, ifList, ReturnItems);
+
+    return *ReturnItems;
+}
+
+void CreateMultipleInterfaces(const char* interfaceName, DType devType, INTERFACE_LIST* ifList, int* ReturnItems)
+{
+    //do something with params
+    (void)devType;
+    // Holds the console ouput containing the current End Point
+    char pciEndPoints[END_POINT_RESULT_MAX_SIZE];
+
+    // This command retrieves the PCI endpoints enumerated
+    const char* szCmdPattern = "ls /sys/module/wil6210/drivers/pci\\:wil6210 | grep :";
+
+    FILE* pIoStream = popen(szCmdPattern, "r");
+    if (!pIoStream)
+    {
+        LOG_MESSAGE_ERROR("Failed to run command to detect End Points\n" );
+        return;
+    }
+
+    LOG_MESSAGE_DEBUG("Searching for PCI end points: %s", szCmdPattern);
+
+    while (fgets(pciEndPoints, END_POINT_RESULT_MAX_SIZE, pIoStream) != NULL)
+    {
+        // The command output contains a newline character that should be removed
+        pciEndPoints[strcspn(pciEndPoints, "\r\n")] = '\0';
+        LOG_MESSAGE_DEBUG("PCI End Point Found: %s", pciEndPoints);
+
+        // Get interface name from End Point
+        char networkInterfaceName[IFNAMSIZ] = {0};
+        GetInterfaceNameFromEP(pciEndPoints, networkInterfaceName);
+
+        // Append driver interface name
+        std::string ifName = interfaceName;
+        ifName += "!";
+        ifName += networkInterfaceName;
+
+        LOG_MESSAGE_DEBUG("Attempting to create interface named: %s", ifName.c_str());
+
+        CreatePciInterface(ifName.c_str(), MST_SPARROW, ifList, ReturnItems);
+    }
+
+    pclose(pIoStream);
+}
+
+
+bool GetInterfaceNameFromEP(const char* pciEndPoint, char* interfaceName)
+{
+    char szInterfaceCmdPattern[END_POINT_RESULT_MAX_SIZE];
+
+    // This command translates the End Point to the interface name
+    snprintf(szInterfaceCmdPattern, END_POINT_RESULT_MAX_SIZE, "ls /sys/module/wil6210/drivers/pci:wil6210/%s/net", pciEndPoint);
+
+    LOG_MESSAGE_DEBUG("Running command: %s", szInterfaceCmdPattern);
+
+    FILE* pIoStream = popen(szInterfaceCmdPattern, "r");
+    if (!pIoStream)
+    {
+        LOG_MESSAGE_ERROR("Failed to run command to detect End Points\n" );
+        return false;
+    }
+
+    while (fgets(interfaceName, IFNAMSIZ, pIoStream) != NULL)
+    {
+        // The command output contains a newline character that should be removed
+        interfaceName[strcspn(interfaceName, "\r\n")] = '\0';
+        LOG_MESSAGE_DEBUG("PCI interface found: %s", interfaceName);
+
+        return true;
+    }
+
+    pclose(pIoStream);
+    return false;
+}
+
+
+void CreatePciInterface(const char* interfaceName, DType devType, INTERFACE_LIST* ifList, int* ReturnItems)
+{
+    void* res = NULL;
+    void** tempAccess = &res;
+
+    if(!CreateDeviceAccessHandler(interfaceName, devType, tempAccess))
+    {
+        snprintf(ifList->list[(*ReturnItems)].ifName, MAX_IF_NAME_LENGTH, "%s", interfaceName);
+        (*ReturnItems) += 1;
+        LOG_MESSAGE_INFO(_T("Found WIGIG interface"));
+        if(res)
+        {
+            CloseDeviceAccessHandler(*tempAccess);
+        }
+    }
+}
+
+int GetSerialInterfaces(INTERFACE_LIST* ifList, int* ReturnItems)
+{
+    // Not supported in Linux
+    WLCT_UNREFERENCED_PARAM(ifList);
+
+    return *ReturnItems;
+}
+
+int GetJtagInterfaces(INTERFACE_LIST* ifList, int* ReturnItems)
+{
+
+#ifdef _WINDOWS
+    DType devType;
+    void* handler = NULL;
+    DWORD err;
+    uint32_t addr;
+    uint32_t val;
+    int ret = 0;
+
+    char ifName[MAX_IF_NAME_LENGTH];
+
+    //////////////////////////////////////////////////////////////////////////
+    // find all jtag channels that connect to a WIGIG card
+    //////////////////////////////////////////////////////////////////////////
+    devType = MST_MARLON;
+    addr = BAUD_RATE_REGISTER;
+
+    int cdvc = 0;
+    DVC dvc;
+    char infoSet[28];
+
+    LOG_MESSAGE_INFO(_T("scan jtag devices"));
+
+    if (!funcDmgrEnumDevices(&cdvc)) {
+        LOG_MESSAGE_INFO(_T("Error enumerating JTAG devices"));
+        cdvc = 0;
+    }
+
+    for (int idvc = 0; idvc < cdvc; idvc++) {
+
+        // DMGR API Call: funcDmgrGetDvc
+        if (!funcDmgrGetDvc(idvc, &dvc)) {
+            LOG_MESSAGE_INFO(_T("Error getting device info"));
+            break;
+        }
+        DINFO dinfo = dinfoUsrName;
+        BOOL bRes;
+        snprintf(infoSet, sizeof(infoSet), "wjtag%d", idvc);
+        bRes = funcDmgrSetInfo(&dvc, dinfo, (void*)infoSet);
+
+        WLCT_UNREFERENCED_PARAM(bRes);
+
+        snprintf(ifName, MAX_IF_NAME_LENGTH, "%s!MARLON", infoSet);
+        err = CreateDeviceAccessHandler(ifName, devType, &handler);
+        if (err == 0 && isInit(handler))
+        {
+            ret = WlctAccssRead(handler, addr, val);
+            if (ret == 0 && val > 0 && val < 0xFFFF)
+            {
+                snprintf(ifList->list[(*ReturnItems)++].ifName, MAX_IF_NAME_LENGTH, "%s", ifName);
+                LOG_MESSAGE_INFO(_T("Found JTAG WIGIG interface [%s]"),
+                                 ifName);
+            }
+            CloseDeviceAccessHandler(handler);
+            handler = NULL;
+        }
+    }
+
+    /* Clean up and get out */
+    // DMGR API Call: DmgrFreeDvcEnum
+    funcDmgrFreeDvcEnum();
+
+#endif
+//do something with params
+    WLCT_UNREFERENCED_PARAM(ifList);
+    return *ReturnItems;
+}
+
+void ComSetParameters(CComPortDeviceAccess* pComDeviceAccss, DType devType)
+{
+    // Not supported in Linux
+    WLCT_UNREFERENCED_PARAM(pComDeviceAccss);
+    WLCT_UNREFERENCED_PARAM(devType);
+}
+
+int SetMachineSpeed(void* pDeviceAccss, DWORD baud_rate_target)
+{
+    // Not supported in Linux
+    WLCT_UNREFERENCED_PARAM(pDeviceAccss);
+    WLCT_UNREFERENCED_PARAM(baud_rate_target);
+
+    return -1;
+}
+
+uint64_t GetTimeStampMs()
+{
+    struct timeval tv = {0,0};
+    if (gettimeofday(&tv, NULL) == 0)
+    {
+        return tv.tv_sec * WLCT_MS_PER_S + tv.tv_usec / WLCT_US_PER_MS;
+    }
+
+    return 0;
+}
+
+int GetPciAcssVersion(WLCT_DLL_VERSION *pVer)
+{
+    WLCT_ASSERT(pVer != NULL);
+    pVer->major       = 0;
+    pVer->minor       = 0;
+    pVer->maintenance = 0;
+    pVer->build       = 0;
+    return 0;
+}
+
diff --git a/debug-tools/lib/inc/basic_types.h b/debug-tools/lib/inc/basic_types.h
new file mode 100644
index 0000000..1145107
--- /dev/null
+++ b/debug-tools/lib/inc/basic_types.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef BASIC_TYPES_H_
+#define BASIC_TYPES_H_
+#define EMPTY_ARRAY_SIZE
+
+#ifdef _WINDOWS
+
+#else
+typedef signed char         INT8;
+typedef signed short        INT16;
+typedef signed int          INT32;
+typedef signed long         INT64;
+typedef unsigned char       UINT8;
+typedef unsigned short      UINT16;
+typedef unsigned int        UINT32;
+typedef UINT32*             PUINT32;
+typedef unsigned long       UINT64;
+typedef UINT64              INT_PTR;
+#endif
+
+typedef UINT64 u64;
+typedef UINT32 u32;
+typedef UINT16 u16;
+typedef UINT8 u8;
+typedef INT64 s64;
+typedef INT32 s32;
+typedef INT16 s16;
+typedef INT8 s8;
+
+
+typedef u8 U08;
+typedef u16 U16;
+typedef u32 U32;
+typedef s32 S32;
+typedef s8 S08;
+typedef u8* PU08;
+typedef u16* PU16;
+
+#endif //BASIC_TYPES_H_
diff --git a/debug-tools/lib/inc/ioctl_if.h b/debug-tools/lib/inc/ioctl_if.h
new file mode 100644
index 0000000..3bfbbb9
--- /dev/null
+++ b/debug-tools/lib/inc/ioctl_if.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "wmi.h"
+
+#define WBE_DRIVER_NAME L"wmp0"
+
+// use INVALID_HANDLE_VALUE to de-register the event
+#define INVALID_HANDLE_VALUE_LEGACY ((ULONG)(LONG_PTR)-1)
+#define INVALID_HANDLE_VALUE        ((HANDLE)(LONG_PTR)-1)
+
+// max value of the device id (user-mode application identifier) - related to WMI_DEVICE_ID
+#define IOCTL_DEVICE_ID_MAX                      0xFF
+#define IOCTL_DEVICE_ID_WBE_OLD                  0x00
+
+#define WILOCITY_DEVICE_TYPE                    FILE_DEVICE_UNKNOWN
+#define WILOCITY_IOCTL(_code_)                  CTL_CODE (WILOCITY_DEVICE_TYPE, _code_, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define WILOCITY_IOCTL_DEVICE_STATUS_EVENT    	WILOCITY_IOCTL (0x208)    // API for Monitoring tool
+#define WILOCITY_IOCTL_INDIRECT_READ            WILOCITY_IOCTL (0x210)
+#define WILOCITY_IOCTL_INDIRECT_WRITE           WILOCITY_IOCTL (0x211)
+#define WILOCITY_IOCTL_INDIRECT_READ_BLOCK      WILOCITY_IOCTL (0x212)
+#define WILOCITY_IOCTL_INDIRECT_WRITE_BLOCK     WILOCITY_IOCTL (0x214)
+#define WILOCITY_IOCTL_SEND_WMI                 WILOCITY_IOCTL (0x800)
+#define WILOCITY_IOCTL_REGISTER_EVENT_NEW       WILOCITY_IOCTL (0x850)
+#define WILOCITY_IOCTL_UNREGISTER_EVENTS        WILOCITY_IOCTL (0x851)
+#define WILOCITY_IOCTL_RECEIVE_WMI_NEW          WILOCITY_IOCTL (0x852)    // New API Not implemented yet by WBE APP
+#define WILOCITY_IOCTL_DEVICE_RESET             WILOCITY_IOCTL (0x807)
+#define WILOCITY_IOCTL_SET_MODE_NEW	            WILOCITY_IOCTL (0x808)    // New API for Concurrent mode controlling (Docking/Networking/hotspot), IOCTL_EVENT_SET_MODE_COMPLETE will be sent to UI on success
+#define WILOCITY_IOCTL_GET_MODE_NEW	            WILOCITY_IOCTL (0x809)    // API for UI to extract driver mode (example: after set mode fail, not event will be sent to UI)
+
+// Deprecated API
+#define WILOCITY_IOCTL_RECEIVE_WMI         		WILOCITY_IOCTL (0x801)
+// registration for indication of incoming WMI command.
+// Following that, client will use IOCTL_RECEIVE_WMI to get the incoming WMI command
+#define WILOCITY_IOCTL_REGISTER_WMI_RX		    WILOCITY_IOCTL (0x803)
+// Registration for driver down event
+#define WILOCITY_IOCTL_REGISTER_DEVICE    		WILOCITY_IOCTL (0x804)
+
+/**
+*    WILOCITY_IOCTL_DEVICE_STATUS_EVENT
+**/
+#pragma pack(1)
+typedef struct _DEVICE_STATUS_EVENT
+{
+    HANDLE  hDnEvent;              		// Link Down
+    HANDLE  hUpEvent; 				// Link up
+    HANDLE  unplugEvent;			// Surprise removal
+    HANDLE  sysAssertEvent;			// Device Fatal Error
+} DEVICE_STATUS_EVENT, *PDEVICE_STATUS_EVENT;
+#pragma pack()
+
+/**
+* WILOCITY_IOCTL_INDIRECT_READ
+**/
+#pragma pack(1)
+typedef struct _DRIVER_READ_DWORD
+{
+    ULONG            address; // Word output will be returned in IOCTL output buffer that was allocated by application
+} DRIVER_READ_DWORD, *PDRIVER_READ_DWORD;
+#pragma pack()
+
+/**
+* WILOCITY_IOCTL_INDIRECT_WRITE
+**/
+#pragma pack(1)
+typedef struct _DRIVER_WRITE_DWORD
+{
+    ULONG            address;
+    ULONG            data;
+} DRIVER_WRITE_DWORD, *PDRIVER_WRITE_DWORD;
+#pragma pack()
+
+/**
+* WILOCITY_IOCTL_INDIRECT_WRITE_BLOCK
+**/
+#pragma pack(1)
+typedef struct _DRIVER_WRITE_BLOCK
+{
+    ULONG            address;
+    ULONG            size;      				// in bytes
+    ULONG            buffer[EMPTY_ARRAY_SIZE]; 	// buffer's data will be allocated by user-mode app right to the end of struct
+} DRIVER_WRITE_BLOCK, *PDRIVER_WRITE_BLOCK;
+#pragma pack()
+
+/**
+* WILOCITY_IOCTL_INDIRECT_READ_BLOCK
+**/
+#pragma pack(1)
+typedef struct _DRIVER_READ_BLOCK
+{
+    ULONG            address;  					// Size is taken from IOCTL output buffer size
+} DRIVER_READ_BLOCK, *PDRIVER_READ_BLOCK;
+#pragma pack()
+
+/**
+* WILOCITY_IOCTL_REGISTER_EVENT_NEW
+**/
+typedef enum _NOTIFY_EVENT {
+    IOCTL_EVENT_PCI_LINK_UP,
+    IOCTL_EVENT_PCI_PRE_LINK_DOWN,
+    IOCTL_EVENT_PCI_LINK_DOWN,
+    IOCTL_EVENT_DEVICE_READY,
+    IOCTL_EVENT_MAILBOX_MSG,
+    IOCTL_EVENT_DEBUG_MAILBOX_MSG,
+    IOCTL_EVENT_SYSASSERT,
+    IOCTL_EVENT_DRIVER_DISABLE,
+    IOCTL_EVENT_SET_MODE_COMPLETE,
+    IOCTL_EVENT_DEVICE_UNPLUG,
+    IOCTL_EVENT_ORACLE_START,
+    IOCTL_EVENT_ORACLE_STOP,
+
+    // !!!do not define any event below MAX_EVENT!!!
+    IOCTL_EVENT_MAX,
+} NOTIFY_EVENT, *PNOTIFY_EVENT;
+
+#pragma pack(1)
+typedef struct _DRIVER_REGISTER_EVENT_NEW
+{
+    ULONG           DeviceId;			// The application identifier from type WMI_DEVICE_ID
+    NOTIFY_EVENT    EventId;
+    HANDLE          UserEventHandle;    	// The application CB to be called on event
+
+} DRIVER_REGISTER_EVENT_NEW, *PDRIVER_REGISTER_EVENT_NEW;
+#pragma pack()
+
+/**
+* WILOCITY_IOCTL_UNREGISTER_EVENTS
+**/
+#pragma pack(1)
+typedef struct _DRIVER_UNREGISTER_EVENTS
+{
+    ULONG           DeviceId;			// of type WMI_DEVICE_ID, driver will unregistered all APP events
+
+} DRIVER_UNREGISTER_EVENTS, *PDRIVER_UNREGISTER_EVENTS;
+#pragma pack()
+
+/**
+* WILOCITY_IOCTL_REGISTER_WMI_RX_EVENT    // Used for WMI event registration
+* WILOCITY_IOCTL_REGISTER_DEVICE          // USed for driver unload event registration
+**/
+#pragma pack(1)
+typedef struct _DRIVER_REGISTER_EVENT
+{
+    ULONG UserEventHandle; // The application CB to be called on event
+
+} DRIVER_REGISTER_EVENT, *PDRIVER_REGISTER_EVENT;
+#pragma pack()
+
+/**
+* WILOCITY_IOCTL_SEND_WMI
+**/
+#pragma pack(1)
+/* used by IOCTL_SEND_WMI and IOCTL_RECEIVE_WMI */
+typedef struct SEND_RECEIVE_WMI_S
+{
+    enum WMI_COMMAND_ID uCmdId;
+    U16                 uContext;
+    U08                 uDevId;
+    U16                 uBufLen;
+    U08                 uBuf[EMPTY_ARRAY_SIZE];
+} SEND_RECEIVE_WMI, *PSEND_RECEIVE_WMI;
+#pragma pack()
+
+/**
+* WILOCITY_IOCTL_RECEIVE_WMI_NEW
+**/
+#pragma pack(1)
+typedef struct RECEIVE_WMI_NEW_S
+{
+    ULONG       DeviceId;                         	// The application identifier from type WMI_DEVICE_ID
+    U08         IsFilterAccordingToMyDeviceId;   	// Input param. If should pass all events (=FALSE) or only events with BCASD id or my id (=TRUE)
+    U08         Reserved[3];
+    U32         OutputBuffSize;                  	// Output param. Number of bytes written to output buffer
+    union {
+        struct {
+        U16     StartSequenceNumber;
+        U16     StartRepCount;
+        };
+        U32     Counter;                         // Input param. 32 bit counter build from 16 bit FW sequence numbers and 16 bit driver's wrap counter
+                                                 // To request first event, set counter to 0x0
+    };
+    U32         NumEventsToRead;                 // Input/Output param.
+                                                 // Input: max number of events to read. Driver reads from the currently available events (does not block if requested more than available)
+                                                 // Output: number of events written to output buffer
+} RECEIVE_WMI_NEW, *PRECEIVE_WMI_NEW;
+#pragma pack()
+
+/**
+* WILOCITY_IOCTL_SET_MODE_NEW
+* input buffer contains SET_MODE_CMD_INPUT
+* output buffer contains SET_MODE_CMD_OUTPUT
+* WILOCITY_IOCTL_GET_MODE_NEW
+* output buffer contains GET_MODE_CMD_OUTPUT
+**/
+typedef enum _DRIVER_MODE {
+    IOCTL_WBE_MODE,
+    IOCTL_WIFI_STA_MODE,
+    IOCTL_WIFI_SOFTAP_MODE,
+    IOCTL_CONCURRENT_MODE,    // This mode is for a full concurrent implementation  (not required mode switch between WBE/WIFI/SOFTAP)
+    IOCTL_SAFE_MODE,          // A safe mode required for driver for protected flows like upgrade and crash dump...
+} DRIVER_MODE, *PDRIVER_MODE;
+
+#pragma pack(1)
+typedef struct _SET_MODE_CMD_INPUT
+{
+    DRIVER_MODE mode;
+} SET_MODE_CMD_INPUT, *PSET_MODE_CMD_INPUT;
+
+typedef struct _SET_MODE_CMD_OUTPUT
+{
+    BOOLEAN result;
+    DRIVER_MODE previousMode; // relevant only if result is TRUE
+} SET_MODE_CMD_OUTPUT, *PSET_MODE_CMD_OUTPUT;
+
+typedef struct _GET_MODE_CMD_OUTPUT
+{
+    DRIVER_MODE currentMode;
+} GET_MODE_CMD_OUTPUT, *PGET_MODE_CMD_OUTPUT;
+#pragma pack()
+
+
+
diff --git a/debug-tools/lib/inc/linux/wlct_cdev_shared.h b/debug-tools/lib/inc/linux/wlct_cdev_shared.h
new file mode 100644
index 0000000..c86aa06
--- /dev/null
+++ b/debug-tools/lib/inc/linux/wlct_cdev_shared.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef __WLCT_CDEV_SHARED_H__
+#define __WLCT_CDEV_SHARED_H__
+
+#include "wlct_os.h"
+
+#define WLCT_IOCTL_MAGIC 0x59076456
+
+#define WLCT_IOCTL_FLAG_SET 0x1
+#define WLCT_IOCTL_FLAG_GET 0x2
+
+typedef struct {
+  uint32_t magic;
+  uint32_t len;
+  uint32_t flags;
+} wlct_cdev_ioctl_hdr_t;
+
+#endif
+
diff --git a/debug-tools/lib/inc/linux/wlct_procfs.h b/debug-tools/lib/inc/linux/wlct_procfs.h
new file mode 100644
index 0000000..4267a1e
--- /dev/null
+++ b/debug-tools/lib/inc/linux/wlct_procfs.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef __WLCT_PROCFS_H__
+#define __WLCT_PROCFS_H__
+
+/******************************************************************
+ * Linux Proc FS related definitions
+ ******************************************************************/
+
+/* CDev file name*/
+#define WLCT_CDEV_NAME                      "wilocity"
+
+/* Root ProcFS dir name*/
+#define WLCT_PROCFS_DNAME                   "wilocity"
+
+/* ProcFS topology file name*/
+#define WLCT_PROCFS_TOPOLOGY_FNAME          "topology"
+
+/* ProcFS topology INI file root section definitions */
+#define WLCT_TOPOLOGY_INI_ROOT_SEC          "root"
+#define WLCT_TOPOLOGY_INI_ROOT_CDEVNAME_KEY "cdev"
+#define WLCT_TOPOLOGY_INI_ROOT_MAJOR_KEY    "major"
+#define WLCT_TOPOLOGY_INI_ROOT_NOF_DEVS_KEY "nof_devs"
+
+/* ProcFS topology INI file device specific section definitions */
+#define WLCT_TOPOLOGY_INI_DEV_SEC_PREFIX    "dev"
+#define WLCT_TOPOLOGY_INI_DEV_UID_KEY       "uid"
+#define WLCT_TOPOLOGY_INI_DEV_BUS_NO_KEY    "bus_no"
+#define WLCT_TOPOLOGY_INI_DEV_NAME_KEY      "name"
+
+#endif /* __WLCT_PROCFS_H__ */
diff --git a/debug-tools/lib/inc/public.h b/debug-tools/lib/inc/public.h
new file mode 100644
index 0000000..19db8ff
--- /dev/null
+++ b/debug-tools/lib/inc/public.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef __PUBLIC_H
+#define __PUBLIC_H
+
+#ifdef _WINDOWS
+#include <initguid.h>
+#define INITGUID
+
+
+#define FSCTL_FILTER_BASE      FILE_DEVICE_UNKNOWN
+
+#define _FILTER_CTL_CODE(_Function, _Method, _Access)  \
+						CTL_CODE(FSCTL_FILTER_BASE, _Function, _Method, _Access)
+
+#define WCLT_SAMPLING_TO_FILE_IS_SUPPORTED
+#else
+typedef unsigned long ULONG;
+#define _FILTER_CTL_CODE(_Function, _Method, _Access) (_Function)
+
+typedef struct
+{
+  DWORD deviceUID;
+  DWORD commandID;
+  DWORD dataSize; /* inBufSize + outBufSize */
+  DWORD inBufOffset;
+  DWORD inBufSize;
+  DWORD outBufOffset;
+  DWORD outBufSize;
+} wlct_ioctl_hdr_t;
+
+static __INLINE BYTE *
+wlct_ioctl_data_in(wlct_ioctl_hdr_t *h)
+{
+  return ((BYTE*)&h[1]) + h->inBufOffset;
+}
+
+static __INLINE BYTE *
+wlct_ioctl_data_out(wlct_ioctl_hdr_t *h)
+{
+  return ((BYTE*)&h[1]) + h->outBufOffset;
+}
+#endif
+
+#ifdef _WINDOWS
+// Main Driver GUID
+DEFINE_GUID (GUID_DEVINTERFACE_wDrvEp, 0x23d1c0df,0x48f9,0x4c38,0x97,0xa2,0x4a,0xba,0x44,0x97,0x36,0xd1);
+// {23D1C0DF-48F9-4C38-97A2-4ABA449736D1}
+#endif
+
+//-----------------------------------------------------------------------------------
+// Old IOCTLS
+//-----------------------------------------------------------------------------------
+#define IOCTL_FILTER_GET_CFG   \
+			_FILTER_CTL_CODE(0x202, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_FILTER_SET_CFG   \
+			_FILTER_CTL_CODE(0x203, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_FILTER_CLOSE_LOCAL_DEVICE   \
+	_FILTER_CTL_CODE(0x204, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_FILTER_CLOSE_REMOTE_DEVICE   \
+	_FILTER_CTL_CODE(0x205, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_FILTER_OPEN_LOCAL_DEVICE   \
+	_FILTER_CTL_CODE(0x206, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_FILTER_OPEN_REMOTE_DEVICE   \
+	_FILTER_CTL_CODE(0x207, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_OPEN_USER_MODE_EVENT   \
+	_FILTER_CTL_CODE(0x208, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_CLOSE_USER_MODE_EVENT   \
+	_FILTER_CTL_CODE(0x209, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_FILTER_GET_INTERRUPT_MODE   \
+	_FILTER_CTL_CODE(0x20A, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_FILTER_SET_INTERRUPT_MODE   \
+	_FILTER_CTL_CODE(0x20B, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_INDIRECT_READ_OLD \
+	_FILTER_CTL_CODE(0x210, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_INDIRECT_WRITE_OLD \
+	_FILTER_CTL_CODE(0x211, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_INDIRECT_READ_BLOCK \
+	_FILTER_CTL_CODE(0x212, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_INDIRECT_READ_REPEAT \
+	_FILTER_CTL_CODE(0x213, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_INDIRECT_WRITE_BLOCK \
+	_FILTER_CTL_CODE(0x214, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+
+//-----------------------------------------------------------------------------------
+// New IOCTLS
+//-----------------------------------------------------------------------------------
+#ifdef _WINDOWS
+#define WILOCITY_DEVICE_TYPE				FILE_DEVICE_UNKNOWN
+#define WILOCITY_IOCTL(_code_)				CTL_CODE (WILOCITY_DEVICE_TYPE, _code_, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#else
+#define WILOCITY_IOCTL(_code_)                          _FILTER_CTL_CODE (_code_, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define ERROR_SUCCESS                                   0L
+#endif
+
+
+/* send WMI command to device.
+   The content of pBuf is the WMI message itself. It doesn't include WMI header
+   and Marlon MBOX header. */
+#define WILOCITY_IOCTL_SEND_WMI					WILOCITY_IOCTL (0x800)
+
+/* receive WMI command from device.
+   upon return, pBuf contains the WMI message itself. It doesn't include WMI header
+   and Marlon MBOX header.
+   This IOCTL should return with error code if there is no pending Rx command */
+#define WILOCITY_IOCTL_RECEIVE_WMI				WILOCITY_IOCTL (0x801)
+
+/* registration for indication of incoming WMI command.
+   Following that, client will use IOCTL_RECEIVE_WMI to get the incoming WMI command */
+#define WILOCITY_IOCTL_REGISTER_WMI_RX_EVENT	WILOCITY_IOCTL (0x803)
+
+/* registration for user mode evnts from Driver. all events besides WMI RX Events */
+#define WILOCITY_IOCTL_REGISTER_DEVICE_EVENT	WILOCITY_IOCTL (0x804)
+#define WILOCITY_IOCTL_GET_DEVICE_EVENT			WILOCITY_IOCTL (0x805)
+#define WILOCITY_IOCTL_REGISTER_EVENT			WILOCITY_IOCTL (0x850)
+
+/* Special IOCTLS */
+#define WILOCITY_IOCTL_DEVICE_SW_RESET			WILOCITY_IOCTL (0x807)
+
+/* MiniPort driver only */
+#define WILOCITY_IOCTL_DRIVER_LOG_LEVELS_CFG	WILOCITY_IOCTL(0x900)
+
+
+
+//-----------------------------------------------------------------------------------
+// Other Definitions
+//-----------------------------------------------------------------------------------
+
+#define BASE_ADDRESS	0x880000
+
+// used to transfer address to the driver (input parameter)
+// or value from the driver (output parameter)
+// for example read register
+typedef struct _FILTER_1_ULONG_PARAM
+{
+	DWORD			param;
+
+} FILTER_1_ULONG_PARAM, *PFILTER_1_ULONG_PARAM;
+
+// used to transfer address and value to the driver (input parameter)
+// for example write register
+typedef struct _FILTER_2_ULONG_PARAMS
+{
+	DWORD			param1;
+	DWORD			param2;
+
+} FILTER_2_ULONG_PARAM, *PFILTER_2_ULONG_PARAM;
+
+#ifdef _WINDOWS
+#pragma warning( disable : 4200 ) //suppress warning
+#endif
+typedef struct _FILTER_WRITE_BLOCK
+{
+	DWORD			address;
+	DWORD			size;	// of 32 bits
+	DWORD			buffer[0];
+
+} FILTER_WRITE_BLOCK, *PFILTER_WRITE_BLOCK;
+
+typedef struct _FILTER_INTERRUPT_MODE
+{
+	BYTE			interruptMode; // 0 - Interrupt, 1 - MSI enable
+
+} FILTER_INTERRUPT_MODE, *PFILTER_INTERRUPT_MODE;
+
+
+//
+//  Structure to go with IOCTL_FILTE_OPEN_DEVICE.
+//
+typedef struct _FILTER_MAP_DEVICE
+{
+	BYTE			*userCRSAddress;
+	size_t			userCRSSize;
+
+} FILTER_MAP_DEVICE, *PFILTER_MAP_DEVICE;
+
+
+typedef struct _FILTER_GET_CFG
+{
+	DWORD			offset;
+	DWORD			value;
+
+} FILTER_GET_CFG, *PFILTER_GET_CFG;
+
+
+typedef struct _FILTER_SET_CFG
+{
+	DWORD			offset;
+	DWORD			value;
+
+} FILTER_SET_CFG, *PFILTER_SET_CFG;
+
+
+typedef struct _FILTER_OPEN_DEVICE
+{
+
+	DWORD 			reserved;
+} FILTER_OPEN_DEVICE, *PFILTER_OPEN_DEVICE;
+
+enum{
+	PCI,
+	CONF
+};
+
+
+
+/**
+* WILOCITY_IOCTL_DRIVER_LOG_LEVELS_CFG
+**/
+enum {WILO_DRV_NUM_LOG_COMPS = 32};
+
+typedef struct _DRIVER_LOGS_CFG
+{
+	ULONG logModulesEnableMsk;
+	ULONG logModuleLevelsMsk[WILO_DRV_NUM_LOG_COMPS];
+} DRIVER_LOGS_CFG, *P_DRIVER_LOGS_CFG;
+
+#ifdef _WINDOWS
+typedef struct _EVENT_HANDLE_64BIT
+{
+	ULONG	DeviceId;
+	int    EventId;
+	INT_PTR hEvent_l;
+	INT_PTR hEvent_h;
+
+} EVENT_HANDLE_64BIT, *PEVENT_HANDLE_64BIT;
+
+typedef struct _EVENT_HANDLE_32BIT
+{
+	ULONG	DeviceId;
+	int    EventId;
+	INT_PTR hEvent;
+} EVENT_HANDLE_32BIT, *PEVENT_HANDLE_32BIT;
+#endif //_WINDOWS
+
+#endif
+
diff --git a/debug-tools/lib/inc/wlct_os.h b/debug-tools/lib/inc/wlct_os.h
new file mode 100644
index 0000000..3c21ae0
--- /dev/null
+++ b/debug-tools/lib/inc/wlct_os.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#ifdef _WINDOWS
+
+#include <windows.h>
+#include <atlbase.h>
+#include <atlstr.h>
+#include <assert.h>
+
+typedef unsigned __int8 u_int8_t;
+typedef unsigned __int16 u_int16_t;
+typedef unsigned __int32 u_int32_t;
+typedef unsigned __int64 u_int64_t;
+#if (defined(_MSC_VER) && (_MSC_VER < 1900))
+typedef __int8 int8_t;
+#endif
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+
+typedef DWORD wlct_os_err_t;
+
+#define WLCT_OS_ERROR_SUCCESS              ERROR_SUCCESS
+#define WLCT_OS_ERROR_NOT_SUPPORTED        ERROR_NOT_SUPPORTED
+#define WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED ERROR_CALL_NOT_IMPLEMENTED
+#define WLCT_OS_ERROR_GEN_FAILURE          ERROR_GEN_FAILURE
+#define WLCT_OS_ERROR_NOT_ENOUGH_MEMORY    ERROR_NOT_ENOUGH_MEMORY
+#define WLCT_OS_ERROR_NO_SUCH_ENTRY        ERROR_FILE_NOT_FOUND
+#define WLCT_OS_ERROR_OPEN_FAILED          ERROR_OPEN_FAILED
+
+#define WLCT_ASSERT assert
+
+#define __TRY __try
+
+#define __EXCEPT __except
+
+#define sleep_ms Sleep
+
+#define WlctGetLastError GetLastError
+
+#else
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <string>
+
+#define WLCT_ASSERT assert
+
+#define __INLINE   __inline
+
+typedef uint8_t         BYTE;
+typedef uint16_t        WORD;
+typedef uint32_t        DWORD;
+
+typedef unsigned char   UCHAR;
+typedef unsigned int    UINT;
+typedef char            CHAR;
+typedef long            LONG;
+typedef unsigned short  USHORT;
+typedef unsigned long   ULONG;
+typedef ULONG*          ULONG_PTR;
+
+typedef char            TCHAR;
+
+typedef uint8_t         u_int8_t;
+typedef uint16_t        u_int16_t;
+typedef uint32_t        u_int32_t;
+typedef uint64_t        u_int64_t;
+
+typedef const TCHAR     *LPCTSTR;
+typedef TCHAR           *LPTSTR;
+typedef CHAR            *LPSTR;
+typedef const CHAR      *LPCSTR;
+
+typedef DWORD           HANDLE;
+
+typedef int             BOOL;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <strings.h>
+
+typedef int wlct_os_err_t;
+
+#define WLCT_OS_ERROR_SUCCESS              0
+#define WLCT_OS_ERROR_NOT_SUPPORTED        -ENOTSUP
+#define WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED -ENOSYS
+#define WLCT_OS_ERROR_GEN_FAILURE          -EINVAL
+#define WLCT_OS_ERROR_NOT_ENOUGH_MEMORY    -ENOMEM
+#define WLCT_OS_ERROR_NO_SUCH_ENTRY        -ENOENT
+#define WLCT_OS_ERROR_OPEN_FAILED          -EBADF
+
+#define _T(x) (x)
+
+#define __TRY if (1)
+#define __EXCEPT(ignore) else if (0)
+
+#define WLCT_MSEC_IN_SEC 1000
+
+#define sleep_ms(msec) usleep(msec * WLCT_MSEC_IN_SEC)
+
+#define USES_CONVERSION
+
+#define T2A(x) (x)
+
+#define _tcscpy_s(x, y, z) snprintf((x), (y), "%s", (z))
+#define _tcslen            strlen
+#define _stprintf_s        snprintf
+#define _snprintf          snprintf
+//#define sprintf_s          sprintf
+//#define _stprintf          sprintf
+#define sscanf_s           sscanf
+#define _tcstok_s          strtok_r
+#define _tcsstr            strstr
+#define _tcsicmp           strcasecmp
+#define _vsntprintf        vsnprintf
+#define _tfopen            fopen
+
+#define WlctGetLastError() errno
+
+#endif
+
+#include "StlChar.h"
+
+
+#define WLCT_UNREFERENCED_PARAM(x)  ((x) = (x))
diff --git a/debug-tools/lib/inc/wmi.h b/debug-tools/lib/inc/wmi.h
new file mode 100644
index 0000000..9896a3a
--- /dev/null
+++ b/debug-tools/lib/inc/wmi.h
@@ -0,0 +1,1184 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef MARLON_WMI_H_
+#define MARLON_WMI_H_
+
+#include "basic_types.h"
+
+#if defined(_MSC_VER)           // Microsoft
+#pragma pack (push, marlon_wmi, 1) /* set alignment to 1 byte boundary */
+#endif
+
+
+
+/**
+ * **********************************************************************************************************************************
+ *                                                          General
+ * **********************************************************************************************************************************
+ */
+
+#define WMI_CONTROL_MSG_MAX_LEN     	256
+#define WMI_MAC_LEN             		6               /* length of mac in bytes */
+#define WMI_PROX_RANGE_NUM              3
+
+
+ enum wmi_phy_capability_e {
+    WMI_11A_CAPABILITY   = 1,
+    WMI_11G_CAPABILITY   = 2,
+    WMI_11AG_CAPABILITY  = 3,
+    WMI_11NA_CAPABILITY  = 4,
+    WMI_11NG_CAPABILITY  = 5,
+    WMI_11NAG_CAPABILITY = 6,
+	WMI_11AD_CAPABILITY  = 7,
+    // END CAPABILITY
+    WMI_11N_CAPABILITY_OFFSET = (WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY),
+} ;
+
+/**
+ *  Marlon Mailbox interface
+ *  used for commands and events
+ */
+#define WMI_GET_DEVICE_ID(info1) ((info1) & 0xF)
+typedef  struct {
+	U16	     padding;
+    U16      commandId;
+/*
+ * info1 - 16 bits
+ * b03:b00 - id
+ * b15:b04 - unused
+ */
+    U16      info1;
+    U16      reserved;      /* For alignment */
+}  WMI_CMD_HDR;
+
+
+
+/**
+ * **********************************************************************************************************************************
+ *                                                          WMI Commands
+ * **********************************************************************************************************************************
+ */
+
+/*
+ * List of Commands
+ */
+typedef enum {
+    WMI_CONNECT_CMDID                       = 0x0001,
+    WMI_DISCONNECT_CMDID                    = 0x0003,
+    WMI_START_SCAN_CMDID                    = 0x0007,
+    WMI_SET_BSS_FILTER_CMDID                = 0x0009,
+    WMI_SET_PROBED_SSID_CMDID               = 0x000a,
+    WMI_SET_LISTEN_INT_CMDID                = 0x000b,
+    WMI_BCON_CTRL_CMDID                     = 0x000f,
+    WMI_ADD_CIPHER_KEY_CMDID                = 0x0016,
+    WMI_DELETE_CIPHER_KEY_CMDID             = 0x0017,
+    WMI_SET_APPIE_CMDID                     = 0x003f,
+    WMI_GET_APPIE_CMDID                     = 0x0040,
+    WMI_SET_WSC_STATUS_CMDID                = 0x0041,
+    WMI_PXMT_RANGE_CFG_CMDID                = 0x0042,
+    WMI_PXMT_SNR2_RANGE_CFG_CMDID           = 0x0043,
+    WMI_FAST_MEM_ACC_MODE_CMDID 	    = 0x0300,
+    WMI_MEM_READ_CMDID			    = 0x0800,
+    WMI_MEM_WR_CMDID			    = 0x0801,
+    WMI_ECHO_CMDID			    = 0x0803,
+    WMI_DEEP_ECHO_CMDID			    = 0x0804,
+    WMI_CONFIG_MAC_CMDID		    = 0x0805,
+    WMI_CONFIG_PHY_DEBUG_CMDID              = 0x0806,
+    WMI_ADD_STATION_CMDID		    = 0x0807,
+    WMI_ADD_DEBUG_TX_PCKT_CMDID		    = 0x0808,
+    WMI_PHY_GET_STATISTICS_CMDID            = 0x0809,
+    WMI_FS_TUNE_CMDID                       = 0x080A,
+    WMI_CORR_MEASURE_CMDID                  = 0x080B,
+    WMI_TEMP_SENSE_CMDID                    = 0x080E,
+    WMI_DC_CALIB_CMDID                      = 0x080F,
+    WMI_SEND_TONE_CMDID                     = 0x0810,
+    WMI_IQ_TX_CALIB_CMDID                   = 0x0811,
+    WMI_IQ_RX_CALIB_CMDID                   = 0x0812,
+    WMI_SET_UCODE_IDLE_CMDID                = 0x0813,
+    WMI_SET_WORK_MODE_CMDID                 = 0x0815,
+    WMI_LO_LEAKAGE_CALIB_CMDID              = 0x0816,
+    WMI_MARLON_R_ACTIVATE_CMDID             = 0x0817,
+    WMI_MARLON_R_READ_CMDID                 = 0x0818,
+    WMI_MARLON_R_WRITE_CMDID                = 0x0819,
+    WMI_MARLON_R_TXRX_SEL_CMDID             = 0x081A,
+    MAC_IO_STATIC_PARAMS_CMDID              = 0x081B,
+    MAC_IO_DYNAMIC_PARAMS_CMDID             = 0x081C,
+    WMI_SILENT_RSSI_CALIB_CMDID             = 0x081D,
+    WMI_CFG_RX_CHAIN_CMDID		    = 0x0820,
+    WMI_VRING_CFG_CMDID		    	    = 0x0821,
+    WMI_RX_ON_CMDID			    = 0x0822,
+    WMI_VRING_BA_EN_CMDID		    = 0x0823,
+    WMI_VRING_BA_DIS_CMDID		    = 0x0824,
+    WMI_RCP_ADDBA_RESP_CMDID		    = 0x0825,
+    WMI_RCP_DELBA_CMDID			    = 0x0826,
+    WMI_SET_SSID_CMDID			    = 0x0827,
+    WMI_GET_SSID_CMDID			    = 0x0828,
+    WMI_SET_PCP_CHANNEL_CMDID               = 0x0829,
+    WMI_GET_PCP_CHANNEL_CMDID               = 0x082a,
+    WMI_SW_TX_REQ_CMDID			    = 0x082b,
+    WMI_READ_MAC_RXQ_CMDID                  = 0x0830,
+    WMI_READ_MAC_TXQ_CMDID                  = 0x0831,
+    WMI_WRITE_MAC_RXQ_CMDID                 = 0x0832,
+    WMI_WRITE_MAC_TXQ_CMDID                 = 0x0833,
+    WMI_WRITE_MAC_XQ_FIELD_CMDID            = 0x0834,
+    WMI_MLME_PUSH_CMDID                     = 0x0835,
+    WMI_BEAMFORMING_MGMT_CMDID              = 0x0836,
+    WMI_BF_TXSS_MGMT_CMDID                  = 0x0837,
+    WMI_BF_SM_MGMT_CMDID                    = 0x0838,
+    WMI_BF_RXSS_MGMT_CMDID                  = 0x0839,
+    WMI_SET_SECTORS_CMDID                   = 0x0849,
+    WMI_MAINTAIN_PAUSE_CMDID                = 0x0850,
+    WMI_MAINTAIN_RESUME_CMDID               = 0x0851,
+    WMI_RS_MGMT_CMDID                       = 0x0852,
+    WMI_RF_MGMT_CMDID		            = 0x0853,
+    /* Performance monitoring commands */
+    WMI_BF_CTRL_CMDID                       = 0x0862,
+    WMI_NOTIFY_REQ_CMDID                    = 0x0863,
+    WMI_GET_STATUS_CMDID                    = 0x0864,
+    WMI_UNIT_TEST_CMDID                     = 0x0900,
+    WMI_HICCUP_CMDID                        = 0x0901,
+    WMI_FLASH_READ_CMDID                    = 0x0902,
+    WMI_FLASH_WRITE_CMDID                   = 0x0903,
+    WMI_SECURITY_UNIT_TEST_CMDID            = 0x0904,
+
+    WMI_SET_MAC_ADDRESS_CMDID               = 0xF003,
+    WMI_ABORT_SCAN_CMDID                    = 0xF007,
+    WMI_SET_PMK_CMDID                       = 0xF028,
+
+    WMI_SET_PROMISCUOUS_MODE_CMDID          = 0xF041,
+    WMI_GET_PMK_CMDID                       = 0xF048,
+    WMI_SET_PASSPHRASE_CMDID                = 0xF049,
+    WMI_SEND_ASSOC_RES_CMDID                = 0xF04a,
+    WMI_SET_ASSOC_REQ_RELAY_CMDID           = 0xF04b,
+    WMI_EAPOL_TX_CMDID                      = 0xF04c,
+    WMI_MAC_ADDR_REQ_CMDID                  = 0xF04d,
+    WMI_FW_VER_CMDID 		            = 0xF04e,
+} WMI_COMMAND_ID;
+
+
+
+/*******************************************************************************************************************
+ *                                              Commands data structures
+ *******************************************************************************************************************/
+
+/*
+ * Frame Types
+ */
+ enum wmi_mgmt_frame_type_e {
+    WMI_FRAME_BEACON        =   0,
+    WMI_FRAME_PROBE_REQ,
+    WMI_FRAME_PROBE_RESP,
+    WMI_FRAME_ASSOC_REQ,
+    WMI_FRAME_ASSOC_RESP,
+    WMI_NUM_MGMT_FRAME
+} ;
+
+/*
+ * WMI_CONNECT_CMDID
+ */
+ enum wmi_network_type_e {
+    INFRA_NETWORK       = 0x01,
+    ADHOC_NETWORK       = 0x02,
+    ADHOC_CREATOR       = 0x04,
+    AP_NETWORK          = 0x10,
+    P2P_NETWORK         = 0x20,
+    WBE_NETWORK         = 0x40,
+} ;
+
+ enum wmi_dot11_auth_mode_e {
+    OPEN_AUTH           = 0x01,
+    SHARED_AUTH         = 0x02,
+    LEAP_AUTH           = 0x04,
+    WSC_AUTH            = 0x08
+} ;
+
+ enum wmi_auth_mode_e {
+    NONE_AUTH           = 0x01,
+    WPA_AUTH            = 0x02,
+    WPA2_AUTH           = 0x04,
+    WPA_PSK_AUTH        = 0x08,
+    WPA2_PSK_AUTH       = 0x10,
+    WPA_AUTH_CCKM       = 0x20,
+    WPA2_AUTH_CCKM      = 0x40,
+} ;
+
+ enum wmi_crypto_type_e {
+    NONE_CRYPT          = 0x01,
+    WEP_CRYPT           = 0x02,
+    TKIP_CRYPT          = 0x04,
+    AES_CRYPT           = 0x08,
+    AES_GCMP_CRYPT      = 0x20
+} ;
+
+
+ enum wmi_connect_ctrl_flag_bits_e {
+    CONNECT_ASSOC_POLICY_USER           = 0x0001,
+    CONNECT_SEND_REASSOC                = 0x0002,
+    CONNECT_IGNORE_WPAx_GROUP_CIPHER    = 0x0004,
+    CONNECT_PROFILE_MATCH_DONE          = 0x0008,
+    CONNECT_IGNORE_AAC_BEACON           = 0x0010,
+    CONNECT_CSA_FOLLOW_BSS              = 0x0020,
+    CONNECT_DO_WPA_OFFLOAD              = 0x0040,
+    CONNECT_DO_NOT_DEAUTH               = 0x0080,
+} ;
+
+#define WMI_MAX_SSID_LEN    32
+
+ typedef PREPACK struct  {
+    U08 networkType;
+    U08 dot11AuthMode;
+    U08 authMode;
+    U08 pairwiseCryptoType;
+    U08 pairwiseCryptoLen;
+    U08 groupCryptoType;
+    U08 groupCryptoLen;
+    U08 ssidLength;
+    U08 ssid[WMI_MAX_SSID_LEN];
+    U16 channel;
+    U08 bssid[WMI_MAC_LEN];
+    U32 ctrl_flags;
+    U08 destMacAddr[WMI_MAC_LEN];
+    U16 reserved;
+}  POSTPACK WMI_CONNECT_CMD;
+
+
+/*
+ * WMI_RECONNECT_CMDID
+ */
+ typedef PREPACK struct  {
+    U16 channel;                    /* hint */
+    U08 bssid[WMI_MAC_LEN];         /* mandatory if set */
+} POSTPACK WMI_RECONNECT_CMD;
+
+
+/*
+ * WMI_SET_PMK_CMDID
+ */
+
+#define WMI_MIN_KEY_INDEX   0
+#define WMI_MAX_KEY_INDEX   3
+#define WMI_MAX_KEY_LEN     32
+#define WMI_PASSPHRASE_LEN  64
+#define WMI_PMK_LEN     	32
+
+typedef PREPACK struct   {
+    U08 pmk[WMI_PMK_LEN];
+} POSTPACK WMI_SET_PMK_CMD;
+
+
+/*
+ * WMI_SET_PASSPHRASE_CMDID
+ */
+ typedef PREPACK struct  {
+    U08 ssid[WMI_MAX_SSID_LEN];
+    U08 passphrase[WMI_PASSPHRASE_LEN];
+    U08 ssid_len;
+    U08 passphrase_len;
+} POSTPACK WMI_SET_PASSPHRASE_CMD;
+
+/*
+ * WMI_ADD_CIPHER_KEY_CMDID
+ */
+enum wmi_connect_key_usage_e {
+    PAIRWISE_USAGE      = 0x00,
+    GROUP_USAGE         = 0x01,
+    TX_USAGE            = 0x02,     /* default Tx Key - Static WEP only */
+} ;
+
+ typedef PREPACK struct  {
+    U08     keyIndex;
+    U08     keyType;
+    U08     keyUsage;           /* wmi_connect_key_usage_e */
+    U08     keyLength;
+    U08     keyRSC[8];          /* key replay sequence counter */
+    U08     key[WMI_MAX_KEY_LEN];
+    U08     key_op_ctrl;       /* Additional Key Control information */
+    U08     key_macaddr[WMI_MAC_LEN];
+} POSTPACK WMI_ADD_CIPHER_KEY_CMD;
+
+/*
+ * WMI_DELETE_CIPHER_KEY_CMDID
+ */
+ typedef PREPACK struct  {
+    U08     keyIndex;
+    U08     key_macaddr[WMI_MAC_LEN];
+} POSTPACK WMI_DELETE_CIPHER_KEY_CMD;
+
+
+/*
+ * WMI_START_SCAN_CMD
+ */
+ enum wmi_scan_type_e {
+    WMI_LONG_SCAN  = 0,
+    WMI_SHORT_SCAN = 1,
+	WMI_PBC_SCAN   = 2
+} ;
+
+ typedef PREPACK struct  {
+    S32	forceFgScan;
+    S32	isLegacy;               /* For Legacy Cisco AP compatibility */
+    U32	homeDwellTime;          /* Maximum duration in the home channel(milliseconds) */
+    U32	forceScanInterval;      /* Time interval between scans (milliseconds)*/
+    U08	scanType;               /* wmi_scan_type_e */
+    U08	numChannels;            /* how many channels follow */
+    U16	channelList[4];         /* channels in Mhz */
+} POSTPACK WMI_START_SCAN_CMD;
+
+/*
+ * WMI_SET_PROBED_SSID_CMDID
+ */
+#define MAX_PROBED_SSID_INDEX   15
+
+ enum wmi_ssid_flag_e {
+    DISABLE_SSID_FLAG  = 0,                  /* disables entry */
+    SPECIFIC_SSID_FLAG = 0x01,               /* probes specified ssid */
+    ANY_SSID_FLAG      = 0x02,               /* probes for any ssid */
+} ;
+
+ typedef PREPACK struct  {
+    U08     entryIndex;                     /* 0 to MAX_PROBED_SSID_INDEX */
+    U08     flag;                           /* wmi_ssid_flag_e */
+    U08     ssidLength;
+    U08     ssid[WMI_MAX_SSID_LEN];
+} POSTPACK WMI_PROBED_SSID_CMD;
+
+
+/*
+ * Add Application specified IE to a management frame
+ */
+#define WMI_MAX_IE_LEN  255
+
+#ifdef _WINDOWS
+#pragma warning( disable : 4200 ) //suppress warning
+#endif
+typedef PREPACK struct  {
+    U08 mgmtFrmType;  /* one of wmi_mgmt_frame_type_e */
+    U08 ieLen;    /* Length  of the IE that should be added to the MGMT frame */
+    U08 ieInfo[EMPTY_ARRAY_SIZE];
+} POSTPACK WMI_SET_APPIE_CMD;
+
+
+typedef PREPACK struct {
+	U08  destMacAddr[WMI_MAC_LEN];
+	U16 range;
+} POSTPACK WMI_PXMT_RANGE_CFG_CMD;
+
+typedef PREPACK struct {
+	S08 snr2range_arr[WMI_PROX_RANGE_NUM-1];
+} POSTPACK WMI_PXMT_SNR2_RANGE_CFG_CMD;
+
+/*
+ * WMI_RF_MGMT_CMDID
+ */
+typedef enum wmi_rf_mgmt_type_e {
+    WMI_RF_MGMT_W_DISABLE	= 0x0,
+    WMI_RF_MGMT_W_ENABLE	= 0x1,
+    WMI_RF_MGMT_GET_STATUS	= 0x2
+} WMI_RF_MGMT_TYPE;
+
+ typedef PREPACK struct  {
+	U32	rf_mgmt_type;
+} POSTPACK WMI_RF_MGMT_CMD;
+
+
+/*
+ * WMI_SET_SSID_CMDID
+ */
+ typedef PREPACK struct  {
+    U32	ssid_len;
+    U08	ssid[WMI_MAX_SSID_LEN];
+} POSTPACK WMI_SET_SSID_CMD;
+
+/*
+ * WMI_SET_PCP_CHANNEL_CMDID
+ */
+ typedef PREPACK struct  {
+    U08	channel_index;
+    U08	reserved[3];
+} POSTPACK WMI_SET_PCP_CHANNEL_CMD;
+
+
+/*
+ * WMI_BCON_CTRL_CMDID
+ */
+ typedef PREPACK struct  {
+    U16	bcon_interval;
+    U16	frag_num;
+    U32	ss_mask_low;
+    U32	ss_mask_high;
+    U16	network_type;
+    U08	disable_sec_offload;
+    U08	disable_sec;
+} POSTPACK WMI_BCON_CTRL_CMD;
+
+/*
+ * WMI_SW_TX_REQ_CMDID
+ */
+typedef PREPACK struct  {
+   U08	destMacAddr[WMI_MAC_LEN];
+   U16  length;
+} POSTPACK WMI_SW_TX_REQ_CMD;
+
+/*
+ * WMI_VRING_CFG_CMDID
+ */
+
+ typedef PREPACK struct  {
+    U32	ring_mem_base_l;
+    U16	ring_mem_base_h;
+    U16	reserved0;
+    U16	ring_size;
+    U16	max_mpdu_size;
+} POSTPACK wmi_sw_ring_cfg_s;
+
+
+
+enum wmi_vring_cfg_schd_params_priority_e {
+	REGULAR = 0x0,
+	HIGH = 0x1,
+};
+
+typedef PREPACK struct  {
+    U16	priority;
+    U16	timeslot_us;
+} POSTPACK wmi_vring_cfg_schd_s;
+
+enum wmi_vring_cfg_encap_trans_type_e {
+	ENC_TYPE_802_3 = 0x0,
+	ENC_TYPE_NATIVE_WIFI = 0x1
+};
+
+enum wmi_vring_cfg_ds_cfg_e {
+	DS_PBSS_MODE = 0x0,
+	DS_STA_MODE = 0x1,
+	DS_AP_MODE = 0x2,
+	DS_ADDR4_MODE = 0x3
+};
+
+enum wmi_vring_cfg_nwifi_ds_trans_type_e {
+	NWIFI_TX_NO_TRANS_MODE = 0x0,
+	NWIFI_TX_AP2PBSS_TRANS_MODE = 0x1,
+	NWIFI_TX_STA2PBSS_TRANS_MODE = 0x2
+};
+
+typedef PREPACK struct  {
+    wmi_sw_ring_cfg_s	tx_sw_ring;
+    U08	ringid;                         /* 0-23 vrings */
+
+	#define CIDXTID_CID_POS 0
+	#define CIDXTID_CID_LEN 4
+	#define CIDXTID_CID_MSK 0xF
+	#define CIDXTID_TID_POS 4
+	#define CIDXTID_TID_LEN 4
+	#define CIDXTID_TID_MSK 0xF0
+	U08 cidxtid_byte;
+
+    U08	encap_trans_type;
+    U08	ds_cfg;                         /* 802.3 DS cfg */
+    U08	nwifi_ds_trans_type;
+
+	#define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS 0
+	#define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN 1
+	#define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK 0x1
+	#define VRING_CFG_MAC_CTRL_AGGR_EN_POS 1
+	#define VRING_CFG_MAC_CTRL_AGGR_EN_LEN 1
+	#define VRING_CFG_MAC_CTRL_AGGR_EN_MSK 0x2
+    U08	mac_ctrl_byte;
+
+	#define VRING_CFG_TO_RESOLUTION_VALUE_POS 0
+	#define VRING_CFG_TO_RESOLUTION_VALUE_LEN 6
+	#define VRING_CFG_TO_RESOLUTION_VALUE_MSK 0x3F
+    U08	to_resolution_byte;
+    U08	agg_max_wsize;
+    wmi_vring_cfg_schd_s	schd_params;
+} POSTPACK wmi_vring_cfg_s;
+
+
+enum wmi_vring_cfg_cmd_action_e {
+	ADD_VRING = 0x0,
+	MODIFY_VRING = 0x1,
+	DELETE_VRING = 0x2
+};
+
+ typedef PREPACK struct  {
+    U32	action;
+    wmi_vring_cfg_s	vring_cfg;
+} POSTPACK WMI_VRING_CFG_CMD;
+
+
+/*
+ * WMI_VRING_BA_EN_CMDID
+ */
+ typedef PREPACK struct  {
+    U08	ringid;
+    U08	agg_max_wsize;
+    U16	ba_timeout;
+} POSTPACK WMI_VRING_BA_EN_CMD;
+
+
+/*
+ * WMI_VRING_BA_DIS_CMDID
+ */
+ typedef PREPACK struct  {
+    U08	ringid;
+    U08	reserved0;
+    U16	reason;
+} POSTPACK WMI_VRING_BA_DIS_CMD;
+
+/*
+ * WMI_START_SCAN_CMDID
+ */
+enum wmi_scan_ctrl_cmd_scan_mode_e {
+	ACTIVE_SCAN = 0x0,
+	PASSIV_SCAN = 0x1,
+	NO_SCAN = 0x2
+};
+
+ typedef PREPACK struct  {
+    U16	in_channel_interval;
+    U16	num_of_channels;
+    U16	channel_list;
+    U16	scan_param;
+    U32	scan_mode;
+} POSTPACK WMI_SCAN_CTRL_CMD;
+
+/*
+ * WMI_NOTIFY_REQ_CMDID
+ */
+ typedef PREPACK struct  {
+	U32 cid;
+	U32 interval_usec;
+} POSTPACK WMI_NOTIFY_REQ_CMD;
+
+/*
+ * WMI_CFG_RX_CHAIN_CMDID
+ */
+enum wmi_sniffer_cfg_mode_e {
+	SNIFFER_OFF = 0x0,
+	SNIFFER_ON = 0x1
+};
+enum wmi_sniffer_cfg_phy_info_mode_e {
+	SNIFFER_PHY_INFO_DISABLED = 0x0,
+	SNIFFER_PHY_INFO_ENABLED = 0x1
+};
+enum wmi_sniffer_cfg_phy_support_e {
+	SNIFFER_CP = 0x0,
+	SNIFFER_DP = 0x1,
+	SNIFFER_BOTH_PHYS = 0x2
+};
+ typedef PREPACK struct  {
+    U32	mode;
+    U32	phy_info_mode;
+    U32	phy_support;
+    U32	channel_id;
+} POSTPACK wmi_sniffer_cfg_s;
+
+enum wmi_cfg_rx_chain_cmd_action_e {
+	ADD_RX_CHAIN = 0x0,
+	DELETE_RX_CHAIN = 0x1
+};
+enum wmi_cfg_rx_chain_cmd_decap_trans_type_e {
+	DECAP_TYPE_802_3 = 0x0,
+	DECAP_TYPE_NATIVE_WIFI = 0x1
+};
+enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type_e {
+	NWIFI_RX_NO_TRANS_MODE = 0x0,
+	NWIFI_RX_PBSS2AP_TRANS_MODE = 0x1,
+	NWIFI_RX_PBSS2STA_TRANS_MODE = 0x2
+};
+
+ typedef PREPACK struct  {
+    U32	action;
+    wmi_sw_ring_cfg_s	rx_sw_ring;
+    U08	mid;
+    U08	decap_trans_type;
+
+	#define CFG_RX_CHAIN_CMD_L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS 0
+	#define CFG_RX_CHAIN_CMD_L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN 1
+	#define CFG_RX_CHAIN_CMD_L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK 0x1
+    U08	l2_802_3_offload_ctrl_byte;
+
+	#define CFG_RX_CHAIN_CMD_L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS 0
+	#define CFG_RX_CHAIN_CMD_L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN 1
+	#define CFG_RX_CHAIN_CMD_L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK 0x1
+	#define CFG_RX_CHAIN_CMD_L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS 1
+	#define CFG_RX_CHAIN_CMD_L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN 1
+	#define CFG_RX_CHAIN_CMD_L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK 0x2
+    U08 l2_nwifi_offload_ctrl_byte;
+
+    U08	vlan_id;
+    U08	nwifi_ds_trans_type;
+
+	#define CFG_RX_CHAIN_CMD_L3_L4_CTRL_IPV4_CHECKSUM_EN_POS 0
+	#define CFG_RX_CHAIN_CMD_L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN 1
+	#define CFG_RX_CHAIN_CMD_L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK 0x1
+	#define CFG_RX_CHAIN_CMD_L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS 1
+	#define CFG_RX_CHAIN_CMD_L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN 1
+	#define CFG_RX_CHAIN_CMD_L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK 0x2
+    U08	l3_l4_ctrl_byte;
+
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS 0
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN 1
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK 0x1
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_WB_THRSH_POS 1
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_WB_THRSH_LEN 1
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_WB_THRSH_MSK 0x2
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_ITR_THRSH_POS 2
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_ITR_THRSH_LEN 1
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_ITR_THRSH_MSK 0x4
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_HOST_THRSH_POS 3
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_HOST_THRSH_LEN 1
+	#define CFG_RX_CHAIN_CMD_RING_CTRL_OVERRIDE_HOST_THRSH_MSK 0x8
+    U08	ring_ctrl;
+
+    U16	prefetch_thrsh;
+    U16	wb_thrsh;
+    U32	itr_value;
+    U16	host_thrsh;
+    U16	reserved;
+    wmi_sniffer_cfg_s	sniffer_cfg;
+} POSTPACK WMI_CFG_RX_CHAIN_CMD;
+
+/*
+ * WMI_RCP_ADDBA_RESP_CMDID
+ */
+ typedef PREPACK struct  {
+
+	#define CIDXTID_CID_POS 0
+	#define CIDXTID_CID_LEN 4
+	#define CIDXTID_CID_MSK 0xF
+	#define CIDXTID_TID_POS 4
+	#define CIDXTID_TID_LEN 4
+	#define CIDXTID_TID_MSK 0xF0
+	U08 cidxtid_byte;
+
+    U08	dialog_token;
+    U16	status_code;
+    U16	ba_param_set;                   /* ieee80211_ba_parameterset field to send */
+    U16	ba_timeout;
+} POSTPACK WMI_RCP_ADDBA_RESP_CMD;
+
+/*
+ * WMI_RCP_DELBA_CMDID
+ */
+ typedef PREPACK struct  {
+
+	#define CIDXTID_CID_POS 0
+	#define CIDXTID_CID_LEN 4
+	#define CIDXTID_CID_MSK 0xF
+	#define CIDXTID_TID_POS 4
+	#define CIDXTID_TID_LEN 4
+	#define CIDXTID_TID_MSK 0xF0
+	U08 cidxtid_byte;
+
+    U08	rsvd;
+    U16	reason;
+} POSTPACK WMI_RCP_DELBA_CMD;
+
+/*
+ * WMI_RCP_ADDBA_REQ_CMDID
+ */
+ typedef PREPACK struct  {
+
+	#define CIDXTID_CID_POS 0
+	#define CIDXTID_CID_LEN 4
+	#define CIDXTID_CID_MSK 0xF
+	#define CIDXTID_TID_POS 4
+	#define CIDXTID_TID_LEN 4
+	#define CIDXTID_TID_MSK 0xF0
+	U08 cidxtid_byte;
+
+    U08	dialog_token;
+    U16	ba_param_set;                   /* ieee80211_ba_parameterset field as it received */
+    U16	ba_timeout;
+    U16	ba_seq_ctrl;                    /* ieee80211_ba_seqstrl field as it received */
+} POSTPACK WMI_RCP_ADDBA_REQ_CMD;
+
+/**
+ *  WMI_SET_MAC_ADDRESS_CMDID
+ */
+typedef PREPACK struct  {
+    U08 macaddr[WMI_MAC_LEN];
+	U16 reserved;
+} POSTPACK WMI_SET_MAC_ADDRESS_CMD;
+
+
+/*
+* WMI_EAPOL_TX_CMDID
+*/
+ typedef PREPACK struct  {
+	U08 dst_mac[WMI_MAC_LEN];
+	U16 eapol_len;
+	U08 eapol[EMPTY_ARRAY_SIZE];
+} POSTPACK WMI_EAPOL_TX_CMD;
+
+/*
+* WMI_ECHO_CMDID
+*/
+typedef PREPACK struct {
+    U32	value;
+} POSTPACK WMI_ECHO_CMD;
+
+/**
+ * **********************************************************************************************************************************
+ *                                                          WMI Events
+ * **********************************************************************************************************************************
+ */
+
+/*
+ * List of Events (target to host)
+ */
+enum WMI_EVENT_ID {
+    WMI_IMM_RSP_EVENTID			= 0x0000,
+    WMI_READY_EVENTID                   = 0x1001,
+    WMI_CONNECT_EVENTID                 = 0x1002,
+    WMI_DISCONNECT_EVENTID              = 0x1003,
+    WMI_SCAN_COMPLETE_EVENTID           = 0x100a,
+    WMI_REPORT_STATISTICS_EVENTID       = 0x100b,
+    WMI_RD_MEM_RSP_EVENTID 		= 0x1800,
+    WMI_FW_READY_EVENTID                = 0x1801,
+    WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID 	= 0x0200,
+    WMI_ECHO_RSP_EVENTID		= 0x1803,
+    WMI_CONFIG_MAC_DONE_EVENTID         = 0x1805,
+    WMI_CONFIG_PHY_DEBUG_DONE_EVENTID   = 0x1806,
+    WMI_ADD_STATION_DONE_EVENTID	= 0x1807,
+    WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID  = 0x1808,
+    WMI_PHY_GET_STATISTICS_EVENTID      = 0x1809,
+    WMI_FS_TUNE_DONE_EVENTID            = 0x180A,
+    WMI_CORR_MEASURE_DONE_EVENTID       = 0x180B,
+    WMI_TEMP_SENSE_DONE_EVENTID         = 0x180E,
+    WMI_DC_CALIB_DONE_EVENTID           = 0x180F,
+    WMI_IQ_TX_CALIB_DONE_EVENTID        = 0x1811,
+    WMI_IQ_RX_CALIB_DONE_EVENTID        = 0x1812,
+    WMI_SET_WORK_MODE_DONE_EVENTID      = 0x1815,
+    WMI_LO_LEAKAGE_CALIB_DONE_EVENTID   = 0x1816,
+    WMI_MARLON_R_ACTIVATE_DONE_EVENTID  = 0x1817,
+    WMI_MARLON_R_READ_DONE_EVENTID      = 0x1818,
+    WMI_MARLON_R_WRITE_DONE_EVENTID     = 0x1819,
+    WMI_MARLON_R_TXRX_SEL_DONE_EVENTID  = 0x181A,
+    WMI_SILENT_RSSI_CALIB_DONE_EVENTID  = 0x181D,
+
+    WMI_CFG_RX_CHAIN_DONE_EVENTID	= 0x1820,
+    WMI_VRING_CFG_DONE_EVENTID		= 0x1821,
+    WMI_RX_ON_EVENTID			= 0x1822,
+    WMI_BA_STATUS_EVENTID		= 0x1823,
+    WMI_RCP_ADDBA_REQ_EVENTID		= 0x1824,
+    WMI_ADDBA_RESP_SENT_EVENTID		= 0x1825,
+    WMI_DELBA_EVENTID			= 0x1826,
+    WMI_GET_SSID_EVENTID		= 0x1828,
+    WMI_GET_PCP_CHANNEL_EVENTID        	= 0x182a,
+    WMI_SW_TX_COMPLETE_EVENTID		= 0x182b,
+
+    WMI_READ_MAC_RXQ_EVENTID		= 0x1830,
+    WMI_READ_MAC_TXQ_EVENTID		= 0x1831,
+    WMI_WRITE_MAC_RXQ_EVENTID		= 0x1832,
+    WMI_WRITE_MAC_TXQ_EVENTID		= 0x1833,
+    WMI_WRITE_MAC_XQ_FIELD_EVENTID	= 0x1834,
+
+    WMI_BEAFORMING_MGMT_DONE_EVENTID    = 0x1836,
+    WMI_BF_TXSS_MGMT_DONE_EVENTID       = 0x1837,
+    WMI_BF_RXSS_MGMT_DONE_EVENTID       = 0x1839,
+    WMI_RS_MGMT_DONE_EVENTID            = 0x1852,
+    WMI_RF_MGMT_STATUS_EVENTID	        = 0x1853,
+    WMI_BF_SM_MGMT_DONE_EVENTID         = 0x1838,
+	WMI_RX_MGMT_PACKET_EVENTID	= 0x1840,
+
+    /* Performance monitoring events */
+    WMI_DATA_PORT_OPEN_EVENTID		= 0x1860,
+    WMI_WBE_LINKDOWN_EVENTID		= 0x1861,
+
+    WMI_BF_CTRL_DONE_EVENTID            = 0x1862,
+    WMI_NOTIFY_REQ_DONE_EVENTID         = 0x1863,
+    WMI_GET_STATUS_DONE_EVENTID         = 0x1864,
+
+    WMI_UNIT_TEST_EVENTID               = 0x1900,
+    WMI_FLASH_READ_DONE_EVENTID         = 0x1902,
+    WMI_FLASH_WRITE_DONE_EVENTID        = 0x1903,
+
+
+    WMI_SET_CHANNEL_EVENTID       	= 0x9000,
+    WMI_ASSOC_REQ_EVENTID      		= 0x9001,
+    WMI_EAPOL_RX_EVENTID     		= 0x9002,
+    WMI_MAC_ADDR_RESP_EVENTID     	= 0x9003,
+	WMI_FW_VER_EVENTID      	= 0x9004,
+} ;
+
+
+
+/*******************************************************************************************************************
+ *                                              Events data structures
+ *******************************************************************************************************************/
+
+/*
+ * WMI_RF_MGMT_STATUS_EVENTID
+ */
+enum wmi_rf_status_e {
+    WMI_RF_ENABLED        	= 0x0,
+	WMI_RF_DISABLED_HW      = 0x1,
+	WMI_RF_DISABLED_SW      = 0x2,
+	WMI_RF_DISABLED_HW_SW	= 0x3
+};
+
+ typedef PREPACK struct  {
+	U32	rf_status;
+} POSTPACK WMI_RF_MGMT_STATUS_EVENT;
+
+/*
+ * WMI_GET_STATUS_DONE_EVENTID
+ */
+ typedef PREPACK struct  {
+    U32	is_associated;
+    U32	cid;
+    U16 bssid[3];
+    U16	channel;
+    U32	network_type;
+    U32	ssid_len;
+    U08	ssid[WMI_MAX_SSID_LEN];
+	U32	rf_status;
+	U32 is_secured;
+} POSTPACK WMI_GET_STATUS_DONE_EVENT;
+
+
+
+/**
+ * WMI_FW_VER_EVENTID
+ */
+ typedef PREPACK struct  {
+    U08 major;
+    U08 minor;
+    U16 subminor;
+    U16 build;
+} POSTPACK WMI_FW_VER_EVENT;
+
+
+
+/*
+* WMI_MAC_ADDR_RESP_EVENTID
+*/
+ typedef PREPACK struct  {
+	U08 mac_addr[WMI_MAC_LEN];
+    U08 auth_mode;
+    U08 crypt_mode;
+    U32 offload_mode; // 0/1
+} POSTPACK WMI_MAC_ADDR_RESP_EVENT;
+
+
+/*
+* WMI_EAPOL_RX_EVENTID
+*/
+ typedef PREPACK struct  {
+	U08 src_mac[WMI_MAC_LEN];
+	U16 eapol_len;
+	U08 eapol[EMPTY_ARRAY_SIZE];
+} POSTPACK WMI_EAPOL_RX_EVENT;
+
+
+/*
+* WMI_READY_EVENTID
+*/
+ typedef PREPACK struct  {
+    U32	sw_version;
+    U32	abi_version;
+    U08	macaddr[WMI_MAC_LEN];
+    U08	phyCapability;              /* wmi_phy_capability_e */
+    U08 reserved;
+    U32 extend_mem_addr;
+    U32 extend_mem_size;
+} POSTPACK WMI_READY_EVENT;
+
+
+/*
+ * WMI_NOTIFY_REQ_DONE_EVENTID
+ */
+ typedef PREPACK struct  {
+	U32 status;
+	U32 tsf_low;
+	U32 tsf_high;
+	U32 snr_val;
+	U32 tx_tpt;
+	U32 tx_goodput;
+	U32 rx_goodput;
+	U16 bf_mcs;
+	U16 my_rx_sector;
+	U16 my_tx_sector;
+	U16 other_rx_sector;
+	U16 other_tx_sector;
+	U16 range;
+} POSTPACK WMI_NOTIFY_REQ_DONE_EVENT;
+
+/*
+ * WMI_CONNECT_EVENTID
+ */
+ typedef PREPACK struct  {
+    U16	channel;
+    U08	bssid[WMI_MAC_LEN];
+    U16	listenInterval;
+    U16	beaconInterval;
+    U32	networkType;
+    U08	beaconIeLen;
+    U08	assocReqLen;
+    U08	assocRespLen;
+    U08	cid;
+    U08	reserved0;
+    U16	reserved1;
+    U08	assocInfo[EMPTY_ARRAY_SIZE];
+} POSTPACK WMI_CONNECT_EVENT;
+
+
+
+/*
+ * WMI_DISCONNECT_EVENTID
+ */
+enum wmi_disconnect_reason_e {
+    NO_NETWORK_AVAIL        = 0x01,
+    LOST_LINK               = 0x02,     /* bmiss */
+    DISCONNECT_CMD          = 0x03,
+    BSS_DISCONNECTED        = 0x04,
+    AUTH_FAILED             = 0x05,
+    ASSOC_FAILED            = 0x06,
+    NO_RESOURCES_AVAIL      = 0x07,
+    CSERV_DISCONNECT        = 0x08,
+    INVALID_PROFILE         = 0x0a,
+    DOT11H_CHANNEL_SWITCH   = 0x0b,
+    PROFILE_MISMATCH        = 0x0c,
+    CONNECTION_EVICTED      = 0x0d,
+    IBSS_MERGE              = 0xe
+};
+
+ typedef PREPACK struct  {
+    U16	protocolReasonStatus;  /* reason code, see 802.11 spec. */
+    U08	bssid[WMI_MAC_LEN];    /* set if known */
+    U08	disconnectReason ;      /* see wmi_disconnect_reason_e */
+    U08	assocRespLen;
+    U08	assocInfo[EMPTY_ARRAY_SIZE];
+} POSTPACK WMI_DISCONNECT_EVENT;
+
+
+/*
+ * WMI_SCAN_COMPLETE_EVENTID
+ */
+ typedef PREPACK struct  {
+    U32 status;
+} POSTPACK WMI_SCAN_COMPLETE_EVENT;
+
+/*
+ * WMI_BA_STATUS_EVENTID
+ */
+enum wmi_vring_ba_status_e {
+	AGREED = 0x0,
+	NON_AGREED = 0x1,
+} ;
+
+ typedef PREPACK struct  {
+    U16	status;
+    U16	reserved0;
+    U08	ringid;
+    U08	agg_wsize;
+    U16	ba_timeout;
+} POSTPACK WMI_VRING_BA_STATUS_EVENT;
+
+
+/*
+ * WMI_DELBA_EVENTID
+ */
+ typedef PREPACK struct  {
+
+	#define CIDXTID_CID_POS 0
+	#define CIDXTID_CID_LEN 4
+	#define CIDXTID_CID_MSK 0xF
+	#define CIDXTID_TID_POS 4
+	#define CIDXTID_TID_LEN 4
+	#define CIDXTID_TID_MSK 0xF0
+	U08 cidxtid_byte;
+
+    U08	from_initiator;
+    U16	reason;
+} POSTPACK WMI_DELBA_EVENT;
+
+/*
+ * WMI_VRING_CFG_DONE_EVENTID
+ */
+enum wmi_vring_cfg_status {
+	VRING_CFG_SUCCESS = 0x0,
+	VRING_CFG_FAILURE = 0x1
+};
+
+ typedef PREPACK struct  {
+    U08	ringid;
+    U08	status;
+    U16	reserved;
+    U32	tx_vring_tail_ptr;
+} POSTPACK WMI_VRING_CFG_DONE_EVENT;
+
+
+/*
+ * WMI_ADDBA_RESP_SENT_EVENTID
+ */
+enum wmi_rcp_addba_resp_sent_event_status_e {
+	SUCCESS = 0x0,
+	FAIL = 0x1
+};
+
+ typedef PREPACK struct  {
+
+	#define CIDXTID_CID_POS 0
+	#define CIDXTID_CID_LEN 4
+	#define CIDXTID_CID_MSK 0xF
+	#define CIDXTID_TID_POS 4
+	#define CIDXTID_TID_LEN 4
+	#define CIDXTID_TID_MSK 0xF0
+	U08 cidxtid_byte;
+
+    U08	rsvd;
+    U16	status;
+} POSTPACK WMI_RCP_ADDBA_RESP_SENT_EVENT;
+
+/*
+ * WMI_RCP_ADDBA_REQ_EVENTID
+ */
+ typedef PREPACK struct  {
+
+	#define CIDXTID_CID_POS 0
+	#define CIDXTID_CID_LEN 4
+	#define CIDXTID_CID_MSK 0xF
+	#define CIDXTID_TID_POS 4
+	#define CIDXTID_TID_LEN 4
+	#define CIDXTID_TID_MSK 0xF0
+	U08 cidxtid_byte;
+
+    U08	dialog_token;
+    U16	ba_param_set;                   /* ieee80211_ba_parameterset field as it received */
+    U16	ba_timeout;
+    U16	ba_seq_ctrl;                    /* ieee80211_ba_seqstrl field as it received */
+} POSTPACK WMI_RCP_ADDBA_REQ_EVENT;
+
+/*
+ * WMI_CFG_RX_CHAIN_DONE_EVENTID
+ */
+enum wmi_cfg_rx_chain_done_event_status_e {
+	CFG_RX_CHAIN_SUCCESS = 0x1,
+};
+
+ typedef PREPACK struct  {
+    U32	rx_ring_tail_ptr;               /* Rx V-Ring Tail pointer */
+    U32	status;
+} POSTPACK WMI_CFG_RX_CHAIN_DONE_EVENT;
+
+
+/*
+ * WMI_WBE_LINKDOWN_EVENTID
+ */
+enum wmi_wbe_link_down_event_reason_e {
+	USER_REQUEST = 0x0,
+	RX_DISASSOC = 0x1,
+	BAD_PHY_LINK = 0x2,
+};
+
+ typedef PREPACK struct  {
+    U08	cid;
+    U08	reserved[3];
+    U32	reason;
+} POSTPACK WMI_WBE_LINK_DOWN_EVENT;
+
+/*
+ * WMI_DATA_PORT_OPEN_EVENTID
+ */
+ typedef PREPACK struct  {
+    U08	cid;
+    U08	reserved0[3];
+} POSTPACK WMI_DATA_PORT_OPEN_EVENT;
+
+
+/*
+ * WMI_GET_PCP_CHANNEL_EVENTID
+ */
+ typedef PREPACK struct  {
+    U08	channel_index;
+    U08	reserved[3];
+} POSTPACK WMI_GET_PCP_CHANNEL_EVENT;
+
+/*
+ * WMI_SW_TX_COMPLETE_EVENTID
+ */
+enum wmi_sw_tx_status_e {
+	TX_SW_STATUS_SUCCESS				= 0x0,
+	TX_SW_STATUS_FAILED_NO_RESOURCES	= 0x1,
+	TX_SW_STATUS_FAILED_TX				= 0x2
+};
+
+typedef PREPACK struct  {
+   U08	status;
+   U08	reserved[3];
+} POSTPACK WMI_SW_TX_COMPLETE_EVENT;
+
+/*
+ * WMI_GET_SSID_EVENTID
+ */
+ typedef PREPACK struct  {
+    U32	ssid_len;
+    U08	ssid[WMI_MAX_SSID_LEN];
+} POSTPACK WMI_GET_SSID_EVENT;
+
+/*
+ * WMI_RX_MGMT_PACKET_EVENTID
+ */
+ typedef PREPACK struct  {
+    U08	mcs;
+	S08 snr;
+	U16 range;
+    U16	stype;
+    U16	status;
+    U32	length;
+    U08	qid;                            /* Not resolved when == 0xFFFFFFFF  ==> Broadcast to all MIDS */
+    U08	mid;                            /* Not resolved when == 0xFFFFFFFF  ==> Broadcast to all MIDS */
+    U08	cid;
+    U08	channel;                        /* From Radio MNGR */
+} POSTPACK wmi_rx_mgmt_info_s;
+
+
+typedef PREPACK struct  {
+    wmi_rx_mgmt_info_s	info;
+    U32	payload;//[EMPTY_ARRAY_SIZE];
+} POSTPACK WMI_RX_MGMT_PACKET_EVENT;
+
+/*
+ * WMI_ECHO_RSP_EVENTID
+ */
+typedef PREPACK struct {
+    U32	echoed_value;
+} POSTPACK WMI_ECHO_EVENT;
+
+
+#if defined(_MSC_VER)           // Microsoft
+#pragma pack (pop, marlon_wmi)  /* restore original alignment from stack */
+#endif
+
+
+#endif /* MARLON_WMI_H_ */
diff --git a/debug-tools/lib/utils/Android.mk b/debug-tools/lib/utils/Android.mk
new file mode 100644
index 0000000..87b5650
--- /dev/null
+++ b/debug-tools/lib/utils/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libwigig_utils
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPPFLAGS := -Wall -lpthread
+
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/../inc \
+	$(LOCAL_PATH)/../inc/linux \
+	$(LOCAL_PATH)/linux
+
+LOCAL_SRC_FILES := $(shell find $(LOCAL_PATH) -name '*.cpp' | sed s:^$(LOCAL_PATH)::g )
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/debug-tools/lib/utils/DebugLogger.cpp b/debug-tools/lib/utils/DebugLogger.cpp
new file mode 100644
index 0000000..003be67
--- /dev/null
+++ b/debug-tools/lib/utils/DebugLogger.cpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "wlct_os.h"
+#include "DebugLogger.h"
+#include "LoggerSupport.h"
+#include "Thread.h"
+
+#ifdef _WINDOWS
+#define TRACING_REGISTRY_PATH _T("Software\\QualcommAtheros\\WIGIG\\Tracing")
+#endif
+
+using namespace std;
+
+CDebugLogger g_Logger(_T("WLCT"));
+
+CDebugLogger *g_pLogger = &g_Logger;
+
+static const int WLCT_MAX_DEBUG_MSG_LEN = 512;
+
+const TCHAR *g_szMessageType[] =
+{
+   _T("ERROR"),
+   _T("WARN"),
+   _T("INFO"),
+   _T("DEBUG"),
+   _T("TRACE"),
+   _T("VERBOSE")
+};
+
+#ifdef _WINDOWS
+void ReadSettingsThread(void *pLogger)
+{
+	LOG_MESSAGE_DEBUG(_T("start running"));
+	CDebugLogger *pDebugLogger = (CDebugLogger*)pLogger;
+	pDebugLogger->m_bExit = false;
+
+	CRegKey regCofig;
+	if ( ERROR_SUCCESS == regCofig.Open(HKEY_LOCAL_MACHINE, TRACING_REGISTRY_PATH, KEY_READ))
+	{
+		// key found, reset settings
+//		pDebugLogger->SetDefaultSettings();
+
+		DWORD dwTraceLevel;
+		if ( ERROR_SUCCESS == regCofig.QueryDWORDValue( _T("TraceLevel"), dwTraceLevel ) )
+		{
+			pDebugLogger->m_eTraceLevel = (COsDebugLogger::E_LOG_LEVEL)dwTraceLevel;
+		}
+
+		DWORD dwLogToFile;
+		if ( ERROR_SUCCESS == regCofig.QueryDWORDValue( _T("LogToFile"), dwLogToFile ) )
+		{
+			TCHAR szPath[MAX_PATH] = { 0 };
+			ULONG ulChars = MAX_PATH;
+			if ( ERROR_SUCCESS == regCofig.QueryStringValue( _T("LogFilePath"), szPath, &ulChars ) )
+			{
+				pDebugLogger->m_sLogFilePath = szPath;
+				//m_bLogToFile   = TRUE;
+			}
+		}
+	}
+
+	// Create an event.
+	pDebugLogger->hNotifyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+	if (pDebugLogger->hNotifyEvent == NULL)
+	{
+		_tprintf(TEXT("Error in CreateEvent (%d).\n"), GetLastError());
+		return;
+	}
+
+	LONG lErrorCode = 0;// regCofig.NotifyChangeKeyValue(FALSE, REG_NOTIFY_CHANGE_LAST_SET, pDebugLogger->hNotifyEvent, TRUE);
+	if (lErrorCode != ERROR_SUCCESS)
+	{
+		//_tprintf(TEXT("Error in RegNotifyChangeKeyValue (%d).\n"), lErrorCode);
+		return;
+	}
+
+	do
+	{
+		if (WaitForSingleObject(pDebugLogger->hNotifyEvent, INFINITE) == WAIT_FAILED)
+		{
+			_tprintf(TEXT("Error in WaitForSingleObject (%d).\n"), GetLastError());
+		}
+
+		DWORD dwTraceLevel;
+		if ( ERROR_SUCCESS == regCofig.QueryDWORDValue( _T("TraceLevel"), dwTraceLevel ) )
+		{
+			pDebugLogger->m_eTraceLevel = (COsDebugLogger::E_LOG_LEVEL)dwTraceLevel;
+		}
+
+	} while (!pDebugLogger->m_bExit);
+
+	CloseHandle(pDebugLogger->hNotifyEvent);
+	regCofig.Close();
+}
+#endif
+
+CDebugLogger::CDebugLogger(const TCHAR *tag, bool logToConsole) :
+  COsDebugLogger(logToConsole)
+{
+	m_sTag = tag;
+	SetDefaultSettings();
+
+// 	ReadTraceSettings( TRACING_REGISTRY_PATH );
+//
+// 	// override settings
+// 	CString sRegKeyPath;
+// 	sRegKeyPath.Format(_T("%s\\%s"), TRACING_REGISTRY_PATH, lpszTag );
+//
+// 	ReadTraceSettings(lpszTag);
+
+	// start the read tread
+#ifdef _WINDOWS
+	m_hThread = (HANDLE)_beginthread(ReadSettingsThread, 0, this);
+#endif
+}
+
+CDebugLogger::~CDebugLogger(void)
+{
+#ifdef _WINDOWS
+	m_bExit = true;
+	SetEvent(hNotifyEvent);
+	if (WaitForSingleObject(m_hThread, 1000) == WAIT_TIMEOUT)
+	{
+		TerminateThread(m_hThread, 1);
+	}
+#endif
+}
+
+void CDebugLogger::SetDefaultSettings(void)
+{
+	m_bLogToFile   = false;
+	m_eTraceLevel = E_LOG_LEVEL_DEBUG;
+	m_sLogFilePath = _T("");
+}
+
+#ifdef _WINDOWS
+void CDebugLogger::ReadTraceSettings( LPCTSTR lpszRegistryPath )
+{
+	CRegKey regCofig;
+	if ( ERROR_SUCCESS == regCofig.Open(HKEY_LOCAL_MACHINE,	lpszRegistryPath, KEY_READ))
+	{
+		// key found, reset settings
+		SetDefaultSettings();
+
+		DWORD dwTraceLevel;
+		if ( ERROR_SUCCESS == regCofig.QueryDWORDValue( _T("TraceLevel"), dwTraceLevel ) )
+		{
+			m_eTraceLevel = (COsDebugLogger::E_LOG_LEVEL)dwTraceLevel;
+		}
+
+		DWORD dwLogToFile;
+		if ( ERROR_SUCCESS == regCofig.QueryDWORDValue( _T("LogToFile"), dwLogToFile ) )
+		{
+			TCHAR szPath[MAX_PATH] = { 0 };
+			ULONG ulChars = MAX_PATH;
+			if ( ERROR_SUCCESS == regCofig.QueryStringValue( _T("LogFilePath"), szPath, &ulChars ) )
+			{
+				m_sLogFilePath = szPath;
+//				m_bLogToFile   = TRUE;
+			}
+		}
+	}
+}
+#endif
+
+void CDebugLogger::LogGlobalDebugMessage(CDebugLogger::E_LOG_LEVEL eTraceLevel,
+  S_LOG_CONTEXT *pCtxt, const TCHAR *fmt, ...)
+{
+  if (!g_pLogger)
+  {
+    return;
+  }
+
+  va_list args;
+  va_start(args, fmt);
+  g_pLogger->LogDebugMessageV(eTraceLevel, pCtxt, fmt, args);
+  va_end(args);
+}
+
+DWORD CDebugLogger::GetGlobalTraceLevel()
+{
+	if (!g_pLogger)
+	{
+		return 0;
+	}
+
+	return g_pLogger->GetGlobalTraceLevel();
+}
+
+void CDebugLogger::LogDebugMessage( CDebugLogger::E_LOG_LEVEL eTraceLevel,
+  S_LOG_CONTEXT *pCtxt, const TCHAR *fmt, ...)
+{
+  va_list args;
+
+  if (eTraceLevel > m_eTraceLevel)
+  {
+    return;
+  }
+
+  va_start(args, fmt);
+  LogDebugMessageV(eTraceLevel, pCtxt, fmt, args);
+  va_end(args);
+}
+
+void CDebugLogger::LogDebugMessageV( CDebugLogger::E_LOG_LEVEL eTraceLevel,
+  S_LOG_CONTEXT *pCtxt, const TCHAR *fmt, va_list args)
+{
+  TCHAR msg[WLCT_MAX_DEBUG_MSG_LEN] = {0};
+  int bytes_written = 0;
+
+	if (eTraceLevel > m_eTraceLevel)
+	{
+		return;
+	}
+
+  bytes_written = _stprintf_s(msg, WLCT_MAX_DEBUG_MSG_LEN,
+	_T("%s(%d): %s: [%s]; pid:%d; tid:%d; err=%d; f=[%s]; "),
+     (pCtxt ? pCtxt->funcName : _T("unknown")),
+    (pCtxt ? pCtxt->line : 0), m_sTag.c_str(), g_szMessageType[eTraceLevel],
+    CWlctThread::getCurrentProcessID(), CWlctThread::getCurrentThreadID(),
+    WlctGetLastError(), (pCtxt ? pCtxt->funcName : _T("unknown")));
+
+  bytes_written += _vsntprintf(msg + bytes_written,
+    WLCT_MAX_DEBUG_MSG_LEN - bytes_written, fmt, args);
+
+  _stprintf_s(msg + bytes_written, WLCT_MAX_DEBUG_MSG_LEN - bytes_written, _T("\n"));
+
+  print(msg);
+
+
+  if (m_bLogToFile)
+  {
+    FILE *fp = 0;
+    fp = _tfopen(m_sLogFilePath.c_str(), _T("a"));
+    if (NULL != fp)
+    {
+      fprintf(fp, "%s", msg);
+      fclose(fp);
+    }
+  }
+}
+
diff --git a/debug-tools/lib/utils/DebugLogger.h b/debug-tools/lib/utils/DebugLogger.h
new file mode 100644
index 0000000..efcff11
--- /dev/null
+++ b/debug-tools/lib/utils/DebugLogger.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "OsDebugLogger.h"
+
+class WLCT_API CDebugLogger : public COsDebugLogger
+{
+public:
+	struct WLCT_API S_LOG_CONTEXT
+	{
+		const TCHAR *funcName;
+		const TCHAR *fileName;
+		DWORD       line;
+	};
+
+	CDebugLogger(const TCHAR *tag, bool logToConsole = false);
+	~CDebugLogger(void);
+	COsDebugLogger::E_LOG_LEVEL GetTraceLevel() const
+	{
+		return m_eTraceLevel;
+	}
+
+	void LogDebugMessage(COsDebugLogger::E_LOG_LEVEL eTraceLevel,
+	S_LOG_CONTEXT *pCtxt, const TCHAR *tmt, ...);
+	void LogDebugMessageV(COsDebugLogger::E_LOG_LEVEL eTraceLevel,
+	S_LOG_CONTEXT *pCtxt, const TCHAR *fmt, va_list args);
+
+	static DWORD GetGlobalTraceLevel(void);
+	static void LogGlobalDebugMessage(COsDebugLogger::E_LOG_LEVEL eTraceLevel,
+	S_LOG_CONTEXT *pCtxt, const TCHAR *fmt, ...);
+
+private:
+	void ReadTraceSettings(const TCHAR *fileName);
+	void SetDefaultSettings();
+
+private:
+#ifdef _WINDOWS
+#pragma warning( disable : 4251 ) //suppress warning - it is OK on private members
+#endif
+	tstring m_sTag;
+	bool    m_bLogToFile;
+#ifdef _WINDOWS
+#pragma warning( disable : 4251 ) //suppress warning - it is OK on private members
+#endif
+	tstring m_sLogFilePath;
+#ifdef _WINDOWS
+	HANDLE	m_hThread;
+	bool	m_bExit;
+	HANDLE	hNotifyEvent;
+
+	friend void ReadSettingsThread(void *pLogger);
+#endif
+};
+
+extern CDebugLogger *g_pLogger;
diff --git a/debug-tools/lib/utils/LoggerSupport.h b/debug-tools/lib/utils/LoggerSupport.h
new file mode 100644
index 0000000..f85e386
--- /dev/null
+++ b/debug-tools/lib/utils/LoggerSupport.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "DebugLogger.h"
+
+#define LOG_MESSAGE( level, format, ...) \
+	{\
+		CDebugLogger::S_LOG_CONTEXT _logContext = { _T(__FUNCTION__), _T(__FILE__), __LINE__ }; \
+		CDebugLogger::LogGlobalDebugMessage( level, &_logContext, format,##__VA_ARGS__ );\
+	}
+
+#define LOG_MESSAGE_ERROR( format,...)	LOG_MESSAGE(COsDebugLogger::E_LOG_LEVEL_ERROR, format,##__VA_ARGS__ )
+#define LOG_MESSAGE_WARN( format,...)	LOG_MESSAGE(COsDebugLogger::E_LOG_LEVEL_WARN, format,##__VA_ARGS__ )
+#define LOG_MESSAGE_INFO( format,...)	LOG_MESSAGE(COsDebugLogger::E_LOG_LEVEL_INFO, format,##__VA_ARGS__ )
+#define LOG_MESSAGE_DEBUG( format,...)	LOG_MESSAGE(COsDebugLogger::E_LOG_LEVEL_DEBUG, format,##__VA_ARGS__ )
+#define LOG_MESSAGE_TRACE( format,...)	LOG_MESSAGE(COsDebugLogger::E_LOG_LEVEL_TRACE, format,##__VA_ARGS__ )
+#define LOG_MESSAGE_VERBOSE( format,...)	LOG_MESSAGE(COsDebugLogger::E_LOG_LEVEL_VERBOSE, format,##__VA_ARGS__ )
+#define LOG_STACK_ENTER LOG_MESSAGE(COsDebugLogger::E_LOG_LEVEL_VERBOSE, _T("Enter."))
+#define LOG_STACK_LEAVE LOG_MESSAGE(COsDebugLogger::E_LOG_LEVEL_VERBOSE, _T("Leave."))
diff --git a/debug-tools/lib/utils/Makefile b/debug-tools/lib/utils/Makefile
new file mode 100644
index 0000000..b648bfc
--- /dev/null
+++ b/debug-tools/lib/utils/Makefile
@@ -0,0 +1,56 @@
+-include $(TOPDIR)/rules.mk
+
+CFLAGS := -fPIC -Wall -g -MMD
+LDFLAGS := -shared -fPIC
+
+LIB := libwigig_utils.so
+
+.DEFAULT_GOAL = all
+
+
+ifneq ($(CONFIG_TARGET_ipq)$(CONFIG_TARGET_ipq806x),)
+is_ipq806x = 1
+endif
+
+ifeq ($(is_ipq806x), 1)
+ifneq ($(strip $(TOOLPREFIX)),)
+CROSS:=$(TOOLPREFIX)
+endif
+endif
+
+CC = $(CROSS)gcc
+CXX = $(CROSS)g++
+
+INCLUDES = -I . \
+	   -I ../inc/linux \
+           -I ../inc \
+           -I ./linux \
+
+
+all: $(LIB)
+
+
+CPP_FILES := $(shell find . -type f -name '*.cpp')
+C_FILES := $(shell find . -type f -name '*.c')
+
+OBJ_FILES :=  $(CPP_FILES:.cpp=.o)
+OBJ_FILES +=  $(C_FILES:.c=.o)
+
+$(LIB): $(OBJ_FILES)
+	$(CXX) $(LDFLAGS) -o $(LIB) $(OBJ_FILES)
+
+%.o : %.cpp
+	$(CXX) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+%.o : %.c
+	$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+
+
+
+clean:
+	rm -rf $(LIB)
+	find . -type f \( -name "*.d" -o -name "*.o" \) -delete
+
+
+-include $(OBJ_FILES:%.o=%.d)
diff --git a/debug-tools/lib/utils/OsDebugLogger.h b/debug-tools/lib/utils/OsDebugLogger.h
new file mode 100644
index 0000000..4377f82
--- /dev/null
+++ b/debug-tools/lib/utils/OsDebugLogger.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "wlct_os.h"
+
+#if defined WLCTPCIACSS_EXPORTS && defined _WINDOWS
+#define WLCT_API __declspec(dllexport)
+#else
+#define WLCT_API
+#endif
+
+class WLCT_API COsDebugLogger {
+  public:
+    enum E_LOG_LEVEL
+    {
+      E_LOG_LEVEL_ERROR,
+      E_LOG_LEVEL_WARN,
+      E_LOG_LEVEL_INFO,
+      E_LOG_LEVEL_DEBUG,
+      E_LOG_LEVEL_TRACE,
+      E_LOG_LEVEL_VERBOSE
+    };
+
+  protected:
+    COsDebugLogger(bool logToConsole);
+    ~COsDebugLogger();
+    void print(const TCHAR *msg);
+
+  protected:
+    E_LOG_LEVEL m_eTraceLevel;
+    bool m_bLogToConsole;
+};
+
diff --git a/debug-tools/lib/utils/StlChar.h b/debug-tools/lib/utils/StlChar.h
new file mode 100644
index 0000000..4ae7bf6
--- /dev/null
+++ b/debug-tools/lib/utils/StlChar.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <map>
+#include <vector>
+#include <sstream>
+
+#define WSTR_ARG(s) ToWString(s).c_str()
+#define TSTR_ARG(s) ToTString(s).c_str()
+
+#if defined(UNICODE) || defined(_UNICODE)
+typedef std::wstring         tstring;
+typedef std::wstringstream   tstringstream;
+typedef std::wostringstream  tostringstream;
+#else
+typedef std::string          tstring;
+typedef std::stringstream    tstringstream;
+typedef std::ostringstream   tostringstream;
+#endif
+
+typedef std::map<tstring, tstring> TStringMap;
+typedef std::vector<std::string> TStringList;
+
+inline std::wstring ToWString(const char *str)
+{
+  std::wostringstream s;
+  s << str;
+  return s.str();
+}
+
+inline std::wstring ToWString(const wchar_t *str)
+{
+  return str;
+}
+
+inline tstring ToTString(const char *str)
+{
+  tostringstream s;
+  s << str;
+  return s.str();
+}
+
+// printf format specifiers
+//
+//| Format Specifier | Win printf | Win wprintf | Lin printf | Lin wprintf |
+//|------------------|------------| ----------- | ---------- | ----------- |
+//|      %s          | char*      | wchar_t*    | char*      | char*       |
+//|      %ls         | wchar_t*   | wchar_t*    | wchar_t*   | wchar_t*    |
+//|      %hs         | char*      | char*       |       NOT SUPPORTED      |
+//|      $S          | wchar_t*   | char*       | wchar_t*   | wchar_t*    |
+//|------------------|------------| ----------- | ---------- | ----------- |
diff --git a/debug-tools/lib/utils/ThreadXFace.h b/debug-tools/lib/utils/ThreadXFace.h
new file mode 100644
index 0000000..8d119f2
--- /dev/null
+++ b/debug-tools/lib/utils/ThreadXFace.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "wlct_os.h"
+
+typedef void (*IWlctThreadThreadProc)(void *p);
+
+class IWlctThread
+{
+public:
+  IWlctThread(IWlctThreadThreadProc tProc, void *tCtx)
+    : threadProc(tProc), threadCtx(tCtx) {}
+  virtual ~IWlctThread() {}
+
+  bool ShouldStop()
+  {
+    return shouldStop;
+  }
+
+  virtual wlct_os_err_t Start()     = 0;
+  virtual void          Stop()      = 0;
+
+protected:
+  IWlctThreadThreadProc threadProc;
+  void                 *threadCtx;
+  volatile bool         shouldStop;
+};
diff --git a/debug-tools/lib/utils/linux/OsDebugLogger.cpp b/debug-tools/lib/utils/linux/OsDebugLogger.cpp
new file mode 100644
index 0000000..916f2bf
--- /dev/null
+++ b/debug-tools/lib/utils/linux/OsDebugLogger.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "OsDebugLogger.h"
+#include <syslog.h>
+
+COsDebugLogger::COsDebugLogger(bool logToConsole) : m_bLogToConsole(logToConsole)
+{
+  openlog("WLCT", m_bLogToConsole ? LOG_PERROR : 0, LOG_USER);
+}
+
+COsDebugLogger::~COsDebugLogger()
+{
+  closelog();
+}
+
+void COsDebugLogger::print(const char *msg)
+{
+  syslog(LOG_USER, "%s", msg);
+}
+
diff --git a/debug-tools/lib/utils/linux/Thread.cpp b/debug-tools/lib/utils/linux/Thread.cpp
new file mode 100644
index 0000000..3bdfc4e
--- /dev/null
+++ b/debug-tools/lib/utils/linux/Thread.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "Thread.h"
+#include "wlct_os.h"
+
+
+void *CWlctThread::GlobalThreadMain(void *p)
+{
+  CWlctThread *threadObj = (CWlctThread *)p;
+
+  threadObj->ThreadMain();
+
+  pthread_exit(&threadObj->threadResult);
+}
+
+void CWlctThread::ThreadMain(void)
+{
+  threadProc(threadCtx);
+}
+
+CWlctThread::CWlctThread(IWlctThreadThreadProc tProc, void *tCtx)
+  : IWlctThread(tProc, tCtx),
+    threadResult(0)
+{
+  memset(&threadObj, 0, sizeof(threadObj));
+}
+
+CWlctThread::~CWlctThread()
+{
+  Stop();
+}
+
+wlct_os_err_t CWlctThread::Start()
+{
+  shouldStop = false;
+
+  pthread_attr_t attr;
+
+  pthread_attr_init(&attr);
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+  threadResult = pthread_create(&threadObj,
+                                &attr,
+                                GlobalThreadMain,
+                                this);
+
+  pthread_attr_destroy(&attr);
+
+  return threadResult;
+}
+
+void CWlctThread::Stop()
+{
+  void *tres = NULL;
+  shouldStop = true;
+  /* Wait for the notification thread to process the signal */
+  pthread_join(threadObj, &tres);
+}
+
+uint32_t CWlctThread::getCurrentThreadID()
+{
+  return (uint32_t)pthread_self();
+}
+
+uint32_t CWlctThread::getCurrentProcessID()
+{
+  return (uint32_t)getpid();
+}
+
diff --git a/debug-tools/lib/utils/linux/Thread.h b/debug-tools/lib/utils/linux/Thread.h
new file mode 100644
index 0000000..438816e
--- /dev/null
+++ b/debug-tools/lib/utils/linux/Thread.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "ThreadXFace.h"
+#include <pthread.h>
+
+class CWlctThread : public IWlctThread
+{
+public:
+  CWlctThread(IWlctThreadThreadProc tProc, void *tCtx);
+  virtual ~CWlctThread();
+
+  virtual wlct_os_err_t Start();
+  virtual void          Stop();
+
+  static uint32_t getCurrentThreadID();
+  static uint32_t getCurrentProcessID();
+
+protected:
+  static void *GlobalThreadMain(void *p);
+  void         ThreadMain();
+
+  pthread_t    threadObj;
+  int          threadResult;
+};
diff --git a/debug-tools/lib/utils/linux/WlctCDevFile.cpp b/debug-tools/lib/utils/linux/WlctCDevFile.cpp
new file mode 100644
index 0000000..4078148
--- /dev/null
+++ b/debug-tools/lib/utils/linux/WlctCDevFile.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "wlct_os.h"
+#include "WlctCDevFile.h"
+#include "LoggerSupport.h"
+
+extern "C" {
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+};
+
+const int CWlctCDevFile::INVALID_FD = -1;
+
+CWlctCDevFile::CWlctCDevFile(): fd(INVALID_FD)
+{
+}
+
+CWlctCDevFile::~CWlctCDevFile()
+{
+  Close();
+}
+
+wlct_os_err_t CWlctCDevFile::Open(const char *fName, const char* interfaceName)
+{
+  //do something with params
+  (void)interfaceName;
+  wlct_os_err_t res = WLCT_OS_ERROR_GEN_FAILURE;
+
+  WLCT_ASSERT(IsOpened() == false);
+  WLCT_ASSERT(fName != NULL);
+
+  devFileName = fName;
+
+  LOG_MESSAGE_DEBUG("Char device file %s opening...", devFileName.c_str());
+
+  fd = open(devFileName.c_str(), 0);
+  if (INVALID_FD == fd)
+  {
+    res = errno;
+    LOG_MESSAGE_ERROR("Failed to open file %s (%d)", devFileName.c_str(), res);
+    goto Exit;
+  }
+
+  LOG_MESSAGE_DEBUG("Char device file opened: fd=%d", fd);
+
+  res = WLCT_OS_ERROR_SUCCESS;
+
+Exit:
+  if (res != WLCT_OS_ERROR_SUCCESS)
+  {
+    Close();
+  }
+
+  return res;
+}
+
+void CWlctCDevFile::Close()
+{
+  if (fd != INVALID_FD)
+  {
+    close(fd);
+    fd = INVALID_FD;
+  }
+
+  devFileName.erase();
+}
+
+wlct_os_err_t CWlctCDevFile::Ioctl(void *dataBuf,
+                                   DWORD dataBufLen,
+                                   DWORD ioctlFlags)
+{
+  wlct_os_err_t res = WLCT_OS_ERROR_GEN_FAILURE;
+  wlct_cdev_ioctl_hdr_t *ioctl_hdr = NULL;
+
+  WLCT_ASSERT(IsOpened() == true);
+  WLCT_ASSERT(dataBuf != NULL);
+  WLCT_ASSERT(dataBufLen != 0);
+
+  ioctl_hdr = (wlct_cdev_ioctl_hdr_t *)malloc((sizeof *ioctl_hdr) + dataBufLen);
+  if (NULL == ioctl_hdr)
+  {
+    LOG_MESSAGE_ERROR("Allocation failed (data of %u bytes)\n", dataBufLen);
+    res = WLCT_OS_ERROR_NOT_ENOUGH_MEMORY;
+    goto Exit;
+  }
+
+  ioctl_hdr->magic = WLCT_IOCTL_MAGIC;
+  ioctl_hdr->len = dataBufLen;
+  ioctl_hdr->flags = ioctlFlags;
+
+  if (ioctlFlags & WLCT_IOCTL_FLAG_SET)
+    memcpy(ioctl_hdr + 1, dataBuf, dataBufLen);
+
+  res = ioctl(fd, 0, ioctl_hdr);
+  if (0 != res)
+  {
+    res = errno;
+    LOG_MESSAGE_ERROR("ioctl failed with error code %d", res);
+    goto Exit;
+  }
+
+  if (ioctlFlags & WLCT_IOCTL_FLAG_GET)
+    memcpy(dataBuf, ioctl_hdr + 1, dataBufLen);
+
+Exit:
+  if (NULL != ioctl_hdr)
+    free(ioctl_hdr);
+
+  return res;
+}
diff --git a/debug-tools/lib/utils/linux/WlctCDevFile.h b/debug-tools/lib/utils/linux/WlctCDevFile.h
new file mode 100644
index 0000000..f1427f3
--- /dev/null
+++ b/debug-tools/lib/utils/linux/WlctCDevFile.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "wlct_cdev_shared.h"
+#include "wlct_os.h"
+
+#include <string>
+
+class CWlctCDevFile
+{
+public:
+  CWlctCDevFile();
+  virtual ~CWlctCDevFile();
+
+  virtual wlct_os_err_t Open(const char *fName, const char* interfaceName);
+  virtual void          Close();
+  virtual wlct_os_err_t Ioctl(void *dataBuf, DWORD dataBufLen, DWORD ioctlFlags);
+  virtual wlct_os_err_t DebugFS(char *FileName, void *dataBuf, DWORD dataBufLen, DWORD DebugFSFlags)
+  {
+    //do something with params
+    (void)FileName;
+    (void)dataBuf;
+    (void)dataBufLen;
+    (void)DebugFSFlags;
+
+    return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
+  }
+
+  bool          IsOpened() const
+  {
+    return (fd != INVALID_FD);
+  }
+
+protected:
+
+  int  fd;
+  static const int INVALID_FD;
+
+private:
+
+  std::string devFileName;
+
+};
+
diff --git a/debug-tools/lib/utils/linux/WlctCDevSocket.cpp b/debug-tools/lib/utils/linux/WlctCDevSocket.cpp
new file mode 100644
index 0000000..5f0b091
--- /dev/null
+++ b/debug-tools/lib/utils/linux/WlctCDevSocket.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "WlctCDevSocket.h"
+#include "LoggerSupport.h"
+#include "public.h"
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <linux/sockios.h>
+#include <linux/if.h>
+#include <sys/ioctl.h>
+#include <stdint.h>
+#include <iostream>
+#include <fstream>
+#include <string.h>
+
+
+//insted of "ioctl_if.h"
+#define WILOCITY_IOCTL_INDIRECT_READ IOCTL_INDIRECT_READ_OLD
+#define WILOCITY_IOCTL_INDIRECT_WRITE IOCTL_INDIRECT_WRITE_OLD
+#define WILOCITY_IOCTL_INDIRECT_READ_BLOCK IOCTL_INDIRECT_READ_BLOCK
+#define WILOCITY_IOCTL_INDIRECT_WRITE_BLOCK IOCTL_INDIRECT_WRITE_BLOCK
+
+#define EP_OPERATION_READ 0
+#define EP_OPERATION_WRITE 1
+#define WIL_IOCTL_MEMIO (SIOCDEVPRIVATE + 2)
+
+const char* DEBUGFS_ROOT = "/sys/kernel/debug/ieee80211/";
+
+CWlctCDevSocket::CWlctCDevSocket():CWlctCDevFile()
+{
+}
+
+int sendRWIoctl(wil_memio & io,int fd, char* interfaceName, bool activateLogs = true)
+{
+    int ret;
+    struct ifreq ifr;
+    ifr.ifr_data = &io;
+
+    snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interfaceName);
+    ifr.ifr_name[IFNAMSIZ - 1] = 0;
+
+    ret = ioctl(fd, WIL_IOCTL_MEMIO, &ifr);
+    if (ret < 0 && activateLogs)
+    {
+        perror("ioctl");
+    }
+
+    return ret;
+}
+
+// Receives interface name (wigig#, wlan#) and checks if it is responding
+bool setInterfaceName(const char* interfaceName, int fd)
+{
+    if (interfaceName == NULL)
+    {
+        LOG_MESSAGE_ERROR("Invalid interface name (NULL)");
+        return false;
+    }
+
+    wil_memio io;
+    io.addr = 0x880050; //baud rate
+    io.op = EP_OPERATION_READ;
+
+    LOG_MESSAGE_DEBUG("Checking interface name: %s", interfaceName);
+
+    int ret = sendRWIoctl(io, fd, (char*)interfaceName, false);
+    if(ret == 0)
+    {
+        LOG_MESSAGE_DEBUG("Successfuly set interface name: %s", interfaceName);
+	return true;
+    }
+
+
+    return false;
+}
+
+wlct_os_err_t CWlctCDevSocket::Open(const char *fName, const char* ifName)
+{
+    wlct_os_err_t res = WLCT_OS_ERROR_GEN_FAILURE;
+
+    WLCT_ASSERT(IsOpened() == false);
+    WLCT_ASSERT(strlen(fName) < WLCT_CDEV_FILE_MAX_NAME_LEN);
+
+    LOG_MESSAGE_DEBUG("Char device file %s opening...", fName);
+
+    fd = socket(AF_INET, SOCK_DGRAM, 0);
+    if (INVALID_FD == fd || fd < 0)
+    {
+	res = errno;
+	LOG_MESSAGE_ERROR("Failed to open socket to device");
+	Close();
+        return res;
+    }
+
+    LOG_MESSAGE_DEBUG("Trying to open socket to driver, device name: %s", ifName);
+
+    const TCHAR* const delimit = _T("!");
+
+    TCHAR* token;
+    TCHAR *next_token = NULL;
+
+    token = _tcstok_s( (char*)ifName, delimit, &next_token);
+    if (NULL == token)
+    {
+        LOG_MESSAGE_ERROR("No token found in %s", ifName);
+        Close();
+        return -1;
+    }
+
+    LOG_MESSAGE_DEBUG(_T("token: %s"), token);
+
+    // SPARROW
+    token = _tcstok_s( NULL, delimit, &next_token);
+    if (NULL == token)
+    {
+        LOG_MESSAGE_ERROR("No card token found in %s", ifName);
+        Close();
+        return -1;
+    }
+
+    LOG_MESSAGE_DEBUG(_T("token: %s"), token);
+
+    // wlan# or wigig#
+    token = _tcstok_s( NULL, delimit, &next_token);
+    if (NULL == token)
+    {
+        LOG_MESSAGE_ERROR("No interface token found in %s", ifName);
+        Close();
+        return -1;
+    }
+    LOG_MESSAGE_DEBUG(_T("token: %s"), token);
+
+    snprintf(interfaceName, IFNAMSIZ, "%s", token);
+
+    // Validate interface is 11ad interface
+    if(!setInterfaceName(interfaceName, fd))
+    {
+        LOG_MESSAGE_ERROR("Failed to query interface %s", interfaceName);
+        Close();
+        return res;
+    }
+
+    LOG_MESSAGE_DEBUG("Char device socket opened: fd=%d", fd);
+    LOG_MESSAGE_DEBUG("Looking for wil6210 in %s", DEBUGFS_ROOT);
+
+    const char* szCmdPattern = "find /sys/kernel/debug/ieee80211/ -name wil6210";
+    FILE* pIoStream = popen(szCmdPattern, "r");
+    if (!pIoStream)
+    {
+        LOG_MESSAGE_ERROR("Failed to run command to detect DebugFS\n" );
+        Close();
+        return res;
+    }
+
+    bool debugFsFound = false;
+    while (fgets(debugFSPath, WLCT_CDEV_FILE_MAX_NAME_LEN, pIoStream) != NULL)
+    {
+        // The command output contains a newline character that should be removed
+        debugFSPath[strcspn(debugFSPath, "\r\n")] = '\0';
+        LOG_MESSAGE_DEBUG("Found DebugFS Path: %s", debugFSPath);
+        if (debugFsFound)
+        {
+            // TODO - support DebugFS with Multiple interfaces for PMC
+            LOG_MESSAGE_INFO("DebugFS for Multiple WIGIG cards is not currently supported\n");
+            //Close();
+            //return res;
+        }
+        debugFsFound = true;
+    }
+
+    pclose(pIoStream);
+    return WLCT_OS_ERROR_SUCCESS;
+}
+
+
+wlct_os_err_t CWlctCDevSocket::Ioctl(void *dataBuf, DWORD dataBufLen, DWORD ioctlFlags)
+{
+    // doing something with unused params:
+    (void)dataBufLen;
+    (void)ioctlFlags;
+
+    wlct_ioctl_hdr_t *header = (wlct_ioctl_hdr_t*)dataBuf;
+    int32_t* inBuf = (int32_t*)((char*)dataBuf + sizeof(wlct_ioctl_hdr_t));
+    int32_t* outBuf = (int32_t*)((char*)dataBuf + sizeof(wlct_ioctl_hdr_t) + header->outBufOffset);
+    int32_t outBufferSize = header->outBufSize;
+    int Id = header->commandID;
+    int ret = 0;
+
+    //init for switch section
+    wil_memio io;
+    int numReads;
+    int32_t sizeToWrite;
+    PFILTER_WRITE_BLOCK inParam;
+    int i;
+    //end init for switch section
+
+
+    switch(Id){
+    case IOCTL_INDIRECT_READ_OLD:
+        //case WILOCITY_IOCTL_INDIRECT_READ:
+        //read is allways 32 bytes
+        io.addr = inBuf[0];
+        io.val = outBuf[0];
+        io.op = EP_OPERATION_READ;
+        ret = sendRWIoctl(io, fd, interfaceName);
+        *outBuf = io.val;
+        break;
+    case IOCTL_INDIRECT_WRITE_OLD:
+        //case WILOCITY_IOCTL_INDIRECT_WRITE:
+        //write parameters are passed only throgth "in param"
+        io.addr = inBuf[0];
+        io.val = inBuf[1];
+        io.op = EP_OPERATION_WRITE;
+        ret = sendRWIoctl(io, fd, interfaceName);
+        break;
+        //rb and wb are temporary! they should be replaced by a driver Ioctl
+    case WILOCITY_IOCTL_INDIRECT_READ_BLOCK:
+        //blocks must be 32bit alligned!
+        numReads = outBufferSize / 4;
+        io.op = EP_OPERATION_READ;
+        io.addr = inBuf[0];
+        for(i = 0 ; i < numReads ; i++){
+            ret = sendRWIoctl(io, fd, interfaceName);
+            if(ret != 0){
+                return -2;
+            }
+            outBuf[i] = io.val;
+            io.addr += sizeof(int32_t);
+        }
+        break;
+    case WILOCITY_IOCTL_INDIRECT_WRITE_BLOCK:
+        //blocks must be 32bit alligned!
+        inParam = reinterpret_cast<PFILTER_WRITE_BLOCK>(inBuf);
+        io.addr = inParam->address;
+        sizeToWrite = inParam->size / 4;
+        io.op = EP_OPERATION_WRITE;
+        for(i = 0 ; i < sizeToWrite ; i++){
+            io.val = inParam->buffer[i];
+            ret = sendRWIoctl(io, fd, interfaceName);
+            if(ret != 0){
+                return -3;
+            }
+            io.addr += sizeof(int32_t);
+        }
+        break;
+    default:
+        return -1;
+    }
+
+    return ret;
+
+}
+
+wlct_os_err_t CWlctCDevSocket::DebugFS(char *FileName, void *dataBuf, DWORD dataBufLen, DWORD DebugFSFlags)
+{
+    //doing somethin with unused params:
+    (void)dataBufLen;
+    (void)DebugFSFlags;
+    char file_to_open[WLCT_CDEV_FILE_MAX_NAME_LEN] ;
+    int *dataBuf_debugFS = (int*) dataBuf;
+    int num_desc = *dataBuf_debugFS;
+    dataBuf_debugFS++;
+    int size_desc = *dataBuf_debugFS;
+
+    LOG_MESSAGE_INFO(_T("DebugFS: %s"), FileName);
+
+    if(strlen(debugFSPath) == 0) return WLCT_OS_ERROR_OPEN_FAILED;
+
+    snprintf( file_to_open, WLCT_CDEV_FILE_MAX_NAME_LEN, "%s/%s", debugFSPath, FileName);
+    std::ofstream debugFSFile;
+    debugFSFile.open(file_to_open);
+
+    if ( (debugFSFile.rdstate() & std::ifstream::failbit ) != 0 ){
+        std::cout << "error while writing to debugfs! trying to write to address : ";
+        std::cout << file_to_open << std::endl;
+        return WLCT_OS_ERROR_GEN_FAILURE;
+    }
+    if(num_desc != 0 && size_desc != 0)	debugFSFile << "alloc " << num_desc << " " << size_desc;
+    else debugFSFile << "free";
+    debugFSFile.close();
+
+    return WLCT_OS_ERROR_SUCCESS;
+}
+
+CWlctCDevSocket::~CWlctCDevSocket(){}
diff --git a/debug-tools/lib/utils/linux/WlctCDevSocket.h b/debug-tools/lib/utils/linux/WlctCDevSocket.h
new file mode 100644
index 0000000..d2998dd
--- /dev/null
+++ b/debug-tools/lib/utils/linux/WlctCDevSocket.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "wlct_os.h"
+#include "WlctCDevFile.h"
+
+#include <sys/socket.h>
+#include <linux/if.h>
+
+
+#define WLCT_CDEV_FILE_MAX_NAME_LEN 225
+
+class CWlctCDevSocket : public CWlctCDevFile
+{
+public:
+  CWlctCDevSocket();
+  virtual ~CWlctCDevSocket();
+
+  virtual wlct_os_err_t Ioctl(void *dataBuf,
+                                   DWORD dataBufLen,
+                                   DWORD ioctlFlags);
+  virtual wlct_os_err_t Open(const char *fName, const char* interfaceName);
+  virtual wlct_os_err_t DebugFS(char *FileName, void *dataBuf, DWORD dataBufLen, DWORD DebugFSFlags);
+
+private:
+
+  char interfaceName[IFNAMSIZ];
+  char debugFSPath[WLCT_CDEV_FILE_MAX_NAME_LEN];
+};
+
+typedef struct {
+  uint32_t op;
+  uint32_t addr; /* should be 32-bit aligned */
+  uint32_t val;
+} wil_memio;
+
+
diff --git a/debug-tools/remoteserver/Android.mk b/debug-tools/remoteserver/Android.mk
new file mode 100644
index 0000000..9a215a8
--- /dev/null
+++ b/debug-tools/remoteserver/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := wigig_remoteserver
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPPFLAGS := -Wall -lpthread -fexceptions
+
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH)/../lib/WlctPciAcss \
+	$(LOCAL_PATH)/../lib/inc \
+	$(LOCAL_PATH)/../lib/utils
+
+LOCAL_SHARED_LIBRARIES := \
+	libwigig_utils \
+	libwigig_pciaccess
+
+LOCAL_SRC_FILES := $(shell find $(LOCAL_PATH) -name '*.cpp' | sed s:^$(LOCAL_PATH)::g )
+LOCAL_SRC_FILES += parser.l
+
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/debug-tools/remoteserver/Makefile b/debug-tools/remoteserver/Makefile
new file mode 100644
index 0000000..e9bef43
--- /dev/null
+++ b/debug-tools/remoteserver/Makefile
@@ -0,0 +1,62 @@
+-include $(TOPDIR)/rules.mk
+
+CFLAGS := -fPIE -Wall -g -MMD -Wno-unused-function
+LDFLAGS := -pie -fPIE -pthread -lwigig_pciaccess -lwigig_utils
+
+ifneq ($(CONFIG_TARGET_ipq)$(CONFIG_TARGET_ipq806x),)
+is_ipq806x = 1
+endif
+
+ifeq ($(is_ipq806x), 1)
+ifneq ($(strip $(TOOLPREFIX)),)
+CROSS:=$(TOOLPREFIX)
+endif
+endif
+
+CC := $(CROSS)gcc
+CXX := $(CROSS)g++
+
+.DEFAULT_GOAL = all
+PROG = wigig_remoteserver
+
+INCLUDES = -I ../lib/WlctPciAcss \
+           -I ../lib/inc \
+           -I ../lib/utils \
+
+LIBS = -L../lib/WlctPciAcss \
+       -L../lib/utils \
+
+all: $(PROG)
+
+CPP_FILES = $(shell find . -type f -name '*.cpp')
+C_FILES = $(shell find . -type f -name '*.c')
+LEX_FILES = $(shell find . -type f -name '*.l')
+
+
+GENERATED_C_FILES=$(LEX_FILES:.l=.c)
+OBJ_FILES=  $(CPP_FILES:.cpp=.o)
+OBJ_FILES += $(C_FILES:.c=.o)
+OBJ_FILES += $(GENERATED_C_FILES:.c=.o)
+
+.PRECIOUS: $(GENERATED_C_FILES)
+
+$(PROG): $(OBJ_FILES)
+	$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)
+
+%.o : %.c
+	$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+%.o : %.cpp
+	$(CXX) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+%.c : %.l
+	flex -o $@ $<
+
+
+
+clean:
+	rm -rf $(PROG) $(GENERATED_C_FILES)
+	find . -type f \( -name "*.d" -o -name "*.o" \) -delete
+
+
+-include $(OBJ_FILES:%.o=%.d)
diff --git a/debug-tools/remoteserver/cmdiface.cpp b/debug-tools/remoteserver/cmdiface.cpp
new file mode 100644
index 0000000..9c03471
--- /dev/null
+++ b/debug-tools/remoteserver/cmdiface.cpp
@@ -0,0 +1,645 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sstream>
+#include <iostream>
+#include <fstream>
+
+#include "cmdiface.h"
+#include "parser.h"
+#include "debug.h"
+#include "WlctPciAcss.h"
+#include "pmc_file.h"
+#include "udp_server.h"
+
+
+struct open_interface_s *CmdIface::open_interfaces = NULL;
+pthread_mutex_t CmdIface::open_interfaces_mutex = PTHREAD_MUTEX_INITIALIZER;
+int CmdIface::interface_id = 0;
+
+/*
+*/
+void *CmdIface::get_interface(const char *name)
+{
+    struct open_interface_s *s = open_interfaces;
+    LOG_DEBUG << "Looking for interface: " << name << std::endl;
+
+    while(s != NULL)
+    {
+        LOG_VERBOSE << "Checking interface for match: " << s->interface << std::endl;
+        if(0 == strncasecmp(name, s->interface, MAX_INTERFACE_NAME))
+        {
+            LOG_VERBOSE << "Match found" << std::endl;
+            return s->handler;
+        }
+        s = s->next;
+    }
+
+    return NULL;
+}
+
+/*
+*/
+void *CmdIface::add_interface(const char *name, void *handler)
+{
+    LOG_DEBUG << "Adding interface: " << name << std::endl;
+
+    void *h = get_interface(name);
+    if(h != NULL)
+    {
+        LOG_DEBUG << "The interface is already open" << std::endl;
+        return h;			// Interface already opened
+    }
+
+    // Add interface to the list
+    struct open_interface_s *s = new struct open_interface_s;
+    if(s == NULL)
+    {
+        return NULL;
+    }
+
+    snprintf(s->interface, MAX_INTERFACE_NAME, "%s", name);
+    s->handler = handler;
+    pthread_mutex_lock(&open_interfaces_mutex);
+    s->next = open_interfaces;
+    open_interfaces = s;
+    pthread_mutex_unlock(&open_interfaces_mutex);
+
+    return handler;
+}
+
+/*
+*/
+void CmdIface::del_interface(void *handler)
+{
+    LOG_DEBUG << "Deleting interfaces by handler" << std::endl;
+
+    struct open_interface_s *s = open_interfaces;
+    struct open_interface_s *prev = NULL;
+
+    while(s != NULL) {
+        if(handler == s->handler)  {
+            // Remove the interface from the list
+            pthread_mutex_lock(&open_interfaces_mutex);
+            if(prev != NULL)
+                prev->next = s->next;
+            else
+                open_interfaces = s->next;
+            pthread_mutex_unlock(&open_interfaces_mutex);
+            delete s;
+        }
+        prev = s;
+        s = s->next;
+    }
+}
+
+/*
+*/
+int CmdIface::cmd_get_interfaces()
+{
+    INTERFACE_LIST interfaces;
+    int num_interfaces;
+    int rc;
+
+    LOG_DEBUG << "Getting active WIGIG card interfaces" << std::endl;
+
+    rc = GetInterfaces(&interfaces, &num_interfaces);
+    LOG_DEBUG << "Found " << num_interfaces << " interfaces" << std::endl;
+
+    std::ostringstream replyBuilder;
+
+    if(rc == 0)
+    {
+        for(int i=0; i < num_interfaces; i++)
+        {
+            replyBuilder << interfaces.list[i].ifName << ' ';
+        }
+    }
+
+    replyBuilder << "\r\n";
+    m_Reply = replyBuilder.str();
+
+    return 0;
+}
+
+/*
+*/
+int CmdIface::cmd_open_interface(char *interface)
+{
+    void *handler = NULL;
+    int rc=0;
+
+    LOG_DEBUG << "Opening an interface: " << interface << std::endl;
+
+    if( strstr(interface, "SPARROW")|| strstr(interface, "sparrow")){
+	rc = CreateDeviceAccessHandler(interface, MST_SPARROW, &handler);
+    }
+    else if(strstr(interface, "MARLON") || strstr(interface, "marlon")){
+	rc = CreateDeviceAccessHandler(interface, MST_MARLON, &handler);
+    }
+    else{
+        m_Reply = "0xDEAD\r\n";
+    }
+    if(rc != 0)
+        m_Reply = "0xDEADDEAD\r\n";
+    else {
+
+        std::ostringstream replyBuilder;
+
+        replyBuilder << interface << '_' << interface_id;
+        add_interface(replyBuilder.str().c_str(), handler);
+        replyBuilder << "\r\n";
+        m_Reply = replyBuilder.str();
+        interface_id++;                     // TODO: Should be protected by a mutex? I didn't see it's being used in the application
+    }
+    return 0;
+}
+
+/*
+*/
+int CmdIface::cmd_close_interface(char *interface)
+{
+    LOG_DEBUG << "Closing interface: " << interface << std::endl;
+
+    void *handler = get_interface(interface);
+
+    if(handler != NULL)
+    {
+        del_interface(handler);
+        interface_id--;
+    }
+    else
+    {
+        LOG_WARNING << "Interface " << interface << " wasn't opened" << std::endl;
+    }
+
+    m_Reply = "0\r\n";
+    return 0;
+}
+
+/*
+*/
+int CmdIface::cmd_r(char *interface, unsigned int address)
+{
+    unsigned int val = 0xDEADDEAD;
+    void *handler = get_interface(interface);
+
+    std::ostringstream replyBuilder;
+    if(handler == NULL)
+    {
+        m_Reply = "0xDEADDEAD";
+    }
+    else
+    {
+        int rc = WlctAccssRead(handler, address, val);
+        (void)rc;
+        replyBuilder << val;
+    }
+
+    replyBuilder << "\r\n";
+    m_Reply = replyBuilder.str();
+
+    return 0;
+}
+
+/*
+*/
+int CmdIface::cmd_w(char *interface, unsigned int address, unsigned int data)
+{
+    int rc;
+    void *handler = get_interface(interface);
+
+    std::ostringstream replyBuilder;
+
+    if(handler == NULL)
+    {
+        replyBuilder << "0xDEADDEAD";
+    }
+    else
+    {
+        rc = WlctAccssWrite(handler, address, data);
+        if(rc == 0)
+            replyBuilder << "0";
+        else
+            replyBuilder << "ERROR";
+    }
+
+    replyBuilder << "\r\n";
+    m_Reply = replyBuilder.str();
+
+    return 0;
+}
+
+/*
+*/
+int CmdIface::cmd_alloc_pmc(char *interface, unsigned int desc_size, unsigned int desc_num)
+{
+    int rc;
+    LOG_DEBUG << "Allocating PMC descriptors:"
+              << " interface = " << interface
+              << " size = " << desc_size
+              << " number = " << desc_num
+              << std::endl;
+
+    std::ostringstream replyBuilder;
+
+    void *handler = get_interface(interface);
+    if(handler == NULL)
+    {
+        LOG_DEBUG << "Cannot get handler for interface " << interface << std::endl;
+        replyBuilder << "0xDEADDEAD";
+    }
+    else
+    {
+	rc = WlctAccssAllocPmc(handler, desc_size, desc_num);
+
+	if(rc == 0)
+        {
+            LOG_DEBUG << "Successfully allocated PMC descriptors" << std::endl;
+            replyBuilder << "0";
+        }
+        else
+        {
+            LOG_ERROR << "Error allocating PMC descriptors" << std::endl;
+            replyBuilder << "ERROR";
+        }
+    }
+
+    replyBuilder << "\r\n";
+    m_Reply = replyBuilder.str();
+
+    return 0;
+}
+
+/*
+*/
+int CmdIface::cmd_read_pmc(char *interface, unsigned int ref_number)
+{
+    LOG_DEBUG << "Reading PMC data:"
+              << " interface = " << interface
+              << " reference number = " << ref_number
+              << std::endl;
+
+    void *handler = get_interface(interface);
+
+    if(handler == NULL)
+    {
+        LOG_ERROR << "No interface found: " << interface << std::endl;
+        m_Reply = "0xDEADDEAD\r\n";
+        return 0;
+    }
+
+    PmcFile pmcFile(ref_number);
+    PmcFileWriter pmcFileWriter(pmcFile);
+    bool status = pmcFileWriter.WriteFile();
+    if (false == status)
+    {
+        LOG_ERROR << "Error creating PMC data file" << std::endl;
+        m_Reply = "0xDEADDEAD\r\n";
+        return 0;
+    }
+
+    // Reply with file size
+    size_t pmcFileSize = pmcFileWriter.GetFileSize();
+
+    std::ostringstream replyBuilder;
+    replyBuilder << pmcFileSize << "\r\n";
+    m_Reply = replyBuilder.str();
+
+    return 0;
+}
+
+/*
+*/
+int CmdIface::cmd_read_pmc_file(unsigned int ref_number)
+{
+    LOG_DEBUG << "Reading PMC File #" << ref_number << std::endl;
+
+    PmcFile pmcFile(ref_number);
+
+    if (NULL == pmcFile.GetFileName())
+    {
+        LOG_ERROR << "Error getting PMC data file #" << ref_number << std::endl;
+        m_Reply = "0xDEADDEAD\r\n";
+        return 0;
+    }
+
+    // Note: No \r\n is needed here, the file name won't be sent to a clientls
+    m_Reply = pmcFile.GetFileName();
+	replyType = REPLY_TYPE_FILE;
+    return 0;
+}
+
+/*
+*/
+int CmdIface::cmd_rb(char *interface, unsigned int address, unsigned int num_regs)
+{
+    void *handler = get_interface(interface);
+
+    if((handler == NULL) || (num_regs > MAX_REGS_LEN))
+    {
+        m_Reply = "0xDEADDEAD\r\n";
+        return 0;
+    }
+
+    unsigned int *val = new unsigned int[num_regs];
+    int rc = readBlock(handler, address, num_regs*sizeof(unsigned int), (char*)val);
+
+    if (rc == 0)
+    {
+        std::ostringstream replyBuilder;
+        replyBuilder << std::hex;
+
+        for(unsigned int i=0; i < num_regs; i++)
+        {
+            replyBuilder << "0x" << val[i];
+            if(i < num_regs -1 )
+            {
+                replyBuilder << ' ';
+            }
+        }
+
+        replyBuilder << "\r\n";
+        m_Reply = replyBuilder.str();
+    }
+    else
+    {
+        m_Reply = "0xDEADDEAD\r\n";
+    }
+
+    delete[] val;
+    return 0;
+}
+
+/*
+*/
+int CmdIface::cmd_wb(char *interface, unsigned int address, unsigned int len, const char *block)
+{
+    void *handler = get_interface(interface);
+
+    if((handler == NULL) || (len > MAX_REGS_LEN))
+    {
+        m_Reply = "0xDEADDEAD\r\n";
+        return 0;
+    }
+
+    LOG_VERBOSE << "current WB is " << block << " length is " << len << std::endl;
+    int rc = writeBlock(handler, address, len, block);
+    if(rc == 0)
+    {
+        m_Reply = "0\r\n";
+    }
+    else
+    {
+        m_Reply = "ERROR\r\n";
+    }
+
+    return 0;
+}
+
+
+int CmdIface::cmd_interface_reset(char *interface)
+{
+    void *handler = get_interface(interface);
+    if(handler == NULL)
+    {
+        m_Reply = "0xDEADDEAD\r\n";
+	}
+    else
+	{
+        int rc = InterfaceReset(handler);
+        if(rc == 0)
+		{
+            m_Reply = "OK\r\n";
+		}
+        else
+		{
+            m_Reply = "0xDEADDEAD\r\n";
+		}
+    }
+
+    return 0;
+}
+
+
+int CmdIface::cmd_sw_reset(char *interface)
+{
+	void *handler = get_interface(interface);
+	if (handler == NULL)
+	{
+		m_Reply = "0xDEADDEAD\r\n";
+	}
+	else
+	{
+		int rc = SwReset(handler);
+		if (rc == 0)
+		{
+			m_Reply = "OK\r\n";
+		}
+		else
+		{
+			m_Reply = "0xDEADDEAD\r\n";
+		}
+	}
+
+	return 0;
+}
+
+int CmdIface::cmd_set_host_alias(char* alias)
+{
+	std::ofstream fd(UdpServer::host_details_file_name.c_str());
+	if (!fd.is_open())
+	{
+		m_Reply = "FAIL : Coudn't set the new alias: failed to open the configuration file";
+		LOG_VERBOSE << m_Reply << std::endl;
+		return -1;
+	}
+	fd << alias;
+	if (fd.bad())
+	{
+		m_Reply = "FAIL : Coudn't set the new alias: failed to write the new alias to the configuration file";
+		LOG_VERBOSE << m_Reply << std::endl;
+		fd.close();
+		return -2;
+	}
+	fd.close();
+
+	UdpServer::SetHostAlias(alias);
+	UdpServer::SendAll(UdpServer::GetHostDetails());
+	return 0;
+}
+
+
+/*
+ Execute command received from a remote client
+ The command of length 'len' is in 'buf'. 'outlen' has
+ the max output buffer size.
+ On return, 'outbuf' may have a reply to be sent to the client,
+ 'outlen' should have the reply length or 0 if no reply required.
+ Returns KEEPALIVE_OK if ok, KEEPALIVE_CLOSE to close the connection, KEEPALIVE_SHUTDOWN to shutdown the server (debug mode)
+*/
+int CmdIface::do_command(const char *buf, int len)
+{
+    servercmd_t s;
+    int result = KEEPALIVE_OK;
+    replyType = REPLY_TYPE_BUFFER;
+
+    ((char*)buf)[len] = '\0';	// Make a zero-terminated string
+
+    // Parse the command
+    parse_line(buf, &s);
+    dump_parser(&s);
+
+    // Check for the parser error. Note, not all the commands in the original protocol report about errors. so we check the error
+    // for selected commands only TODO: verify the commands list reporting the error
+    if(s.cmd == CMD_OPEN_INTERFACE || s.cmd == CMD_R || s.cmd == CMD_RB || s.cmd == CMD_W || s.cmd == CMD_WB)
+    {
+        if(s.error != 0)
+        {
+            LOG_ERROR << "Command line parsing error" << std::endl;
+            m_Reply = "0xDEADDEAD\r\n";    // TODO: or should it be "dmtools_error"??
+            return result;
+        }
+    }
+
+    switch(s.cmd)
+    {
+    case CMD_GET_INTERFACES:
+        cmd_get_interfaces();
+        break;
+    case CMD_OPEN_INTERFACE:
+        cmd_open_interface(s.interface);
+        break;
+    case CMD_CLOSE_INTERFACE:
+        cmd_close_interface(s.interface);
+        break;
+    case CMD_R:
+        cmd_r(s.interface, s.address);
+        break;
+    case CMD_RB:
+        cmd_rb(s.interface, s.address, s.value);
+        break;
+    case CMD_W:
+        cmd_w(s.interface, s.address, s.value);
+        break;
+    case CMD_WB:
+        // hexdata_len is in dwords, cmd_wb works in bytes. (hence * 4)
+        cmd_wb(s.interface, s.address, s.hexdata_len * 4, (const char*)s.hexdata);
+        break;
+    case CMD_INTERFACE_RESET:
+        cmd_interface_reset(s.interface);
+        break;
+    case CMD_SW_RESET:
+	cmd_sw_reset(s.interface);
+	break;
+    case CMD_EXIT:
+        result = KEEPALIVE_CLOSE;   // Terminate the connection
+        break;
+    case CMD_ALLOC_PMC:
+        cmd_alloc_pmc(s.interface, s.address, s.value);
+        break;
+    case CMD_READ_PMC:
+        cmd_read_pmc(s.interface, s.address);
+        break;
+    case CMD_READ_PMC_FILE:
+        cmd_read_pmc_file(s.address);
+        break;
+	case CMD_SET_HOST_ALIAS:
+		cmd_set_host_alias(s.interface);
+		break;
+    case CMD_COMMAND_UNKNOWN:
+    default:
+        m_Reply = "dmtools_error\r\n";
+
+    }
+    return result;
+}
+
+/*
+ Dump the parser structure, for debugging only
+*/
+void CmdIface::dump_parser(servercmd_t *s)
+{
+    if(s->error)
+    {
+        LOG_ERROR << "Parser error in comand parsing."
+            << " Error: " << s->error
+            << " Message: " << parser_error_to_string(s->error)
+            << std::endl;
+
+        return;
+    }
+
+    LOG_VERBOSE << "Parsed Command: " << command_to_string(s->cmd)
+                << " Interface: " <<  s->interface  << std::endl;
+
+    if(s->address != (unsigned int)-1)
+    {
+        LOG_VERBOSE << "Address: " << s->address << std::endl;
+    }
+    if(s->value != (unsigned int)-1)
+    {
+        LOG_VERBOSE << "Value: " << s->value << std::endl;
+    }
+    if(s->hexdata_len)
+    {
+        for(int i=0; i < s->hexdata_len && i < MAX_REGS_LEN; i++)
+            LOG_VERBOSE << std::hex << "0x" << s->hexdata[i] << std::dec << std::endl;
+    }
+}
+
+/*
+*/
+int CmdIface::get_reply_len()
+{
+    return m_Reply.size();
+}
+
+/*
+*/
+void CmdIface::to_lower(char* string)
+{
+    for (int i = 0; string[i]; i++)
+    {
+	string[i] = tolower(string[i]);
+    }
+
+    return;
+}
+
+/*
+*/
+CmdIface::CmdIface()
+    : replyType(REPLY_TYPE_BUFFER)
+{
+}
diff --git a/debug-tools/remoteserver/cmdiface.h b/debug-tools/remoteserver/cmdiface.h
new file mode 100644
index 0000000..a58864e
--- /dev/null
+++ b/debug-tools/remoteserver/cmdiface.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef __interface_h
+#define __interface_h
+
+#include <pthread.h>
+#include <string>
+
+extern "C"
+{
+#include "parser.h"
+}
+
+struct open_interface_s {
+    char interface[MAX_INTERFACE_NAME];
+    void *handler;
+    struct open_interface_s *next;
+};
+
+#define KEEPALIVE_OK    0    // keep the connection
+#define KEEPALIVE_CLOSE 1    // close the connection
+#define KEEPALIVE_SHUTDOWN 2 // close the connection and shutdown the server. For debugging only, remove from the production
+
+
+// Max buffer size for a command and a reply. We should consider the longest command/data sequence to fit in a buffer.
+// rb reading 1024 (MAX_REGS_LEN) registers: rb HHHHHHHH HHHH 1024*(0xHHHHHHHH) = 17 + 1024*10 = 10257 bytes
+// wb writing 1024 (MAX_REGS_LEN) hex values: wb HHHHHHHH "1024*HH" = 14+1024*2 = 2062 bytes
+#define MAX_INPUT_BUF (11*MAX_REGS_LEN)
+
+// The reply data may be generated in several ways, the data is expected to be obtained according to this type
+enum REPLY_TYPE
+{
+    REPLY_TYPE_NONE,
+    REPLY_TYPE_BUFFER,
+    REPLY_TYPE_FILE
+};
+
+
+class CmdIface
+{
+public:
+    CmdIface();
+
+    int do_command(const char *buf, int len);
+    const char *get_reply() const { return m_Reply.c_str(); };
+    int   get_reply_len();
+    REPLY_TYPE get_reply_type() const { return replyType; }
+
+private:
+
+    static struct open_interface_s *open_interfaces;
+    static pthread_mutex_t open_interfaces_mutex;
+    static int interface_id;                        // Interface id counter returned in open_interface
+
+    void *get_interface(const char *name);
+    void *add_interface(const char *name, void *handler);
+    void del_interface(void *handler);
+
+    int cmd_get_interfaces();
+    int cmd_open_interface(char *interface);
+    int cmd_close_interface(char *interface);
+    int cmd_r(char *interface, unsigned int address);
+    int cmd_rb(char *interface, unsigned int address, unsigned int num_regs);
+    int cmd_w(char *interface, unsigned int address, unsigned int data);
+    int cmd_wb(char *interface, unsigned int address, unsigned int len, const char *block);
+    int cmd_interface_reset(char *interface);
+    int cmd_sw_reset(char *interface);
+    int cmd_alloc_pmc(char *interface, unsigned int desc_size, unsigned int desc_num);
+    int cmd_read_pmc(char *interface, unsigned int ref_number);
+    int cmd_read_pmc_file(unsigned int ref_number);
+    void dump_parser(servercmd_t *s);
+    int cmd_set_host_alias(char *alias);
+
+    void to_lower(char* string);
+
+    REPLY_TYPE replyType;
+    std::string m_Reply;
+
+};
+
+#endif // interface_h
+
diff --git a/debug-tools/remoteserver/debug.cpp b/debug-tools/remoteserver/debug.cpp
new file mode 100644
index 0000000..7a3502d
--- /dev/null
+++ b/debug-tools/remoteserver/debug.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "debug.h"
+#include <stdio.h>
+
+// *************************************************************************************************
+
+LogConfig g_LogConfig(LOG_SEV_INFO, false);
+
+// *************************************************************************************************
+
+LogConfig::LogConfig(LogSeverity maxSeverity, bool bPrintLocation)
+    : m_MaxSeverity(maxSeverity), m_PrintLocation(bPrintLocation)
+{
+}
+
+void LogConfig::SetMaxSeverity(int traceLevel)
+{
+    if (traceLevel > LOG_SEV_VERBOSE)
+    {
+        fprintf(stderr, "Invalid trace level, setting %d\n", LOG_SEV_VERBOSE);
+        m_MaxSeverity = LOG_SEV_VERBOSE;
+    }
+    else
+    {
+        m_MaxSeverity = static_cast<LogSeverity>(traceLevel);
+        fprintf(stdout, "Setting trace level to %d\n", m_MaxSeverity);
+    }
+}
+
+// *************************************************************************************************
+
+const char* LogMsgPrefix::SeverityToString(LogSeverity sev)
+{
+    static const char* const pSeverityToString[] = { "ERR", "WRN", "INF", "DBG", "VRB" };
+
+    size_t index = static_cast<size_t>(sev);
+    if (index >= sizeof(pSeverityToString)/sizeof(pSeverityToString[0]))
+    {
+        return "---";
+    }
+
+    return pSeverityToString[index];
+}
+
+std::ostream& operator<<(std::ostream& os, const LogMsgPrefix& prefix)
+{
+    os << '[' << LogMsgPrefix::SeverityToString(prefix.Severity) << "] ";
+    if (!g_LogConfig.ShouldPrintLocation()) return os;
+    return os << "(" << prefix.File << ':' << prefix.Line << ") ";
+}
diff --git a/debug-tools/remoteserver/debug.h b/debug-tools/remoteserver/debug.h
new file mode 100644
index 0000000..d3c99bf
--- /dev/null
+++ b/debug-tools/remoteserver/debug.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef __debug_h
+#define __debug_h
+
+#include <iostream>
+
+// Severity values are expected to raise from zero
+enum LogSeverity
+{
+    LOG_SEV_ERROR   = 0,   // Unexpected input/events that may cause server misbehavior
+    LOG_SEV_WARNING = 1,   // Suspicious events
+    LOG_SEV_INFO    = 2,   // Events like command/response
+    LOG_SEV_DEBUG   = 3,   // Detailed functionality
+    LOG_SEV_VERBOSE = 4    // Excessive debug
+};
+
+#define TRACE_WITH_PREFIX(SEV)    \
+    g_LogConfig.ShouldPrint(SEV) && std::cout << LogMsgPrefix(SEV, __FILE__, __LINE__)
+
+#define LOG_ERROR   TRACE_WITH_PREFIX(LOG_SEV_ERROR)
+#define LOG_WARNING TRACE_WITH_PREFIX(LOG_SEV_WARNING)
+#define LOG_INFO    TRACE_WITH_PREFIX(LOG_SEV_INFO)
+#define LOG_DEBUG   TRACE_WITH_PREFIX(LOG_SEV_DEBUG)
+#define LOG_VERBOSE TRACE_WITH_PREFIX(LOG_SEV_VERBOSE)
+
+// *************************************************************************************************
+
+struct LogConfig
+{
+public:
+    LogConfig(LogSeverity maxSeverity, bool bPrintLocation);
+    void SetMaxSeverity(int traceLevel);
+
+    bool ShouldPrint(LogSeverity sev) const { return sev <= m_MaxSeverity; }
+    bool ShouldPrintLocation() const { return m_PrintLocation; }
+
+private:
+
+    LogSeverity m_MaxSeverity;
+    const bool m_PrintLocation;
+
+};
+
+// *************************************************************************************************
+
+extern LogConfig g_LogConfig;
+
+// *************************************************************************************************
+
+class LogMsgPrefix
+{
+    friend std::ostream& operator<<(std::ostream& os, const LogMsgPrefix& prefix);
+
+public:
+
+    LogMsgPrefix(LogSeverity severity, const char* pFile, int line)
+        : Severity(severity), File(pFile), Line(line) {}
+
+private:
+
+    static const char* SeverityToString(LogSeverity sev);
+
+    const LogSeverity Severity;
+    const char* const File;
+    const int Line;
+};
+
+
+// *************************************************************************************************
+// Stream Formatters
+// *************************************************************************************************
+
+// Print a boolean value as a string
+struct BoolStr
+{
+    explicit BoolStr(bool value): Value(value) {}
+    const bool Value;
+};
+
+inline std::ostream& operator<<(std::ostream& os, const BoolStr& boolStr)
+{
+    return os << std::boolalpha << boolStr.Value << std::noboolalpha;
+}
+
+// *************************************************************************************************
+
+// Print a string while displaying newline characters
+struct PlainStr
+{
+    explicit PlainStr(const std::string& value): Value(value) {}
+    const std::string& Value;
+};
+
+inline std::ostream& operator<<(std::ostream& os, const PlainStr& plainStr)
+{
+    for (std::string::const_iterator it = plainStr.Value.begin(); it != plainStr.Value.end(); ++it)
+    {
+        switch (*it)
+        {
+        case '\r': os << "\\r"; break;
+        case '\n': os << "\\n"; break;
+        case '\t': os << "\\t"; break;
+        default:   os << *it; break;
+        }
+    }
+
+    return os;
+}
+
+
+#endif
diff --git a/debug-tools/remoteserver/file_reader.cpp b/debug-tools/remoteserver/file_reader.cpp
new file mode 100644
index 0000000..3e08e73
--- /dev/null
+++ b/debug-tools/remoteserver/file_reader.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "file_reader.h"
+#include "debug.h"
+
+#include <cstring>
+#include <cerrno>
+#include <stdio.h>
+
+// *************************************************************************************************
+
+FileReader::FileReader(const char* pFileName)
+    : m_FileName(pFileName)
+    , m_pFile(NULL)
+    , m_FileSize(0)
+    , m_ReadTillNow(0)
+    , m_IsCompleted(false)
+    , m_IsError(false)
+{
+    if (NULL == pFileName)
+    {
+        LOG_ERROR << "No file name provided" << std::endl;
+        return;
+    }
+
+    LOG_DEBUG << "Opening file reader for: " << m_FileName << std::endl;
+    m_pFile = fopen(pFileName, "rb");
+
+    if (NULL == m_pFile)
+    {
+        int lastErrno = errno;
+        LOG_ERROR << "Error opening file."
+                  << " Name: " << pFileName
+                  << " Error: " << lastErrno
+                  << " Message: " << strerror(lastErrno)
+                  << std::endl;
+        return;
+    }
+
+    fseek (m_pFile, 0, SEEK_END);
+    m_FileSize = ftell(m_pFile);
+    rewind(m_pFile);
+
+    LOG_DEBUG <<"Get file size for " << pFileName << ": " << m_FileSize << "B" << std::endl;
+}
+
+// *************************************************************************************************
+
+FileReader::~FileReader()
+{
+    if (m_pFile)
+    {
+        LOG_DEBUG << "Closing the file: " << m_FileName << std::endl;
+        fclose (m_pFile);
+        m_pFile = NULL;
+    }
+}
+
+// *************************************************************************************************
+
+bool FileReader::CanReadFromFile(char* pBuf, size_t availableSpace)
+{
+    if (!pBuf)
+    {
+        LOG_ERROR << "Cannot read from file " << m_FileName << ": "
+                  << "No buffer is provided" << std::endl;
+        return false;
+    }
+
+    if (0 == availableSpace)
+    {
+        LOG_ERROR << "Cannot read from file " << m_FileName << ": "
+                  << "No buffer space is provided" << std::endl;
+        return false;
+    }
+
+    if (NULL == m_pFile)
+    {
+        LOG_ERROR << "Cannot read from file " << m_FileName << ": "
+                  << "No file handle is available" << std::endl;
+        return false;
+    }
+
+    if (m_IsCompleted)
+    {
+        LOG_ERROR << "Unexpected read from file " << m_FileName << ": "
+                  << "EoF is reached" << std::endl;
+        return false;
+    }
+
+    if (m_IsError)
+    {
+        LOG_ERROR << "Unexpected read from file " << m_FileName << ": "
+                  << "Error occured" << std::endl;
+        return false;
+    }
+
+    return true;
+
+}
+
+// *************************************************************************************************
+
+size_t FileReader::ReadChunk(char* pBuf, size_t availableSpace)
+{
+    LOG_DEBUG << "Reading a chunk."
+              << " File Name: "     << m_FileName
+              << " File Size: "     << m_FileSize << "B"
+              << " Read till now: " << m_ReadTillNow << "B"
+              << " Buffer: "        << availableSpace << "B"
+              << " Completed: "     << BoolStr(m_IsCompleted)
+              << " Error: "         << BoolStr(m_IsError)
+              << std::endl;
+
+    if (false == CanReadFromFile(pBuf, availableSpace))
+    {
+        LOG_ERROR << "Cannot read from file: " << m_FileName
+                  << " Check previous errors/status" << std::endl;
+        m_IsError = true;
+        return 0;
+    }
+
+    // Read up to availableSpace. Reading less means either EoF is reached or read error occured
+    size_t readBytes = fread(pBuf, 1, availableSpace, m_pFile);
+    m_ReadTillNow += readBytes;
+
+    if (feof(m_pFile))
+    {
+        LOG_DEBUG << "EOF reached" << std::endl;
+        m_IsCompleted = true;
+    }
+
+    if (ferror(m_pFile))
+    {
+        int lastErrno = errno;
+        m_IsError = true;
+        LOG_ERROR << "Cannot read file"
+                  << " Name: "   << m_FileName
+                  << " Error: "  << lastErrno
+                  << " Message:" << strerror(lastErrno)
+                  << std::endl;
+    }
+
+    LOG_VERBOSE << "Got a chunk."
+                << " File Name: "     << m_FileName
+                << " File Size: "     << m_FileSize << "B"
+                << " Read till now: " << m_ReadTillNow << "B"
+                << " Buffer: "        << availableSpace << "B"
+                << " Completed: "     << BoolStr(m_IsCompleted)
+                << " Error: "         << BoolStr(m_IsError)
+                << std::endl;
+
+    return readBytes;
+
+}
diff --git a/debug-tools/remoteserver/file_reader.h b/debug-tools/remoteserver/file_reader.h
new file mode 100644
index 0000000..2b7b12f
--- /dev/null
+++ b/debug-tools/remoteserver/file_reader.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _FILE_READER_H_
+#define _FILE_READER_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+
+// *************************************************************************************************
+
+// Reads a file from the file system and exports its content to a buffer provided by the caller.
+// If the file is larger than a provide bugffer, it is delivered by chunks of the buffer size.
+// The last chunk may occupy less than the whole buffer. It's a caller's responsibility to allocate
+// the buffer and call the FileReader API untill the file is fully exported.
+
+class FileReader
+{
+public:
+
+    explicit FileReader(const char* pFileName);
+    ~FileReader();
+
+    size_t ReadChunk(char* pBuf, size_t availableSpace);
+
+    bool IsCompleted() const { return m_ReadTillNow == m_FileSize; }
+    bool IsError() const { return m_IsError; }
+
+    size_t ReadTillNow() const { return m_ReadTillNow; }
+    size_t GetFileSize() const { return m_FileSize; }
+
+private:
+
+    bool CanReadFromFile(char* pBuf, size_t availableSpace);
+
+    const std::string m_FileName;        // File name - cached for tracing
+    FILE* m_pFile;                       // File Handler - open for read
+    size_t m_FileSize;                   // File Size
+    size_t m_ReadTillNow;                // Bytes read till now
+    bool m_IsCompleted;                  // Set to true when OEF is reached
+    bool m_IsError;                      // Error flag
+
+};
+
+
+#endif    // _FILE_READER_H_
diff --git a/debug-tools/remoteserver/main.cpp b/debug-tools/remoteserver/main.cpp
new file mode 100644
index 0000000..dae1030
--- /dev/null
+++ b/debug-tools/remoteserver/main.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>     // getopt
+#include <stdlib.h>     // atoi
+#include <signal.h>	// SIGQUIT handling
+#include "parser.h"
+#include "server.h"
+#include "udp_server.h"
+#include "debug.h"
+
+#define WILSERVER_VERSION 0x0100
+#define DEFAULT_SERVER_PORT 12348
+#define DEFAULT_UDP_LOCAL_SERVER_PORT_IN 12349
+#define DEFAULT_UDP_REMOTE_SERVER_PORT_IN 12350
+
+UdpServer us;
+Server s;
+
+void sig_quit_handler(int signum)
+{
+    if (signum == SIGQUIT)
+    {
+        printf("Exiting Wilserver as per user request\n");
+        us.stop();
+        s.stop();
+        exit(signum);
+    }
+}
+
+int main(int argc, char* argv[])
+{
+    // Register for SIGQUIT signal
+    signal(SIGQUIT, sig_quit_handler);
+
+    int opt;
+    int port=DEFAULT_SERVER_PORT;
+    int localUdpPortIn = DEFAULT_UDP_LOCAL_SERVER_PORT_IN;
+    int remoteUdpPortIn = DEFAULT_UDP_REMOTE_SERVER_PORT_IN;
+    int traceLevel = LOG_SEV_WARNING;
+
+    while ((opt = getopt(argc, argv, "d:vp:")) != -1) {
+        switch (opt) {
+        case 'd':
+            traceLevel = atoi(optarg);
+            g_LogConfig.SetMaxSeverity(traceLevel);
+            break;
+        case 'p':
+            port = atoi(optarg);
+            if(port == 0)  {
+                LOG_ERROR << "Invalid port specified" << optarg << std::endl;
+                exit(EXIT_FAILURE);
+            }
+            break;
+        default:
+            fprintf(stderr, "Usage: %s [-d debug_level] | [-p port]\n", argv[0]);
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    LOG_INFO << "Starting WIGIG Remote Server" << std::endl;
+    us.start(localUdpPortIn, remoteUdpPortIn);
+    s.start(port);
+    return 0;
+}
+
+
diff --git a/debug-tools/remoteserver/parser.h b/debug-tools/remoteserver/parser.h
new file mode 100644
index 0000000..112f90f
--- /dev/null
+++ b/debug-tools/remoteserver/parser.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef __parser_h
+#define __parser_h
+
+#include "servercmd.h"
+
+
+int parse_line(const char *line, servercmd_t *s);
+
+#endif /* __parser_h */
diff --git a/debug-tools/remoteserver/parser.l b/debug-tools/remoteserver/parser.l
new file mode 100644
index 0000000..e4d0507
--- /dev/null
+++ b/debug-tools/remoteserver/parser.l
@@ -0,0 +1,211 @@
+%{
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "servercmd.h"
+
+static int acc_byte = 0;
+static int acc_len =  0;
+
+%}
+%option noyywrap
+%option nounput
+/* We need reentratnt scanner for multiple connections */
+%option reentrant
+/* %option c++ */
+%x str
+DIGIT		[0-9]
+HEXDIGIT	[0-9A-Fa-f]
+
+ID		[A-Za-z_!][A-Za-z_!0-9]*
+
+%%
+"get_interfaces"  {
+		if(cb_cmd(yyextra, CMD_GET_INTERFACES))
+			yyterminate();
+		}
+"open_interface"	{
+		if(cb_cmd(yyextra, CMD_OPEN_INTERFACE))
+			yyterminate();
+		}
+"close_interface" {
+		if(cb_cmd(yyextra, CMD_CLOSE_INTERFACE))
+			yyterminate();
+		}
+"r"		{
+		if(cb_cmd(yyextra, CMD_R))
+			yyterminate();
+		}
+"rb"		{
+		if(cb_cmd(yyextra, CMD_RB))
+			yyterminate();
+		}
+"w"		{
+		if(cb_cmd(yyextra, CMD_W))
+			yyterminate();
+		}
+"wb"		{
+		if(cb_cmd(yyextra, CMD_WB))
+			yyterminate();
+		}
+"alloc_pmc"	{
+		if(cb_cmd(yyextra, CMD_ALLOC_PMC))
+			yyterminate();
+		}
+"read_pmc"	{
+		if(cb_cmd(yyextra, CMD_READ_PMC))
+			yyterminate();
+		}
+"read_pmc_file" {
+		if(cb_cmd(yyextra, CMD_READ_PMC_FILE))
+			yyterminate();
+		}
+"interface_reset" {
+		if(cb_cmd(yyextra, CMD_INTERFACE_RESET))
+			yyterminate();
+		}
+
+"sw_reset"      {
+		if(cb_cmd(yyextra, CMD_SW_RESET))
+			yyterminate();
+		}
+"exit"  {
+        if(cb_cmd(yyextra, CMD_EXIT))
+            yyterminate();
+        }
+"set_host_alias"  {
+        if(cb_cmd(yyextra, CMD_SET_HOST_ALIAS))
+            yyterminate();
+        }
+{DIGIT}+	{
+		/* A decimal number represents the address/value */
+		if(cb_number(yyextra, yytext))
+			yyterminate();
+		}
+
+{ID}		{
+		/* The protocol doesn't separate between interface id and command */
+		if(cb_id(yyextra, yytext))
+			yyterminate();
+		}
+\"		{
+		/* Start of string */
+		BEGIN(str);
+		acc_byte = 0;
+		acc_len = 0;
+		}
+<str>\"		{
+		/* End of string */
+		if(acc_len > 0) {
+			if(cb_hexbyte(yyextra, acc_byte))
+				yyterminate();
+		}
+		/* Callback for end of hex string */
+		if(cb_endhex(yyextra))
+			yyterminate();
+		BEGIN(INITIAL);
+		}
+<str>{HEXDIGIT}	{
+		/* We get hex bytes in the string */
+		if(acc_len == 10)  {
+			cb_error(yyextra, ERR_BAD_HEX_VALUE, "");
+			yyterminate();
+		}else if(acc_len <= 1){
+			acc_len++;
+		// do nothing on the 0x
+		}
+		else  {
+			acc_len++;
+			acc_byte = acc_byte * 16 +  hexdigit(yytext[0]);
+			}
+		}
+<str>[ \t]	{
+		/* Hex bytes separated by spaces */
+			if(acc_len > 0) {
+				if(cb_hexbyte(yyextra, acc_byte))
+					yyterminate();
+				acc_len = 0;
+				acc_byte = 0;
+			}
+		}
+<str><<EOF>>	{
+		/* Check the end of string with unterminated quote */
+		cb_error(yyextra, ERR_UNTERMINATED_STRING, "");
+		yyterminate();
+		}
+<str>x		{
+		/* if we ancounter 0x, remove the x and continue */
+			if(acc_len != 1){
+				cb_error(yyextra, ERR_BAD_HEX_VALUE, "");
+			}
+			acc_len++;
+		}
+<str>.		{
+		/* Anything except the hex bytes is not allowed in the string parameter */
+		cb_error(yyextra, ERR_BAD_HEX_VALUE, "");
+		yyterminate();
+		}
+
+[ \t\r\n]+	{
+		/* Whitespace */
+		if(cb_separator(yyextra))
+			yyterminate();
+		}
+.		{
+		cb_error(yyextra, ERR_BAD_TOKEN, yytext);
+		yyterminate();
+		}
+%%
+
+/*
+ Parses the input line
+*/
+int parse_line(const char *line, servercmd_t *s)
+{
+	yyscan_t scanner;
+	YY_BUFFER_STATE bs;
+	cb_parser_start(s);
+        yylex_init(&scanner);
+
+        if (!scanner)
+        {
+            return 1;
+        }
+
+	yyset_extra(s, scanner);
+	bs = yy_scan_string(line, scanner);
+	yylex(scanner);
+	yy_delete_buffer(bs, scanner);
+	yylex_destroy(scanner);
+	cb_parser_end(s);
+	return s->error;
+}
+
+
+
diff --git a/debug-tools/remoteserver/pmc_file.cpp b/debug-tools/remoteserver/pmc_file.cpp
new file mode 100644
index 0000000..e449739
--- /dev/null
+++ b/debug-tools/remoteserver/pmc_file.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "pmc_file.h"
+#include "debug.h"
+
+#include <cstring>
+#include <cerrno>
+#include <sstream>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+// *************************************************************************************************
+#ifdef __ANDROID__
+#define PMC_DATA_DIRECTORY "/data/pmc"
+#else
+#define PMC_DATA_DIRECTORY "/var/pmc"
+#endif
+
+// PMC directory and file name pattern should be managed separately as directory is required as a
+// separate variable.
+
+const char* const PmcFile::s_pDirectory = PMC_DATA_DIRECTORY;
+const char* const PmcFile::s_pFileNamePrefix = "pmc_data_";
+
+// *************************************************************************************************
+
+PmcFile::PmcFile(int fileId)
+    : m_FileId(fileId)
+{
+    std::stringstream ss;
+    ss << s_pDirectory << '/' << s_pFileNamePrefix << fileId;
+    m_FileName = ss.str();
+
+    LOG_DEBUG << "PMC file name #" << fileId << " generated: " << m_FileName << std::endl;
+}
+
+std::ostream& operator<<(std::ostream& os, const PmcFile& pmcFile)
+{
+    return os << "PMC file #" << pmcFile.GetFileId() << " (" << pmcFile.GetFileName() << ')';
+}
+
+// *************************************************************************************************
+
+PmcFileWriter::PmcFileWriter(const PmcFile& pmcFile)
+    : m_PmcFile(pmcFile)
+{
+}
+
+// *************************************************************************************************
+
+bool PmcFileWriter::CreateDirectoryIfNeeded() const
+{
+    // Create a PMC directory if does not exist
+    struct stat st = {};
+    if (stat(m_PmcFile.GetDirectory(), &st) != -1)
+    {
+        LOG_DEBUG << "PMC directory " << m_PmcFile.GetDirectory()
+                  << " exists for " << m_PmcFile.GetFileName() << std::endl;
+        return true;
+    }
+
+    LOG_DEBUG << "Creating a PMC directory: " << m_PmcFile.GetDirectory() << std::endl;
+
+    int status = mkdir(m_PmcFile.GetDirectory(), 0700);
+    if (0 != status)
+    {
+        int lastErrno = errno;
+        LOG_ERROR << "Cannot create PMC directory."
+                  << " Path: "    << m_PmcFile.GetDirectory()
+                  << " Error:"    <<  lastErrno
+                  << " Message: " << strerror(lastErrno)
+                  << std::endl;
+
+        return false;
+    }
+
+    return true;
+}
+
+// *************************************************************************************************
+
+bool PmcFileWriter::WriteFile() const
+{
+    if (false == CreateDirectoryIfNeeded())
+    {
+        LOG_ERROR << "Cannot create a PMC directory for " << m_PmcFile << std::endl;
+        return false;
+    }
+
+    // Create a PMC file
+    const char* pCmdPrefix =
+        "D=$(find /sys/kernel/debug/ieee80211/ -name wil6210); cat $D/pmcdata >> ";
+    std::stringstream ss;
+    ss << pCmdPrefix << m_PmcFile.GetFileName();
+
+    system(ss.str().c_str());
+    return true;
+
+}
+
+// *************************************************************************************************
+
+size_t PmcFileWriter::GetFileSize() const
+{
+    FILE *pFile = fopen(m_PmcFile.GetFileName(), "r");
+
+    if (NULL == pFile)
+    {
+        int lastErrno = errno;
+        LOG_ERROR << "Cannot open " << m_PmcFile << " for writing."
+                  << " Error: "   << lastErrno
+                  << " Message: " << strerror(lastErrno)
+                  << std::endl;
+        return 0;
+    }
+
+    fseek (pFile, 0, SEEK_END);
+    size_t fileSize = ftell(pFile);
+    fclose(pFile);
+
+    LOG_DEBUG << "Get PMC file size for " << m_PmcFile
+              << ": " << fileSize << "B" << std::endl;
+
+    return fileSize;
+}
diff --git a/debug-tools/remoteserver/pmc_file.h b/debug-tools/remoteserver/pmc_file.h
new file mode 100644
index 0000000..b7af0b7
--- /dev/null
+++ b/debug-tools/remoteserver/pmc_file.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _PMC_FILE_H_
+#define _PMC_FILE_H_
+
+#include <stdio.h>
+#include <string>
+
+// *************************************************************************************************
+
+// Generates a PMC file name from its ID.
+class PmcFile
+{
+public:
+
+    explicit PmcFile(int fileId);
+
+    int GetFileId() const { return m_FileId; }
+    const char* GetFileName() const { return m_FileName.c_str(); }
+
+    static const char* GetDirectory() { return s_pDirectory; }
+
+private:
+
+    static const char* const s_pDirectory;
+    static const char* const s_pFileNamePrefix;
+
+    const int m_FileId;        // File ID (expected to be unique)
+    std::string m_FileName;    // File Name Buffer
+
+};
+
+std::ostream& operator<<(std::ostream& os, const PmcFile& pmcFile);
+
+// *************************************************************************************************
+
+// Creates a PMC data file according to a provided ID.
+class PmcFileWriter
+{
+public:
+
+    explicit PmcFileWriter(const PmcFile& pmcFile);
+
+    bool WriteFile() const;
+    size_t GetFileSize() const;
+
+private:
+
+    bool CreateDirectoryIfNeeded() const;
+
+    const PmcFile& m_PmcFile;
+
+};
+
+
+#endif    // PMC_FILE_H_
diff --git a/debug-tools/remoteserver/server.cpp b/debug-tools/remoteserver/server.cpp
new file mode 100644
index 0000000..5ee1b48
--- /dev/null
+++ b/debug-tools/remoteserver/server.cpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cerrno>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <fstream>
+#include "server.h"
+#include "cmdiface.h"
+#include "debug.h"
+#include "pmc_file.h"
+#include "file_reader.h"
+
+// Thread parameters structure
+typedef struct {
+    int sock;
+    struct sockaddr address;
+    int addr_len;
+} connection_par_t;
+
+volatile int Server::shutdown_flag = 0;
+volatile int Server::running_threads = 0;
+pthread_mutex_t Server::threads_counter_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void *Server::server_process(void *ptr)
+{
+    char *buf;
+    CmdIface *iface;
+    int rw;
+
+    if(ptr == NULL)
+    {
+        pthread_exit(0);
+    }
+
+    connection_par_t *par = (connection_par_t*)ptr;
+    iface = new CmdIface();
+    buf = new char[MAX_INPUT_BUF+1];
+    memset(buf, 0, MAX_INPUT_BUF+1);
+    rw = read(par->sock, buf, MAX_INPUT_BUF);
+
+    while(rw > 0)
+    {
+        // Got some data
+        if(rw)
+        {
+            buf[rw] = '\0';
+            LOG_INFO << "Client Command: " << PlainStr(buf) << std::endl;
+            int cmdKeepalive = iface->do_command((const char*)buf, rw);
+            LOG_DEBUG << "Command handling keepalive: " << cmdKeepalive << std::endl;
+
+            // Check for keepalive return value
+            int replyKeepalive = reply(par->sock, iface);
+
+            if(cmdKeepalive == KEEPALIVE_CLOSE || replyKeepalive == KEEPALIVE_CLOSE)
+            {
+                // Handler asked to close the connection
+                rw = 0;
+                break;
+            }
+        }
+        rw = read(par->sock, buf, MAX_INPUT_BUF);
+    }
+
+    // if 0 - connection is closed, <0 - error
+    LOG_DEBUG << "Closing connection. Read result: " << rw << std::endl;
+    close(par->sock);
+    delete[] buf;
+    delete iface;
+    delete par;
+    pthread_mutex_lock(&threads_counter_mutex);
+    running_threads--;
+    pthread_mutex_unlock(&threads_counter_mutex);
+    pthread_exit(0);
+}
+
+int Server::reply(int sock, CmdIface* iface)
+{
+    LOG_INFO << "Reply: " << PlainStr(iface->get_reply()) << std::endl;
+
+    switch (iface->get_reply_type())
+    {
+    case REPLY_TYPE_BUFFER:
+        return reply_buffer(sock, iface->get_reply(), iface->get_reply_len());
+
+    case REPLY_TYPE_FILE:
+        return reply_file(sock, iface->get_reply());
+
+    default:
+        LOG_ERROR << "Unexpected reply type: " << iface->get_reply_type() << std::endl;
+        return KEEPALIVE_CLOSE;
+    }
+}
+
+int Server::reply_buffer(int sock, const char* pBuf, size_t len)
+{
+    LOG_DEBUG << "Replying from a buffer (" << len << "B) Content: " << PlainStr(pBuf) << std::endl;
+
+    if (0 == len)
+    {
+        LOG_ERROR << "No reply generated by a command handler - connection will be closed" << std::endl;
+        return KEEPALIVE_CLOSE;
+    }
+
+    if (false == send_buffer(sock, pBuf, len))
+    {
+        return KEEPALIVE_CLOSE;
+    }
+
+    return KEEPALIVE_OK;
+}
+
+int Server::reply_file(int sock, const char* pFileName)
+{
+    LOG_DEBUG << "Replying from a file: " << pFileName << std::endl;
+
+    FileReader fileReader(pFileName);
+    size_t fileSize = fileReader.GetFileSize();
+
+    if (0 == fileSize)
+    {
+        LOG_ERROR << "No file content is available for reply" << std::endl;
+        return KEEPALIVE_CLOSE;
+    }
+
+    static const size_t BUF_LEN = 64 * 1024;
+
+    char* pBuf = new char[BUF_LEN];
+    size_t chunkSize = 0;
+    bool isError = false;
+
+    do
+    {
+        LOG_VERBOSE << "Requesting for a file chunk" << std::endl;
+
+        chunkSize = fileReader.ReadChunk(pBuf, BUF_LEN);
+        if (chunkSize > 0)
+        {
+            if (false == send_buffer(sock, pBuf, chunkSize))
+            {
+                LOG_ERROR << "Send error detected" << std::endl;
+                isError = true;
+                break;
+            }
+        }
+
+        // Error/Completion may occur with non-zero chunk as well
+        if (fileReader.IsError())
+        {
+            LOG_ERROR << "File read error detected" << std::endl;
+            isError = true;
+            break;
+        }
+
+        if (fileReader.IsCompleted())
+        {
+            LOG_DEBUG << "File completion detected" << std::endl;
+            break;
+        }
+
+        LOG_DEBUG << "File Chunk Delivered: " << chunkSize << "B" << std::endl;
+    }
+    while (chunkSize > 0);
+
+    delete[] pBuf;
+
+    if (isError)
+    {
+        LOG_ERROR << "Error occured while replying file content" << std::endl;
+        return KEEPALIVE_CLOSE;
+    }
+    else
+    {
+        LOG_DEBUG << "File Content successfully delivered" << std::endl;
+        return KEEPALIVE_OK;
+    }
+}
+
+bool Server::send_buffer(int sock, const char* pBuf, size_t len)
+{
+    if (!pBuf)
+    {
+        LOG_ERROR << "Cannot reply to a command - No buffer is provided" << std::endl;
+        return false;
+    }
+
+    size_t sentTillNow = 0;
+
+    while(sentTillNow < len)
+    {
+        ssize_t sentBytes = write(sock, pBuf, len);
+        if (sentBytes < 0)
+        {
+            int lastErrno = errno;
+            LOG_ERROR << "Cannot send response buffer."
+                      << " Error:" << lastErrno
+                      << " Message: " << strerror(lastErrno)
+                      << std::endl;
+            return false;
+        }
+
+        sentTillNow += sentBytes;
+        LOG_DEBUG << "Sent response chunk."
+                  << " Chunk Size: "      << sentBytes
+                  << " Sent till now: "   << sentTillNow
+                  << " Response Length: " <<  len
+                  << std::endl;
+    }
+
+    LOG_DEBUG << "Response buffer fully sent" << std::endl;
+    return true;
+}
+
+/*
+  Close the server to allow un-bind te socket - allowing future connections without delay
+*/
+int Server::stop()
+{
+    LOG_INFO << "Stopping the server" << std::endl;
+    shutdown(sock, SHUT_RDWR);
+    return 0;
+}
+
+/*
+  Initialize server on the given port. The function returns in case of error,
+  otherwise it doesn't return
+*/
+int Server::start(int port)
+{
+    LOG_INFO << "Starting the server on port " << port << std::endl;
+
+    struct sockaddr_in address;
+    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+    if(sock < 0)
+    {
+        LOG_ERROR << "Cannot create a socket on port " << port << std::endl;
+        return -1;
+    }
+
+    address.sin_family = AF_INET;
+    address.sin_addr.s_addr = INADDR_ANY;
+    address.sin_port = htons(port);
+
+    // Set the "Re-Use" socket option - allows reconnections after wilserver exit
+    int reuse = 1;
+    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
+
+    if(bind(sock, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0)
+    {
+        LOG_ERROR << "Cannot bind socket to port " << port << std::endl;
+        return -2;
+    }
+
+    if (listen(sock, 5) < 0)
+    {
+        LOG_ERROR << "Cannot listen on port " << port << std::endl;
+        return -3;
+    }
+
+    shutdown_flag = 0;
+    while (shutdown_flag == 0)  {
+        pthread_t thread;
+        connection_par_t *par = new connection_par_t;
+        par->sock = accept(sock, &par->address, (socklen_t*)&par->addr_len);
+        if(par->sock < 0)
+            delete par;
+        else {
+            pthread_mutex_lock(&threads_counter_mutex);
+            running_threads++;
+            pthread_mutex_unlock(&threads_counter_mutex);
+            pthread_create(&thread, 0, &Server::server_process, (void *)par);
+            pthread_detach(thread);
+        }
+
+    }
+    // Wait till all the threads are done in case we ever exit the loop above
+    while(running_threads > 0)
+        sleep(1);
+
+    LOG_INFO << "Server shutdown" << std::endl;
+
+    return 0; // Wont get here, just to avoid the warning
+}
diff --git a/debug-tools/remoteserver/server.h b/debug-tools/remoteserver/server.h
new file mode 100644
index 0000000..01cd080
--- /dev/null
+++ b/debug-tools/remoteserver/server.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef __server_h
+#define __server_h
+#include <pthread.h>
+#include <string>
+
+class CmdIface;
+
+class Server
+{
+public:
+
+    int start(int port);
+    int stop();
+
+    static int get_shutdown_flag() { return shutdown_flag; }
+
+
+private:
+
+    static volatile int shutdown_flag;
+    static volatile int running_threads;
+    static pthread_mutex_t threads_counter_mutex;
+    int sock;
+
+    static void *server_process(void *ptr);
+    static bool send_buffer(int sock, const char* pBuf, size_t len);
+    static int reply(int sock, CmdIface* iface);
+    static int reply_buffer(int sock, const char* pBuf, size_t len);
+    static int reply_file(int sock, const char* pFileName);
+};
+
+#endif // server_h
+
diff --git a/debug-tools/remoteserver/servercmd.cpp b/debug-tools/remoteserver/servercmd.cpp
new file mode 100644
index 0000000..bfc180b
--- /dev/null
+++ b/debug-tools/remoteserver/servercmd.cpp
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sstream>
+
+#include "servercmd.h"
+#include "debug.h"
+
+#define EXP_NON		0
+#define EXP_CMD		(-1)
+#define EXP_IFC		1
+#define EXP_NUM		2
+#define EXP_HEX		3
+#define EXP_SEP		4
+#define EXP_END		5
+
+const char* parser_state_to_string(int parserState)
+{
+    switch (parserState)
+    {
+    case EXP_NON: return "EXP_NON";
+    case EXP_CMD: return "EXP_CMD";
+    case EXP_IFC: return "EXP_IFC";
+    case EXP_NUM: return "EXP_NUM";
+    case EXP_HEX: return "EXP_HEX";
+    case EXP_SEP: return "EXP_SEP";
+    case EXP_END: return "EXP_END";
+    default:      return "<unknown>";
+    }
+}
+
+
+static int states_table[][5] =
+{
+    { EXP_END, 0,       0,       0,       0 },      // 0 - get_interfaces
+    { EXP_IFC, EXP_END, 0,       0,       0 },      // 1 - open_interface name
+    { EXP_IFC, EXP_END, 0,       0,       0 },      // 2 - close_interface name
+    { EXP_IFC, EXP_NUM, EXP_END, 0,       0 },      // 3 - r name address
+    { EXP_IFC, EXP_NUM, EXP_NUM, EXP_END, 0 },      // 4 - rb name address count
+    { EXP_IFC, EXP_NUM, EXP_NUM, EXP_END, 0 },      // 5 - w name address value
+    { EXP_IFC, EXP_NUM, EXP_HEX, EXP_END, 0 },      // 6 - wb name address hexstring
+    { EXP_IFC, EXP_END, 0,       0,       0 },      // 7 - interface_reset name
+    { EXP_IFC, EXP_END, 0,       0,       0 },      // 8 - sw_reset name
+    { EXP_END, 0,       0,       0,       0 },      // 9 - exit
+    { EXP_IFC, EXP_NUM, EXP_NUM, EXP_END, 0 },      // 10 - Alloc_PMC name number_of_descriptors size_of_descriptors
+    { EXP_IFC, EXP_NUM, EXP_END, 0,       0 },      // 11 - read_pmc interface requestReferenceNumber
+    { EXP_NUM, EXP_END, 0,       0,       0 },      // 12 - read_pmc_file requestReferenceNumber
+    { EXP_IFC, EXP_END, 0, 		 0, 	  0 }, 		// 13 - set_host_alias
+};
+
+
+// The return value is copied because std::stringstream::str() returns a temporary object
+std::string parser_state_machine_to_string(int* pStateMachine)
+{
+    if (!pStateMachine)
+    {
+        return std::string("{}");
+    }
+
+    std::stringstream ss;
+
+    ss << "{ ";
+
+    size_t numStates = sizeof(states_table[0])/sizeof(int);
+    for (size_t i = 0; i < numStates; ++i)
+    {
+        ss << parser_state_to_string(pStateMachine[i]) << " ";
+    }
+    ss << "}";
+
+    return ss.str();
+}
+
+
+const char* command_to_string(int cmdCode)
+{
+    switch (cmdCode)
+    {
+    case CMD_COMMAND_UNKNOWN: return "CMD_COMMAND_UNKNOWN";
+    case CMD_GET_INTERFACES:  return "CMD_GET_INTERFACES";
+    case CMD_OPEN_INTERFACE:  return "CMD_OPEN_INTERFACE";
+    case CMD_CLOSE_INTERFACE: return "CMD_CLOSE_INTERFACE";
+    case CMD_R:               return "CMD_R";
+    case CMD_RB:              return "CMD_RB";
+    case CMD_W:               return "CMD_W";
+    case CMD_WB:              return "CMD_WB";
+    case CMD_INTERFACE_RESET: return "CMD_INTERFACE_RESET";
+    case CMD_SW_RESET:        return "CMD_SW_RESET";
+    case CMD_EXIT:            return "CMD_EXIT";
+    case CMD_ALLOC_PMC:       return "CMD_ALLOC_PMC";
+    case CMD_READ_PMC:        return "CMD_READ_PMC";
+    case CMD_READ_PMC_FILE:   return "CMD_READ_PMC_FILE";
+    case CMD_SET_HOST_ALIAS:  return "CMD_SET_HOST_ALIAS";
+    default:                  return "<unknown>";
+    }
+}
+
+
+const char* parser_error_to_string(int parserError)
+{
+    switch (parserError)
+    {
+    case ERR_BAD_TOKEN:           return "ERR_BAD_TOKEN";
+    case ERR_BAD_VALUE:           return "VALUE";
+    case ERR_UNTERMINATED_STRING: return "ERR_UNTERMINATED_STRING";
+    case ERR_BAD_HEX_VALUE:       return "ERR_BAD_HEX_VALUE";
+    case ERR_CMD_NOT_EXPECTED:    return "ERR_CMD_NOT_EXPECTED";
+    case ERR_IFACE_NOT_EXPECTED:  return "ERR_IFACE_NOT_EXPECTED";
+    case ERR_VALUE_NOT_EXPECTED:  return "ERR_VALUE_NOT_EXPECTED";
+    case ERR_HEX_NOT_EXPECTED:    return "ERR_HEX_NOT_EXPECTED";
+    case ERR_END_NOT_EXPECTED:    return "ERR_END_NOT_EXPECTED";
+    default:                      return "<unknown>";
+    }
+}
+
+
+
+/*
+  Callback on parser start.
+  Returns the handler to be used in all subsequent callbacks
+  or NULL in case of error, the parsing will be aborted then
+*/
+void cb_parser_start(servercmd_t *s)
+{
+    s->states = NULL;
+    s->state = EXP_CMD;	// We start with expecting a command
+    s->cmd = CMD_COMMAND_UNKNOWN;
+    s->error = 0;
+    s->address = (unsigned int)-1;
+    s->value = (unsigned int)-1;
+    s->hexdata_len = 0;
+    s->hexdata = (unsigned int*)malloc (sizeof(int)*MAX_REGS_LEN);
+}
+
+/*
+  Callback on a command. Gets the command code.
+  Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+int  cb_cmd(servercmd_t *s, int cmd)
+{
+    LOG_VERBOSE <<"cb_cmd(" << cmd << ") state index = " << s->state << std::endl;
+    LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+    if(s->state != EXP_CMD)  {
+        s->error = ERR_CMD_NOT_EXPECTED;
+        LOG_ERROR << "Command not expected, expecting " << s->state << std::endl;
+        return -1;
+    }
+    LOG_VERBOSE << "Parsed Command: " << cmd << "(" << command_to_string(cmd) << ")" << std::endl;
+    s->cmd = cmd;
+    s->states = states_table[cmd];
+    s->state++;
+
+    return 0;
+}
+
+
+/*
+  Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+int  cb_id(servercmd_t *s, const char *id)
+{
+    LOG_VERBOSE << "cb_id(" << id << ") state index = " << s->state << std::endl;
+    LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+    if((s->states == NULL) || (s->states[s->state] != EXP_IFC)) {
+        s->error = ERR_IFACE_NOT_EXPECTED;
+        LOG_ERROR << "Interface not expected, expecting: "
+                  << (s->states?s->states[s->state]:-1) << std::endl;
+        return -1;
+    }
+
+    LOG_VERBOSE << "Interface id: " << id << std::endl;
+    snprintf(s->interface, MAX_INTERFACE_NAME, "%s", id);
+    s->state++;
+    return 0;
+}
+
+/*
+  Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+int  cb_number(servercmd_t *s, const char *id)
+{
+    LOG_VERBOSE << "cb_number(" << id << ") state index = " << s->state << std::endl;
+    LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+    if((s->states == NULL) || (s->states[s->state] != EXP_NUM))  {
+        s->error = ERR_VALUE_NOT_EXPECTED;
+        LOG_ERROR << "Number not expected, expecting " << (s->states?s->states[s->state]:-1) << std::endl;
+        return -1;
+    }
+
+    // A hack now. if address already set, the number is for data
+    LOG_VERBOSE << "string number " << id << std::endl;
+
+    if(s->address != (unsigned int)-1){
+        sscanf(id, "%u", &(s->value));
+        //s->value = strtoul(id, tmp, 10); //10 is the base for conversion
+	//	dprint("str to uint Parsed val %u\n",  strtoul(id, tmp, 10));
+	//	dprint("str to int Parsed val %u\n", atol(id));//s->value = atol(id);
+        LOG_VERBOSE << "scanf Parsed value: " << s->value << std::endl;
+    }
+    else{
+	//	s->address = atol(id);
+        sscanf(id, "%u", &(s->address));
+        LOG_VERBOSE << "Parsed addr " << s->address << std::endl;
+    }
+    s->state++;
+    return 0;
+}
+
+/*
+  Callback on hex data
+  Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+int  cb_hexbyte(servercmd_t *s, int b)
+{
+    LOG_VERBOSE << "cb_hexbyte(0x" << std::hex << b << std::dec << ") state index = " << s->state << std::endl;
+    LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+    if((s->states == NULL) || (s->states[s->state] != EXP_HEX)) {
+        s->error = ERR_HEX_NOT_EXPECTED;
+        LOG_ERROR << "Hex not expected, expecting " << (s->states?s->states[s->state]:-1) << std::endl;
+        return -1;
+    }
+    if(s->hexdata_len == MAX_REGS_LEN) {
+        s->error = ERR_BAD_HEX_VALUE;
+        LOG_ERROR << "Too long hex data" << std::endl;
+        return -1;
+    }
+    LOG_VERBOSE << "Hex byte 0x" << std::hex << b << std::dec << std::endl;
+    s->hexdata[s->hexdata_len] = b;
+    s->hexdata_len++;
+    // Do not change the s->state here, we are still expecting hex data. cb_endhex will change the state
+    return 0;
+}
+
+/*
+  Callback on end of hex data string
+  Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+
+int cb_endhex(servercmd_t *s)
+{
+    LOG_VERBOSE << "cb_endhex() state index = " << s->state << std::endl;
+    LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+    if((s->states == NULL) || (s->states[s->state] != EXP_HEX)) {
+        s->error = ERR_HEX_NOT_EXPECTED;
+        LOG_ERROR << "Hex not expected, expecting " << (s->states?s->states[s->state]:-1) << std::endl;
+        return -1;
+    }
+    s->state++;
+    return 0;
+}
+
+/*
+  Callback on a separator, not used.
+  Returns 0 if ok, 1 if error, the parsing will be aborted then
+*/
+int  cb_separator(servercmd_t *s)
+{
+    (void)s;
+    return 0;
+}
+
+/*
+  Callback on the parser end
+  Returns the parser result: 0 if ok, error otherwise
+*/
+void  cb_parser_end(servercmd_t *s)
+{
+    LOG_VERBOSE << "cb_parser_end() state index = " << s->state << std::endl;
+    LOG_VERBOSE << "State Machine: " << parser_state_machine_to_string(s->states) << std::endl;
+
+    if((s->error == 0) && ((s->states == NULL) || (s->states[s->state] != EXP_END)))  {
+        LOG_ERROR << "End of parser while still expecting " << (s->states?s->states[s->state]:-1) << std::endl;
+        s->error = ERR_END_NOT_EXPECTED;
+    }
+
+    free(s->hexdata);
+}
+
+/*
+  Callback on parser error
+*/
+void cb_error(servercmd_t *s, int error, const char *str)
+{
+    (void)str;
+    s->error = error;
+    LOG_ERROR << "Parser error: " << error << std::endl;
+}
+
+/*
+  Service function. Converting a hex digit from a character.
+*/
+int hexdigit(char d)
+{
+    if((d >= '0') && (d <= '9'))
+        return d-'0';
+    else if((d >= 'A') && (d <= 'F'))
+        return d-'A'+10;
+    else if((d >- 'a') && (d <= 'f'))
+        return d-'a'+10;
+    else	// This shouldn't happen, it's the parser's responsibility to parse valid hex digits
+        return 0;
+}
diff --git a/debug-tools/remoteserver/servercmd.h b/debug-tools/remoteserver/servercmd.h
new file mode 100644
index 0000000..c63e3c7
--- /dev/null
+++ b/debug-tools/remoteserver/servercmd.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef __servercmd_h
+#define __servercmd_h
+
+// This header is included by the parser, which is flex-generated C code
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Commands list
+#define CMD_COMMAND_UNKNOWN     (-1)
+#define CMD_GET_INTERFACES      0
+#define CMD_OPEN_INTERFACE      1
+#define CMD_CLOSE_INTERFACE     2
+#define CMD_R                   3
+#define CMD_RB                  4
+#define CMD_W                   5
+#define CMD_WB                  6
+#define CMD_INTERFACE_RESET     7
+#define CMD_SW_RESET            8
+#define CMD_EXIT                9  // debug command
+#define CMD_ALLOC_PMC           10
+#define CMD_READ_PMC            11
+#define CMD_READ_PMC_FILE       12
+#define CMD_SET_HOST_ALIAS		13
+
+
+const char* command_to_string(int cmdCode);
+
+#define MAX_INTERFACE_NAME 32          // TODO: better to include WlctPciAcss.h that defines MAX_IF_NAME_LENGTH==32
+#define MAX_REGS_LEN    (256* 1024)    // Max registers to read/write at once
+
+// Parser errors
+#define ERR_BAD_TOKEN (-1)
+#define ERR_BAD_VALUE (-2)
+#define ERR_UNTERMINATED_STRING (-3)
+#define ERR_BAD_HEX_VALUE (-4)
+#define ERR_CMD_NOT_EXPECTED (-5)
+#define ERR_IFACE_NOT_EXPECTED (-6)
+#define ERR_VALUE_NOT_EXPECTED (-7)
+#define ERR_HEX_NOT_EXPECTED (-8)
+#define ERR_END_NOT_EXPECTED (-9)
+
+const char* parser_error_to_string(int parserError);
+
+
+/*
+ Parser result/state structure
+*/
+typedef struct {
+	int state;
+	int cmd;
+	int *states;
+	char interface[MAX_INTERFACE_NAME+1];
+	unsigned int address;
+	unsigned int value;
+	unsigned int* hexdata;
+	int hexdata_len;
+	int error;
+} servercmd_t;
+
+
+
+/*
+ Parser callbacks
+*/
+void cb_parser_start(servercmd_t *s);
+int  cb_cmd(servercmd_t *s, int cmd);
+int  cb_id(servercmd_t *s, const char *id);
+int  cb_number(servercmd_t *s, const char *id);
+int  cb_hexbyte(servercmd_t *s, int b);
+int  cb_endhex(servercmd_t *s);
+int  cb_separator(servercmd_t *s);
+void cb_parser_end(servercmd_t *s);
+void cb_error(servercmd_t *s, int error, const char *str);
+
+/* helper functions */
+int hexdigit(char d);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // servercmd_h
diff --git a/debug-tools/remoteserver/udp_server.cpp b/debug-tools/remoteserver/udp_server.cpp
new file mode 100644
index 0000000..64c161d
--- /dev/null
+++ b/debug-tools/remoteserver/udp_server.cpp
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cerrno>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <fstream>
+#include "server.h"
+#include "cmdiface.h"
+#include "debug.h"
+#include "pmc_file.h"
+#include "file_reader.h"
+#include "udp_server.h"
+
+const std::string UdpServer::local_host = "127.0.0.1";
+const std::string UdpServer::host_details_file_name = "/etc/wigig_remoteserver_details";
+const std::string UdpServer::cmd_get_host_identity = "GetHostIdentity";
+const std::string UdpServer::cmd_delimiter = ";";
+
+std::string UdpServer::host_broadcast_ip = "";
+std::string UdpServer::host_ip = "";
+std::string UdpServer::host_alias = "";
+int UdpServer::sock_in = 0;
+int UdpServer::sock_out = 0;
+int UdpServer::port_in = 0;
+int UdpServer::port_out = 0;
+
+int UdpServer::SendAll(std::string message)
+{
+    int result = -1;
+
+    struct sockaddr_in dstAddress;
+    dstAddress.sin_family = AF_INET;
+    inet_pton(AF_INET , host_broadcast_ip.c_str(), &dstAddress.sin_addr.s_addr);
+    dstAddress.sin_port = htons(UdpServer::port_out);
+    int messageSize = message.length() * sizeof(char);
+    result = sendto(UdpServer::sock_out, message.c_str(), messageSize, 0, (sockaddr*)&dstAddress, sizeof(dstAddress));
+    LOG_DEBUG << "INFO : sendto with sock_out=" << UdpServer::sock_out << ", message=" << message << " messageSize=" << messageSize << " returned with " << result << std::endl;
+    if (result < 0)
+    {
+        LOG_DEBUG << "ERROR : Cannot send udp broadcast message, error " << errno << ": " << strerror(errno)  << std::endl;
+        return -4;
+    }
+
+    return 0;
+}
+
+int UdpServer::HandleRequest(char* buf)
+{
+    if(NULL == buf)
+    {
+        return 0;
+    }
+
+    LOG_DEBUG << "INFO : Client Command: " << PlainStr(buf) << std::endl;
+
+    std::string cmd(buf);
+    std::string answer;
+
+    if (UdpServer::local_host == host_ip)
+    {
+        LOG_DEBUG << "WARNING : There is no support in UDP srevices when using local host" << std::endl;
+        return 0;
+    }
+
+    if (UdpServer::cmd_get_host_identity == cmd)
+    {
+        answer = GetHostDetails();
+    }
+    else
+    {
+        LOG_DEBUG << "ERROR : Unkonwn UDP command" << std::endl;
+    }
+
+    // send back response in broadcast
+    // For the time being, all requests will have broadcast response
+    // All responses will use the same outgoing communication port
+    LOG_DEBUG << "INFO : Answer is: " << PlainStr(answer.c_str()) << std::endl;
+    SendAll(answer);
+
+    return 0;
+}
+
+
+/*
+  Close the server to allow un-bind te socket - allowing future connections without delay
+*/
+int UdpServer::stop()
+{
+    LOG_DEBUG << "INFO : Stopping the UDP server" << std::endl;
+    shutdown(UdpServer::sock_in, SHUT_RDWR);
+    return 0;
+}
+
+/*
+  Initialize UPD server on the given port. The function returns in case of error,
+  otherwise it doesn't return
+*/
+int UdpServer::start(int localUdpPortIn, int remoteUdpPortIn)
+{
+    LOG_DEBUG << "INFO : Starting UDP server on port " << localUdpPortIn << std::endl;
+    LOG_DEBUG << "INFO : Sending broadcast answers to port " << remoteUdpPortIn << std::endl;
+
+    //  open the UDP server on a new thread
+    UdpServer::port_in = localUdpPortIn;
+    UdpServer::port_out = remoteUdpPortIn;
+    pthread_t thread;
+    pthread_create(&thread, 0, start_udp_server, NULL);
+    pthread_detach(thread);
+
+    return 0;
+}
+
+void* UdpServer::start_udp_server(void* unused)
+{
+    (void)unused;
+    if (LoadHostDetails() < 0)
+    {
+        return NULL;
+    }
+
+    // Create outgoing response socket
+    UdpServer::sock_out = socket(AF_INET, SOCK_DGRAM, 0);
+    if (UdpServer::sock_out < 0)
+    {
+        LOG_DEBUG << "ERROR : Cannot open udp broadcast outgoing socket" << std::endl;
+        return NULL;
+    }
+
+    int enabled = 1;
+    int result;
+    result = setsockopt(UdpServer::sock_out, SOL_SOCKET, SO_BROADCAST, (char*)&enabled, sizeof(enabled));
+    if (result < 0)
+    {
+        LOG_DEBUG << "ERROR : Cannot set broadcast option for udp socket, error " << errno << ": " << strerror(errno) << std::endl;
+        shutdown(UdpServer::sock_out, SHUT_RDWR);
+        return NULL;
+    }
+
+    // Create incoming request socket
+    struct sockaddr_in address;
+    UdpServer::sock_in = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if(UdpServer::sock_in < 0)
+    {
+        LOG_DEBUG << "ERROR : Cannot create a socket on port " << UdpServer::port_in << std::endl;
+        return NULL;
+    }
+
+    address.sin_family = AF_INET;
+    address.sin_addr.s_addr = INADDR_ANY;
+    address.sin_port = htons(UdpServer::port_in);
+    // Set the "Re-Use" socket option - allows reconnections after wilserver exit
+    int reuse = 1;
+    setsockopt(UdpServer::sock_in, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
+    if(bind(UdpServer::sock_in, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0)
+    {
+        LOG_DEBUG << "ERROR : Cannot bind socket to port " << UdpServer::port_in << ", error " << errno << ": " << strerror(errno)  << std::endl;
+        return NULL;
+    }
+
+    char* buf = new char[MAX_INPUT_BUF];
+
+    do
+    {
+        if (recvfrom(UdpServer::sock_in, buf, MAX_INPUT_BUF, 0, NULL, 0) < 0)
+        {
+            LOG_DEBUG << "ERROR : Cannot listen on port " << UdpServer::port_in << std::endl;
+            return NULL;
+        }
+
+        HandleRequest(buf);
+
+    } while (true);
+
+    LOG_DEBUG << "INFO : UDP server shutdown" << std::endl;
+    return NULL; // Wont get here, just to avoid the warning
+}
+
+bool FindEthernetInterface(struct ifreq& ifr, int& fd)
+{
+    fd = socket(AF_INET, SOCK_DGRAM, 0);
+    if(fd < 0)
+    {
+        LOG_DEBUG << "ERROR : Cannot get host and broadcast IPs" << std::endl;
+        return -1;
+    }
+
+    for (int i = 0; i < 100; i++)
+    {
+        snprintf(ifr.ifr_name, IFNAMSIZ-1, "eth%d", i);
+
+        if (ioctl(fd, SIOCGIFADDR, &ifr) >= 0)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+int UdpServer::LoadHostAndBroadcastIps()
+{
+    int fd;
+    struct ifreq ifr;
+
+    ifr.ifr_addr.sa_family = AF_INET; // IP4V
+
+    // Get IP address according to OS
+    if (FindEthernetInterface(ifr, fd))
+    {
+        LOG_INFO << "Linux OS" << std::endl;
+    }
+    else
+    {
+        snprintf(ifr.ifr_name, IFNAMSIZ, "br-lan");
+        if (ioctl(fd, SIOCGIFADDR, &ifr) >= 0)
+        {
+            LOG_INFO << "OpenWRT OS" << std::endl;
+        }
+        else
+        {
+            // Probably Android OS
+            LOG_INFO << "Android OS (no external IP Adress)" << std::endl;
+            host_ip = UdpServer::local_host;
+            host_broadcast_ip = UdpServer::local_host;
+            return 0;
+        }
+    }
+    host_ip = inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr);
+
+    if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
+    {
+        LOG_DEBUG << "ERROR : Cannot get broadcast IP" << std::endl;
+        return -3;
+    }
+    host_broadcast_ip = inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr);
+    LOG_DEBUG << "INFO : " << "host_ip=" << host_ip << std::endl;
+    LOG_DEBUG << "INFO : " << "host_broadcast_ip=" << host_broadcast_ip << std::endl;
+
+    close(fd);
+    return 0;
+}
+
+void UdpServer::LoadHostAlias()
+{
+    std::ifstream infile;
+    infile.open(host_details_file_name.c_str());
+    std::getline(infile, host_alias);
+    infile.close();
+}
+
+int UdpServer::LoadHostDetails()
+{
+    if (LoadHostAndBroadcastIps() < 0)
+    {
+        return -1;
+    }
+    LoadHostAlias();
+    return 0;
+}
diff --git a/debug-tools/remoteserver/udp_server.h b/debug-tools/remoteserver/udp_server.h
new file mode 100644
index 0000000..01855d7
--- /dev/null
+++ b/debug-tools/remoteserver/udp_server.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef __udp_server_h
+#define __udp_server_h
+
+class UdpServer
+{
+public:
+    int start(int localUdpPortIn, int remoteUdpPortIn);
+    int stop();
+
+    static int SendAll(std::string message);
+    static std::string GetHostDetails() { return  UdpServer::cmd_get_host_identity + UdpServer::cmd_delimiter + host_ip + UdpServer::cmd_delimiter + host_alias; }
+    static void SetHostAlias(std::string alias) { host_alias = alias; }
+
+    static const std::string host_details_file_name;
+
+private:
+    // members
+    static const std::string local_host;
+    static const std::string cmd_get_host_identity;
+    static const std::string cmd_delimiter;
+    static std::string host_broadcast_ip;
+    static std::string host_ip;
+    static std::string host_alias;
+    static int sock_in;
+    static int sock_out;
+    static int port_in;
+    static int port_out;
+
+    // methods
+    static void* start_udp_server(void* unused);
+    static int LoadHostDetails();
+    static int  LoadHostIp(); // assumption: each host has only one IP address for ethernet interfaces
+    static void LoadHostAlias();
+    static int HandleRequest(char* buf);
+    static int LoadHostAndBroadcastIps();
+};
+
+#endif // udp_server_h
diff --git a/debug-tools/wiburn/Android.mk b/debug-tools/wiburn/Android.mk
new file mode 100644
index 0000000..34521f6
--- /dev/null
+++ b/debug-tools/wiburn/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := wigig_wiburn
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPPFLAGS := -Wall -lpthread -fexceptions
+
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH)/../lib/WlctPciAcss \
+	$(LOCAL_PATH)/../lib/FlashAcss \
+	$(LOCAL_PATH)/../lib/inc \
+	$(LOCAL_PATH)/../lib/utils
+
+LOCAL_SHARED_LIBRARIES := \
+	libwigig_utils \
+	libwigig_pciaccess \
+	libwigig_flashaccess
+
+LOCAL_SRC_FILES := \
+	wiburn.cpp \
+	translation_map.cpp \
+	ParameterParser.cpp \
+	template_inst.cpp \
+	CCRC32.cpp
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/debug-tools/wiburn/CCRC32.cpp b/debug-tools/wiburn/CCRC32.cpp
new file mode 100644
index 0000000..7352264
--- /dev/null
+++ b/debug-tools/wiburn/CCRC32.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "wlct_os.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "CCRC32.h"
+
+CCRC32::CCRC32(void)
+{
+    int index = 0;
+    while (index <= BYTE_MASK)
+    {
+        lookup[index] = Reflect(index, 8);
+        lookup[index] = lookup[index] << 24;
+
+        // Repeat 8 times
+        int subindex = 0;
+        while(subindex < 8)
+        {
+            subindex++;
+
+            int check;
+            if (lookup[index] & (1 << 31))
+            {
+                check = POLYNOMIAL;
+            }
+            else
+            {
+                check = 0;
+            }
+
+            lookup[index] = (lookup[index] << 1);
+            lookup[index] = lookup[index] ^ check;
+        }
+
+        lookup[index] = Reflect(lookup[index], 32);
+        index++;
+    }
+}
+
+uint32_t CCRC32::Reflect(uint32_t reflected, const char bitsToReflect)
+{
+    uint32_t retVal = 0;
+
+    int index = 1;
+
+    while(index < (bitsToReflect + 1))
+    {
+        if((reflected % 2) == 1)
+        {
+            retVal |= (1 << (bitsToReflect - index));
+        }
+        else
+        {
+            // do nothing
+        }
+        reflected >>= 1;
+        index++;
+    }
+
+    return retVal;
+}
+
+void CCRC32::CalcCRCStep(uint32_t *crc, const unsigned char *data, uint32_t length)
+{
+    uint32_t tempCRC = *crc;
+
+    for (uint32_t index = 0; index < length; index++)
+    {
+        tempCRC = (tempCRC >> 8) ^ lookup[(tempCRC & BYTE_MASK) ^ *data++];
+    }
+
+    *crc = tempCRC;
+}
+
+uint32_t CCRC32::CalcCRC(const unsigned char *data, uint32_t length)
+{
+    uint32_t crc = CRC_MASK;
+    CalcCRCStep(&crc, data, length);
+    return(crc ^ CRC_MASK);
+}
diff --git a/debug-tools/wiburn/CCRC32.h b/debug-tools/wiburn/CCRC32.h
new file mode 100644
index 0000000..aa896f8
--- /dev/null
+++ b/debug-tools/wiburn/CCRC32.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef CRC32_H
+#define CRC32_H
+
+#define POLYNOMIAL 0x04C11DB7
+#define CRC_MASK 0xffffffff
+#define LOOKUP_SIZE 256
+#define BYTE_MASK 0xff
+
+class CCRC32
+{
+public:
+    CCRC32();
+
+    uint32_t CalcCRC(const unsigned char *data, uint32_t length);
+
+private:
+    uint32_t Reflect(uint32_t ulReflect, const char bitsToReflect);
+    uint32_t lookup[LOOKUP_SIZE];
+    void CalcCRCStep(uint32_t *ulCRC, const unsigned char *data, uint32_t length);
+};
+
+#endif
diff --git a/debug-tools/wiburn/Makefile b/debug-tools/wiburn/Makefile
new file mode 100644
index 0000000..1e8f296
--- /dev/null
+++ b/debug-tools/wiburn/Makefile
@@ -0,0 +1,53 @@
+-include $(TOPDIR)/rules.mk
+
+CFLAGS := -fPIE -Wall -g -MMD -fPIE -Wno-reorder
+LDFLAGS := -pie -fPIE -pthread -lwigig_flashaccess -lwigig_pciaccess -lwigig_utils
+
+ifneq ($(CONFIG_TARGET_ipq)$(CONFIG_TARGET_ipq806x),)
+is_ipq806x = 1
+endif
+
+ifeq ($(is_ipq806x), 1)
+ifneq ($(strip $(TOOLPREFIX)),)
+CROSS:=$(TOOLPREFIX)
+endif
+endif
+
+CC := $(CROSS)gcc
+CXX := $(CROSS)g++
+
+.DEFAULT_GOAL = all
+PROG = wigig_wiburn
+
+INCLUDES += -I ../lib/WlctPciAcss \
+            -I ../lib/FlashAcss \
+            -I ../lib/inc \
+            -I ../lib/utils \
+
+LIBS = -L../lib/FlashAcss \
+       -L../lib/WlctPciAcss \
+       -L../lib/utils \
+
+all: $(PROG)
+
+CPP_FILES = wiburn.cpp \
+            translation_map.cpp \
+            ParameterParser.cpp \
+            template_inst.cpp \
+            CCRC32.cpp \
+
+OBJ_FILES = $(CPP_FILES:.cpp=.o)
+
+$(PROG): $(OBJ_FILES)
+	$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)
+
+%.o : %.cpp
+	$(CXX) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+clean:
+	rm -rf $(PROG)
+	find . -type f \( -name "*.d" -o -name "*.o" \) -delete
+
+
+-include $(OBJ_FILES:%.o=%.d)
+
diff --git a/debug-tools/wiburn/ParameterParser.cpp b/debug-tools/wiburn/ParameterParser.cpp
new file mode 100644
index 0000000..84980e2
--- /dev/null
+++ b/debug-tools/wiburn/ParameterParser.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "ParameterParser.h"
+
+#include "wlct_os.h"
+
+ParameterParser::ParameterParser()
+{
+}
+
+void ParameterParser::setVerbose()
+{
+    verbose = true ;
+}
+
+void ParameterParser::printVerbose()
+{
+    if( verbose )
+        cout << endl  ;
+}
+void ParameterParser::printVerbose( const char *INFO )
+{
+    if( verbose )
+        cout << INFO  ;
+}
+
+int ParameterParser::processCommandArgs( int _argc, char **_argv )
+{
+    for (int index = 1; index < _argc; index++)
+    {
+        if (IsFlag(_argv[index]))
+        {
+            Flags[_argv[index]] = true;
+        }
+        else if (IsParam(_argv[index]))
+        {
+            Parameters[_argv[index]] = _argv[index + 1];
+            index++;
+        }
+        else
+        {
+            printUsage();
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+bool ParameterParser::IsFlag(string flag)
+{
+    for (list<string>::iterator iterator = flags.begin(); iterator != flags.end(); iterator++)
+    {
+        if (flag.compare(*iterator) == 0)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ParameterParser::IsParam(string param)
+{
+    for (list<string>::iterator iterator = params.begin(); iterator != params.end(); iterator++)
+    {
+        if (param.compare(*iterator) == 0)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ParameterParser::ParamFound(string param)
+{
+    return (Parameters.find(param) != Parameters.end());
+}
+
+bool ParameterParser::FlagFound(string flag)
+{
+    return (Flags.find(flag) != Flags.end());
+}
+
+void ParameterParser::addFlag(string flag)
+{
+    flags.push_front(flag);
+}
+
+void ParameterParser::addParam(string param)
+{
+    params.push_front(param);
+}
+
+char* ParameterParser::getValue(string option)
+{
+    if (IsParam(option) && ParamFound(option))
+    {
+        return Parameters[option];
+    }
+    else
+    {
+        return NULL;
+    }
+}
+
+bool ParameterParser::getFlag(string option)
+{
+    if (IsFlag(option) && FlagFound(option))
+    {
+        return Flags[option];
+    }
+    else
+    {
+        return false;
+    }
+}
+
+void ParameterParser::printUsage()
+{
+    cout<<
+        "***************\n"\
+        "Usage \n" \
+        "***************\n" \
+        "Commands:\n" \
+        " -help              --- Prints this help \n" \
+        " -burn              --- Burn to flash\n" \
+        " -query             --- disaply the image info section from flash\n" \
+        " -read              --- read image from flash\n" \
+        " -read_formatted    --- read image from flash and display in formatted manner\n" \
+        " -erase             --- Erase the flash\n" \
+        " -debug             --- Prints debug messages\n" \
+        " -verify            --- Verify burning\n" \
+        " -force             --- Force burning even if it is unsafe\n" \
+        " -ignore_lock       --- Ignore flash lock mechanism\n" \
+        " -read_ids_to_file  --- Read the IDS section in the Flash, and write it to file\n" \
+        "\n" \
+        "Parameters:\n" \
+        " -bin binary_image_filename      --- The binary image filename to use\n" \
+        " -fw fw_ini_filename             --- The FW INI filename to use\n" \
+        " -ids ids_ini_filename           --- The IDs INI filename to use\n" \
+        " -production prod_ini_filename   --- The Production INI filename to use\n" \
+        " -board board_ini_filename       --- The board INI filename to use\n" \
+        " -board2 board_ini_filename      --- The board 2 INI filename to use\n" \
+        " -board3 board_ini_filename      --- The board 3 INI filename to use\n" \
+        " -setup_ini setup_ini_filename   --- The setup_ini INI filename to use\n" \
+        " -usb usb_ini_filename           --- The USB INI filename to use\n" \
+        " -interface interface_name       --- The interface to use\n" \
+        " -device device_type             --- The type of device\n" \
+        " -offset                         --- offset address\n" \
+        " -length                         --- Length (in bytes)\n" \
+        "\n" \
+        "Examples\n" \
+        "To burn FW INI file to flash using PCI on MARLON with ignore_loc\n" \
+        "   wiburn -erase -burn -fw fw.ini -interface wpci2l!malon -ignore_lock -device MARLO\n" \
+        "\n" \
+        "To burn FW INI file to binary image file out.bi\n" \
+        "   wiburn -burn -erase -fw fw.ini -interface out.bin -device MARLO\n" \
+        "\n" \
+        "To burn FW INI file to flash using automatically selected interfac\n" \
+        "   wiburn -burn -erase -fw fw.ini -device MARLO\n" \
+        "\n" \
+        "To read image from flash on Sparrow using Jtag\n" \
+        "   wiburn -read_formatted -length 0x80000 -offset 0 -interface wjtag0!sparrow -device SPARRO\n" \
+        "\n" \
+        "To burn IDS section to flash using JTAG\n" \
+        "   wiburn -section -ids ids_file.ini -interface wjtag0!sparrow -device SPARRO\n" \
+        "\n" \
+        "To erase the flash using JTA\n" \
+        "   wiburn -interface wjtag0!sparrow -erase -device SPARRO\n";
+}
diff --git a/debug-tools/wiburn/ParameterParser.h b/debug-tools/wiburn/ParameterParser.h
new file mode 100644
index 0000000..92f586a
--- /dev/null
+++ b/debug-tools/wiburn/ParameterParser.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _PARAMETER_PARSER_H
+#define _PARAMETER_PARSER_H
+
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <string>
+#include <map>
+#include <list>
+#include <algorithm>
+
+using namespace std;
+
+class ParameterParser
+{
+    map<string, char*> Parameters;
+    map<string, bool> Flags;
+    list<string> flags;
+    list<string> params;
+
+public:
+    ParameterParser();
+    ~ParameterParser();
+
+    int processCommandArgs( int _argc, char **_argv );
+
+    char *getValue(string _option);
+    bool  getFlag(string _option);
+
+    void printUsage();
+
+    void printHelp();
+
+    void setVerbose();
+
+    void addFlag(string flag);
+    void addParam(string param);
+
+private:
+    int argc;
+    char **argv;
+
+    bool verbose;
+
+    void printVerbose( const char *INFO );
+    void printVerbose( char *INFO );
+    void printVerbose( char ch );
+    void printVerbose( );
+
+    bool IsFlag(string flag);
+    bool IsParam(string param);
+
+    bool ParamFound(string param);
+
+    bool FlagFound(string flag);
+};
+
+#endif /* ! _PARAMETER_PARSER_H */
diff --git a/debug-tools/wiburn/flash_image.cpp b/debug-tools/wiburn/flash_image.cpp
new file mode 100644
index 0000000..6d87c22
--- /dev/null
+++ b/debug-tools/wiburn/flash_image.cpp
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "flash_image.h"
+#include <memory.h>
+#include <iostream>
+
+
+//extern ini_parser g_parser;
+
+#define NEXT_PTR(ptr) (((ptr) & SUB_SECTOR_MASK) + SUB_SECTOR )
+
+u_int16_t crc_16 (const u_int32_t *buffer, int size)
+{
+    return 0;
+    u_int16_t      crc;
+    u_int32_t element;
+
+    crc = 0xffff;
+
+    for (int j = 0; j < size; j++) {
+        element = buffer[j];
+        for (int i=0; i<32; i++) {
+            if (crc & 0x8000) {
+                crc = (u_int16_t) ((((crc<<1) | (element>>31)) ^  0x100b) & 0xffff);
+            }
+            else {
+                crc= (u_int16_t) (((crc<<1) | (element>>31)) & 0xffff);
+            }
+            element = (element<<1) & 0xffffffff;
+        }
+    }
+
+    for (int k=0; k<16; k++) {
+        if (crc & 0x8000)
+            crc=((crc<<1)  ^  0x100b) & 0xffff;
+        else
+            crc=(crc<<1) & 0xffff;
+    }
+
+    // Revert 16 low bits
+    crc = crc ^ 0xffff;
+    return crc;
+}
+
+
+template <class PRODUCT>
+flash_image<PRODUCT>::flash_image () :
+    pointer_section ("pointer_section"),
+    hw_conf_section ("hw_conf_section", hw_conf_section_id, &pointer_section.m_pointers.hw_pointer),
+
+    fw1_code_section ("fw1_code_section", fw1_code_section_id, &pointer_section.m_pointers.fw1_pointer, &pointer_section.m_pointers.fw1_length),
+    fw1_data_section ("fw1_data_section",fw1_data_section_id, &pointer_section.m_pointers.fw1_data_pointer, &pointer_section.m_pointers.fw1_data_length),
+    fw1_static_conf_section ("fw1_static_conf_section",fw1_static_conf_section_id, &pointer_section.m_pointers.fw1_static_conf_pointer),
+
+    fw2_code_section ("fw2_code_section",fw2_code_section_id, &pointer_section.m_pointers.fw2_pointer, &pointer_section.m_pointers.fw2_length),
+    fw2_data_section ("fw2_data_section",fw2_data_section_id, &pointer_section.m_pointers.fw2_data_pointer, &pointer_section.m_pointers.fw2_data_length),
+    fw2_static_conf_section ( "fw2_static_conf_section",fw2_static_conf_section_id, &pointer_section.m_pointers.fw2_static_conf_pointer),
+
+    system_config_section ( "config_section", &pointer_section.m_pointers.config_section_pointer),
+
+    production_section ("production_section",production_section_id, &pointer_section.m_pointers.production_pointer),
+    user_conf_section ("user_conf_section",user_conf_section_id, &pointer_section.m_pointers.user_pointer),
+
+    image_info_section ("image_info_section",image_info_section_id, &pointer_section.m_pointers.image_info_pointer),
+    ids_section("ids_section", ids_section_id, &pointer_section.m_pointers.ids_pointer),
+
+    usb_section("usb_section", &pointer_section.m_pointers.usb_pointer),
+    usb_info_section("usb_info_section", usb_info_section_id, &pointer_section.m_pointers.usb_info_pointer),
+
+    radio_tx_conf_section ("radio_tx_conf_section", radio_tx_conf_section_id, &pointer_section.m_pointers.radio_tx_cnf_pointer),
+    radio_rx_conf_section ("radio_rx_conf_section", radio_rx_conf_section_id, &pointer_section.m_pointers.radio_rx_cnf_pointer),
+    radio_tx_conf2_section ("radio_tx_conf2_section", radio_tx_conf2_section_id, &pointer_section.m_pointers.radio_tx_cnf2_pointer),
+    radio_rx_conf2_section ("radio_rx_conf2_section", radio_rx_conf2_section_id, &pointer_section.m_pointers.radio_rx_cnf2_pointer),
+
+    // The following is unused!
+    raw_data_section ("raw_data_section", raw_data_section_id, &pointer_section.m_pointers.raw_data_pointer, &pointer_section.m_pointers.raw_data_length),
+    proxy_product(NULL)
+{
+    //    proxy_product = new PRODUCT;
+    memset(m_image, -1, sizeof m_image);
+}
+
+template <class PRODUCT>
+flash_image<PRODUCT>::~flash_image ()
+{
+}
+
+template <class PRODUCT>
+const BYTE* flash_image<PRODUCT>::get_image (void) const
+{
+    return m_image;
+}
+
+template <class PRODUCT>
+u_int32_t flash_image<PRODUCT>::get_image_size (void) const
+{
+    return sizeof m_image;
+}
+
+template <class PRODUCT>
+void flash_image<PRODUCT>::init( const char *filename)
+{
+    FILE *stream;
+    stream = fopen(filename, "r");
+    if( NULL == stream  )
+    {
+        ERR("Failed opening file %s for reading\n", filename);
+        EXIT (-1);
+    }
+
+    u_int32_t cnt = fread(m_image, sizeof m_image, 1, stream);
+    if (cnt < sizeof m_image) {
+        INFO("Initialized from partial image file of size 0x%04x\n", cnt);
+    }
+    fclose(stream);
+}
+
+template <class PRODUCT>
+void flash_image<PRODUCT>::init_pointer_section (flash_base *fl)
+{
+    pointer_section.init(fl);
+
+    // In order to prevent reading from the flash over the signature
+    // when the flash is un-initiated, we reset the signature
+    // after reading from flash.
+    pointer_section.m_pointers.signature = 0x40;
+}
+
+template <class PRODUCT>
+void flash_image<PRODUCT>::init_hw_conf_section (flash_base *fl)
+{
+    hw_conf_section.init(fl);
+}
+
+// template <class PRODUCT>
+// void flash_image<PRODUCT>::init_radio_tx_conf_section (flash_base *fl)
+// {
+//     radio_tx_conf_section.init(fl);
+// }
+//
+// template <class PRODUCT>
+// void flash_image<PRODUCT>::init_radio_rx_conf_section (flash_base *fl)
+// {
+//     radio_rx_conf_section.init(fl);
+// }
+//
+// template <class PRODUCT>
+// void flash_image<PRODUCT>::init_radio_tx_conf2_section (flash_base *fl)
+// {
+//     radio_tx_conf2_section.init(fl);
+// }
+//
+// template <class PRODUCT>
+// void flash_image<PRODUCT>::init_radio_rx_conf2_section (flash_base *fl)
+// {
+//     radio_rx_conf2_section.init(fl);
+// }
+
+template <class PRODUCT>
+void flash_image<PRODUCT>::init_image_info_section (flash_base *fl)
+{
+    image_info_section.init(fl);
+}
+
+template <class PRODUCT>
+void flash_image<PRODUCT>::init_ids_section (flash_base *fl, bool isReduced)
+{
+    if (isReduced)
+    {
+        *ids_section.m_ptr = 4 * 1024 + sizeof(section_header_t);
+    }
+    else
+    {
+        *ids_section.m_ptr = 44 * 1024 + sizeof(section_header_t);
+    }
+
+    ids_section.init(fl);
+}
+
+template <class PRODUCT>
+void flash_image<PRODUCT>::init_usb_info_section (flash_base *fl)
+{
+    usb_info_section.init(fl);
+}
+
+template <class PRODUCT>
+const pointer_section_t<PRODUCT>& flash_image<PRODUCT>::get_pointer_section(void) const
+{
+    return pointer_section;
+}
+
+template <class PRODUCT>
+const hw_section_t<PRODUCT>& flash_image<PRODUCT>::get_hw_conf_section(void) const
+{
+    return hw_conf_section;
+}
+
+// template <class PRODUCT>
+// const hw_section_t<marlon>& flash_image<PRODUCT>::get_radio_tx_conf_section(void) const
+// {
+//     return radio_tx_conf_section;
+// }
+//
+// template <class PRODUCT>
+// const hw_section_t<marlon>& flash_image<PRODUCT>::get_radio_rx_conf_section(void) const
+// {
+//     return radio_rx_conf_section;
+// }
+//
+// template <class PRODUCT>
+// const hw_section_t<marlon>& flash_image<PRODUCT>::get_radio_tx_conf2_section(void) const
+// {
+//     return radio_tx_conf2_section;
+// }
+//
+// template <class PRODUCT>
+// const hw_section_t<marlon>& flash_image<PRODUCT>::get_radio_rx_conf2_section(void) const
+// {
+//     return radio_rx_conf2_section;
+// }
+
+template <class PRODUCT>
+const image_info_section_t<PRODUCT>& flash_image<PRODUCT>::get_image_info_section(void) const
+{
+    return image_info_section;
+}
+
+template <class PRODUCT>
+const usb_info_section_t<PRODUCT>& flash_image<PRODUCT>::get_usb_info_section(void) const
+{
+    return usb_info_section;
+}
+
+template <class PRODUCT>
+const ids_section_t<PRODUCT>& flash_image<PRODUCT>::get_ids_section(void) const
+{
+    return ids_section;
+}
+
+
+// template <class PRODUCT>
+// const image_section_t<PRODUCT>& flash_image<PRODUCT>::get_fw1_code_section () const
+// {
+//     return fw1_code_section;
+// }
+//
+// template <class PRODUCT>
+// const image_section_t<PRODUCT>& flash_image<PRODUCT>::get_fw2_code_section () const
+// {
+//     return fw2_code_section;
+// }
+
+template <class PRODUCT>
+void flash_image<PRODUCT>::save( const char *filename)
+{
+    FILE *stream;
+    stream = fopen(filename, "wb");
+    if( NULL == stream  )
+    {
+        ERR("Failed opening file %s for writing\n", filename);
+        EXIT (-1);
+    }
+
+    fwrite(m_image, sizeof m_image, 1, stream);
+    fclose(stream);
+}
+
+/*
+        MARLON:                                                            SPARROW:                                               SPARROW REDUCED:
+        +-------------------------------------------+   0k                +-------------------------------------------+   0k       +-------------------------------------------+  0k
+        |    POINTER                                |                     |    POINTER                                |            |    POINTER                                |
+        +-------------------------------------------+   4k                +-------------------------------------------+   4k       +-------------------------------------------+  4k
+        |    production         (40K)               |                     |    production        (40K)                |            |    IDS                (4K)                |
+        +-------------------------------------------+  48k                +-------------------------------------------+  48k       +-------------------------------------------+
+        |    IDS                (4K)                |                     |    IDS                (4K)                |            +-------------------------------------------+  8k
+        +-------------------------------------------+                     +-------------------------------------------+            |    HW                (4k)                 |
+        +-------------------------------------------+  52k                +-------------------------------------------+  52k       +-------------------------------------------+  12k
+        |    HW                 (4k)                |                     |    HW                (4k)                 |            |    FW CODE            (44K)               |
+        +-------------------------------------------+  56k                +-------------------------------------------+  56k       +-------------------------------------------+  56k
+        |    FW CODE            (256K)              |                     |    FW CODE            (256K)              |            |    FW DATA            (8K)                |
+        +-------------------------------------------+  312k               +-------------------------------------------+  312k      +-------------------------------------------+  64k
+        |    FW DATA            (32K)               |                     |    FW DATA            (32K)               |
+        +-------------------------------------------+  344k               +-------------------------------------------+  344k
+        |    uCode CODE         (64K)               |                     |    uCode CODE        (128K)               |
+        +-------------------------------------------+  408k               +-------------------------------------------+  472k
+        |    uCode DATA         (8K)                |                     |    uCode DATA         (8K)                |
+        +-------------------------------------------+  416k               +-------------------------------------------+  480k
+        |    FW STATICS         (4K)                |                     |    FW STATICS        (4K)                 |
+        +-------------------------------------------+  420k               +-------------------------------------------+  484k
+        |    uCode STATICS      (4K)                |                     |    uCode STATICS    (4K)                  |
+        +-------------------------------------------+                     +-------------------------------------------+
+        +-------------------------------------------+  424k               +-------------------------------------------+  488k
+        |    System Config Selector    (4K)         |                     |    System Config Selector    (4K)         |
+        +-------------------------------------------+  428k               +-------------------------------------------+  492k
+        |    System Config Factory    (4K)          |                     |    System Config Factory    (4K)          |
+        +-------------------------------------------+  432k               +-------------------------------------------+  496k
+        |    System Config User1        (4K)        |                     |    System Config User1        (4K)        |
+        +-------------------------------------------+  436k               +-------------------------------------------+  500k
+        |    System Config User2        (4K)        |                     |    System Config User2        (4K)        |
+        +-------------------------------------------+                     +-------------------------------------------+
+        +-------------------------------------------+  440k               +-------------------------------------------+  504k
+        |    IMAGE INFO        (4K)                 |                     |    IMAGE INFO        (4K)                 |
+        |            image format version           |                     |            image format version           |
+        |            FW VERSION                     |                     |            FW VERSION                     |
+        |            fw_timestamp                   |                     |            fw_timestamp                   |
+        |            ucode_version                  |                     |            ucode_version                  |
+        |            ucode_timestamp                |                     |            ucode_timestamp                |
+        |            configuration_id               |                     |            configuration_id               |
+        |            device_id                      |                     |            device_id                      |
+        |            hw_id                          |                     |            hw_id                          |
+        +-------------------------------------------+  444k               +-------------------------------------------+  508k
+        |    radio_tx_conf    (8K)                  |
+        +-------------------------------------------+  452k
+        |    radio_rx_conf    (8K)                  |
+        +-------------------------------------------+  460k
+        |    radio_tx_conf2    (8K)                 |
+        +-------------------------------------------+  468k
+        |    radio_rx_conf2    (8K)                 |
+        +-------------------------------------------+  476k
+        |    RAW DATA        (4K)                   |
+        +-------------------------------------------+  480k
+*/
+template <class PRODUCT>
+void flash_image<PRODUCT>::init(ini_parser_base *parser, bool full_image, bool isReducedSip)
+{
+	ini_file_t::iterator iter1;
+	ini_file_t::const_iterator iter2;
+	int ptr;
+	ptr = NEXT_PTR( 0 );
+	string section_name;
+	bool reducedSip = isReducedSip && ((PRODUCT::id == sparrow::id) || (PRODUCT::id == talyn::id));
+
+    if (!reducedSip)
+    {
+        section_name = "production";
+        if (parser->get_section(section_name, 0, &iter1, false, false) )
+        {
+            production_section.set_max_size( flash::SUB_SECTOR_SIZE * 10 );
+            production_section.handle_ini_section(0, *(iter1->second));
+            production_section.set_offset( ptr );
+            production_section.write_to_buffer(m_image);
+        }
+
+        //Force the section size to be 40K
+        ptr += NEXT_PTR( (1<<15) -1 );        // 32K
+        ptr += NEXT_PTR( (1<<13) -1 );        //  8K
+    }
+
+    section_name = "ids";
+
+    // Always set ids section. The existing values remain if input file is not provided
+    ids_section.set_max_size( flash::SUB_SECTOR_SIZE );
+    if (parser->get_section(section_name, 0, &iter1, true, false))
+    {
+        ids_section.handle_ini_section( *(iter1->second));
+    }
+
+    ids_section.set_offset( ptr );
+    ids_section.write_to_buffer(m_image);
+
+    ptr += NEXT_PTR( 0 );
+
+    section_name = "hw_config";
+    if (parser->get_section(section_name, TRANSLATION_MAP_REGTREE, &iter1, false, full_image))
+    {
+        hw_conf_section.set_max_size( flash::SUB_SECTOR_SIZE );
+        hw_conf_section.handle_ini_section(TRANSLATION_MAP_REGTREE, *(iter1->second));
+        hw_conf_section.set_offset( ptr );
+        hw_conf_section.write_to_buffer(m_image);
+    }
+    ptr += NEXT_PTR( 0 );
+
+    section_name = "fw_code";
+    if (parser->get_section(section_name, 0, &iter1, false, full_image))
+    {
+        if (reducedSip)
+        {
+            fw1_code_section.set_max_size( flash::SUB_SECTOR_SIZE * 11);
+        }
+        else
+        {
+            // FW code limit to 256K
+#ifdef FLASH_256KB
+            fw1_code_section.set_max_size( flash::SUB_SECTOR_SIZE * 16);
+#else
+			if (PRODUCT::id == sparrow::id)
+			{
+				fw1_code_section.set_max_size( flash::SUB_SECTOR_SIZE * 64);
+			}
+			else if (PRODUCT::id == talyn::id)
+			{
+				fw1_code_section.set_max_size( flash::SUB_SECTOR_SIZE * 256);
+			}
+			else
+			{
+				fw1_code_section.set_max_size( flash::SUB_SECTOR_SIZE * 64);
+			}
+#endif
+        }
+
+        fw1_code_section.handle_ini_section( *(iter1->second));
+        fw1_code_section.set_offset( ptr );
+        fw1_code_section.write_to_buffer(m_image);
+    }
+
+    if (reducedSip)
+    {
+        ptr += NEXT_PTR( (0xB000) -1 ); //Force the Code size to be 44K (including header+CRC)
+    }
+    else
+    {
+#ifdef FLASH_256KB
+        ptr += NEXT_PTR( (1<<16) -1 ); //Force the Code size to be 64K (including header+CRC)
+#else
+		if (PRODUCT::id == sparrow::id)
+		{
+			ptr += NEXT_PTR( (1<<18) -1 ); //Force the Code size to be 256K (including header+CRC)
+		}
+		else if (PRODUCT::id == talyn::id)
+		{
+			ptr += NEXT_PTR( (1<<20) -1 ); //Force the Code size to be 1M (including header+CRC)
+		}
+		else
+		{
+			ptr += NEXT_PTR( (1<<18) -1 ); //Force the Code size to be 256K (including header+CRC)
+		}
+#endif
+    }
+
+	section_name = "fw_data";
+	if (parser->get_section(section_name, 0, &iter1, false, full_image))
+	{
+		if (reducedSip)
+		{
+				// FW data limit to 8K
+				fw1_data_section.set_max_size( flash::SUB_SECTOR_SIZE * 2 );
+		}
+		else
+		{
+			if (PRODUCT::id == sparrow::id)
+			{
+				// FW data limit to 32K
+				fw1_data_section.set_max_size( flash::SUB_SECTOR_SIZE * 8 );
+			}
+			else if (PRODUCT::id == talyn::id)
+			{
+				// FW data limit to 128K
+				fw1_data_section.set_max_size( flash::SUB_SECTOR_SIZE * 32 );
+			}
+			else
+			{
+				// FW data limit to 32K
+				fw1_data_section.set_max_size( flash::SUB_SECTOR_SIZE * 8 );
+			}
+		}
+		fw1_data_section.handle_ini_section( *(iter1->second));
+		fw1_data_section.set_offset( ptr );
+		fw1_data_section.write_to_buffer(m_image);
+	}
+	if (reducedSip)
+	{
+		ptr += NEXT_PTR( (1<<13) -1 ); //Force the Data size to be 8K (including header+CRC)
+	}
+	else
+	{
+		ptr += NEXT_PTR( (1<<15) -1 ); //Force the Data size to be 32K (including header+CRC)
+	}
+
+	if (!reducedSip)
+	{
+		section_name = "ucode_code";
+		if (parser->get_section(section_name, 0, &iter1, false, full_image))
+		{
+			if (PRODUCT::id == sparrow::id)
+			{
+				// ucode code limit to 128K - Sparrow
+				fw2_code_section.set_max_size( flash::SUB_SECTOR_SIZE * 32 );
+			}
+			else if (PRODUCT::id == talyn::id)
+			{
+				// ucode code limit to 256K - Talyn
+				fw2_code_section.set_max_size( flash::SUB_SECTOR_SIZE * 64 );
+			}
+			else
+			{
+				// ucode code limit to 64K - Marlon, default
+				fw2_code_section.set_max_size( flash::SUB_SECTOR_SIZE * 16 );
+			}
+
+            fw2_code_section.handle_ini_section( *(iter1->second));
+            fw2_code_section.set_offset( ptr );
+            fw2_code_section.write_to_buffer(m_image);
+        }
+
+		if (PRODUCT::id == sparrow::id)
+		{
+			ptr += NEXT_PTR( (1<<17) -1 ); //Force the Code size to be 128K - Sparrow (including header+CRC)
+		}
+		else if (PRODUCT::id == talyn::id)
+		{
+			ptr += NEXT_PTR( (1<<18) -1 ); //Force the Code size to be 256K - Talyn (including header+CRC)
+		}
+		else
+		{
+			ptr += NEXT_PTR( (1<<16) -1 ); //Force the Code size to be 64K - Marlon, default (including header+CRC)
+		}
+
+		section_name = "ucode_data";
+		if (parser->get_section(section_name, 0, &iter1, false, full_image))
+		{
+			if (PRODUCT::id == sparrow::id)
+			{
+				// ucode data limit to 16K
+				fw2_data_section.set_max_size( flash::SUB_SECTOR_SIZE * 4);
+			}
+			else if (PRODUCT::id == talyn::id)
+			{
+				// ucode data limit to 32K
+				fw2_data_section.set_max_size( flash::SUB_SECTOR_SIZE * 8);
+			}
+			else
+			{
+				// ucode data limit to 8K
+				fw2_data_section.set_max_size( flash::SUB_SECTOR_SIZE * 2);
+			}
+
+			fw2_data_section.handle_ini_section( *(iter1->second));
+			fw2_data_section.set_offset( ptr );
+			fw2_data_section.write_to_buffer(m_image);
+		}
+		//ptr += NEXT_PTR( 0 );
+		ptr += NEXT_PTR( (1<<13) -1 );
+
+		section_name = "fw_static";
+		if (full_image) {
+			if (parser->get_section(section_name, TRANSLATION_MAP_REGTREE | TRANSLATION_MAP_FW, &iter1, false, full_image))
+			{
+				fw1_static_conf_section.set_max_size( flash::SUB_SECTOR_SIZE );
+				fw1_static_conf_section.handle_ini_section(TRANSLATION_MAP_REGTREE | TRANSLATION_MAP_FW, *(iter1->second));
+				fw1_static_conf_section.set_offset( ptr );
+				fw1_static_conf_section.write_to_buffer(m_image);
+			}
+			else
+			{
+				//ERR("Could not find mandatory section %s\n", section_name.c_str() );
+				//EXIT (-1);
+			}
+		}
+		ptr += NEXT_PTR( 0 );
+
+        if (full_image) {
+            section_name = "ucode_static";
+            if (parser->get_section(section_name, TRANSLATION_MAP_REGTREE | TRANSLATION_MAP_UCODE, &iter1, false, full_image))
+            {
+                fw2_static_conf_section.set_max_size( flash::SUB_SECTOR_SIZE );
+                fw2_static_conf_section.handle_ini_section(TRANSLATION_MAP_REGTREE | TRANSLATION_MAP_UCODE, *(iter1->second));
+                fw2_static_conf_section.set_offset( ptr );
+                fw2_static_conf_section.write_to_buffer(m_image);
+            }else{
+                //ERR("Could not find mandatory section %s\n", section_name.c_str() );
+                //EXIT (-1);
+            }
+        }
+        ptr += NEXT_PTR( 0 );
+
+        section_name = "system_config_section";
+        system_config_section.set_max_size( flash::SUB_SECTOR_SIZE * 4 );
+        if (full_image) {
+            system_config_section.set_offset( ptr );
+            system_config_section.write_to_buffer(m_image);
+        }
+
+        ptr += NEXT_PTR( (1<<14) -1 );
+
+        /*section_name = "user";
+          if (parser->get_section(section_name, TRANSLATION_MAP_REGTREE | TRANSLATION_MAP_FW, &iter1, false, full_image))
+          {
+          user_conf_section.set_max_size( flash::SUB_SECTOR_SIZE );
+          user_conf_section.handle_ini_section(TRANSLATION_MAP_REGTREE | TRANSLATION_MAP_FW, *(iter1->second));
+          user_conf_section.set_offset( ptr );
+          user_conf_section.write_to_buffer(m_image);
+          }
+          ptr += NEXT_PTR( 0 ); */
+
+        bool image_info_section_exist = false;
+        section_name = "image_format_version";
+        if (parser->get_section(section_name, 0, &iter1, true, full_image))
+        {
+            image_info_section.set_max_size( flash::SUB_SECTOR_SIZE );
+            image_info_section.handle_ini_section( *(iter1->second), section_name);
+            image_info_section_exist = true;
+        }
+
+        section_name = "fw_version";
+        if (parser->get_section(section_name, 0, &iter1, true, full_image))
+        {
+            image_info_section.handle_ini_section( *(iter1->second), section_name);
+            image_info_section_exist = true;
+        }
+
+        section_name = "fw_timestamp";
+        if (parser->get_section(section_name, 0, &iter1, true, full_image))
+        {
+            image_info_section.handle_ini_section( *(iter1->second), section_name);
+            image_info_section_exist = true;
+        }
+
+        section_name = "ucode_version";
+        if (parser->get_section(section_name, 0, &iter1, true, full_image))
+        {
+            image_info_section.handle_ini_section( *(iter1->second), section_name);
+            image_info_section_exist = true;
+        }
+
+        section_name = "ucode_timestamp";
+        if (parser->get_section(section_name, 0, &iter1, true, full_image))
+        {
+            image_info_section.handle_ini_section( *(iter1->second), section_name);
+            image_info_section_exist = true;
+        }
+
+        section_name = "configuration_id";
+        if (parser->get_section(section_name, 0, &iter1, true, full_image))
+        {
+            image_info_section.handle_ini_section( *(iter1->second), section_name);
+            image_info_section_exist = true;
+        }
+
+        section_name = "device_id";
+        if (parser->get_section(section_name, 0, &iter1, true, full_image))
+        {
+            image_info_section.handle_ini_section( *(iter1->second), section_name);
+            image_info_section_exist = true;
+        }
+
+        section_name = "hw_id";
+        if (parser->get_section(section_name, 0, &iter1, true, full_image))
+        {
+            image_info_section.handle_ini_section( *(iter1->second), section_name);
+            image_info_section_exist = true;
+        }
+
+        if ( image_info_section_exist ) {
+            image_info_section.set_offset( ptr );
+            image_info_section.write_to_buffer(m_image);
+        }
+        ptr += NEXT_PTR( 0 );
+
+        if (PRODUCT::id == marlon::id) {
+
+            section_name = "radio_tx_conf";
+            if (parser->get_section(section_name, 0, &iter1, false, false) )
+            {
+                //        parser->update_section(iter1->second, *(iter2->second), false);
+                radio_tx_conf_section.set_max_size( flash::SUB_SECTOR_SIZE * 2);
+                radio_tx_conf_section.handle_ini_section(0, *(iter1->second));
+                radio_tx_conf_section.set_offset( ptr );
+                radio_tx_conf_section.write_to_buffer(m_image);
+            }
+
+            ptr += NEXT_PTR( (1<<13) -1 ); //Force the section size to be 8K
+            section_name = "radio_rx_conf";
+            if (parser->get_section(section_name, 0, &iter1, false, false) )
+            {
+                //        parser->update_section(iter1->second, *(iter2->second), false);
+                radio_rx_conf_section.set_max_size( flash::SUB_SECTOR_SIZE * 2);
+                radio_rx_conf_section.handle_ini_section(0, *(iter1->second));
+                radio_rx_conf_section.set_offset( ptr );
+                radio_rx_conf_section.write_to_buffer(m_image);
+            }
+
+            ptr += NEXT_PTR( (1<<13) -1 ); //Force the section size to be 8K
+            section_name = "radio_tx_conf2";
+            if (parser->get_section(section_name, 0, &iter1, false, false) )
+            {
+                //        parser->update_section(iter1->second, *(iter2->second), false);
+                radio_tx_conf2_section.set_max_size( flash::SUB_SECTOR_SIZE * 2);
+                radio_tx_conf2_section.handle_ini_section(0, *(iter1->second));
+                radio_tx_conf2_section.set_offset( ptr );
+                radio_tx_conf2_section.write_to_buffer(m_image);
+            }
+
+            ptr += NEXT_PTR( (1<<13) -1 ); //Force the section size to be 8K
+            section_name = "radio_rx_conf2";
+            if (parser->get_section(section_name, 0, &iter1, false, false) )
+            {
+                //        parser->update_section(iter1->second, *(iter2->second), false);
+                radio_rx_conf2_section.set_max_size( flash::SUB_SECTOR_SIZE * 2);
+                radio_rx_conf2_section.handle_ini_section(0, *(iter1->second));
+                radio_rx_conf2_section.set_offset( ptr );
+                radio_rx_conf2_section.write_to_buffer(m_image);
+            }
+
+            ptr += NEXT_PTR( (1<<13) -1 ); //Force the section size to be 8K
+        }
+        section_name = "raw_data";
+        if (parser->get_section(section_name, 0, &iter1, false, false) )
+        {
+            // data_raw limit to 4K
+            raw_data_section.set_max_size( flash::SUB_SECTOR_SIZE);
+            raw_data_section.handle_ini_section( *(iter1->second));
+            raw_data_section.set_offset( ptr );
+            raw_data_section.write_to_buffer(m_image);
+
+        }
+
+    }
+
+    // At the end write the pointer section
+    pointer_section.set_offset( 0 );
+
+    if (full_image)
+        pointer_section.write_to_buffer(m_image);
+
+}
+
diff --git a/debug-tools/wiburn/flash_image.h b/debug-tools/wiburn/flash_image.h
new file mode 100644
index 0000000..167a6a0
--- /dev/null
+++ b/debug-tools/wiburn/flash_image.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _FLASH_IMAGE_H_
+#define _FLASH_IMAGE_H_
+
+#include "wiburn.h"
+#include "flash_sections.h"
+#include "ini_parser.h"
+#include "product.h"
+
+u_int16_t crc_16 (const u_int32_t *buffer, int size);
+
+template <class PRODUCT>
+class flash_image
+{
+public:
+    flash_image ();
+    ~flash_image ();
+    void init (ini_parser_base *parser, bool full_image, bool isReducedSip); // init from ini file
+    void init (const char *filename); // init from image file
+    void init_pointer_section (flash_base *fl); // init from flash
+    void init_hw_conf_section (flash_base *fl); // init from flash
+    //    void init_radio_tx_conf_section (flash_base *fl); // init from flash
+    //    void init_radio_rx_conf_section (flash_base *fl); // init from flash
+    //    void init_radio_tx_conf2_section (flash_base *fl); // init from flash
+    //    void init_radio_rx_conf2_section (flash_base *fl); // init from flash
+    void init_image_info_section (flash_base *fl); // init from flash
+    void init_ids_section (flash_base *fl, bool isReduced); // init from flash
+    void init_usb_info_section (flash_base *fl); // init from flash
+    void save (const char *filename);
+    const BYTE* get_image (void) const;
+    u_int32_t get_image_size (void) const;
+    const pointer_section_t <PRODUCT> & get_pointer_section(void) const;
+    const hw_section_t <PRODUCT> & get_hw_conf_section(void) const;
+    //    const hw_section_t <marlon> & get_radio_tx_conf_section(void) const;
+    //    const hw_section_t <marlon> & get_radio_rx_conf_section(void) const;
+    //    const hw_section_t <marlon> & get_radio_tx_conf2_section(void) const;
+    //    const hw_section_t <marlon> & get_radio_rx_conf2_section(void) const;
+    const image_info_section_t<PRODUCT>& get_image_info_section(void) const;
+    const usb_info_section_t<PRODUCT>& get_usb_info_section(void) const;
+    const ids_section_t<PRODUCT>& get_ids_section(void) const;
+    //    const image_section_t<PRODUCT>& get_fw1_code_section () const;
+    //    const image_section_t<PRODUCT>& get_fw2_code_section () const;
+private:
+    pointer_section_t <PRODUCT>         pointer_section;
+    hw_section_t <PRODUCT>              hw_conf_section;
+
+    image_section_t<PRODUCT>            fw1_code_section;
+    image_section_t<PRODUCT>            fw1_data_section;
+    fw_section_t <PRODUCT>              fw1_static_conf_section;
+
+    image_section_t<PRODUCT>            fw2_code_section;
+    image_section_t<PRODUCT>            fw2_data_section;
+    fw_section_t <PRODUCT>              fw2_static_conf_section;
+
+    system_config_section_t <PRODUCT>   system_config_section;
+
+    hw_section_t <PRODUCT>              production_section;
+    fw_section_t <PRODUCT>              user_conf_section;
+
+    image_info_section_t<PRODUCT>       image_info_section;
+    ids_section_t<PRODUCT>              ids_section;
+
+    usb_section_t                       usb_section;
+    usb_info_section_t<PRODUCT>         usb_info_section;
+
+    hw_section_t <marlon> radio_tx_conf_section;
+    hw_section_t <marlon> radio_rx_conf_section;
+    hw_section_t <marlon> radio_tx_conf2_section;
+    hw_section_t <marlon> radio_rx_conf2_section;
+
+    image_section_t<PRODUCT> raw_data_section;
+
+    IProduct* proxy_product;
+
+private:
+#ifdef FLASH_256KB
+    BYTE m_image [(1<<21)/8]; //2Mbits - 256KB
+#else
+	BYTE m_image [1024*512]; //1MB
+	// TALYN BYTE m_image [1024*4*512]; //1MB
+#endif
+};
+
+#endif //#ifndef _FLASH_IMAGE_H_
diff --git a/debug-tools/wiburn/flash_sections.cpp b/debug-tools/wiburn/flash_sections.cpp
new file mode 100644
index 0000000..1080832
--- /dev/null
+++ b/debug-tools/wiburn/flash_sections.cpp
@@ -0,0 +1,1382 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "flash_sections.h"
+#include "ini_parser.h"
+#include "flash_image.h"
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+
+//extern class ini_parser g_parser;
+//extern ini_parser g_parser;
+
+u_int64_t current_fw_build = 999999;
+
+void format_version_tag_t::disp(const char *name)
+{
+    printf("%s : %d\n", name, format_version);
+}
+
+void version_tag_t::disp(const char *name)
+{
+    printf("%s : %02d.%02d.%02d.%02d\n",name, major, minor, sub_minor, build);
+}
+
+void timestamp_tag_t::disp(const char *name)
+{
+    printf("%s (D/M/Y H:M:S) : %02d/%02d/%04d %02d:%02d:%02d\n"
+           ,name, day, month, year, hour, min, sec );
+}
+
+void configuration_id_tag_t::disp(const char *name)
+{
+    //unused param
+    (void)name;
+    BYTE *null_terminated_buffer = new BYTE [sizeof (id) + 1];
+    memcpy(null_terminated_buffer, id, sizeof (id));
+    null_terminated_buffer[sizeof (id)] = 0;
+    printf("CONFIGURATION_ID = %s\n", null_terminated_buffer);
+    delete[] null_terminated_buffer;
+
+    //printf("CONFIGURATION_ID = ");
+    //print_buffer(id, sizeof id);
+    //printf("\n");
+}
+
+void device_id_tag_t::disp(const char *name)
+{
+    //unused param
+    (void)name;
+    cout << "device_id :" << endl;
+    cout << " device_id = " << (int)device_id << endl;
+    cout << " revision_id = " << (int)revision_id << endl;
+    cout << " misc = " << (int)misc << endl;
+}
+
+void hw_id_tag_t::disp(const char *name)
+{
+    //unused param
+    (void)name;
+    cout << "hw_id :" << endl;
+    cout << " digital_soc_id = " << (int)digital_soc_id << endl;
+    cout << " board_id = " << (int)board_id<< endl;
+    cout << " antenna_id = " << (int)antenna_id<< endl;
+    cout << " rf_id = " << (int)rf_id<< endl;
+    cout << " serial_id = " << (int)serial_id<< endl;
+}
+
+void end_tag_t::disp(const char *name)
+{
+    //unused param
+    (void)name;
+}
+
+//
+// TAG
+//
+tag_base_t::tag_base_t (BYTE id, const char *name)
+{
+    m_header.reserved = 0;
+    m_header.tag_id = id;
+    this->m_name = name;
+}
+
+template <typename Tag>
+tag_t <Tag> ::tag_t (BYTE id, const char* name)
+    :tag_base_t(id, name)
+{
+    m_header.tag_size = sizeof(Tag);
+    memset(&m_tag, 0, sizeof(Tag));
+}
+
+template <typename Tag>
+char *tag_t <Tag>::get_tag()
+{
+    return (char*)&m_tag;
+};
+
+template <typename Tag>
+void tag_t<Tag>::disp()
+{
+    m_tag.disp(this->m_name);
+}
+
+
+//
+// FLASH section
+//
+flash_section::flash_section (const char *name)
+{
+    this->m_name = name;
+    this->m_size = 0;
+    m_offset = 0;
+    this->m_crc = 0;
+    this->m_max_size = 0;
+}
+
+int flash_section::size () const
+{
+    return this->m_size;
+}
+
+int flash_section::get_max_size () const
+{
+    return this->m_max_size;
+}
+
+void flash_section::set_max_size ( u_int32_t max_size ) {
+    this->m_max_size = max_size;
+}
+
+void flash_section::set_offset( u_int32_t offset )
+{
+    m_offset = offset;
+}
+
+u_int32_t flash_section::get_offset () const
+{
+    return m_offset;
+}
+
+//
+// POINTER section
+//
+template <class PRODUCT>
+pointer_section_t<PRODUCT>::pointer_section_t (const char *name)
+    : flash_section(name)
+{
+    memset(&m_pointers, -1, sizeof (m_pointers));
+    m_pointers.signature = 0x40;
+    this->m_size = sizeof (m_pointers);
+}
+
+template <class PRODUCT>
+void pointer_section_t<PRODUCT>::init (flash_base *fl)
+{
+    fl->read(0, this->m_size, (BYTE*)&m_pointers);
+}
+
+template <class PRODUCT>
+bool pointer_section_t<PRODUCT>::operator == (const pointer_section_t <PRODUCT> &r_side) const
+{
+    int res = memcmp(&m_pointers, &(r_side.m_pointers), sizeof (m_pointers));
+    return (res == 0);
+}
+
+template <class PRODUCT>
+void pointer_section_t<PRODUCT>::write_to_buffer( BYTE *buffer )
+{
+    INFO("%s: Writing section of size 0x%04x at offset 0x%04x\n",this->m_name, this->m_size, m_offset);
+    int current_offset = m_offset;
+    memcpy(buffer + current_offset, &m_pointers, sizeof (m_pointers));
+    current_offset += sizeof (m_pointers);
+
+//   this->m_crc = crc_16((u_int32_t*)(buffer+m_offset), this->m_size - sizeof (this->m_crc));
+    this->m_crc = m_CalcCRC.CalcCRC((UCHAR*)(buffer+m_offset), this->m_size - sizeof (this->m_crc));
+    memcpy(buffer+current_offset, &this->m_crc, sizeof (this->m_crc));
+}
+
+//
+// ID section
+//
+//id_section::id_section (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t* ptr_high)
+id_section::id_section (const char *name, BYTE id, ADDRESS32 *ptr)
+    : flash_section(name)
+{
+    this->header.reserved = 0;
+    this->header.section_id = id;
+//   m_ptr_low = ptr_low;
+//   m_ptr_high = ptr_high;
+    this->m_ptr = ptr;
+    this->m_size = sizeof(section_header_t);
+};
+
+void id_section::set_offset (int offset)
+{
+    flash_section::set_offset(offset);
+    offset += sizeof(section_header_t);
+    //*m_ptr_low = (u_int16_t)offset;
+    //*m_ptr_high = (u_int16_t)(offset>>16);
+    *this->m_ptr = offset;
+}
+
+//
+// VARIABLE section
+//variable_section_t::variable_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t* ptr_high)
+//: id_section( name, id, ptr_low, ptr_high)
+variable_section_t::variable_section_t (const char *name, BYTE id, ADDRESS32* ptr)
+    : id_section( name, id, ptr)
+{
+    //nothing to do
+}
+
+variable_section_t::~variable_section_t ()
+{
+    //nothing to do
+}
+
+//
+// HW SECTION
+//
+template <class PRODUCT>
+//hw_section_t<PRODUCT>::hw_section_t (const char *name, BYTE id, u_int16_t *ptr_low , u_int16_t *ptr_high)
+//: variable_section_t(name, id, ptr_low, ptr_high)
+hw_section_t<PRODUCT>::hw_section_t (const char *name, BYTE id, ADDRESS32 *ptr)
+    : variable_section_t(name, id, ptr)
+{
+    m_termination[0] = -1;
+    m_termination[1] = -1;
+    m_buffer = 0;
+}
+
+template <class PRODUCT>
+void hw_section_t<PRODUCT>::write_to_buffer( BYTE *buffer )
+{
+    INFO("%s: Writing section of size 0x%04x at offset 0x%04x\n",this->m_name, this->m_size, m_offset);
+
+    int current_offset = m_offset;
+    memcpy(buffer + current_offset, &this->header, sizeof(this->header));
+    current_offset += sizeof(this->header);
+    memcpy(buffer + current_offset, m_buffer, m_buffer_size);
+    current_offset += m_buffer_size;
+
+    memcpy(buffer + current_offset, (char*)&m_termination, sizeof(m_termination));
+    current_offset += sizeof (m_termination);
+
+//   this->m_crc = crc_16((u_int32_t*)(buffer+m_offset), this->m_size - sizeof (this->m_crc));
+    this->m_crc = m_CalcCRC.CalcCRC((UCHAR*)(buffer+m_offset), this->m_size - sizeof (this->m_crc));
+    memcpy(buffer+current_offset, &this->m_crc, sizeof (this->m_crc));
+}
+
+template <class PRODUCT>
+void hw_section_t<PRODUCT>::handle_ini_section (u_int8_t translation_map_bits, const ini_section_t &ini_section)
+{
+    int size = ini_section.size();
+    m_buffer = new address_value_t<PRODUCT> [size];
+    m_buffer_size = size * (sizeof (address_value_t<PRODUCT>));
+    memset((void*)m_buffer, -1, m_buffer_size);
+    // buffer + this->header + FFFFs
+    this->m_size += m_buffer_size + sizeof (m_termination) + sizeof (this->m_crc);
+    this->header.section_size = (u_int16_t)this->m_size;
+    this->header.section_size -= sizeof (this->m_crc); //TBD remove - FW does not support CRC yet
+
+    ini_section_t::const_iterator sec_iter;
+    sec_iter = ini_section.begin();
+    int index = 0;
+    typename PRODUCT::ADDRESS temp_address;
+    typename PRODUCT::REG temp_value;
+    while (sec_iter != ini_section.end())
+    {
+        ini_parser<PRODUCT>::get_resolved_address_data(translation_map_bits,
+                                                       sec_iter,
+                                                       &temp_address,
+                                                       &temp_value);
+
+        m_buffer[index].address = temp_address;
+        m_buffer[index].value = temp_value;
+
+        index++;
+        sec_iter++;
+    }
+
+    if (this->m_size > this->m_max_size) {
+        ERR("Section %s with size %d exceeds maximum section size of %d\n",
+            this->m_name, this->m_size, this->m_max_size );
+        EXIT (-1);
+    }
+}
+
+template <class PRODUCT>
+void hw_section_t<PRODUCT>::init (flash_base *fl)
+{
+    //u_int32_t section_address = (*m_ptr_low | ((*m_ptr_high) << 16));
+    u_int32_t section_address = *this->m_ptr;
+    u_int32_t header_address = section_address - sizeof (section_header_t);
+
+    // get the section this->header
+    fl->read(header_address, sizeof (section_header_t), (BYTE*)&this->header);
+
+    // get the section
+    m_buffer_size = this->header.section_size - sizeof (section_header_t) - sizeof (this->m_crc) - sizeof (m_termination);
+    m_buffer_size += sizeof (this->m_crc); // TBD remove when CRC is supported by FW
+    m_buffer = new address_value_t<PRODUCT> [m_buffer_size / (sizeof (address_value_t<PRODUCT>))];
+    fl->read(section_address, m_buffer_size, (BYTE*)m_buffer);
+
+    // get the termination
+    fl->read(section_address+m_buffer_size, sizeof (m_termination), (BYTE*)&m_termination);
+    // get the CRC ???
+
+}
+
+template <class PRODUCT>
+bool hw_section_t<PRODUCT>::operator == (const hw_section_t <PRODUCT> &r_side) const
+{
+    int res = memcmp(&this->header, &r_side.header, sizeof (section_header_t));
+    res |= memcmp(m_buffer, r_side.m_buffer, m_buffer_size);
+    res |= memcmp(m_termination, r_side.m_termination, sizeof (m_termination));
+    return (res == 0);
+}
+
+template <class PRODUCT>
+hw_section_t<PRODUCT>::~hw_section_t ()
+{
+    delete m_buffer;
+};
+
+
+//
+// System Config Section
+//
+template <class PRODUCT>
+system_config_section_t<PRODUCT>::system_config_section_t (const char *name, ADDRESS32 *ptr)
+    : flash_section(name)
+{
+    this->m_ptr = ptr;
+}
+
+template <class PRODUCT>
+void system_config_section_t<PRODUCT>::write_to_buffer( BYTE *buffer )
+{
+    //unused param
+    (void)buffer;
+    INFO("%s: Preparing empty section at offset 0x%04x\n",this->m_name, m_offset);
+}
+
+template <class PRODUCT>
+void system_config_section_t<PRODUCT>::set_offset (int offset)
+{
+    this->m_offset = offset;
+
+    *this->m_ptr = offset;
+    //pointer_section.m_pointers.config_section_pointer = ptr;
+}
+
+
+//
+// FW section
+//
+template <class PRODUCT>
+//fw_section_t<PRODUCT>::fw_section_t (const char *name, BYTE id, u_int16_t *ptr_low , u_int16_t *ptr_high)
+//: variable_section_t(name, id, ptr_low , ptr_high)
+fw_section_t<PRODUCT>::fw_section_t (const char *name, BYTE id, ADDRESS32 *ptr)
+    : variable_section_t(name, id, ptr)
+{
+    m_buffer = 0;
+}
+
+template <class PRODUCT>
+void fw_section_t<PRODUCT>::write_to_buffer(BYTE *buffer )
+{
+    INFO("%s: Writing section of size 0x%04x at offset 0x%04x\n",this->m_name, this->m_size, m_offset);
+
+    int current_offset = m_offset;
+    memcpy(buffer + current_offset, &this->header, sizeof (this->header));
+    current_offset += sizeof (this->header);
+    memcpy(buffer + current_offset, m_buffer, m_buffer_size);
+    current_offset += m_buffer_size;
+
+//   this->m_crc = crc_16((u_int32_t*)(buffer+m_offset), this->m_size - sizeof (this->m_crc));
+    this->m_crc = m_CalcCRC.CalcCRC((UCHAR*)(buffer+m_offset), this->m_size - sizeof (this->m_crc));
+    memcpy(buffer+current_offset, &this->m_crc, sizeof (this->m_crc));
+}
+
+template <class PRODUCT>
+void fw_section_t<PRODUCT>::handle_ini_section (u_int8_t translation_map_bits, const ini_section_t &ini_section)
+{
+    int size = ini_section.size();
+    m_buffer = new address_value_mask_t<PRODUCT> [size];
+    m_buffer_size = size * (sizeof (address_value_mask_t<PRODUCT>));
+    memset((void*)m_buffer, -1, m_buffer_size);
+    // buffer + this->header + CRC
+    this->m_size += m_buffer_size + sizeof (this->m_crc);
+    this->header.section_size = (u_int16_t)this->m_size;
+//   this->header.section_size -= sizeof (this->m_crc); //TBD remove - FW does not support CRC yet
+
+    ini_section_t::const_iterator sec_iter;
+    sec_iter = ini_section.begin();
+    int index = 0;
+    typename PRODUCT::ADDRESS temp_address;
+    typename PRODUCT::REG temp_value;
+    int start, end;
+    while (sec_iter != ini_section.end())
+    {
+        ini_parser<PRODUCT>::get_resolved_address_data(
+            translation_map_bits,
+            sec_iter,
+            &temp_address,
+            &temp_value,
+            &start,
+            &end);
+        m_buffer[index].address = temp_address;
+        m_buffer[index].value = temp_value;
+        m_buffer[index].value <<= start;
+        m_buffer[index].mask = ~(((2 << (end - start)) - 1) << start);
+        index++;
+        sec_iter++;
+    }
+    if (this->m_size > this->m_max_size) {
+        ERR("Section %s with size %d exceeds maximum section size of %d\n",
+            this->m_name, this->m_size, this->m_max_size );
+        EXIT (-1);
+    }
+}
+
+template <class PRODUCT>
+fw_section_t<PRODUCT>::~fw_section_t ()
+{
+    delete m_buffer;
+};
+
+//
+// Image section
+//
+//image_section_t::image_section_t (const char *name, BYTE id, u_int16_t *ptr_low,
+//                                  u_int16_t *ptr_high, u_int16_t *length)
+//: variable_section_t(name, id, ptr_low , ptr_high)
+template <class PRODUCT>
+image_section_t<PRODUCT>::image_section_t (const char *name, BYTE id, ADDRESS32 *ptr, typename PRODUCT::REG *length)
+    : variable_section_t(name, id, ptr)
+{
+    m_length = length;
+    m_buffer = 0;
+}
+
+template <class PRODUCT>
+void image_section_t<PRODUCT>::set_offset (int offset)
+{
+    id_section::set_offset(offset);
+    // length in pointer section is w/o the section this->header and w/o the CRC
+    *m_length = ( typename PRODUCT::REG)(this->m_size - sizeof (section_header_t) - sizeof (this->m_crc));
+}
+
+template <class PRODUCT>
+void image_section_t<PRODUCT>::write_to_buffer(BYTE *buffer)
+{
+    INFO("%s: Writing section of size 0x%04x at offset 0x%04x\n",this->m_name, this->m_size, m_offset);
+
+    int current_offset = m_offset;
+    memcpy(buffer + current_offset, &this->header, sizeof (this->header));
+    current_offset += sizeof (this->header);
+    memcpy(buffer + current_offset, m_buffer, m_buffer_size);
+    current_offset += m_buffer_size;
+
+//   this->m_crc = crc_16((u_int32_t*)(buffer+m_offset), this->m_size - sizeof (this->m_crc));
+    this->m_crc = m_CalcCRC.CalcCRC((UCHAR*)(buffer+m_offset+sizeof (this->header)), m_buffer_size);
+    memcpy(buffer+current_offset, &this->m_crc, sizeof (this->m_crc));
+}
+
+template <class PRODUCT>
+void image_section_t<PRODUCT>::handle_ini_section (const ini_section_t &ini_section)
+{
+    int size = ini_section.size();
+    m_buffer = new IMAGE [size];
+    m_buffer_size = size * (sizeof (IMAGE));
+    memset((void*)m_buffer, -1, m_buffer_size);
+    // buffer + this->header + CRC
+    this->m_size += m_buffer_size + sizeof (this->m_crc);
+    this->header.section_size = (u_int16_t)this->m_size;
+//   this->header.section_size -= sizeof (this->m_crc); //TBD remove - FW does not support CRC yet
+
+    ini_section_t::const_iterator sec_iter;
+    sec_iter = ini_section.begin();
+    int index = 0;
+    while (sec_iter != ini_section.end())
+    {
+        get_resolved_data(sec_iter, &m_buffer[index]);
+        index++;
+        sec_iter++;
+    }
+
+    if (this->m_size > this->m_max_size) {
+        ERR("Section %s with size %d exceeds maximum section size of %d\n",
+            this->m_name, this->m_size, this->m_max_size );
+        EXIT (-1);
+    }
+}
+
+template <class PRODUCT>
+image_section_t<PRODUCT>::~image_section_t ()
+{
+    delete m_buffer;
+};
+
+//
+// TAG section
+//
+
+//info_section_t::info_section_t (const char *name, BYTE id, u_int16_t *ptr_low , u_int16_t *ptr_high)
+//: variable_section_t(name, id, ptr_low , ptr_high)
+template <class PRODUCT>
+info_section_t<PRODUCT>::info_section_t (const char *name, BYTE id, ADDRESS32* ptr)
+    : variable_section_t(name, id, ptr)
+{
+    this->m_size += sizeof (this->m_crc); //for CRC
+}
+
+template <class PRODUCT>
+void info_section_t<PRODUCT>::write_to_buffer(BYTE *buffer)
+{
+    tag_t<end_tag_t> *tag = new tag_t<end_tag_t> (end_tag_id);
+    this->m_size += sizeof (end_tag_t) + sizeof (tag_header_t);
+    this->m_tags.insert(this->m_tags.end(), tag);
+    this->header.section_size = (u_int16_t)this->m_size;
+//    this->header.section_size -= sizeof (this->m_crc); //TBD remove - FW does not support CRC yet
+
+    INFO("%s: Writing section of size 0x%04x at offset 0x%04x\n",this->m_name, this->m_size, m_offset);
+
+    int current_offset = m_offset;
+    memcpy(buffer + current_offset, &this->header, sizeof (this->header));
+    current_offset += sizeof (this->header);
+
+    tag_vector_t::const_iterator iter = this->m_tags.begin();
+    while (iter != this->m_tags.end()) {
+        tag_base_t *tag_base = *iter;
+        memcpy(buffer + current_offset, &(tag_base->m_header), sizeof (tag_header_t));
+        current_offset += sizeof (tag_header_t);
+
+        memcpy(buffer + current_offset, tag_base->get_tag(), tag_base->m_header.tag_size);
+        current_offset += tag_base->m_header.tag_size;
+        iter++;
+    }
+
+//   this->m_crc = crc_16((u_int32_t*)(buffer+m_offset), this->m_size - sizeof (this->m_crc));
+    this->m_crc = m_CalcCRC.CalcCRC((UCHAR*)(buffer+m_offset), this->m_size - sizeof (this->m_crc));
+    memcpy(buffer+current_offset, &this->m_crc, sizeof (this->m_crc));
+}
+
+template <class PRODUCT>
+void info_section_t<PRODUCT>::disp() const
+{
+    tag_vector_t::const_iterator iter = this->m_tags.begin();
+    while (iter != this->m_tags.end()) {
+        tag_base_t *tag_base = *iter;
+        tag_base->disp();
+        iter++;
+    }
+}
+
+template <class PRODUCT>
+info_section_t<PRODUCT>::~info_section_t ()
+{
+    tag_vector_t::const_iterator iter = this->m_tags.begin();
+    while (iter != this->m_tags.end()) {
+        tag_base_t *tag_base = *iter;
+        delete tag_base;
+        iter++;
+    }
+}
+
+//
+// Image_info
+//
+//image_info_section_t::image_info_section_t (const char *name, BYTE id, u_int16_t *ptr_low , u_int16_t *ptr_high)
+//:info_section_t(name, id, ptr_low, ptr_high)
+template <class PRODUCT>
+image_info_section_t<PRODUCT>::image_info_section_t (const char *name, BYTE id, ADDRESS32 *ptr)
+    :info_section_t<PRODUCT>(name, id, ptr)
+{
+    // nothing to do
+}
+
+template <class PRODUCT>
+void image_info_section_t<PRODUCT>::handle_ini_section (const ini_section_t &ini_section,
+                                                        const string &name)
+{
+    string key;
+    u_int64_t value;
+    if( "image_format_version" == name ) {
+        tag_t<format_version_tag_t> *tag = new tag_t<format_version_tag_t> (image_format_version_tag_id, name.data());
+        this->m_size += sizeof (format_version_tag_t) + sizeof (tag_header_t);
+        this->m_tags.insert(this->m_tags.end(), tag);
+        key = "format_version";
+        get_value(ini_section, key, &value );
+        tag->m_tag.format_version = (BYTE)value;
+    }
+    else if (( "fw_version" == name ) || ( "ucode_version" == name )){
+        tag_t<version_tag_t> *tag = new tag_t<version_tag_t> (fw_version_tag_id, name.data());
+        this->m_size += sizeof (version_tag_t) + sizeof (tag_header_t);
+        this->m_tags.insert(this->m_tags.end(), tag);
+        key = "build";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.build = value;
+            if ("fw_version" == name) {
+                // Remember the current fw build number for later use
+                current_fw_build = value;
+            }
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "major";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.major = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "minor";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.minor = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "sub_minor";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.sub_minor = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+    }
+    else if (("fw_timestamp" == name ) || ( "ucode_timestamp" == name )) {
+        tag_t<timestamp_tag_t> *tag = new tag_t<timestamp_tag_t> (fw_timestamp_tag_id, name.data());
+        this->m_size += sizeof (timestamp_tag_t) + sizeof (tag_header_t);
+        this->m_tags.insert(this->m_tags.end(), tag);
+        key = "sec";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.sec = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "min";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.min = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "hour";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.hour = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "day";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.day = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "month";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.month = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "year";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.year = (u_int16_t)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+    }
+    else if ("configuration_id" == name ) {
+        tag_t<configuration_id_tag_t> *tag = new tag_t<configuration_id_tag_t> (configuration_id_tag_id, name.data());
+        this->m_size += sizeof (configuration_id_tag_t) + sizeof (tag_header_t);
+        this->m_tags.insert(this->m_tags.end(), tag);
+        key = "configuration_id";
+        get_string(ini_section, key, tag->m_tag.id, sizeof (tag->m_tag.id));
+    }
+    else if ("device_id" == name ) {
+        tag_t<device_id_tag_t> *tag = new tag_t<device_id_tag_t> (device_id_tag_id, name.data());
+        this->m_size += sizeof (device_id_tag_t) + sizeof (tag_header_t);
+        this->m_tags.insert(this->m_tags.end(), tag);
+        key = "device_id";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.device_id = (u_int16_t)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "misc";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.misc = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "revision_id";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.revision_id = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+    }
+    else if ("hw_id" == name ) {
+        tag_t<hw_id_tag_t> *tag = new tag_t<hw_id_tag_t> (hw_id_tag_id, name.data());
+        this->m_size += sizeof (hw_id_tag_t) + sizeof (tag_header_t);
+        this->m_tags.insert(this->m_tags.end(), tag);
+        key = "antenna_id";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.antenna_id = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "board_id";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.board_id = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "digital_soc_id";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.digital_soc_id = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "rf_id";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.rf_id = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "serial_id";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.serial_id = (u_int16_t)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+    } else {
+        ERR("Unknown tag name %s\n", name.c_str());
+        EXIT (-1);
+    }
+
+    this->header.section_size = (u_int16_t)this->m_size;
+    this->header.section_size -= sizeof (this->m_crc); //TBD remove - FW does not support CRC yet
+
+    if (this->m_size > this->m_max_size) {
+        ERR("Section %s with size %d exceeds maximum section size of %d\n",
+            this->m_name, this->m_size, this->m_max_size );
+        EXIT (-1);
+    }
+}
+
+template <class PRODUCT>
+void image_info_section_t<PRODUCT>::init(flash_base *fl)
+{
+    //u_int32_t section_address = (*m_ptr_low | ((*m_ptr_high) << 16));
+    u_int32_t section_address = *this->m_ptr;
+    u_int32_t header_address = section_address - sizeof (section_header_t);
+
+    // get the section header
+    fl->read(header_address, sizeof (section_header_t), (BYTE*)&this->header);
+    this->m_size = this->header.section_size;
+
+    u_int16_t offset = sizeof (section_header_t);
+    while (offset < this->header.section_size) {
+        tag_header_t tag_header;
+        fl->read(header_address+offset, sizeof (tag_header_t), (BYTE*)&tag_header);
+        offset += sizeof (tag_header_t);
+
+        tag_base_t *tag = NULL;
+        switch (tag_header.tag_id) {
+        case image_format_version_tag_id : {
+            tag = new tag_t<format_version_tag_t> (tag_header.tag_id, "image_format_version");
+            break;
+        }
+        case fw_version_tag_id : {
+            tag = new tag_t<version_tag_t> (tag_header.tag_id, "fw_version");
+            break;
+        }
+        case fw_timestamp_tag_id : {
+            tag = new tag_t<timestamp_tag_t> (tag_header.tag_id, "fw_timestamp");
+            break;
+        }
+        case configuration_id_tag_id : {
+            tag = new tag_t<configuration_id_tag_t> (tag_header.tag_id, "configuration_id");
+            break;
+        }
+        case device_id_tag_id : {
+            tag = new tag_t<device_id_tag_t> (tag_header.tag_id, "device_id");
+            break;
+        }
+        case hw_id_tag_id : {
+            tag = new tag_t<hw_id_tag_t> (tag_header.tag_id, "hw_id");
+            break;
+        }
+        case end_tag_id : {
+            tag = new tag_t<end_tag_t> (tag_header.tag_id);
+            break;
+        }
+        default: {
+            ERR("Unknown tag id %d\n", tag_header.tag_id);
+//            EXIT (-1);
+        }
+        }
+
+        if (tag != NULL)
+        {
+            fl->read(header_address+offset, tag_header.tag_size, (BYTE*)tag->get_tag());
+            offset += tag_header.tag_size;
+
+            this->m_tags.insert(this->m_tags.end(), tag);
+        }
+    }
+}
+
+template <class PRODUCT>
+image_info_section_t<PRODUCT>::~image_info_section_t ()
+{
+    // nothing to do
+}
+
+//
+// USB_Info
+//
+//usb_info_section_t::usb_info_section_t (const char *name, BYTE id, u_int16_t *ptr_low , u_int16_t *ptr_high)
+//:info_section_t(name, id, ptr_low, ptr_high)
+template <class PRODUCT>
+usb_info_section_t<PRODUCT>::usb_info_section_t (const char *name, BYTE id, ADDRESS32 *ptr)
+    :info_section_t<PRODUCT>(name, id, ptr)
+{
+    // nothing to do
+}
+
+template <class PRODUCT>
+void usb_info_section_t<PRODUCT>::handle_ini_section (const ini_section_t &ini_section,
+                                                      const string &name)
+{
+    string key;
+    u_int64_t value;
+    if( "usb_image_format_version" == name ) {
+        tag_t<format_version_tag_t> *tag = new tag_t<format_version_tag_t> (usb_format_version_tag_id, name.data());
+        this->m_size += sizeof (format_version_tag_t) + sizeof (tag_header_t);
+        this->m_tags.insert(this->m_tags.end(), tag);
+        key = "format_version";
+        get_value(ini_section, key, &value );
+        tag->m_tag.format_version = (BYTE)value;
+    }
+    else if( "usb_version" == name ) {
+        tag_t<version_tag_t> *tag = new tag_t<version_tag_t> (usb_version_tag_id, name.data());
+        this->m_size += sizeof (version_tag_t) + sizeof (tag_header_t);
+        this->m_tags.insert(this->m_tags.end(), tag);
+        key = "build";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.build = value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "major";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.major = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "minor";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.minor = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "sub_minor";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.sub_minor = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+    }
+    else if ("usb_timestamp" == name ) {
+        tag_t<timestamp_tag_t> *tag = new tag_t<timestamp_tag_t> (usb_timestamp_tag_id, name.data());
+        this->m_size += sizeof (timestamp_tag_t) + sizeof (tag_header_t);
+        this->m_tags.insert(this->m_tags.end(), tag);
+        key = "sec";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.sec = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "min";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.min = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "hour";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.hour = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "day";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.day = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "month";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.month = (BYTE)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+        key = "year";
+        if( get_value(ini_section, key, &value )) {
+            tag->m_tag.year = (u_int16_t)value;
+        }
+        else {
+            ERR("Missing key %s in tag %s\n", key.c_str(), name.c_str());
+            EXIT (-1);
+        }
+    } else {
+        ERR("Unknown tag name %s\n", name.c_str());
+        EXIT (-1);
+    }
+
+    this->header.section_size = (u_int16_t)this->m_size;
+    this->header.section_size -= sizeof (this->m_crc); //TBD remove - FW does not support CRC yet
+
+    if (this->m_size > this->m_max_size) {
+        ERR("Section %s with size %d exceeds maximum section size of %d\n",
+            this->m_name, this->m_size, this->m_max_size );
+        EXIT (-1);
+    }
+}
+
+template <class PRODUCT>
+void usb_info_section_t<PRODUCT>::init(flash_base *fl)
+{
+    //u_int32_t section_address = (*m_ptr_low | ((*m_ptr_high) << 16));
+    u_int32_t section_address = *this->m_ptr;
+    u_int32_t header_address = section_address - sizeof (section_header_t);
+
+    // get the section header
+    fl->read(header_address, sizeof (section_header_t), (BYTE*)&this->header);
+    this->m_size = this->header.section_size;
+
+    u_int16_t offset = sizeof (section_header_t);
+    while (offset < this->header.section_size) {
+        tag_header_t tag_header;
+        fl->read(header_address+offset, sizeof (tag_header_t), (BYTE*)&tag_header);
+        offset += sizeof (tag_header_t);
+
+        tag_base_t *tag = nullptr;
+        switch (tag_header.tag_id) {
+        case usb_format_version_tag_id: {
+            tag = new tag_t<format_version_tag_t> (tag_header.tag_id, "usb_format_version");
+            break;
+        }
+        case usb_version_tag_id : {
+            tag = new tag_t<version_tag_t> (tag_header.tag_id, "usb_version");
+            break;
+        }
+        case usb_timestamp_tag_id : {
+            tag = new tag_t<timestamp_tag_t> (tag_header.tag_id, "usb_timestamp");
+            break;
+        }
+        case end_tag_id : {
+            tag = new tag_t<end_tag_t> (tag_header.tag_id);
+            break;
+        }
+        default: {
+            ERR("Unknown tag id %d\n", tag_header.tag_id);
+            return;
+        }
+        }
+
+        fl->read(header_address+offset, tag_header.tag_size, (BYTE*)tag->get_tag());
+        offset += tag_header.tag_size;
+
+        this->m_tags.insert(this->m_tags.end(), tag);
+    }
+}
+
+template <class PRODUCT>
+usb_info_section_t<PRODUCT>::~usb_info_section_t ()
+{
+    // nothing to do
+}
+
+
+//
+// Const section
+//
+template <typename T, class PRODUCT>
+//const_section_t<T>::const_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t* ptr_high)
+//: id_section(name, id, ptr_low, ptr_high)
+const_section_t<T,PRODUCT>::const_section_t (const char *name, BYTE id, ADDRESS32 *ptr)
+    : id_section(name, id, ptr)
+{
+    memset(&this->m_section, 0, sizeof (T));
+    this->m_size += sizeof (T) + sizeof (this->m_crc);
+    this->header.section_size = (u_int16_t)this->m_size;
+}
+
+template <typename T, class PRODUCT>
+void const_section_t<T,PRODUCT>::write_to_buffer(BYTE *buffer )
+{
+    INFO("%s: Writing section of size 0x%04x at offset 0x%04x\n",this->m_name, this->m_size, m_offset);
+    int current_offset = m_offset;
+
+    memcpy(buffer + current_offset, &this->header, sizeof (this->header));
+    current_offset += sizeof (this->header);
+
+    memcpy(buffer + current_offset, &this->m_section, sizeof (T));
+    current_offset += sizeof (T);
+
+    this->m_crc = crc_16((u_int32_t*)(buffer+m_offset), this->m_size - sizeof (this->m_crc));
+    memcpy(buffer+current_offset, &this->m_crc, sizeof (this->m_crc));
+}
+
+template <typename T, class PRODUCT>
+void const_section_t<T,PRODUCT>::init(flash_base *fl)
+{
+    //u_int32_t section_address = (*m_ptr_low | ((*m_ptr_high) << 16));
+    u_int32_t section_address = *this->m_ptr;
+    fl->read(section_address, sizeof (this->m_section), (BYTE*)&this->m_section);
+}
+
+template <typename T, class PRODUCT>
+void const_section_t<T,PRODUCT>::initReduced(flash_base *fl, int reductionSize)
+{
+    //u_int32_t section_address = (*m_ptr_low | ((*m_ptr_high) << 16));
+    u_int32_t section_address = *this->m_ptr - reductionSize;
+    fl->read(section_address, sizeof (this->m_section), (BYTE*)&this->m_section);
+}
+
+
+//
+// IDs section
+//
+//ids_section_t::ids_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t* ptr_high)
+//: const_section_t(name, id, ptr_low, ptr_high)
+template <class PRODUCT>
+ids_section_t<PRODUCT>::ids_section_t (const char *name, BYTE id, ADDRESS32 *ptr)
+    : const_section_t<ids_section,PRODUCT>(name, id, ptr)
+{
+    //nothing to do
+}
+
+template <class PRODUCT>
+void ids_section_t<PRODUCT>::handle_ini_section (const ini_section_t &ini_section)
+{
+    u_int64_t value;
+
+    get_value(ini_section, "version", &value);
+    this->m_section.version = (BYTE)value;
+
+    get_value(ini_section, "mac_address" , &value);
+    memcpy(&this->m_section.mac_address, &value, sizeof (this->m_section.mac_address));
+
+    get_string(ini_section, "ssid" , &this->m_section.ssid, sizeof (this->m_section.ssid));
+
+    get_value(ini_section, "local", &value);
+    this->m_section.local = (u_int16_t)value;
+
+    get_value(ini_section, "ppm", &value);
+    this->m_section.ppm = (u_int16_t)value;
+
+    get_value(ini_section, "board", &value);
+    this->m_section.board_type = (u_int32_t)value;
+
+    get_value(ini_section, "lo_power_xif_gc", &value);
+    this->m_section.lo_power_xif_gc = (u_int16_t)value;
+
+    get_value(ini_section, "lo_power_stg2_bias", &value);
+    this->m_section.lo_power_stg2_bias = (u_int16_t)value;
+
+    get_value(ini_section, "vga_bias", &value);
+    this->m_section.vga_bias = (u_int16_t)value;
+
+    get_value(ini_section, "vga_stg1_fine_bias", &value);
+    this->m_section.vga_stg1_fine_bias = (u_int16_t)value;
+
+    get_value(ini_section, "ats_ver", &value);
+    this->m_section.ats_ver = (u_int16_t)value;
+
+    get_value(ini_section, "mlt_ver", &value);
+    this->m_section.mlt_ver = (u_int16_t)value;
+
+    get_value(ini_section, "bl_ver", &value);
+    this->m_section.bl_ver = (u_int16_t)value;
+
+    get_value(ini_section, "lo_power_gc_ctrl", &value);
+    this->m_section.lo_power_gc_ctrl = (u_int16_t)value;
+
+    get_value(ini_section, "production1", &value);
+    this->m_section.production1 = (u_int16_t)value;
+
+    get_value(ini_section, "production2", &value);
+    this->m_section.production2 = (u_int16_t)value;
+
+    get_value(ini_section, "production3", &value);
+    this->m_section.production3 = (u_int16_t)value;
+
+    get_value(ini_section, "production4", &value);
+    this->m_section.production4 = (u_int16_t)value;
+
+    get_value(ini_section, "production5", &value);
+    this->m_section.production5 = (u_int16_t)value;
+
+    get_value(ini_section, "production6", &value);
+    this->m_section.production6 = (u_int16_t)value;
+
+    get_value(ini_section, "production7", &value);
+    this->m_section.production7 = (u_int16_t)value;
+
+    get_value(ini_section, "production8", &value);
+    this->m_section.production8 = (u_int16_t)value;
+
+    get_value(ini_section, "production9", &value);
+    this->m_section.production9 = (u_int16_t)value;
+
+    get_value(ini_section, "production10", &value);
+    this->m_section.production10 = (u_int16_t)value;
+
+    get_value(ini_section, "production11", &value);
+    this->m_section.production11 = (u_int16_t)value;
+
+    get_value(ini_section, "production12", &value);
+    this->m_section.production12 = (u_int16_t)value;
+
+    get_value(ini_section, "production13", &value);
+    this->m_section.production13 = (u_int16_t)value;
+
+    get_value(ini_section, "production14", &value);
+    this->m_section.production14 = (u_int16_t)value;
+
+    get_value(ini_section, "production15", &value);
+    this->m_section.production15 = (u_int16_t)value;
+
+    get_value(ini_section, "production16", &value);
+    this->m_section.production16 = (u_int16_t)value;
+
+
+    if (this->m_size > this->m_max_size) {
+        ERR("Section %s with size %d exceeds maximum section size of %d\n",
+            this->m_name, this->m_size, this->m_max_size );
+        EXIT (-1);
+    }
+}
+
+template <class PRODUCT>
+void ids_section_t<PRODUCT>::disp() const
+{
+    printf("version = %d\n",this->m_section.version);
+    printf("MAC address = 0x%02x%02x%02x%02x%02x%02x\n", this->m_section.mac_address[5],
+           this->m_section.mac_address[4],
+           this->m_section.mac_address[3],
+           this->m_section.mac_address[2],
+           this->m_section.mac_address[1],
+           this->m_section.mac_address[0]);
+    printf("SSID = ");
+    print_buffer(&this->m_section.ssid, sizeof (this->m_section.ssid));
+    printf("\n");
+    printf("local = %d\n",this->m_section.local);
+    printf("ppm = %d\n",this->m_section.ppm);
+    printf("board = %d\n",this->m_section.board_type);
+    printf("lo_power_xif_gc = %d\n",this->m_section.lo_power_xif_gc);
+    printf("lo_power_stg2_bias = %d\n",this->m_section.lo_power_stg2_bias);
+    printf("vga_bias = %d\n",this->m_section.vga_bias);
+    printf("vga_stg1_fine_bias = %d\n",this->m_section.vga_stg1_fine_bias);
+    printf("ats_ver = %d\n",this->m_section.ats_ver);
+    printf("mlt_ver = %d\n",this->m_section.mlt_ver);
+    printf("bl_ver = %d\n",this->m_section.bl_ver);
+    printf("lo_power_gc_ctrl = %d\n",this->m_section.lo_power_gc_ctrl);
+    printf("production1 = %d\n",this->m_section.production1);
+    printf("production2 = %d\n",this->m_section.production2);
+    printf("production3 = %d\n",this->m_section.production3);
+    printf("production4 = %d\n",this->m_section.production4);
+    printf("production5 = %d\n",this->m_section.production5);
+    printf("production6 = %d\n",this->m_section.production6);
+    printf("production7 = %d\n",this->m_section.production7);
+    printf("production8 = %d\n",this->m_section.production8);
+    printf("production9 = %d\n",this->m_section.production9);
+    printf("production10 = %d\n",this->m_section.production10);
+    printf("production11 = %d\n",this->m_section.production11);
+    printf("production12 = %d\n",this->m_section.production12);
+    printf("production13 = %d\n",this->m_section.production13);
+    printf("production14 = %d\n",this->m_section.production14);
+    printf("production15 = %d\n",this->m_section.production15);
+    printf("production16 = %d\n",this->m_section.production16);
+}
+
+template <class PRODUCT>
+void ids_section_t<PRODUCT>::disp_to_file(const char* ids_ini_file) const
+{
+    std::ofstream fs(ids_ini_file);
+
+    if(!fs)
+    {
+        printf("Cannot open the output file\n");
+        return;
+    }
+
+
+    fs << "[IDS]" << endl;
+    fs << "version = " << (int)(this->m_section.version) << endl;
+
+    // Mac address
+    fs << "mac_address = 0x" ;
+    fs << hex << std::setw(2) << std::setfill('0') << (int)(this->m_section.mac_address[5]);
+    fs << hex << std::setw(2) << std::setfill('0') << (int)(this->m_section.mac_address[4]);
+    fs << hex << std::setw(2) << std::setfill('0') << (int)(this->m_section.mac_address[3]);
+    fs << hex << std::setw(2) << std::setfill('0') << (int)(this->m_section.mac_address[2]);
+    fs << hex << std::setw(2) << std::setfill('0') << (int)(this->m_section.mac_address[1]);
+    fs << hex << std::setw(2) << std::setfill('0') << (int)(this->m_section.mac_address[0]);
+    fs << endl;
+
+
+    fs << std::setbase(10);
+    fs << "local = " << (int)(this->m_section.local) << endl;
+    fs << "ssid = " << this->m_section.ssid << endl;
+    fs << "ppm = " << this->m_section.ppm << endl;
+    fs << "board = " << this->m_section.board_type << endl;
+    fs << "lo_power_xif_gc = " << this->m_section.lo_power_xif_gc << endl;
+    fs << "lo_power_stg2_bias = " << this->m_section.lo_power_stg2_bias << endl;
+    fs << "vga_bias = " << this->m_section.vga_bias << endl;
+    fs << "vga_stg1_fine_bias = " << this->m_section.vga_stg1_fine_bias << endl;
+    fs << "ats_ver = " << this->m_section.ats_ver << endl;
+    fs << "mlt_ver = " << this->m_section.mlt_ver << endl;
+    fs << "bl_ver = " << this->m_section.bl_ver << endl;
+    fs << "lo_power_gc_ctrl = " << this->m_section.lo_power_gc_ctrl << endl;
+    fs << "production1 = " << this->m_section.production1 << endl;
+    fs << "production2 = " << this->m_section.production2 << endl;
+    fs << "production3 = " << this->m_section.production3 << endl;
+    fs << "production4 = " << this->m_section.production4 << endl;
+    fs << "production5 = " << this->m_section.production5 << endl;
+    fs << "production6 = " << this->m_section.production6 << endl;
+    fs << "production7 = " << this->m_section.production7 << endl;
+    fs << "production8 = " << this->m_section.production8 << endl;
+    fs << "production9 = " << this->m_section.production9 << endl;
+    fs << "production10 = " << this->m_section.production10 << endl;
+    fs << "production11 = " << this->m_section.production11 << endl;
+    fs << "production12 = " << this->m_section.production12 << endl;
+    fs << "production13 = " << this->m_section.production13 << endl;
+    fs << "production14 = " << this->m_section.production14 << endl;
+    fs << "production15 = " << this->m_section.production15 << endl;
+    fs << "production16 = " << this->m_section.production16 << endl;
+    fs << std::setbase(16);
+    fs.close();
+}
+
+//usb_section_t::usb_section_t (const char *name, u_int16_t *ptr_low, u_int16_t* ptr_high)
+usb_section_t::usb_section_t (const char *name, ADDRESS32 *ptr)
+    :flash_section(name)
+{
+    //m_ptr_low = ptr_low;
+    //m_ptr_high = ptr_high;
+    this->m_ptr = ptr;
+    this->m_size = 0;
+    m_buffer = 0;
+}
+
+void usb_section_t::write_to_buffer(BYTE *buffer )
+{
+    INFO("%s: Writing section of size 0x%04x at offset 0x%04x\n",this->m_name, this->m_size, m_offset);
+
+    memcpy(buffer + m_offset, m_buffer, this->m_size);
+}
+
+void usb_section_t::handle_ini_section (const ini_section_t &ini_section)
+{
+    this->m_size = ini_section.size() * sizeof (IMAGE);
+    m_buffer = new IMAGE [ini_section.size()];
+    memset((void*)m_buffer, -1, this->m_size);
+
+    ini_section_t::const_iterator sec_iter;
+    sec_iter = ini_section.begin();
+    int index = 0;
+    while (sec_iter != ini_section.end())
+    {
+        get_resolved_data(sec_iter, &m_buffer[index]);
+        index++;
+        sec_iter++;
+    }
+
+    if (this->m_size > this->m_max_size) {
+        ERR("Section %s with size %d exceeds maximum section size of %d\n",
+            this->m_name, this->m_size, this->m_max_size );
+        EXIT (-1);
+    }
+}
+
+void usb_section_t::set_offset (int offset)
+{
+    flash_section::set_offset(offset);
+    //*m_ptr_low = (u_int16_t)offset;
+    //*m_ptr_high = (u_int16_t)(offset>>16);
+    *this->m_ptr = offset;
+}
+
+usb_section_t::~usb_section_t()
+{
+    delete m_buffer;
+}
+
+//template class pointer_section_t<u_int16_t>;
+//template class pointer_section_t<u_int32_t>;
diff --git a/debug-tools/wiburn/flash_sections.h b/debug-tools/wiburn/flash_sections.h
new file mode 100644
index 0000000..9d7b543
--- /dev/null
+++ b/debug-tools/wiburn/flash_sections.h
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _FLASH_SECTIONS_H_
+#define _FLASH_SECTIONS_H_
+
+#include "wiburn.h"
+#include "ini_parser_types.h"
+#include "flash.h"
+#include "CCRC32.h"
+
+enum tag_ids {
+    image_format_version_tag_id = 0x1,
+    fw_version_tag_id = 0x2,
+    fw_timestamp_tag_id = 0x3,
+    usb_format_version_tag_id = 0x1,
+    usb_version_tag_id = 0x2,
+    usb_timestamp_tag_id = 0x3,
+    configuration_id_tag_id = 0x4,
+    device_id_tag_id = 0x5,
+    hw_id_tag_id = 0x6,
+    end_tag_id =    0xff
+};
+
+#pragma pack(push, 1)
+template <class PRODUCT>
+struct pointers_t
+{
+    typename PRODUCT::REG   signature;
+    ADDRESS32               hw_pointer;
+    ADDRESS32               fw1_pointer;
+    typename PRODUCT::REG   fw1_length;
+    ADDRESS32               fw1_data_pointer;
+    typename PRODUCT::REG   fw1_data_length;
+    ADDRESS32               fw2_pointer;
+    typename PRODUCT::REG   fw2_length;
+    ADDRESS32               fw2_data_pointer;
+    typename PRODUCT::REG   fw2_data_length;
+    ADDRESS32               production_pointer;
+    ADDRESS32               ids_pointer;
+    typename PRODUCT::REG   pointer_section_version;
+    ADDRESS32               fw1_static_conf_pointer;
+    ADDRESS32               fw2_static_conf_pointer;
+    ADDRESS32               config_section_pointer;
+    ADDRESS32               image_info_pointer;
+    ADDRESS32               radio_tx_cnf_pointer;
+    ADDRESS32               radio_rx_cnf_pointer;
+    ADDRESS32               radio_tx_cnf2_pointer;
+    ADDRESS32               radio_rx_cnf2_pointer;
+    ADDRESS32               raw_data_pointer;
+    typename PRODUCT::REG   raw_data_length;
+
+    // Unused
+    ADDRESS32               usb_pointer;
+    ADDRESS32               usb_info_pointer;
+    ADDRESS32               user_pointer;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+template <class PRODUCT>
+struct address_value_t
+{
+    typename PRODUCT::ADDRESS address;
+    typename PRODUCT::REG value;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+template <class PRODUCT>
+struct address_value_mask_t
+{
+    typename PRODUCT::ADDRESS address;
+    typename PRODUCT::REG value;
+    typename PRODUCT::REG mask;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct tag_header_t
+{
+    BYTE reserved;
+    BYTE tag_id;
+    u_int16_t tag_size;
+    void disp(const char *name);
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct format_version_tag_t
+{
+    BYTE format_version;
+    BYTE reserved [3];
+    void disp(const char *name);
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct version_tag_t
+{
+    u_int32_t minor : 8;
+    u_int32_t major : 8;
+    u_int32_t build : 13;
+    u_int32_t sub_minor : 3;
+    void disp(const char *name);
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct timestamp_tag_t
+{
+    BYTE min;
+    BYTE hour;
+    BYTE reserved1;
+    BYTE sec;
+    BYTE month;
+    BYTE day;
+    u_int16_t year;
+    void disp(const char *name);
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct configuration_id_tag_t
+{
+    BYTE id [16];
+    void disp(const char *name);
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct device_id_tag_t
+{
+    u_int16_t device_id;
+    BYTE revision_id;
+    BYTE misc;
+    void disp(const char *name);
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct hw_id_tag_t
+{
+    BYTE digital_soc_id;
+    BYTE board_id;
+    BYTE antenna_id;
+    BYTE rf_id;
+    u_int16_t serial_id;
+    u_int16_t reserved;
+    void disp(const char *name);
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct end_tag_t
+{
+    u_int16_t reserved1;
+    u_int16_t reserved2;
+    void disp(const char *name);
+};
+#pragma pack(pop)
+
+class tag_base_t
+{
+public:
+    virtual char *get_tag() = 0;
+    tag_base_t (BYTE id, const char* name);
+    virtual ~tag_base_t() {};
+    virtual void disp() = 0;
+public:
+    tag_header_t m_header;
+    const char *m_name;
+};
+
+template <class Tag>
+class tag_t: public tag_base_t
+{
+public:
+    char *get_tag();
+    tag_t (BYTE id, const char* name = 0);
+    virtual ~tag_t() {};
+    void disp();
+public:
+    Tag m_tag;
+};
+
+
+#pragma pack(push, 1)
+struct section_header_t
+{
+    BYTE reserved;
+    BYTE section_id;
+    u_int16_t section_size;
+};
+#pragma pack(pop)
+
+class flash_section
+{
+public:
+    flash_section (const char *name);
+    virtual void write_to_buffer(BYTE *buffer ) = 0;
+    int size () const;
+    int get_max_size () const;
+    void set_max_size ( u_int32_t max_size );
+    void set_offset (u_int32_t offset);
+    u_int32_t get_offset () const;
+    virtual ~flash_section() {};
+protected:
+    u_int32_t m_size;
+    u_int32_t m_max_size;
+    u_int32_t m_offset;
+    const char *m_name;
+    u_int32_t m_crc;
+    CCRC32 m_CalcCRC;
+};
+
+class usb_section_t : public flash_section
+{
+public:
+    //usb_section_t (const char *name, u_int16_t *ptr_low, u_int16_t* ptr_high);
+    usb_section_t (const char *name, ADDRESS32 *ptr);
+    void write_to_buffer(BYTE *buffer ) ;
+    void handle_ini_section (const ini_section_t &ini_section);
+    void set_offset (int offset);
+    ~usb_section_t();
+public:
+    IMAGE *m_buffer;
+//   u_int16_t *m_ptr_low;
+//   u_int16_t *m_ptr_high;
+    ADDRESS32 *m_ptr;
+};
+
+class id_section : public flash_section
+{
+public:
+    //id_section (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t* ptr_high);
+    id_section (const char *name, BYTE id, ADDRESS32 *ptr);
+    void set_offset (int offset);
+
+public:
+    section_header_t header;
+//   u_int16_t *m_ptr_low;
+//   u_int16_t *m_ptr_high;
+    ADDRESS32 *m_ptr;
+};
+
+class variable_section_t : public id_section
+{
+public:
+//   variable_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t *ptr_high);
+    variable_section_t (const char *name, BYTE id, ADDRESS32 *ptr);
+    ~variable_section_t ();
+protected:
+    int m_buffer_size;
+};
+
+template <class PRODUCT>
+class hw_section_t : public variable_section_t
+{
+public:
+//   hw_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t *ptr_high);
+    hw_section_t (const char *name, BYTE id, ADDRESS32 *ptr);
+public:
+    void handle_ini_section (u_int8_t translation_map_bits, const ini_section_t &ini_section);
+    void init (flash_base *flash);
+    bool operator == (const hw_section_t &r_side) const;
+    void write_to_buffer(BYTE *buffer ) ;
+    ~hw_section_t ();
+    address_value_t <PRODUCT> *m_buffer;
+    u_int16_t *m_length;
+    u_int32_t m_termination [2];
+
+};
+
+template <class PRODUCT>
+class fw_section_t : public variable_section_t
+{
+public:
+    //fw_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t *ptr_high);
+    fw_section_t (const char *name, BYTE id, ADDRESS32 *ptr);
+public:
+    void handle_ini_section (u_int8_t translation_map_bits, const ini_section_t &ini_section);
+    void write_to_buffer(BYTE *buffer ) ;
+    ~fw_section_t ();
+    address_value_mask_t <PRODUCT> *m_buffer;
+};
+
+template <class PRODUCT>
+class image_section_t : public variable_section_t
+{
+public:
+    //image_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t *ptr_high, u_int16_t *length);
+    image_section_t (const char *name, BYTE id, ADDRESS32 *ptr, typename PRODUCT::REG *length);
+    void handle_ini_section (const ini_section_t &ini_section);
+    void write_to_buffer(BYTE *buffer ) ;
+    void set_offset (int offset);
+    ~image_section_t ();
+public:
+    IMAGE *m_buffer;
+    //u_int16_t *m_length;
+    typename PRODUCT::REG *m_length;
+};
+
+template <class PRODUCT>
+class pointer_section_t : public flash_section
+{
+public:
+    pointer_section_t (const char *name);
+    void init (flash_base *fl);
+    void write_to_buffer(BYTE *buffer ) ;
+    bool operator == (const pointer_section_t <PRODUCT> &r_side) const;
+public:
+    pointers_t <PRODUCT> m_pointers;
+};
+
+template <class PRODUCT>
+class info_section_t : public variable_section_t
+{
+public:
+    typedef vector <tag_base_t*> tag_vector_t;
+public:
+//   info_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t *ptr_high);
+    info_section_t (const char *name, BYTE id, ADDRESS32 *ptr);
+    virtual void handle_ini_section (const ini_section_t &ini_section,
+                                     const string &name) = 0;
+    virtual void init (flash_base *flash) = 0;
+    void write_to_buffer(BYTE *buffer ) ;
+    ~info_section_t ();
+    void disp() const;
+
+public:
+    tag_vector_t m_tags;
+    u_int16_t *m_length;
+};
+
+template <class PRODUCT>
+class image_info_section_t : public info_section_t<PRODUCT>
+{
+public:
+    //image_info_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t *ptr_high);
+    image_info_section_t (const char *name, BYTE id, ADDRESS32 *ptr);
+    void handle_ini_section (const ini_section_t &ini_section,
+                             const string &name);
+    void init (flash_base *fl);
+    ~image_info_section_t ();
+};
+
+template <class PRODUCT>
+class usb_info_section_t : public info_section_t<PRODUCT>
+{
+public:
+//   usb_info_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t *ptr_high);
+    usb_info_section_t (const char *name, BYTE id, ADDRESS32 *ptr);
+    void handle_ini_section (const ini_section_t &ini_section,
+                             const string &name);
+    void init (flash_base *fl);
+    ~usb_info_section_t ();
+};
+
+template <class PRODUCT>
+class system_config_section_t : public flash_section
+{
+public:
+    system_config_section_t (const char *name, ADDRESS32 *ptr);
+    void set_offset (int offset);
+    void write_to_buffer(BYTE *buffer ) ;
+
+public:
+    ADDRESS32 *m_ptr;
+};
+
+
+#pragma pack(push, 1)
+struct ids_section
+{
+    BYTE reserved1;
+    BYTE version;
+    BYTE mac_address [6];
+    BYTE ssid [32];
+    u_int16_t local;
+    u_int16_t reserved2;
+    u_int16_t ppm;
+    u_int16_t reserved3;
+    u_int32_t board_type;
+    u_int16_t lo_power_xif_gc;
+    u_int16_t lo_power_stg2_bias;
+    u_int16_t vga_bias;
+    u_int16_t vga_stg1_fine_bias;
+    u_int16_t ats_ver;
+    u_int16_t mlt_ver;
+    u_int16_t bl_ver;
+    u_int16_t lo_power_gc_ctrl;
+    u_int16_t production1;
+    u_int16_t production2;
+    u_int16_t production3;
+    u_int16_t production4;
+    u_int16_t production5;
+    u_int16_t production6;
+    u_int16_t production7;
+    u_int16_t production8;
+    u_int16_t production9;
+    u_int16_t production10;
+    u_int16_t production11;
+    u_int16_t production12;
+    u_int16_t production13;
+    u_int16_t production14;
+    u_int16_t production15;
+    u_int16_t production16;
+};
+#pragma pack(pop)
+
+template <typename T, class PRODUCT>
+    struct const_section_t: public id_section
+{
+public:
+//   const_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t* ptr_high);
+    const_section_t (const char *name, BYTE id, ADDRESS32 *ptr);
+    virtual void handle_ini_section (const ini_section_t &ini_section) = 0;
+    void write_to_buffer(BYTE *buffer ) ;
+    virtual void init (flash_base *fl);
+    virtual void initReduced (flash_base *fl, int reductionSize);
+public:
+    T m_section;
+};
+
+
+template <class PRODUCT>
+struct ids_section_t: public const_section_t <ids_section, PRODUCT>
+{
+public:
+//   ids_section_t (const char *name, BYTE id, u_int16_t *ptr_low, u_int16_t* ptr_high);
+    ids_section_t (const char *name, BYTE id, ADDRESS32 *ptr);
+    void handle_ini_section (const ini_section_t &ini_section);
+    void disp() const;
+    void disp_to_file(const char* ids_ini_file) const;
+};
+#endif //#ifndef _FLASH_SECTIONS_H_
diff --git a/debug-tools/wiburn/ini_parser.cpp b/debug-tools/wiburn/ini_parser.cpp
new file mode 100644
index 0000000..4783f60
--- /dev/null
+++ b/debug-tools/wiburn/ini_parser.cpp
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#pragma once
+
+#include "ini_parser.h"
+#include <algorithm>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+template <class PRODUCT>
+void ini_parser<PRODUCT>::update_section(u_int8_t translation_map_bits, ini_section_t *orig, const ini_section_t &update, bool is_string)
+{
+    if (*orig == update) {
+        return;
+    }
+
+    ini_section_t::const_iterator update_iter = update.begin();
+    ini_section_t::iterator orig_iter;
+    while (update_iter != update.end() ) {
+        orig_iter = find(translation_map_bits, update_iter, *orig, is_string);
+        if (orig_iter == orig->end() ) {
+            if (g_debug) DBG("Appending key %s value %s\n", update_iter->first.c_str(), update_iter->second.c_str());
+            orig->insert(orig->end(), *update_iter); // append entry from the update section
+        } else {
+            if (g_debug) DBG("Replacing Key %s value %s with key %s value %s\n"
+                             , orig_iter->first.c_str()
+                             , orig_iter->second.c_str()
+                             , update_iter->first.c_str()
+                             , update_iter->second.c_str());
+            *orig_iter = *update_iter; // replace the original entry with the entry from the update section
+        }
+        update_iter++;
+    }
+}
+
+template <class PRODUCT>
+ini_section_t::iterator ini_parser<PRODUCT>::find(
+    u_int8_t                        translation_map_bits,
+    ini_section_t::const_iterator   &lside,
+    ini_section_t                   &ini_section,
+    bool                            is_string) const
+{
+    //u_int8_t                        translation_map_bits = 1;
+    typename PRODUCT::ADDRESS laddress,raddress;
+    typename PRODUCT::REG lvalue, rvalue;
+    int lstart, lend, rstart, rend;
+    if (!is_string) {
+        get_resolved_address_data(translation_map_bits, lside, &laddress, &lvalue, &lstart, &lend);
+    }
+
+    ini_section_t::iterator rside = ini_section.begin();
+    while (rside != ini_section.end() ) {
+        if (is_string) {
+            if (lside->first == rside->first) {
+                break;
+            }
+        } else {
+            get_resolved_address_data(translation_map_bits, rside, &raddress, &rvalue, &rstart, &rend);
+            if (laddress == raddress && lstart == rstart && lend == rend ) {
+                break;
+            }
+        }
+        rside++;
+    }
+    return rside;
+}
+
+//bool ini_parser::get_value (const ini_section_t &ini_section,
+//const string &key,
+//u_int64_t *value,
+//bool must_be) const
+bool get_value (const ini_section_t &ini_section,
+                const string &key,
+                u_int64_t *value,
+                bool must_be)
+{
+    ini_section_t::const_iterator iter = ini_section.begin();
+    while( ini_section.end() != iter ) {
+        if( iter->first == key ) {
+            char *end_ptr;
+            *value = STRTOULL(iter->second.c_str(), &end_ptr, 0);
+            if(*end_ptr != 0) {
+                ERR("Key %s: Failed converting value %s\n", key.c_str(), iter->second.c_str());
+                EXIT (-1);
+            }
+            return true;
+        }
+        iter++;
+    }
+
+    if(must_be) {
+        ERR("Could not find key %s\n", key.c_str());
+        EXIT (-1);
+    }
+
+    return false;
+}
+
+
+//bool ini_parser::get_string(const ini_section_t &ini_section,
+//const string &key,
+//void *str,
+//u_int32_t max_length,
+//bool must_be) const
+bool get_string(const ini_section_t &ini_section,
+                const string &key,
+                void *str,
+                u_int32_t max_length,
+                bool must_be)
+{
+    ini_section_t::const_iterator iter = ini_section.begin();
+    while( ini_section.end() != iter ) {
+        if( iter->first == key ) {
+            if (iter->second.size() > max_length ) {
+                ERR("Key %s: length %lu exceeded maximal length of %u\n", key.c_str(), (unsigned long)iter->second.size(), max_length);
+                EXIT (-1);
+            }
+
+            iter->second.copy((char*)str, max_length);
+
+            return true;
+        }
+        iter++;
+    }
+
+    if(must_be) {
+        ERR("Could not find key %s\n", key.c_str());
+        EXIT (-1);
+    }
+
+    return false;
+}
+
+template <class PRODUCT>
+void ini_parser<PRODUCT>::get_resolved_address_data (
+    u_int8_t                        translation_map_bits,
+    ini_section_t::const_iterator    sec_iter,
+    typename PRODUCT::ADDRESS        *address,
+    typename PRODUCT::REG            *value,
+    bool                            word_addresses)
+{
+    int start, end;
+    get_resolved_address_data(translation_map_bits, sec_iter, address, value, &start, &end, word_addresses);
+}
+
+template <class PRODUCT>
+void ini_parser<PRODUCT>::get_resolved_address_data (
+    u_int8_t                        translation_map_bits,
+    ini_section_t::const_iterator    sec_iter,
+    typename PRODUCT::ADDRESS        *address,
+    typename PRODUCT::REG            *value,
+    int                                *start,
+    int                                *end,
+    bool                            word_addresses
+    )
+{
+    char *end_ptr;
+    if(g_debug) DBG( "Dumping address %s  value %s\n", sec_iter->first.c_str(),sec_iter->second.c_str());
+    *address = ( typename PRODUCT::ADDRESS)strtoul(sec_iter->first.c_str(), &end_ptr, 0);
+    if (0 != *end_ptr) // it was a pathname
+    {
+        if(g_debug) DBG("Converting %s to ", sec_iter->first.c_str());
+        u_int32_t temp_address;
+        bool found = false;
+        if (!found && (translation_map_bits & TRANSLATION_MAP_REGTREE))
+        {
+            found = g_reg_tree_t_map.get_from_translation_map(sec_iter->first.c_str(), &temp_address, start, end);
+        }
+        if (!found && (translation_map_bits & TRANSLATION_MAP_FW))
+        {
+            found = g_fw_t_map.get_from_translation_map(sec_iter->first.c_str(), &temp_address, start, end);
+        }
+        if (!found && (translation_map_bits & TRANSLATION_MAP_UCODE))
+        {
+            found = g_ucode_t_map.get_from_translation_map(sec_iter->first.c_str(), &temp_address, start, end);
+        }
+
+//      bool found = ::g_t_map.get_from_translation_map(sec_iter->first.c_str(), &temp_address, start, end);
+        *address = ( typename PRODUCT::ADDRESS)temp_address;
+        if (!found) {
+            ERR("Could not find %s in translation map. Make sure that it is in the REG_TREE section in your INI file\n",
+                sec_iter->first.c_str());
+            EXIT (-1);
+        }
+        if (word_addresses) {
+            if (*address & 0x1) {
+                ERR("%s was converted to 0x%04x, which is not dword aligned\n",
+                    sec_iter->first.c_str(),
+                    *address );
+                EXIT (-1);
+            }
+
+            *address = *address / 2;
+        }
+    }
+    else
+    {
+        *start = 0;
+        *end = sizeof ( typename PRODUCT::REG) * 8 - 1;
+    }
+
+    *value = ( typename PRODUCT::REG)strtoul(sec_iter->second.c_str(), &end_ptr, 0);
+
+    if(g_debug) DBG( "Address %0#4x value %0#4x start %d end %d\n", *address, *value, *start, *end);
+}
+
+//void ini_parser::get_resolved_data (ini_section_t::const_iterator sec_iter,
+//                                IMAGE *value) const
+void get_resolved_data (ini_section_t::const_iterator sec_iter,
+                        IMAGE *value)
+{
+    char *end_ptr;
+    *value = strtoul(sec_iter->second.c_str(), &end_ptr, 0);
+    if(g_debug) DBG( "Image %0#4x\n", *value);
+}
+
+template <class PRODUCT>
+ini_parser<PRODUCT>::ini_parser ()
+{
+    this ->hadProductionSeciton = false;
+    //nothing to do
+}
+
+template <class PRODUCT>
+bool ini_parser<PRODUCT>::init (const char *filename, u_int32_t option)
+{
+    FILE *stream;
+    printf("%s\n", filename);
+    stream = fopen( filename, "r" );
+    if( stream == NULL )
+    {
+//        char cwd[1024];
+//        if (getcwd(cwd, sizeof(cwd)) != NULL)
+//                   fprintf(stdout, "Current working dir: %s\n", cwd);
+        printf("%s\n", strerror(errno));
+        ERR( "Failed opening file %s \n", filename );
+        EXIT (-1);
+    }
+    else
+    {
+        int reg_tree_section_index = 0;
+        bool skip_section = false;
+        char buffer [1100];
+        char a1 [1000];
+        char a2 [256];
+        char a3 [256];
+        char a4 [256];
+
+        int ch;
+        int num;
+        u_int8_t translation_map_bits = TRANSLATION_MAP_NONE;
+
+        do
+        {
+            ch = get_clean_line (stream, buffer, sizeof buffer);
+
+            num = sscanf(buffer, "%999s %256s %256s %256s", a1, a2, a3, a4);
+            switch (num)
+            {
+            case 1:
+            {
+                INFO( "Section [%s]\n", a1 );
+                string section = a1;
+
+                if (section == "production")
+                {
+                    if (hadProductionSeciton == true)
+                    {
+                        ERR( "Only one PRODUCTION Section is allowed in one burn command ! \n");
+                        EXIT (-1);
+                    }
+                    hadProductionSeciton = true;
+                }
+
+                if (option == 1)
+                {
+                    if (section == "radio_tx_conf")
+                    {
+                        section += "2";
+                    }
+                    if (section == "radio_rx_conf")
+                    {
+                        section += "2";
+                    }
+                }
+
+                skip_section = false;
+
+                if (section == "fw_symbols")
+                {
+                    translation_map_bits = TRANSLATION_MAP_FW;
+                }
+                else if (section == "ucode_symbols")
+                {
+                    translation_map_bits = TRANSLATION_MAP_UCODE;
+                }
+                else if (section == "reg_tree")
+                {
+                    translation_map_bits = TRANSLATION_MAP_REGTREE;
+                    // if [REG_TREE] section appear more then once then do not process
+                    // its key, values
+                    reg_tree_section_index++;
+                    if (reg_tree_section_index > 1)
+                    {
+                        skip_section = true;
+                    }
+                }
+                if (section != "reg_tree")
+                {
+                    if(g_debug) DBG("Adding ini section\n");
+                    ini_section_t *sec = new ini_section_t;
+                    pair <string, ini_section_t*> p (section, sec);
+                    current_ini_section = ini_file.insert(p);
+                }
+                break;
+            }
+            case 2:
+            {
+                if(g_debug) DBG( "Address %s Value %s\n", a1, a2 );
+                key_value_t entry (a1, a2);
+                pair <ini_section_t::iterator, bool> ret;
+                ini_section_t *sec = this->current_ini_section->second;
+                sec->push_back(entry);
+                break;
+            }
+            case 3:
+            {
+                if(g_debug) DBG( "Address %s[%s] Value %s\n", a1, a3, a2 );
+                string temp = a1;
+                temp += '#';
+                temp.append(a3);
+                key_value_t entry (temp, a2);
+                pair <ini_section_t::iterator, bool> ret;
+                ini_section_t *sec = this->current_ini_section->second;
+                sec->push_back(entry);
+                break;
+            }
+
+            case 4:
+            {
+                if (!skip_section)
+                {
+                    bool bInsert = false;
+
+                    if(g_debug) DBG ("path %s address %s start %s end %s\n", a1, a2, a3, a4);
+
+                    if (translation_map_bits == TRANSLATION_MAP_REGTREE)
+                    {
+                        bInsert = g_reg_tree_t_map.add_to_translation_map(a1, a2, a3, a4);
+                    }
+                    else if (translation_map_bits == TRANSLATION_MAP_FW)
+                    {
+                        bInsert = g_fw_t_map.add_to_translation_map(a1, a2, a3, a4);
+                    }
+                    else if (translation_map_bits == TRANSLATION_MAP_UCODE)
+                    {
+                        bInsert = g_ucode_t_map.add_to_translation_map(a1, a2, a3, a4);
+                    }
+
+                    //                        if( !g_t_map.add_to_translation_map(a1, a2, a3, a4) )
+                    if (!bInsert)
+                    {
+                        ERR("Failed adding to translation map: path %s address %s start %s end %s\n", a1, a2, a3, a4);
+                        EXIT (-1);
+                    };
+                }
+                break;
+            }
+            default : if(g_debug) DBG( "empty line or comment line\n" );break;
+            }
+        } while (EOF != ch);
+
+        fclose(stream);
+    }
+    return true;
+}
+
+template <class PRODUCT>
+int ini_parser<PRODUCT>::get_clean_line (FILE *stream, char *buffer, const int buffer_size) const
+{
+    int i;
+    int ch=0;
+    bool alpha_detected = false;
+    bool section_detected = false;
+
+    for (i = 0; i < buffer_size; i++)
+    {
+        ch = getc(stream);
+        if( ch >= 'A' && ch <= 'Z' )
+        {
+            ch = ch - 'A' + 'a'; // change to lower case
+        }
+
+        alpha_detected  = alpha_detected | (ch >= 'a' && ch <= 'z') ;
+
+        if (EOF == ch || '\n' == ch)
+        {
+            buffer[i] = '\0';
+            break;
+        }
+        else if ('[' == ch && !alpha_detected)
+        {
+            section_detected = true;
+            buffer[i] = ' ';
+        }
+        else if (']' == ch && section_detected)
+        {
+            buffer[i] = ' ';
+        }
+        else if ( '=' == ch)
+        {
+            buffer[i] = ' ';
+        }
+        else if ('#' == ch || ';' == ch)
+        {
+            buffer[i] = '\0';
+        } else
+        {
+            buffer[i] = (char)ch;
+        }
+    }
+    return ch;
+}
+template <class PRODUCT>
+bool ini_parser<PRODUCT>::get_section(const string &section_name, u_int8_t translation_map_bits, ini_file_t::iterator *iter1, bool is_string, bool must_be)
+{
+    //unused param
+    (void)must_be;
+
+    ini_file_t::iterator iter = ini_file.begin();
+    *iter1 = ini_file.end();
+    while (iter != ini_file.end() ) {
+        if (iter->first == section_name ) {
+            if (*iter1 == ini_file.end()){
+                *iter1 = iter;
+            }else{
+                this->update_section(translation_map_bits, (*iter1)->second, *(iter->second), is_string);
+            }
+        }
+        iter++;
+    }
+
+    //
+    // adding this lines cause the application stop running if the section must_be and did not find
+    // in other words, this function always return true
+    // if you decide to remove these lines, you should handle the return code in the caller function
+    //
+    /*if (must_be && *iter1 == ini_file.end()) {
+      ERR("Could not find mandatory section %s\n", section_name.c_str() );
+      EXIT (-1);
+      }*/
+
+    return (*iter1 != ini_file.end() );
+}
+
diff --git a/debug-tools/wiburn/ini_parser.h b/debug-tools/wiburn/ini_parser.h
new file mode 100644
index 0000000..01e625c
--- /dev/null
+++ b/debug-tools/wiburn/ini_parser.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _INI_PARSER_H_
+#define _INI_PARSER_H_
+
+#include "wiburn.h"
+#include "ini_parser_types.h"
+//#include "flash_sections.h"
+#include "translation_map.h"
+
+extern translation_map g_reg_tree_t_map;
+extern translation_map g_ucode_t_map;
+extern translation_map g_fw_t_map;
+
+typedef enum _TRANSLATION_MAP_BITS
+{
+    TRANSLATION_MAP_NONE    = 0,
+    TRANSLATION_MAP_REGTREE = 1,
+    TRANSLATION_MAP_FW      = 2,
+    TRANSLATION_MAP_UCODE    = 4,
+
+} TRANSLATION_MAP_BITS;
+
+bool get_value(const ini_section_t &ini_section,
+               const string &key,
+               u_int64_t *value,
+               bool must_be = true);
+
+bool get_string(const ini_section_t &ini_section,
+                const string &key,
+                void *string,
+                u_int32_t max_length,
+                bool must_be = true);
+
+
+
+void get_resolved_data (ini_section_t::const_iterator sec_iter,
+                        IMAGE *value);
+
+
+class ini_parser_base
+{
+public:
+    ini_parser_base () {};
+    virtual ~ini_parser_base () {};
+    virtual bool init (const char *filename, u_int32_t option = 0) = 0;
+    virtual bool get_section(const string &section_name, u_int8_t translation_map_bits, ini_file_t::iterator *iter1, bool is_string, bool must_be) = 0;
+    virtual void update_section(u_int8_t translation_map_bits, ini_section_t *orig, const ini_section_t &update, bool is_string) = 0;
+};
+
+template <class PRODUCT>
+class ini_parser: public ini_parser_base
+{
+private:
+    ini_file_t ini_file;
+    ini_file_t::iterator current_ini_section;
+
+public:
+    ini_parser ();
+    bool init (const char *filename, u_int32_t option = 0);
+    bool get_section(const string &section_name, u_int8_t translation_map_bits, ini_file_t::iterator *iter1, bool is_string, bool must_be);
+
+    //bool get_value(const ini_section_t &ini_section,
+    //               const string &key,
+    //               u_int64_t *value,
+    //               bool must_be = true) const;
+    //bool get_string(const ini_section_t &ini_section,
+    //                  const string &key,
+    //                  void *string,
+    //                  u_int32_t max_length,
+    //                  bool must_be = true) const;
+
+    static void get_resolved_address_data (
+        u_int8_t                        translation_map_bits,
+        ini_section_t::const_iterator    sec_iter,
+        typename PRODUCT::ADDRESS        *address,
+        typename PRODUCT::REG            *value,
+        bool                            word_addresses = false);
+
+    static void get_resolved_address_data (
+        u_int8_t                        translation_map_bits,
+        ini_section_t::const_iterator    sec_iter,
+        typename PRODUCT::ADDRESS        *address,
+        typename PRODUCT::REG            *value,
+        int                                *start,
+        int                                *end,
+        bool                                word_addresses = false);
+
+    //void get_resolved_data (ini_section_t::const_iterator sec_iter,
+    //                             IMAGE *value) const;
+
+    void update_section(u_int8_t translation_map_bits, ini_section_t *orig, const ini_section_t &update, bool is_string);
+private:
+    ini_section_t::iterator find(
+        u_int8_t                        translation_map_bits,
+        ini_section_t::const_iterator    &lside,
+        ini_section_t                    &ini_section,
+        bool                            is_string) const;
+    int get_clean_line (FILE *stream, char *buffer, const int buffer_size) const;
+
+    bool hadProductionSeciton;
+
+};
+
+
+#endif// #ifndef _INI_PARSER_H_
diff --git a/debug-tools/wiburn/ini_parser_types.h b/debug-tools/wiburn/ini_parser_types.h
new file mode 100644
index 0000000..96fd562
--- /dev/null
+++ b/debug-tools/wiburn/ini_parser_types.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _INI_PARSER_TYPES_H_
+#define _INI_PARSER_TYPES_H_
+
+#include <string>
+#include <map>
+#include <vector>
+
+using namespace std;
+
+typedef pair <string,string> key_value_t;
+typedef vector <key_value_t> ini_section_t;
+typedef multimap <string, ini_section_t*> ini_file_t;
+
+enum section_id_t {
+    production_section_id = 0,
+    ids_section_id = 1,
+    hw_conf_section_id = 2,
+    fw1_code_section_id = 3,
+    fw1_data_section_id = 4,
+    fw2_code_section_id = 5,
+    fw2_data_section_id = 6,
+    fw1_static_conf_section_id = 7,
+    fw2_static_conf_section_id = 8,
+    config_section_id = 9,
+    image_info_section_id = 10,
+    radio_tx_conf_section_id = 11,
+    radio_rx_conf_section_id = 12,
+    radio_tx_conf2_section_id = 13,
+    radio_rx_conf2_section_id = 14,
+    raw_data_section_id = 15,
+
+    // The Following is unused !
+    usb_info_section_id = 16,
+    user_conf_section_id = 17,
+    usb_section_id = 18,
+};
+
+#endif //#ifndef _INI_PARSER_TYPES_H_
diff --git a/debug-tools/wiburn/product.h b/debug-tools/wiburn/product.h
new file mode 100644
index 0000000..e163c2f
--- /dev/null
+++ b/debug-tools/wiburn/product.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _PRODUCT_H_
+#define _PRODUCT_H_
+
+#include "wiburn.h"
+
+#define MARLON_ID 612072
+#define SPARROW_ID 632072
+#define TALYN_ID 642072
+
+class IProduct
+{
+public:
+    IProduct(){}
+    virtual ~IProduct(void){}
+    virtual int Section2ID() = 0;
+};
+
+class talyn : public IProduct
+{
+public:
+   typedef u_int32_t REG;
+   typedef u_int32_t ADDRESS;
+   static const u_int64_t id = TALYN_ID;
+
+   virtual int Section2ID() {return 0;}
+};
+
+class sparrow : public IProduct
+{
+public:
+    typedef u_int32_t REG;
+    typedef u_int32_t ADDRESS;
+    static const u_int64_t id = SPARROW_ID;
+
+    virtual int Section2ID() {return 0;}
+};
+
+class marlon : public IProduct
+{
+public:
+    typedef u_int32_t REG;
+    typedef u_int32_t ADDRESS;
+    static const u_int64_t id = MARLON_ID;
+
+    virtual int Section2ID() {return 0;}
+};
+
+#endif //#ifndef _PRODUCT_H_
diff --git a/debug-tools/wiburn/template_inst.cpp b/debug-tools/wiburn/template_inst.cpp
new file mode 100644
index 0000000..c1cdf42
--- /dev/null
+++ b/debug-tools/wiburn/template_inst.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _TEMPLATE_INST_
+#define _TEMPLATE_INST_
+
+#include "product.h"
+
+#include "flash_sections.cpp"
+template class pointer_section_t<talyn>;
+template class pointer_section_t<sparrow>;
+template class pointer_section_t<marlon>;
+
+template class hw_section_t<talyn>;
+template class hw_section_t<sparrow>;
+template class hw_section_t<marlon>;
+
+template struct ids_section_t<talyn>;
+template struct ids_section_t<sparrow>;
+template struct ids_section_t<marlon>;
+
+template class info_section_t<talyn>;
+template class info_section_t<sparrow>;
+template class info_section_t<marlon>;
+
+
+#include "flash_image.cpp"
+template class flash_image<talyn>;
+template class flash_image<sparrow>;
+template class flash_image<marlon>;
+
+#include "ini_parser.cpp"
+template class ini_parser<talyn>;
+template class ini_parser<sparrow>;
+template class ini_parser<marlon>;
+
+//#include "flash.cpp"
+// template class flash<sparrow>;
+// template class flash<marlon>;
+// template class flash_file<sparrow>;
+// template class flash_file<marlon>;
+
+#endif
diff --git a/debug-tools/wiburn/translation_map.cpp b/debug-tools/wiburn/translation_map.cpp
new file mode 100644
index 0000000..627eacc
--- /dev/null
+++ b/debug-tools/wiburn/translation_map.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "translation_map.h"
+
+#include "wlct_os.h"
+
+translation_map::translation_map ()
+{
+    //nothing to do
+}
+
+translation_map::~translation_map ()
+{
+    //nothing to do
+}
+
+bool translation_map::add_to_translation_map (const char* key, const char* address, const char* start, const char* end)
+{
+    u_int32_t int_address;
+    int int_start, int_end;
+    char *end_ptr;
+
+    int_address = (u_int32_t)strtoul(address, &end_ptr, 0);
+    if (0 != *end_ptr) {
+        ERR("Error converting %s to int\n", address);
+        EXIT (-1);
+    }
+
+    int_start = strtoul(start, &end_ptr, 0);
+    if (0 != *end_ptr) {
+        ERR("Error converting %s to int\n", start);
+        EXIT (-1);
+    }
+
+    int_end = strtoul(end, &end_ptr, 0);
+    if (0 != *end_ptr) {
+        ERR("Error converting %s to int\n", end);
+        EXIT (-1);
+    }
+
+    return add_to_translation_map(key, int_address, int_start, int_end);
+}
+
+
+bool translation_map::add_to_translation_map (const char* key, const u_int32_t address, const int start, const int end)
+{
+    full_address_t temp_address = {address, start, end};
+    string temp_string (key);
+    translation_map_t::value_type entry (key, temp_address);
+    pair <translation_map_t::iterator, bool> ret;
+    ret = m_map.insert(entry);
+    return (ret.second);
+}
+
+bool translation_map::get_from_translation_map (const char* key, u_int32_t *address, int *start, int *end) const
+{
+    translation_map_t::const_iterator iter;
+    string temp_string (key);
+    iter = m_map.find(temp_string);
+    if ( iter == m_map.end( ) )
+    {
+        return false;
+    } else {
+        *address = iter->second.address;
+        *start = iter->second.start;
+        *end = iter->second.end;
+        return true;
+    }
+}
+
diff --git a/debug-tools/wiburn/translation_map.h b/debug-tools/wiburn/translation_map.h
new file mode 100644
index 0000000..d7bd823
--- /dev/null
+++ b/debug-tools/wiburn/translation_map.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _TRANSLATION_MAP_H
+#define _TRANSLATION_MAP_H
+
+#include <map>
+#include <string>
+#include "wiburn.h"
+using namespace std;
+
+class translation_map
+{
+private:
+    typedef struct {
+        u_int32_t address;
+        int start;
+        int end;
+    } full_address_t;
+
+    typedef map <string, full_address_t> translation_map_t;
+
+private:
+    translation_map_t m_map;
+
+public:
+    translation_map ();
+    ~translation_map ();
+    bool add_to_translation_map (const char* key, const u_int32_t address, const int start, const int end);
+    bool add_to_translation_map (const char* key, const char* address, const char* start, const char* end);
+    bool get_from_translation_map (const char* key, u_int32_t *address, int *start, int *end) const;
+};
+
+#endif //#ifndef _TRANSLATION_MAP_H
diff --git a/debug-tools/wiburn/wiburn.cpp b/debug-tools/wiburn/wiburn.cpp
new file mode 100644
index 0000000..97f4268
--- /dev/null
+++ b/debug-tools/wiburn/wiburn.cpp
@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#include "flash.h"
+#include "translation_map.h"
+#include "flash_image.h"
+#include <signal.h>
+#include "ParameterParser.h"
+#include "product.h"
+#include <iostream>
+
+#ifdef _WINDOWS
+bool g_debug = false;
+#else
+extern bool g_debug;
+#endif
+translation_map g_reg_tree_t_map;
+translation_map g_ucode_t_map;
+translation_map g_fw_t_map;
+
+extern u_int64_t current_fw_build;
+
+ini_parser_base *g_parser = 0;
+flash_base *g_flash = 0;
+
+volatile bool g_exit = false;
+
+int g_signals_for_termination[] = {
+    SIGINT,
+    SIGTERM
+};
+
+bool IsReduced();
+
+
+void EXIT (int val) {
+    delete g_flash;
+    exit (val);
+}
+
+bool get_interface (string *name) {
+    INFO("Acquiring available interfaces. Please wait...\n");
+    INTERFACE_LIST interfaces;
+    int num_items;
+    int res;
+    res = GetInterfaces(&interfaces, &num_items);
+    INFO("\n");
+
+    if (res != 0 || num_items == 0) {
+        return false;
+    }
+
+    if (num_items == 1 ) {
+        *name = interfaces.list[0].ifName;
+        INFO("Using the single available interface %s\n", interfaces.list[0].ifName);
+        return true;
+    }
+
+    printf("Please choose interface index:\n");
+    for (int i = 0; i < num_items; i++) {
+        std::cout << "[" << i << "] " << interfaces.list[i].ifName << std::endl;
+    }
+
+    u_int32_t index;
+    std::cin >> index;
+
+    if (!std::cin.good() || index >= (u_int32_t)num_items ) {
+        ERR("Invalid interface chosen\n");
+        EXIT (-1);
+    }
+
+    *name = interfaces.list[index].ifName;
+    return true;
+}
+
+void print_buffer(const void *buffer, int length)
+{
+    for(int i=0; i< length; i++) {
+        putchar(*((char*)(buffer) + i));
+    }
+}
+
+void set_exit_flag(bool bExit)
+{
+    g_exit = bExit;
+    if (g_flash)
+    {
+        g_flash->set_exit_flag(bExit);
+    }
+}
+
+void TerminationHandler (int signum)
+{
+    static int termination_cnt = 0;
+    if (signum == 0) {
+        INFO ("\nTrying to exit...\n");
+        set_exit_flag(true);
+        return;
+    }
+
+    termination_cnt++;
+
+    if (termination_cnt == 2) {
+        INFO ("\nTrying to exit...\n");
+        set_exit_flag(true);
+    }
+    else {
+        INFO ("\nWarning: Please wait for program normal termination or press ^C again to exit.\n");
+        signal(signum, TerminationHandler);
+        return;
+    }
+}
+
+void compatibility_check() {
+    /* const u_int64_t minimal_ver_supported = 2026;
+       if (current_fw_build < minimal_ver_supported) {
+       ERR("Current INI file is older than %lu and is not supported by this wiburn version !\n", (long unsigned int)minimal_ver_supported);
+       //EXIT (-1);
+       }*/
+}
+
+void param_parsing (ParameterParser *opt)
+{
+    opt->addFlag(  "-debug" ); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-verify" ); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-help" ); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-save"); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-burn" ); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-read" ); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-read_formatted" ); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-query" ); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-erase"); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-force"); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-ignore_lock"); /* a flag (takes no argument), supporting long and short form */
+    opt->addFlag(  "-read_ids_to_file"); /* a flag (takes no argument), supporting long and short form */
+
+    opt->addParam( "-bin" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-fw" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-board" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-board2" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-board3" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-setup_ini" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-ids" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-production" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-usb" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-interface" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-device" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-offset" );/* an option (takes an argument), supporting long and short form */
+    opt->addParam( "-length" );/* an option (takes an argument), supporting long and short form */
+}
+
+template <typename PRODUCT>
+void sub_main(bool burn,
+              bool erase,
+              bool burn_full_image,
+              bool query,
+              bool verify,
+              bool read,
+              bool read_formatted,
+              bool read_ids_to_file,
+              bool force,
+              const char* offset,
+              const char* length,
+              const char* bin_file,
+              const char* fw_ini_file,
+              const char* ids_ini_file,
+              const char* production_ini_file,
+              const char* board_ini_file,
+              const char* board_ini_file2,
+              const char* board_ini_file3,
+              const char* setup_ini_file,
+              const char* usb_ini_file)
+{
+    flash_image<PRODUCT>* new_flash_image = 0;
+    flash_image<PRODUCT>* old_flash_image = 0;
+
+    bool reducedSip = IsReduced();
+
+    if (reducedSip)
+    {
+        INFO("SIP type: REDUCED");
+    }
+    else
+    {
+        INFO("SIP type: FULL");
+    }
+
+    old_flash_image = new flash_image<PRODUCT>;
+    old_flash_image->init_pointer_section(g_flash);
+    old_flash_image->init_ids_section(g_flash, reducedSip);
+    const ids_section_t<PRODUCT> &ids = old_flash_image->get_ids_section();
+
+    if( read_ids_to_file ) {
+        INFO("\nReading current IDS section into file: %s\n", ids_ini_file);
+        ids.disp();
+        ids.disp_to_file( ids_ini_file );
+    }
+
+    // parse INI file if needed
+    if( burn ) {
+        new_flash_image = new flash_image<PRODUCT>;
+        if( bin_file ) {
+            INFO("\n######### Initializing from BIN file %s ###########\n", bin_file);
+            new_flash_image->init(bin_file);
+        } else {
+            if( fw_ini_file ) {
+                INFO("\n######### Initializing from FW INI file %s ###########\n", fw_ini_file);
+                g_parser->init(fw_ini_file);
+            }
+            if( ids_ini_file ) {
+                INFO("\n######### Initializing from IDs INI file %s ###########\n", ids_ini_file);
+                g_parser->init(ids_ini_file);
+            }
+            else
+            {
+                INFO("\n######### Taking IDs section from flash ###########\n");
+                new_flash_image->init_ids_section( g_flash, reducedSip );
+            }
+
+            if( production_ini_file ) {
+                INFO("\n######### Initializing from Production INI file %s ###########\n", production_ini_file);
+                g_parser->init(production_ini_file);
+            }
+            if( board_ini_file ) {
+                INFO("\n######### Initializing from Board INI file %s ###########\n", board_ini_file);
+                g_parser->init(board_ini_file);
+            }
+            if( board_ini_file2 ) {
+                INFO("\n######### Initializing from Board2 INI file %s ###########\n", board_ini_file2);
+                g_parser->init(board_ini_file2, 1);
+            }
+            if( board_ini_file3 ) {
+                INFO("\n######### Initializing from Board3 INI file %s ###########\n", board_ini_file3);
+                g_parser->init(board_ini_file3, 1);
+            }
+            if( setup_ini_file ) {
+                INFO("\n######### Initializing from setup_ini INI file %s ###########\n", setup_ini_file);
+                g_parser->init(setup_ini_file);
+            }
+            if( usb_ini_file ) {
+                INFO("\n######### Initializing from USB INI file %s ###########\n", usb_ini_file);
+                g_parser->init(usb_ini_file);
+            }
+            INFO("\n#########    Building flash sections    ###########\n");
+
+            if (!erase) {
+                new_flash_image->init_pointer_section(g_flash);
+            }
+
+            new_flash_image->init(g_parser, burn_full_image, reducedSip);
+            INFO("\n#########    Flash sections are ready   ###########\n");
+        }
+    }
+
+    if( query ) {
+        old_flash_image = new flash_image<PRODUCT>;
+        old_flash_image->init_pointer_section( g_flash );
+        old_flash_image->init_image_info_section( g_flash );
+        old_flash_image->init_ids_section( g_flash, reducedSip );
+//        old_flash_image->init_usb_info_section( g_flash );
+        const image_info_section_t<PRODUCT> &info = old_flash_image->get_image_info_section();
+        info.disp();
+        const ids_section_t<PRODUCT> &ids = old_flash_image->get_ids_section();
+        ids.disp();
+        const usb_info_section_t<PRODUCT> &usb_info = old_flash_image->get_usb_info_section();
+        usb_info.disp();
+    }
+
+    if( erase ) {
+        compatibility_check();
+        INFO("Erasing flash ...");
+        g_flash->erase();
+        INFO("done\n");
+    }
+
+    if( burn ) {
+        compatibility_check();
+        if (erase) {// Full image burn
+            INFO("Burning image...\n");
+            int res = g_flash->program(4, new_flash_image->get_image_size() - 4, new_flash_image->get_image() + 4, verify);
+
+            if (res != 0)  {
+                ERR("\nBurning failed !\n\n");
+                EXIT (-1);
+            }
+
+            INFO("Burning signature...\n");
+            g_flash->program(0, 4, new_flash_image->get_image(), verify);
+            INFO("Burning done\n");
+
+        } else {
+            flash_image<PRODUCT> *old_flash_image = new flash_image<PRODUCT>;
+            old_flash_image->init_pointer_section( g_flash );
+            const pointer_section_t<PRODUCT> &new_pointer_section = new_flash_image->get_pointer_section();
+            if( !(old_flash_image->get_pointer_section() == new_pointer_section )) {
+                ERR("Current INI file will cause changes in the pointer section."
+                    " Changes in pointer section are not supported\n");
+                //EXIT (-1);
+            }
+
+            ini_file_t::iterator dummy1;
+            ini_file_t::const_iterator dummy2;
+
+            const hw_section_t<PRODUCT> &new_hw_conf_section = new_flash_image->get_hw_conf_section();
+            const hw_section_t<PRODUCT> &old_hw_conf_section = old_flash_image->get_hw_conf_section();
+            if (!force ) {
+                string section_name = "hw_config";
+                if (g_parser->get_section(section_name, TRANSLATION_MAP_REGTREE, &dummy1, false, false)) {
+                    //if (g_parser->get_section(section_name, &dummy1, &dummy2, false)) {
+                    old_flash_image->init_hw_conf_section( g_flash );
+                    if( !(old_hw_conf_section == new_hw_conf_section ) ) {
+                        ERR("Current INI file will cause changes in the hw_configuration "
+                            "section. These changes may leave the device in an unstable state."
+                            " Use -force option to force the operation.\n");
+                        EXIT(-1);
+                    }
+                }
+            }
+
+            INFO("Burning image...\n");
+            // write all sections following the pointer_section.
+            // Only modified sections will be written.
+            // Unmodified sections will be skipped
+            u_int32_t start_offset = new_pointer_section.size() + sizeof(u_int32_t); //For CRC
+            g_flash->program(start_offset,
+                             new_flash_image->get_image_size() - start_offset,
+                             new_flash_image->get_image() + start_offset,
+                             verify);
+
+            INFO("Burning done\n");
+        }
+    }
+
+    if(read | read_formatted) {
+        char *end_ptr;
+        int int_offset = strtoul(offset, &end_ptr, 0);
+        if (*end_ptr != 0 ) {
+            ERR("Expected offset and got %s\n", offset);
+            EXIT(-1);
+        }
+        int int_length = strtoul(length, &end_ptr, 0);
+        if (*end_ptr != 0 ) {
+            ERR("Expected length and got %s\n", length);
+            EXIT(-1);
+        }
+
+        BYTE *tmp_buffer = new BYTE [int_length];
+        g_flash->read(int_offset, int_length, tmp_buffer);
+
+        if (read_formatted) {
+            int step = 16;
+            for(int i = 0; i < int_length; i += step) {
+                printf("0x%05x:", int_offset+i);
+                for( int j = 0; j < min(step, int_length - i); j += 2 ) {
+                    printf(" 0x%04x", *(u_int16_t*)(tmp_buffer+i+j));
+                }
+                printf("\n");
+            }
+        } else {
+            for(int i = 0; i < int_length; i += 2) {
+                printf("0x%04x ", *(u_int16_t*)(tmp_buffer+i));
+            }
+            printf("\n");
+        }
+        delete[] tmp_buffer;
+
+    }
+
+    delete old_flash_image;
+    delete new_flash_image;
+
+    EXIT(0);
+}
+
+bool IsReduced()
+{
+    u_int32_t verifyAddress = 256 * 1024;
+
+    BYTE testSequence[8] = {0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x64, 0x21}; // ASCII for "Reduced!"
+    BYTE verifySequence[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    BYTE originalData[4096] = {1};
+    BYTE manipulatedData[4096] = {2};
+
+    // Save the original data to be restored later
+    g_flash->read(verifyAddress, sizeof(originalData), originalData);
+    //INFO("1. %d %d %d\n", verifyAddress, sizeof(originalData), originalData);
+
+    memcpy(manipulatedData, originalData, sizeof(originalData));
+    memcpy(manipulatedData, testSequence, sizeof(testSequence));
+    //INFO("%s\n",manipulatedData);
+
+    // We are writing the testSequence to an address which will not exist in reduced SIP (which is 64K) with verify set to true
+    g_flash->program(verifyAddress /*This address will not exist in reduced SIP*/, sizeof(manipulatedData), manipulatedData, true);
+
+    //INFO("2. %d %d %d\n", verifyAddress, sizeof(manipulatedData), manipulatedData);
+    g_flash->read(verifyAddress & ((64 * 1024) - 1), sizeof(verifySequence), verifySequence);
+
+    // Restore the original data
+    g_flash->clear_erased(verifyAddress);
+    g_flash->program(verifyAddress, sizeof(originalData), originalData, true);
+    //INFO("3. %d %d %d\n", verifyAddress, sizeof(originalData), originalData);
+
+    if (0 == memcmp(testSequence, verifySequence, sizeof(testSequence)))
+    {
+        return true;
+    }
+    //else
+    {
+        return false;
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    const char *fw_ini_file;
+    const char *bin_file;
+    const char *board_ini_file;
+    const char *board_ini_file2;
+    const char *board_ini_file3;
+    const char *setup_ini_file;
+    const char *ids_ini_file;
+    const char *production_ini_file;
+    const char *usb_ini_file;
+    const char *flash_image_file;
+    const char *interface_name;
+    const char *device_type_string;
+    DType device_type = MST_NONE;
+    string str_interface_name;
+    const char *offset;
+    const char *length;
+    bool erase, verify, save, burn, read, read_formatted, query, force, read_ids_to_file;
+    bool ignore_lock, burn_full_image;
+
+//    printf("Press enter to debug ErezK..");
+//    getchar();
+
+    //
+    // Map termination signal handlers
+    //
+    //int i;
+//     for (i = 0 ; i < (int)(sizeof(g_signals_for_termination)/sizeof(g_signals_for_termination[0])) ; i++ ) {
+//         signal (g_signals_for_termination[i], TerminationHandler);
+//     }
+
+    //
+    // command line parsing
+    //
+    ParameterParser *opt = new ParameterParser();
+    param_parsing(opt);
+    if (opt->processCommandArgs( argc, argv ) != 0) {
+        EXIT (-1);
+    }
+
+    if( opt->getFlag( "-help" ) ) {
+        opt->printUsage();
+        EXIT(0);
+    }
+
+    flash_image_file = opt->getValue( "-bin" );
+    fw_ini_file = opt->getValue( "-fw" );
+    bin_file = opt->getValue( "-bin" );
+    ids_ini_file = opt->getValue( "-ids" );
+    production_ini_file = opt->getValue( "-production" );
+    board_ini_file = opt->getValue( "-board" );
+    board_ini_file2 = opt->getValue( "-board2" );
+    board_ini_file3 = opt->getValue( "-board3" );
+    setup_ini_file = opt->getValue( "-setup_ini" );
+    usb_ini_file = opt->getValue( "-usb" );
+    interface_name = opt->getValue( "-interface" );
+    device_type_string = opt->getValue( "-device" );
+    offset = opt->getValue( "-offset" );
+    length = opt->getValue( "-length" );
+    g_debug = opt->getFlag( "-debug" );
+    erase = opt->getFlag( "-erase" );
+    verify = opt->getFlag( "-verify" );// | opt->getFlag( 'v' );
+    save = opt->getFlag( "-save" );
+    burn = opt->getFlag( "-burn" );// | opt->getFlag( 'b' );
+    read = opt->getFlag( "-read" ); //| opt->getFlag( 'r' );
+    read_formatted = opt->getFlag( "-read_formatted" ); //| opt->getFlag( 'r' );
+    query = opt->getFlag( "-query" );
+    force = opt->getFlag( "-force" );
+    ignore_lock = opt->getFlag ("-ignore_lock" );
+    read_ids_to_file = opt->getFlag ("-read_ids_to_file" );
+
+    WLCT_UNREFERENCED_PARAM(flash_image_file);
+    WLCT_UNREFERENCED_PARAM(save);
+
+    //
+    // check missing/extra params
+    //
+    bool has_ini_file = fw_ini_file != 0 || ids_ini_file != 0 || usb_ini_file != 0 || board_ini_file != 0 || board_ini_file2 != 0 || board_ini_file3 != 0 || production_ini_file != 0;
+    bool has_bin_file = bin_file != 0;
+    bool missing_ini_file = board_ini_file == 0 && board_ini_file2 != 0 && board_ini_file3 != 0;
+
+    if ( burn ) {
+        if ( !(has_ini_file | has_bin_file)) {
+            ERR("option -burn require INI or BIN file name\nUse wiburn -h for usage info\n");
+            EXIT(-1);
+        }
+        if ( has_ini_file && has_bin_file) {
+            ERR("option -burn require INI or BIN file name. Not both\nUse wiburn -h for usage info\n");
+            EXIT(-1);
+        }
+        if ( missing_ini_file ) {
+            ERR("option -board2/-board3 require -board.\nUse wiburn -h for usage info\n");
+            EXIT(-1);
+        }
+    }
+
+    if (read_ids_to_file) {
+        if (ids_ini_file == 0) {
+            ERR("option -read_ids_to_file require IDS file name.\nUse wiburn -h for usage info\n");
+            EXIT(-1);
+        }
+        if(burn){
+            INFO("\nCurrent IDS section will not be changed !\n\n");
+        }
+    }
+
+    if ( burn | erase | read | read_formatted | query | read_ids_to_file) {
+        if (interface_name == 0) {
+            if( get_interface(&str_interface_name) == false ) {
+                ERR("Missing interface name\nUse wiburn -h for usage info\n");
+                EXIT(-1);
+            } else {
+                interface_name = str_interface_name.c_str();
+            }
+        }
+    }
+
+    if (read | read_formatted) {
+        if( length == 0 || offset == 0 ) {
+            ERR("Missing length or offset\nUse wiburn -h for usage info\n");
+            EXIT(-1);
+        }
+    }
+
+
+
+    burn_full_image = burn && erase;
+
+    //
+    // DLL info
+    //
+    WLCT_DLL_VERSION dll_ver;
+    GetMyVersion(&dll_ver);
+    INFO("Using DLL version %d.%d.%d.%d\n",
+         dll_ver.major,
+         dll_ver.minor,
+         dll_ver.maintenance,
+         dll_ver.build );
+
+    if (device_type_string == 0) {
+        ERR("Missing device type\nUse wiburn -h for usage info\n");
+        EXIT(-1);
+    }
+    else
+    {
+        if( strcmp("MARLON", device_type_string) == 0 )
+        {
+            device_type = MST_MARLON;
+        }
+        else if( strcmp("SPARROW", device_type_string) == 0 )
+        {
+            device_type = MST_SPARROW;
+        }
+        else if( strcmp("TALYN", device_type_string) == 0 )
+        {
+            device_type = MST_TALYN;
+        }
+        else
+        {
+            ERR("Unknown device type %s. Supported device types are SPARROW and MARLON\n", device_type_string);
+            EXIT(-1);
+        }
+    }
+
+    //
+    // Start executing
+    //
+    if ( burn | erase | query)
+    {
+        if( device_type == MST_MARLON )
+        {
+            g_parser = new ini_parser<marlon>;
+        }
+        else if( device_type == MST_SPARROW )
+        {
+            g_parser = new ini_parser<sparrow>;
+        }
+        else if( device_type == MST_TALYN )
+        {
+            g_parser = new ini_parser<talyn>;
+        }
+        else {
+            ERR("Unknown device type %s. Supported device types are SPARROW and MARLON\n", device_type_string);
+            EXIT(-1);
+        }
+    }
+
+    if (burn | erase | read | read_formatted | query | read_ids_to_file) {
+        if (strchr(interface_name, '.') != NULL) {
+            g_flash = new flash_file(device_type);
+        } else {
+            g_flash = new flash(device_type);
+        }
+        if (g_flash->open(interface_name, device_type, ignore_lock) != 0)
+        {
+            ERR("Can't open device %s with specified type %s.\n", interface_name, device_type_string);
+            EXIT(-1);
+        }
+    }
+
+    if (device_type == MST_TALYN) {
+        sub_main<talyn> (burn,
+                         erase,
+                         burn_full_image,
+                         query,
+                         verify,
+                         read,
+                         read_formatted,
+                         read_ids_to_file,
+                         force,
+                         offset,
+                         length,
+                         bin_file,
+                         fw_ini_file,
+                         ids_ini_file,
+                         production_ini_file,
+                         board_ini_file,
+                         board_ini_file2,
+                         board_ini_file3,
+                         setup_ini_file,
+                         usb_ini_file);
+    }
+    if (device_type == MST_SPARROW) {
+        sub_main<sparrow> (burn,
+                           erase,
+                           burn_full_image,
+                           query,
+                           verify,
+                           read,
+                           read_formatted,
+                           read_ids_to_file,
+                           force,
+                           offset,
+                           length,
+                           bin_file,
+                           fw_ini_file,
+                           ids_ini_file,
+                           production_ini_file,
+                           board_ini_file,
+                           board_ini_file2,
+                           board_ini_file3,
+                           setup_ini_file,
+                           usb_ini_file);
+    } else {
+        sub_main<marlon> (burn,
+                          erase,
+                          burn_full_image,
+                          query,
+                          verify,
+                          read,
+                          read_formatted,
+                          read_ids_to_file,
+                          force,
+                          offset,
+                          length,
+                          bin_file,
+                          fw_ini_file,
+                          ids_ini_file,
+                          production_ini_file,
+                          board_ini_file,
+                          board_ini_file2,
+                          board_ini_file3,
+                          setup_ini_file,
+                          usb_ini_file);
+    }
+
+}
+
diff --git a/debug-tools/wiburn/wiburn.h b/debug-tools/wiburn/wiburn.h
new file mode 100644
index 0000000..bd195f6
--- /dev/null
+++ b/debug-tools/wiburn/wiburn.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+#ifndef _WIBURN_H_
+#define _WIBURN_H_
+
+extern bool g_debug;
+extern volatile bool g_exit;
+
+#ifdef _WINDOWS
+#include <windows.h>
+
+#define STRTOULL _strtoui64
+
+typedef unsigned __int8 u_int8_t;
+typedef unsigned __int16 u_int16_t;
+typedef unsigned __int32 u_int32_t;
+typedef unsigned __int64 u_int64_t;
+#if (defined(_MSC_VER) && (_MSC_VER < 1900))
+typedef __int8 int8_t;
+#endif
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+
+#else //#ifdef _WINDOWS
+
+#define STRTOULL strtoull
+
+#include <sys/types.h>
+typedef u_int8_t u_int8_t;
+typedef u_int16_t u_int16_t;
+typedef u_int32_t u_int32_t;
+typedef u_int64_t u_int64_t;
+typedef int8_t int8_t;
+typedef int16_t int16_t;
+typedef int32_t int32_t;
+typedef int64_t int64_t;
+#endif  //#ifdef _WINDOWS
+
+typedef u_int32_t ADDRESS32;
+
+typedef u_int8_t BYTE;
+typedef u_int32_t IMAGE;
+
+
+#define PAGE 256
+#define FLASH_PAGE_MASK 0xffffff00
+#define SUB_SECTOR (16*PAGE) // 4KB
+#define SUB_SECTOR_MASK 0xfffff000
+#define SECTOR (16*SUB_SECTOR) // 64KB
+
+#define ERR printf
+#define DBG printf
+#define INFO printf
+
+void EXIT( int val );
+
+void print_buffer(const void *buffer, int length);
+#endif //#ifndef _WIBURN_H_