Upgrade  to v1.3.12 am: 32dc029601

Original change: https://android-review.googlesource.com/c/platform/external/rmi4utils/+/2351022

Change-Id: I0b91035f2c8600659808517c628d3978473fd624
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/METADATA b/METADATA
index 6cd8a37..04756bb 100644
--- a/METADATA
+++ b/METADATA
@@ -1,8 +1,17 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rmi4utils
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 third_party {
-  license_type: NOTICE
   url {
     type: GIT
     value: "https://github.com/aduggan/rmi4utils.git"
   }
-  version: "v1.3.5"
+  version: "v1.3.12"
+  license_type: NOTICE
+  last_upgrade_date {
+    year: 2022
+    month: 12
+    day: 13
+  }
 }
diff --git a/f54test/Makefile b/f54test/Makefile
index e0f1b64..272646c 100644
--- a/f54test/Makefile
+++ b/f54test/Makefile
@@ -1,5 +1,6 @@
 CXX ?= g++
 CPPFLAGS += -I../include -I./include -I../rmidevice
+CPPFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
 CXXFLAGS += -Wall
 LDFLAGS += -L.
 LIBS =  -lrmidevice -lrt
diff --git a/f54test/f54test.cpp b/f54test/f54test.cpp
index 4b4f6b1..c6b351e 100644
--- a/f54test/f54test.cpp
+++ b/f54test/f54test.cpp
@@ -695,7 +695,7 @@
 				sizeof(m_f54Query_61.data));
 		if (retval < 0)
 			return retval;
-			offset += 1;
+		offset += 1;
 	}
 
 	/* query 62 63 */
diff --git a/rmi4update/Android.bp b/rmi4update/Android.bp
index e3ba434..72a4437 100644
--- a/rmi4update/Android.bp
+++ b/rmi4update/Android.bp
@@ -20,6 +20,7 @@
         "-Werror",
         "-Wno-unused-parameter",
         "-Wno-unused-private-field",
+        "-Wno-unused-variable",
     ],
     static_libs: ["rmidevice"],
 }
diff --git a/rmi4update/Makefile b/rmi4update/Makefile
index b8ce096..c8fe3cc 100644
--- a/rmi4update/Makefile
+++ b/rmi4update/Makefile
@@ -1,5 +1,6 @@
 CXX ?= g++
 CPPFLAGS += -I../include -I./include -I../rmidevice
+CPPFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
 CXXFLAGS += -Wall
 LDFLAGS += -L.
 LIBS =  -lrmidevice -lrt
diff --git a/rmi4update/firmware_image.cpp b/rmi4update/firmware_image.cpp
index 6cc18c0..dbc4822 100755
--- a/rmi4update/firmware_image.cpp
+++ b/rmi4update/firmware_image.cpp
@@ -54,6 +54,16 @@
 	unsigned int length;
 	unsigned char *content;
 	unsigned short container_id;
+	unsigned int sigature_size;
+	
+	for (ii = 0; ii < BLv7_MAX; ii++) {
+		m_signatureInfo[ii].bExisted = false;
+		m_signatureInfo[ii].size = 0;
+	}
+
+	if (m_bootloaderVersion == RMI_IMG_V10_SIGNATURE_VERSION_NUMBER) {
+		fprintf (stdout, "has signature\n");	
+	}
 
 	m_cntrAddr = extract_long(&m_memBlock[RMI_IMG_V10_CNTR_ADDR_OFFSET]);
 	descriptor = (struct container_descriptor *)(m_memBlock + m_cntrAddr);
@@ -68,21 +78,37 @@
 				descriptor->container_id[1] << 8;
 		content = m_memBlock + extract_long(descriptor->content_address);
 		length = extract_long(descriptor->content_length);
+		sigature_size = extract_long(descriptor->signature_size);
 		switch (container_id) {
 		case BL_CONTAINER:
 			m_bootloaderVersion = *content;
 			break;
 		case UI_CONTAINER:
 		case CORE_CODE_CONTAINER:
+			if (sigature_size != 0) {
+				fprintf(stdout, "CORE CODE signature size : 0x%x\n", sigature_size);
+				m_signatureInfo[BLv7_CORE_CODE].bExisted = true;
+				m_signatureInfo[BLv7_CORE_CODE].size = sigature_size;
+			}
 			m_firmwareData = content;
 			m_firmwareSize = length;
 			break;
 		case FLASH_CONFIG_CONTAINER:
+			if (sigature_size != 0) {
+				fprintf(stdout, "FLASH CONFIG signature size : 0x%x\n", sigature_size);
+				m_signatureInfo[BLv7_FLASH_CONFIG].bExisted = true;
+				m_signatureInfo[BLv7_FLASH_CONFIG].size = sigature_size;
+			}
 			m_flashConfigData = content;
 			m_flashConfigSize = length;
 			break;
 		case UI_CONFIG_CONTAINER:
 		case CORE_CONFIG_CONTAINER:
+			if (sigature_size != 0) {
+				fprintf(stdout, "CORE CONFIG signature size : 0x%x\n", sigature_size);
+				m_signatureInfo[BLv7_CORE_CONFIG].bExisted = true;
+				m_signatureInfo[BLv7_CORE_CONFIG].size = sigature_size;
+			}
 			m_configData = content;
 			m_configSize = length;
 			break;
@@ -97,6 +123,26 @@
 			m_firmwareBuildID = extract_long(content + 4);
 			memcpy(m_productID, (content + 0x18), RMI_PRODUCT_ID_LENGTH);
 			m_productID[RMI_PRODUCT_ID_LENGTH] = 0;
+			if ((descriptor->major_version == 0) && 
+				(descriptor->minor_version > 0)) {
+				m_hasFirmwareVersion = true;
+				fprintf(stdout, "General Information version : %d.%d\n", descriptor->major_version, descriptor->minor_version);
+				m_firmwareVersion = *(content + 0x26) << 8 | *(content + 0x27);
+				fprintf(stdout, "Firmware version : 0x%x\n", m_firmwareVersion);
+			}
+			break;
+		case FIXED_LOCATION_DATA_CONTAINER:
+			if (sigature_size != 0) {
+				fprintf(stdout, "FLD signature size : 0x%x\n", sigature_size);
+				m_signatureInfo[BLv7_FLD].bExisted = true;
+				m_signatureInfo[BLv7_FLD].size = sigature_size;
+			}
+			m_fldData = content;
+			m_fldSize = length;
+			break;
+		case GLOBAL_PARAMETERS_CONTAINER:
+			m_globalparaData = content;
+			m_globalparaSize = length;
 			break;
 		default:
 			break;
@@ -182,6 +228,7 @@
 			m_lockdownData = &m_memBlock[RMI_IMG_LOCKDOWN_V5_OFFSET];
 			break;
 		case 16:
+		case RMI_IMG_V10_SIGNATURE_VERSION_NUMBER:
 			ParseHierarchicalImg();
 			break;
 		default:
@@ -226,6 +273,17 @@
 	return UPDATE_SUCCESS;
 }
 
+int FirmwareImage::VerifyImageProductID(char* deviceProductID)
+{
+	if (strcmp(m_productID, deviceProductID) == 0) {
+		fprintf(stdout, "image matched\n");
+		return UPDATE_SUCCESS;
+	} else {
+		fprintf (stdout, "image not match, terminated\n");
+		return UPDATE_FAIL_VERIFY_IMAGE_PRODUCTID_NOT_MATCH;
+	}
+}
+
 FirmwareImage::~FirmwareImage()
 {
 	delete [] m_memBlock;
diff --git a/rmi4update/firmware_image.h b/rmi4update/firmware_image.h
index 3ce1c59..3558b07 100755
--- a/rmi4update/firmware_image.h
+++ b/rmi4update/firmware_image.h
@@ -45,16 +45,16 @@
 
 // Leon add for BL_V7
 #define RMI_IMG_V10_CNTR_ADDR_OFFSET		0x0C
+#define RMI_IMG_V10_SIGNATURE_VERSION_NUMBER 0x11
+#define RMI_IMG_V10_SIGNATURE_LENGTH_OFFSET 0x8
+#define RMI_IMG_V10_SIGNATURE_LENGTH_SIZE 4
 
 struct container_descriptor {
 	unsigned char content_checksum[4];
 	unsigned char container_id[2];
 	unsigned char minor_version;
 	unsigned char major_version;
-	unsigned char reserved_08;
-	unsigned char reserved_09;
-	unsigned char reserved_0a;
-	unsigned char reserved_0b;
+	unsigned char signature_size[4];
 	unsigned char container_option_flags[4];
 	unsigned char content_options_length[4];
 	unsigned char content_options_address[4];
@@ -87,6 +87,22 @@
 	EXTERNAL_TOUCH_AFE_CONFIG_CONTAINER,
 	UTILITY_CONTAINER,
 	UTILITY_PARAMETER_CONTAINER,
+	// Reserved : 24 ~ 26
+	// V10 above
+	FIXED_LOCATION_DATA_CONTAINER = 27,
+};
+
+enum signature_BLv7 {
+	BLv7_CORE_CODE = 0,
+	BLv7_CORE_CONFIG,
+	BLv7_FLASH_CONFIG,
+	BLv7_FLD,
+	BLv7_MAX
+};
+
+struct signature_info {
+	bool bExisted;
+	unsigned short size;
 };
 // BL_V7 end
 
@@ -94,7 +110,8 @@
 {
 public:
 	FirmwareImage() : m_firmwareBuildID(0), m_packageID(0), m_firmwareData(NULL), m_configData(NULL), m_lockdownData(NULL),
-				m_memBlock(NULL)
+				m_memBlock(NULL), m_hasSignature(false), m_fldData(NULL), m_fldSize(0), m_globalparaData(NULL), m_globalparaSize(0),
+				m_firmwareVersion(0), m_hasFirmwareVersion(false)
 	{}
 	int Initialize(const char * filename);
 	int VerifyImageMatchesDevice(unsigned long deviceFirmwareSize,
@@ -103,11 +120,20 @@
 	unsigned char * GetConfigData() { return m_configData; }
 	unsigned char * GetFlashConfigData() { return m_flashConfigData; }
 	unsigned char * GetLockdownData() { return m_lockdownData; }
+	unsigned char * GetFLDData() { return m_fldData; }
+	unsigned char * GetGlobalParametersData() { return m_globalparaData; }
 	unsigned long GetFirmwareSize() { return m_firmwareSize; }
 	unsigned long GetConfigSize() { return m_configSize; }
 	unsigned long GetFlashConfigSize() { return m_flashConfigSize; }
 	unsigned long GetLockdownSize() { return m_lockdownSize; }
 	unsigned long GetFirmwareID() { return m_firmwareBuildID; }
+	unsigned long GetFLDSize() { return m_fldSize; }
+	unsigned long GetGlobalParametersSize() { return m_globalparaSize; }
+	unsigned short GetFirmwareVersion() { return m_firmwareVersion; }
+	signature_info *GetSignatureInfo() { return m_signatureInfo; }
+	int VerifyImageProductID(char* deviceProductID);
+	bool IsImageHasFirmwareVersion() { return m_hasFirmwareVersion; }
+
 	bool HasIO() { return m_io; }
 	~FirmwareImage();
 
@@ -136,6 +162,15 @@
 	unsigned char * m_lockdownData;
 	unsigned char * m_memBlock;
 	unsigned long m_cntrAddr;	// BL_V7
+	bool m_hasSignature;
+	unsigned char * m_fldData;
+	unsigned long m_fldSize;
+	unsigned char * m_globalparaData;
+	unsigned long m_globalparaSize;
+	unsigned short m_firmwareVersion;
+	bool m_hasFirmwareVersion;
+
+	signature_info m_signatureInfo[BLv7_MAX];
 };
 
 #endif // _FIRMWAREIMAGE_H_
diff --git a/rmi4update/main.cpp b/rmi4update/main.cpp
index a710764..56871ed 100755
--- a/rmi4update/main.cpp
+++ b/rmi4update/main.cpp
@@ -27,15 +27,18 @@
 #include <time.h>
 #include <string>
 #include <sstream>
+#include <time.h>
 
 #include "hiddevice.h"
 #include "rmi4update.h"
 
 #define VERSION_MAJOR		1
 #define VERSION_MINOR		3
-#define VERSION_SUBMINOR	5
+#define VERSION_SUBMINOR	12
 
-#define RMI4UPDATE_GETOPTS	"hfd:t:pclv"
+#define RMI4UPDATE_GETOPTS	"hfd:t:pclvm"
+
+bool needDebugMessage; 
 
 void printHelp(const char *prog_name)
 {
@@ -65,10 +68,19 @@
 	rc = rmidevice.Open(deviceFile);
 	if (rc)
 		return rc;
+	
+	if (needDebugMessage)
+		rmidevice.m_hasDebug = true;
+
+	// Clear all interrupts before parsing to avoid unexpected interrupts.
+	rmidevice.ToggleInterruptMask(false);
 
 	rmidevice.ScanPDT(0x1);
 	rmidevice.QueryBasicProperties();
 
+	// Restore the interrupts
+	rmidevice.ToggleInterruptMask(true);
+
 	if (configid) {
 		ss << std::hex << rmidevice.GetConfigID();
 	} else {
@@ -108,6 +120,7 @@
 	bool printFirmwareProps = false;
 	bool printConfigid = false;
 	bool performLockdown = false;
+	needDebugMessage = false;
 	HIDDevice device;
 	enum RMIDeviceType deviceType = RMI_DEVICE_TYPE_ANY;
 
@@ -141,6 +154,9 @@
 			case 'v':
 				printVersion();
 				return 0;
+			case 'm':
+				needDebugMessage = true;
+				break;
 			default:
 				break;
 
@@ -149,7 +165,7 @@
 
 	if (printFirmwareProps) {
 		std::string props;
-
+		
 		if (!deviceName) {
 			fprintf(stderr, "Specifiy which device to query\n");
 			return 1;
@@ -188,6 +204,9 @@
 			return 1;
 	}
 
+	if (needDebugMessage) {
+		device.m_hasDebug = true;
+	}
 
 	RMI4Update update(device, image);
 	rc = update.UpdateFirmware(force, performLockdown);
diff --git a/rmi4update/rmi4update.cpp b/rmi4update/rmi4update.cpp
index 19eadb5..cec3a84 100755
--- a/rmi4update/rmi4update.cpp
+++ b/rmi4update/rmi4update.cpp
@@ -61,6 +61,7 @@
 #define RMI_F34_ERASE_WAIT_MS (5 * 1000)
 #define RMI_F34_ERASE_V8_WAIT_MS (10000)
 #define RMI_F34_IDLE_WAIT_MS 500
+#define RMI_F34_PARTITION_READ_WAIT_MS 20
 
 /* Most recent device status event */
 #define RMI_F01_STATUS_CODE(status)		((status) & 0x0f)
@@ -96,13 +97,22 @@
 	long long int duration_us = 0;
 	int rc;
 	const unsigned char eraseAll = RMI_F34_ERASE_ALL;
+
+	// Clear all interrupts before parsing to avoid unexpected interrupts.
+	m_device.ToggleInterruptMask(false);
 	rc = FindUpdateFunctions();
-	if (rc != UPDATE_SUCCESS)
+	if (rc != UPDATE_SUCCESS) {
+		m_device.ToggleInterruptMask(true);
 		return rc;
+	}
 
 	rc = m_device.QueryBasicProperties();
-	if (rc < 0)
-		return UPDATE_FAIL_QUERY_BASIC_PROPERTIES;
+	if (rc < 0) {
+		m_device.ToggleInterruptMask(true);
+		return UPDATE_FAIL_QUERY_BASIC_PROPERTIES; 
+	}
+	// Restore the interrupts
+	m_device.ToggleInterruptMask(true);
 
 	if (!force && m_firmwareImage.HasIO()) {
 		if (m_firmwareImage.GetFirmwareID() <= m_device.GetFirmwareID()) {
@@ -115,6 +125,14 @@
 
 	fprintf(stdout, "Device Properties:\n");
 	m_device.PrintProperties();
+	if (m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) {
+		rc = m_firmwareImage.VerifyImageProductID(m_device.GetProductID());
+		if (rc != UPDATE_SUCCESS)
+			return rc;
+	} else {
+		fprintf(stdout, "not touchpad, skip checking product ID\n");
+	}
+	
 
 	rc = DisableNonessentialInterupts();
 	if (rc != UPDATE_SUCCESS)
@@ -123,9 +141,13 @@
 	rc = ReadF34Queries();
 	if (rc != UPDATE_SUCCESS)
 		return rc;
-	rc = m_firmwareImage.VerifyImageMatchesDevice(GetFirmwareSize(), GetConfigSize());
-	if (rc != UPDATE_SUCCESS)
-		return rc;
+
+	if (m_bootloaderID[1] < 10) {
+		// Checking size alignment for the device prior to BL v10.
+		rc = m_firmwareImage.VerifyImageMatchesDevice(GetFirmwareSize(), GetConfigSize());
+		if (rc != UPDATE_SUCCESS)
+			return rc;
+	} 
 
 	if (m_f34.GetFunctionVersion() == 0x02) {
 		fprintf(stdout, "Enable Flash V7+...\n");
@@ -136,46 +158,136 @@
 		}
 		fprintf(stdout, "Enable Flash done V7+...\n");
 
-		if (!m_IsErased){
-			fprintf(stdout, "Erasing FW V7+...\n");
-			rc = EraseFirmwareV7();
+		if (IsBLv87()) {
+			if (m_firmwareImage.IsImageHasFirmwareVersion()) {
+				rc = ReadMSL();
+				if (rc != UPDATE_SUCCESS) {
+					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+					goto reset;
+				}
+				fprintf(stdout, "MSL : 0x%x\n", m_MSL);
+				if (m_MSL > m_firmwareImage.GetFirmwareVersion()) {
+					fprintf(stdout, "MSL checking failed. device(0x%x) > image(0x%x)\n", 
+						m_MSL, m_firmwareImage.GetFirmwareVersion());
+					rc = UPDATE_FAIL_MSL_CHECKING;
+					goto reset;
+				} else {
+					fprintf(stdout, "Passing MSL checking\n");
+				}
+			}
+		}
+
+		if (m_bootloaderID[1] >= 10) {
+			fprintf(stdout, "Writing FLD V10...\n");
+			rc = WriteFLDV7();
 			if (rc != UPDATE_SUCCESS) {
 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
 				goto reset;
 			}
-			fprintf(stdout, "Erasing FW done V7+...\n");
-		}
-		if(m_bootloaderID[1] == 8){
+			fprintf(stdout, "Writing FLD done V10...\n");
+
+			fprintf(stdout, "Erasing Flash Config V10...\n");
+			rc = EraseFlashConfigV10();
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				goto reset;
+			}
+			fprintf(stdout, "Erasing Flash Config done V10...\n");
+
 			if (m_firmwareImage.GetFlashConfigData()) {
-				fprintf(stdout, "Writing flash configuration V8...\n");
+				fprintf(stdout, "Writing flash configuration V10...\n");
 				rc = WriteFlashConfigV7();
 				if (rc != UPDATE_SUCCESS) {
 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
 					goto reset;
 				}
-				fprintf(stdout, "Writing flash config done V8...\n");
+				fprintf(stdout, "Writing flash config done V10...\n");
 			}
-		}
-		if (m_firmwareImage.GetFirmwareData()) {
-			fprintf(stdout, "Writing firmware V7+...\n");
-			rc = WriteFirmwareV7();
+
+			fprintf(stdout, "Erasing Core Code V10...\n");
+			rc = EraseCoreCodeV10();
 			if (rc != UPDATE_SUCCESS) {
 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
 				goto reset;
 			}
-			fprintf(stdout, "Writing firmware done V7+...\n");
-		}
-		if (m_firmwareImage.GetConfigData()) {
-			fprintf(stdout, "Writing core configuration V7+...\n");
-			rc = WriteCoreConfigV7();
-			if (rc != UPDATE_SUCCESS) {
-				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+			fprintf(stdout, "Erasing Core Code done V10...\n");
+
+			if (m_firmwareImage.GetFirmwareData()) {
+				fprintf(stdout, "Writing Core Code V10...\n");
+				rc = WriteFirmwareV7();
+				if (rc != UPDATE_SUCCESS) {
+					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+					goto reset;
+				}
+				fprintf(stdout, "Writing Core Code done V10...\n");
+			}
+
+			if (m_firmwareImage.GetConfigData()) {
+				fprintf(stdout, "Writing Core Config V10...\n");
+				rc = WriteCoreConfigV7();
+				if (rc != UPDATE_SUCCESS) {
+					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+					goto reset;
+				}
+				fprintf(stdout, "Writing Core Config done V10...\n");
 				goto reset;
 			}
-			fprintf(stdout, "Writing core config done V7+...\n");
-			goto reset;
+			
+			if (m_firmwareImage.GetGlobalParametersSize() && m_hasGlobalParameters) {
+				fprintf(stdout, "Writing Global Parameters V10...\n");
+				rc = WriteGlobalParametersV7();
+				if (rc != UPDATE_SUCCESS) {
+					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+					goto reset;
+				}
+				fprintf(stdout, "Writing Global Parameters done V10...\n");
+				goto reset;	
+			}
+
+
+		} else {
+			if (!m_IsErased){
+				fprintf(stdout, "Erasing FW V7+...\n");
+				rc = EraseFirmwareV7();
+				if (rc != UPDATE_SUCCESS) {
+					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+					goto reset;
+				}
+				fprintf(stdout, "Erasing FW done V7+...\n");
+			}
+			if(m_bootloaderID[1] == 8){
+				if (m_firmwareImage.GetFlashConfigData()) {
+					fprintf(stdout, "Writing flash configuration V8...\n");
+					rc = WriteFlashConfigV7();
+					if (rc != UPDATE_SUCCESS) {
+						fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+						goto reset;
+					}
+					fprintf(stdout, "Writing flash config done V8...\n");
+				}
+			}
+			if (m_firmwareImage.GetFirmwareData()) {
+				fprintf(stdout, "Writing firmware V7+...\n");
+				rc = WriteFirmwareV7();
+				if (rc != UPDATE_SUCCESS) {
+					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+					goto reset;
+				}
+				fprintf(stdout, "Writing firmware done V7+...\n");
+			}
+			if (m_firmwareImage.GetConfigData()) {
+				fprintf(stdout, "Writing core configuration V7+...\n");
+				rc = WriteCoreConfigV7();
+				if (rc != UPDATE_SUCCESS) {
+					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+					goto reset;
+				}
+				fprintf(stdout, "Writing core config done V7+...\n");
+				goto reset;
+			}
 		}
 		
+		
 	} else {
 		rc = EnterFlashProgramming();
 		if (rc != UPDATE_SUCCESS) {
@@ -262,6 +374,9 @@
 reset:
 	m_device.Reset();
 rebind:
+	if (m_bootloaderID[1] >= 10) {
+		Sleep(5000);
+	}
 	m_device.RebindDriver();
 	if(!m_device.CheckABSEvent())
 	{
@@ -384,6 +499,17 @@
 		if (rc != sizeof(cmd_buf))
 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
 
+		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+			// Sleep 20 ms and wait for attention for touchpad only.
+			Sleep(20);
+			rc = WaitForIdle(RMI_F34_PARTITION_READ_WAIT_MS, false);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+			}
+			fprintf(stdout, "Got attention\n");
+		}
+
 		//Wait for completion
 		do {
 			Sleep(20);
@@ -495,6 +621,17 @@
 	idStr[1] = m_bootloaderID[1];
 	idStr[2] = 0;
 
+	m_hasCoreCode = query_1_7.has_core_code;
+	m_hasCoreConfig = query_1_7.has_core_config;
+	m_hasFlashConfig = query_1_7.has_flash_config;
+	m_hasFLD = query_1_7.has_fld;
+	m_hasGlobalParameters = query_1_7.has_global_parameters;
+
+	fprintf(stdout, "F34 has CoreCode: %d\n", m_hasCoreCode);
+	fprintf(stdout, "F34 has CoreConfig: %d\n", m_hasCoreConfig);
+	fprintf(stdout, "F34 has FlashConfig: %d\n", m_hasFlashConfig);
+	fprintf(stdout, "F34 has FLD: %d\n", m_hasFLD);
+
 	fprintf(stdout, "F34 bootloader id: %s (%#04x %#04x)\n", idStr, m_bootloaderID[0],
 		m_bootloaderID[1]);
 	fprintf(stdout, "F34 has config id: %d\n", m_hasConfigID);
@@ -504,7 +641,12 @@
 	fprintf(stdout, "F34 payload length:%d\n", m_payloadLength);
 	fprintf(stdout, "F34 build id:      %lu\n", m_buildID);
 
-	return ReadFlashConfig();
+	if ((m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) && (m_bootloaderID[1] == 10)) {
+		// FW size would be different from the one in image file in bootloader v10,
+		// we use size parsing in image file instead.
+		return UPDATE_SUCCESS;
+	} else 
+		return ReadFlashConfig();
 }
 
 int RMI4Update::ReadF34Queries()
@@ -653,10 +795,16 @@
 	unsigned short max_write_size;
 	unsigned short dataAddr = m_f34.GetDataBase();
 
+	if (m_bootloaderID[1] == 10) {
+		m_fwBlockCount = m_firmwareImage.GetFirmwareSize() / m_blockSize;
+	}
+
 	/* calculate the count */
 	partition_id = CORE_CODE_PARTITION;
+
 	remain_block = (m_fwBlockCount % m_payloadLength);
 	transaction_count = (m_fwBlockCount / m_payloadLength);
+	
 	if (remain_block > 0)
 		transaction_count++;
 
@@ -718,13 +866,16 @@
 			free(data_temp);
 		} while (left_bytes);
 
-		// Sleep 100 ms and wait for attention.
-		Sleep(100);
-		rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
-		if (rc != UPDATE_SUCCESS) {
-			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
-			return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+			// Sleep 100 ms and wait for attention for touchpad only.
+			Sleep(100);
+			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+			}
 		}
+		
 
 		//Wait for completion
 		do {
@@ -743,6 +894,18 @@
 		}
 
 	}
+
+	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+		if (m_firmwareImage.GetSignatureInfo()[BLv7_CORE_CODE].bExisted) {
+			// Write signature.
+			rc = WriteSignatureV7(BLv7_CORE_CODE, m_firmwareImage.GetFirmwareData(), offset);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return rc;	
+			}
+		}
+	}
+
 	return UPDATE_SUCCESS;
 }
 
@@ -763,11 +926,16 @@
 	int i;
 	int retry = 0;
 	unsigned char *data_temp;
+	if (m_bootloaderID[1] == 10) {
+		m_configBlockCount = m_firmwareImage.GetConfigSize() / m_blockSize;
+	}
 
 	/* calculate the count */
 	partition_id = CORE_CONFIG_PARTITION;
+	
 	remain_block = (m_configBlockCount % m_payloadLength);
 	transaction_count = (m_configBlockCount / m_payloadLength);
+
 	if (remain_block > 0)
 		transaction_count++;
 
@@ -829,11 +997,13 @@
 			free(data_temp);
 		} while (left_bytes);
 
-		// Wait for attention.
-		rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
-		if (rc != UPDATE_SUCCESS) {
-			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
-			return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+			// Wait for attention for touchpad only.
+			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+			}
 		}
 
 		//Wait for completion
@@ -852,6 +1022,18 @@
 		}
 
 	}
+
+	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+		if (m_firmwareImage.GetSignatureInfo()[BLv7_CORE_CONFIG].bExisted) {
+			// Write signature.
+			rc = WriteSignatureV7(BLv7_CORE_CONFIG, m_firmwareImage.GetConfigData(), offset);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return rc;	
+			}
+		}
+	}
+
 	return UPDATE_SUCCESS;
 }
 
@@ -943,17 +1125,23 @@
 			free(data_temp);
 		} while (left_bytes);
 
-		// Wair for attention.
-		rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
-		if (rc != UPDATE_SUCCESS) {
-			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
-			return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+			// Wair for attention for touchpad only.
+			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+			}
 		}
 
 		//Wait for completion
 		do {
 			Sleep(20);
 			rmi4update_poll();
+			if (IsBLv87()) {
+				if (m_flashStatus == WRITE_PROTECTION)
+					return UPDATE_FAIL_WRITE_PROTECTED;
+			}
 			if (m_flashStatus == SUCCESS){
 				break;
 			}
@@ -966,6 +1154,394 @@
 		}
 
 	}
+
+	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+		if (m_firmwareImage.GetSignatureInfo()[BLv7_FLASH_CONFIG].bExisted) {
+			// Write signature.
+			rc = WriteSignatureV7(BLv7_FLASH_CONFIG, m_firmwareImage.GetFlashConfigData(), offset);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return rc;	
+			}
+		}
+	}
+
+	return UPDATE_SUCCESS;
+}
+
+int RMI4Update::WriteFLDV7()
+{
+	int transaction_count, remain_block;
+	int transfer_leng = 0;
+	int offset = 0;
+	unsigned char trans_leng_buf[2];
+	unsigned char cmd_buf[1];
+	unsigned char off[2] = {0, 0};
+	unsigned char partition_id;
+	int i;
+	int retry = 0;
+	unsigned char *data_temp;
+	int rc;
+	unsigned short left_bytes;
+	unsigned short write_size;
+	unsigned short max_write_size;
+	unsigned short dataAddr = m_f34.GetDataBase();
+	unsigned short fldBlockCount = m_firmwareImage.GetFLDSize() / m_blockSize;
+
+	if (m_bootloaderID[1] < 10) {
+		// Not support writing FLD before bootloader v10
+		return UPDATE_SUCCESS;
+	}
+
+	/* calculate the count */
+	partition_id = FIXED_LOCATION_DATA_PARTITION;
+	
+	remain_block = (fldBlockCount % m_payloadLength);
+	transaction_count = (fldBlockCount / m_payloadLength);
+	
+	if (remain_block > 0)
+		transaction_count++;
+
+	/* set partition id for bootloader 7 */
+	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
+	if (rc != sizeof(partition_id))
+		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
+
+	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
+	if (rc != sizeof(off))
+		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
+
+	for (i = 0; i < transaction_count; i++)
+	{
+		if ((i == (transaction_count -1)) && (remain_block > 0))
+			transfer_leng = remain_block;
+		else
+			transfer_leng = m_payloadLength;
+
+		// Set Transfer Length
+		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
+		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
+
+		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
+		if (rc != sizeof(trans_leng_buf))
+			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
+
+		// Set Command to Write
+		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
+		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
+		if (rc != sizeof(cmd_buf))
+			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
+
+		max_write_size = 16;
+		if (max_write_size >= transfer_leng * m_blockSize)
+			max_write_size = transfer_leng * m_blockSize;
+		else if (max_write_size > m_blockSize)
+			max_write_size -= max_write_size % m_blockSize;
+		else
+			max_write_size = m_blockSize;
+
+		left_bytes = transfer_leng * m_blockSize;
+		do {
+			if (left_bytes / max_write_size)
+				write_size = max_write_size;
+			else
+				write_size = left_bytes;
+
+			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
+			memcpy(data_temp, m_firmwareImage.GetFLDData() + offset, sizeof(char) * write_size);
+			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
+			if (rc != ((ssize_t)sizeof(char) * write_size)) {
+				fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
+				return UPDATE_FAIL_READ_F34_QUERIES;
+			}
+
+			offset += write_size;
+			left_bytes -= write_size;
+			free(data_temp);
+		} while (left_bytes);
+
+		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+			// Sleep 100 ms and wait for attention for touchpad only.
+			Sleep(100);
+			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+			}
+		}
+		
+
+		//Wait for completion
+		do {
+			Sleep(20);
+			rmi4update_poll();
+			if (IsBLv87()) {
+				if (m_flashStatus == WRITE_PROTECTION)
+					return UPDATE_FAIL_WRITE_PROTECTED;
+			}
+			if (m_flashStatus == SUCCESS){
+				break;
+
+			}
+			retry++;
+		} while(retry < 20);
+
+		if (m_flashStatus != SUCCESS) {
+			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
+			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
+		}
+
+	}
+
+	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+		if (m_firmwareImage.GetSignatureInfo()[BLv7_FLD].bExisted) {
+			// Write signature.
+			rc = WriteSignatureV7(BLv7_FLD, m_firmwareImage.GetFLDData(), offset);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return rc;	
+			}
+		}
+	}
+
+	return UPDATE_SUCCESS;
+}
+
+int RMI4Update::WriteGlobalParametersV7()
+{
+	int transaction_count, remain_block;
+	int transfer_leng = 0;
+	int offset = 0;
+	unsigned char trans_leng_buf[2];
+	unsigned char cmd_buf[1];
+	unsigned char off[2] = {0, 0};
+	unsigned char partition_id;
+	int i;
+	int retry = 0;
+	unsigned char *data_temp;
+	int rc;
+	unsigned short left_bytes;
+	unsigned short write_size;
+	unsigned short max_write_size;
+	unsigned short dataAddr = m_f34.GetDataBase();
+	unsigned short glpBlockCount = m_firmwareImage.GetGlobalParametersSize() / m_blockSize;
+
+	/* calculate the count */
+	partition_id = GLOBAL_PARAMETERS_PARTITION;
+	
+	remain_block = (glpBlockCount % m_payloadLength);
+	transaction_count = (glpBlockCount / m_payloadLength);
+	
+	if (remain_block > 0)
+		transaction_count++;
+
+	/* set partition id for bootloader 7 */
+	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
+	if (rc != sizeof(partition_id))
+		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
+
+	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
+	if (rc != sizeof(off))
+		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
+
+	for (i = 0; i < transaction_count; i++)
+	{
+		if ((i == (transaction_count -1)) && (remain_block > 0))
+			transfer_leng = remain_block;
+		else
+			transfer_leng = m_payloadLength;
+
+		// Set Transfer Length
+		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
+		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
+
+		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
+		if (rc != sizeof(trans_leng_buf))
+			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
+
+		// Set Command to Write
+		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
+		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
+		if (rc != sizeof(cmd_buf))
+			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
+
+		max_write_size = 16;
+		if (max_write_size >= transfer_leng * m_blockSize)
+			max_write_size = transfer_leng * m_blockSize;
+		else if (max_write_size > m_blockSize)
+			max_write_size -= max_write_size % m_blockSize;
+		else
+			max_write_size = m_blockSize;
+
+		left_bytes = transfer_leng * m_blockSize;
+		do {
+			if (left_bytes / max_write_size)
+				write_size = max_write_size;
+			else
+				write_size = left_bytes;
+
+			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
+			memcpy(data_temp, m_firmwareImage.GetFLDData() + offset, sizeof(char) * write_size);
+			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
+			if (rc != ((ssize_t)sizeof(char) * write_size)) {
+				fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
+				return UPDATE_FAIL_READ_F34_QUERIES;
+			}
+
+			offset += write_size;
+			left_bytes -= write_size;
+			free(data_temp);
+		} while (left_bytes);
+
+		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+			// Sleep 100 ms and wait for attention for touchpad only.
+			Sleep(100);
+			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+			}
+		}
+		
+
+		//Wait for completion
+		do {
+			Sleep(20);
+			rmi4update_poll();
+			if (m_flashStatus == SUCCESS){
+				break;
+
+			}
+			retry++;
+		} while(retry < 20);
+
+		if (m_flashStatus != SUCCESS) {
+			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
+			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
+		}
+
+	}
+
+	return UPDATE_SUCCESS;
+}
+
+int RMI4Update::EraseFlashConfigV10()
+{
+	unsigned char erase_cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+	int retry = 0;
+	int rc;
+
+	/* set partition id for bootloader 10 */
+	erase_cmd[0] = FLASH_CONFIG_PARTITION;
+	/* write bootloader id */
+	erase_cmd[6] = m_bootloaderID[0];
+	erase_cmd[7] = m_bootloaderID[1];
+	erase_cmd[5] = (unsigned char)CMD_V7_ERASE;
+	
+	fprintf(stdout, "Erase command : ");
+	for(int i = 0 ;i<8;i++){
+		fprintf(stdout, "%d ", erase_cmd[i]);
+	}
+	fprintf(stdout, "\n");
+
+	rmi4update_poll();
+	if (!m_inBLmode)
+		return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
+	
+	// For BL8 device, we need hold 1 seconds after querying
+	// F34 status to avoid not get attention by following giving 
+	// erase command.
+	Sleep(1000);
+
+	rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
+	if (rc != sizeof(erase_cmd))
+		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
+
+	Sleep(100);
+
+	//Wait from ATTN
+	rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
+	if (rc != UPDATE_SUCCESS) {
+		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+		return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+	}
+
+	do {
+		Sleep(20);
+		rmi4update_poll();
+		if (IsBLv87()) {
+			if (m_flashStatus == WRITE_PROTECTION)
+				return UPDATE_FAIL_WRITE_PROTECTED;
+		}
+		if (m_flashStatus == SUCCESS){
+			break;
+		}
+		retry++;
+	} while(retry < 20);
+
+	if (m_flashStatus != SUCCESS) {
+		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
+		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
+	}
+
+	return UPDATE_SUCCESS;
+}
+
+int RMI4Update::EraseCoreCodeV10()
+{
+	unsigned char erase_cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+	int retry = 0;
+	int rc;
+
+	/* set partition id for bootloader 10 */
+	erase_cmd[0] = CORE_CODE_PARTITION;
+	/* write bootloader id */
+	erase_cmd[6] = m_bootloaderID[0];
+	erase_cmd[7] = m_bootloaderID[1];
+	erase_cmd[5] = (unsigned char)CMD_V7_ERASE_AP;
+	
+	fprintf(stdout, "Erase command : ");
+	for(int i = 0 ;i<8;i++){
+		fprintf(stdout, "%d ", erase_cmd[i]);
+	}
+	fprintf(stdout, "\n");
+
+	rmi4update_poll();
+	if (!m_inBLmode)
+		return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
+	
+	// For BL8 device, we need hold 1 seconds after querying
+	// F34 status to avoid not get attention by following giving 
+	// erase command.
+	Sleep(1000);
+
+	rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
+	if (rc != sizeof(erase_cmd))
+		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
+
+	Sleep(100);
+
+	//Wait from ATTN
+	rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
+	if (rc != UPDATE_SUCCESS) {
+		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+		return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+	}
+
+	do {
+		Sleep(20);
+		rmi4update_poll();
+		if (m_flashStatus == SUCCESS){
+			break;
+		}
+		retry++;
+	} while(retry < 20);
+
+	if (m_flashStatus != SUCCESS) {
+		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
+		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
+	}
+
 	return UPDATE_SUCCESS;
 }
 
@@ -1012,16 +1588,22 @@
 
 	//Wait from ATTN
 	if(m_bootloaderID[1] == 8){
-		// Wait for attention for BL8 device.
-		rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
-		if (rc != UPDATE_SUCCESS) {
-			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
-			return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+			// Wait for attention for BL8 touchpad.
+			rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+			}
 		}
 	}
 	do {
 		Sleep(20);
 		rmi4update_poll();
+		if (IsBLv87()) {
+			if (m_flashStatus == WRITE_PROTECTION)
+				return UPDATE_FAIL_WRITE_PROTECTED;
+		}
 		if (m_flashStatus == SUCCESS){
 			break;
 		}
@@ -1050,13 +1632,15 @@
 		if (rc != sizeof(erase_cmd))
 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
 
-		//Wait from ATTN
-		Sleep(100);
+		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+			//Wait from ATTN for touchpad only.
+			Sleep(100);
 
-		rc = WaitForIdle(RMI_F34_ERASE_WAIT_MS, true);
-		if (rc != UPDATE_SUCCESS) {
-			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
-			return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+			rc = WaitForIdle(RMI_F34_ERASE_WAIT_MS, true);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+			}
 		}
 
 
@@ -1103,10 +1687,12 @@
 		if (rc != sizeof(EnterCmd))
 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
 
-		rc = WaitForIdle(RMI_F34_ENABLE_WAIT_MS, false);
-		if (rc != UPDATE_SUCCESS) {
-			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
-			return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
+			rc = WaitForIdle(RMI_F34_ENABLE_WAIT_MS, false);
+			if (rc != UPDATE_SUCCESS) {
+				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+			}
 		}
 
 		//Wait from ATTN
@@ -1130,7 +1716,7 @@
 		rmi4update_poll();
 		if (!m_inBLmode)
 			return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
-
+			
 	} else
 		fprintf(stdout, "Already in BL mode, skip...\n");
 
@@ -1174,14 +1760,20 @@
 	if (rc != 1)
 		return UPDATE_FAIL_ENABLE_FLASH_PROGRAMMING;
 
-	Sleep(RMI_F34_ENABLE_WAIT_MS);
+	
 	if(m_device.GetDeviceType() != RMI_DEVICE_TYPE_TOUCHPAD) {
 		fprintf(stdout, "not TouchPad, rebind driver here\n");
+		Sleep(RMI_F34_ENABLE_WAIT_MS);
 		m_device.RebindDriver();
+		rc = WaitForIdle(0);
+		if (rc != UPDATE_SUCCESS)
+			return UPDATE_FAIL_NOT_IN_IDLE_STATE;
+	} else {
+		// For TouchPad
+		rc = WaitForIdle(RMI_F34_ENABLE_WAIT_MS);
+		if (rc != UPDATE_SUCCESS)
+			return UPDATE_FAIL_NOT_IN_IDLE_STATE;
 	}
-	rc = WaitForIdle(0);
-	if (rc != UPDATE_SUCCESS)
-		return UPDATE_FAIL_NOT_IN_IDLE_STATE;
 
 	if (!m_programEnabled)
 		return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED;
@@ -1276,6 +1868,93 @@
 	return UPDATE_SUCCESS;
 }
 
+int RMI4Update::WriteSignatureV7(enum signature_BLv7 signature_partition, unsigned char* data, int offset)
+{
+	fprintf(stdout, "Write Signature...\n");
+	int rc;
+	unsigned char off[2] = {0, 0};
+	unsigned char cmd_buf[1];
+	unsigned short dataAddr = m_f34.GetDataBase();
+	int transfer_leng = 0;
+	signature_info signature = m_firmwareImage.GetSignatureInfo()[signature_partition];
+	unsigned char trans_leng_buf[2];
+	unsigned short left_bytes;
+	unsigned short write_size;
+	unsigned short max_write_size;
+	unsigned char *data_temp;
+	int retry = 0;
+	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
+	if (rc != sizeof(off))
+		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
+
+	// Set Transfer Length
+	transfer_leng = signature.size / m_blockSize;
+	trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
+	trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
+
+	rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
+	if (rc != sizeof(trans_leng_buf))
+		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
+
+	// Set Command to Signature
+	cmd_buf[0] = (unsigned char)CMD_V7_SIGNATURE;
+	rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
+	if (rc != sizeof(cmd_buf))
+		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
+
+	max_write_size = 16;
+	if (max_write_size >= transfer_leng * m_blockSize)
+		max_write_size = transfer_leng * m_blockSize;
+	else if (max_write_size > m_blockSize)
+		max_write_size -= max_write_size % m_blockSize;
+	else
+		max_write_size = m_blockSize;
+
+	left_bytes = transfer_leng * m_blockSize;
+
+	do {
+		if (left_bytes / max_write_size)
+			write_size = max_write_size;
+		else
+			write_size = left_bytes;
+
+		data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
+		memcpy(data_temp, data + offset, sizeof(char) * write_size);
+		rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
+		if (rc != ((ssize_t)sizeof(char) * write_size)) {
+			fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
+			return UPDATE_FAIL_WRITE_BLOCK;
+		}
+
+		offset += write_size;
+		left_bytes -= write_size;
+		free(data_temp);
+	} while (left_bytes);
+
+	// Wair for attention for touchpad only.
+	rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
+	if (rc != UPDATE_SUCCESS) {
+		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
+		return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
+	}
+	
+	//Wait for completion
+	do {
+		Sleep(20);
+		rmi4update_poll();
+		if (m_flashStatus == SUCCESS){
+			break;
+		}
+		retry++;
+	} while(retry < 20);
+
+	if (m_flashStatus != SUCCESS) {
+		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
+		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
+	}
+	return UPDATE_SUCCESS;
+}
+
 /*
  * This is a limited implementation of WaitForIdle which assumes WaitForAttention is supported
  * this will be true for HID, but other protocols will need to revert polling. Polling
@@ -1328,3 +2007,28 @@
 
 	return UPDATE_SUCCESS;
 }
+
+bool RMI4Update::IsBLv87()
+{
+	if ((m_bootloaderID[1] >= 10) ||
+		((m_bootloaderID[1] == 8) && (m_bootloaderID[0] >= 7))){
+		return true;
+	} else 
+		return false;
+}
+
+int RMI4Update::ReadMSL()
+{
+	int rc;
+	unsigned char idStr[3];
+	unsigned short query9Addr = m_f34.GetQueryBase() + 9;
+	unsigned char offset;
+	unsigned char MSL[2];
+
+	rc = m_device.Read(query9Addr, MSL, sizeof(MSL));
+	if (rc != sizeof(MSL))
+		return UPDATE_FAIL_READ_F34_QUERIES;
+
+	m_MSL = MSL[0] << 8 | MSL[1];
+	return UPDATE_SUCCESS;
+}
diff --git a/rmi4update/rmi4update.h b/rmi4update/rmi4update.h
index b9de4ec..ea87653 100755
--- a/rmi4update/rmi4update.h
+++ b/rmi4update/rmi4update.h
@@ -35,6 +35,7 @@
 	FLASH_PROGRAMMING_KEY_INCORRECT,
 	BAD_PARTITION_TABLE,
 	CHECKSUM_FAILED,
+	WRITE_PROTECTION = 0x0E,
 	FLASH_HARDWARE_FAILURE = 0x1f,
 };
 
@@ -52,6 +53,7 @@
 	DISPLAY_CONFIG_PARTITION,
 	EXTERNAL_TOUCH_AFE_CONFIG_PARTITION,
 	UTILITY_PARAMETER_PARTITION,
+	FIXED_LOCATION_DATA_PARTITION = 0x0E,
 };
 
 enum v7_flash_command {
@@ -62,6 +64,7 @@
 	CMD_V7_ERASE,
 	CMD_V7_ERASE_AP,
 	CMD_V7_SENSOR_ID,
+	CMD_V7_SIGNATURE,
 };
 
 enum bl_version {
@@ -69,6 +72,7 @@
 	BL_V6 = 6,
 	BL_V7 = 7,
 	BL_V8 = 8,
+	BL_V10 = 10,
 };
 
 struct f34_v7_query_0 {
@@ -128,7 +132,9 @@
 			unsigned char has_core_config:1;
 			unsigned char has_guest_code:1;
 			unsigned char has_display_config:1;
-			unsigned char f34_query7_b11__15:5;
+			unsigned char f34_query7_b11_13:3;
+			unsigned char has_fld:1;
+			unsigned char f34_query7_b15:1;
 			unsigned char f34_query7_b16__23;
 			unsigned char f34_query7_b24__31;
 		} __attribute__((packed));;
@@ -157,6 +163,11 @@
 			m_firmwareImage(firmwareImage), m_writeBlockWithCmd(true)
 	{
 		m_IsErased = false;
+		m_hasCoreCode = false;
+		m_hasCoreConfig = false;
+		m_hasFlashConfig = false;
+		m_hasFLD = false;
+		m_hasGlobalParameters = false;
 	}
 	int UpdateFirmware(bool force = false, bool performLockdown = false);
 
@@ -171,14 +182,21 @@
 	int WriteBootloaderID();
 	int EnterFlashProgrammingV7();
 	int EraseFirmwareV7();
+	int EraseFlashConfigV10();
+	int EraseCoreCodeV10();
 	int WriteFirmwareV7();
 	int WriteCoreConfigV7();
 	int WriteFlashConfigV7();
+	int WriteFLDV7();
+	int WriteGlobalParametersV7();
 	int EnterFlashProgramming();
 	int WriteBlocks(unsigned char *block, unsigned short count, unsigned char cmd);
 	int WaitForIdle(int timeout_ms, bool readF34OnSucess = true);
 	int GetFirmwareSize() { return m_blockSize * m_fwBlockCount; }
 	int GetConfigSize() { return m_blockSize * m_configBlockCount; }
+	int WriteSignatureV7(enum signature_BLv7 signature_partition, unsigned char* data, int offset);
+	bool IsBLv87();
+	int ReadMSL();
 
 private:
 	RMIDevice & m_device;
@@ -215,6 +233,18 @@
 	unsigned char m_inBLmode;
 	unsigned long m_buildID;
 	unsigned char *m_guestData;
+	bool m_hasCoreCode;
+	bool m_hasCoreConfig;
+	bool m_hasFlashConfig;
+	bool m_hasGlobalParameters;
+	/* BL_V7 end */
+
+	/* BL v8.7 */
+	unsigned short m_MSL;
+	/* BL v8.7 end */
+
+	/* for BL V10 */
+	bool m_hasFLD;
 	/* BL_V7 end */
 
 	unsigned short m_f34StatusAddr;
diff --git a/rmi4update/updateutil.cpp b/rmi4update/updateutil.cpp
index 1d654cd..cc607d2 100644
--- a/rmi4update/updateutil.cpp
+++ b/rmi4update/updateutil.cpp
@@ -27,6 +27,7 @@
 	"checksum does not match image",				// UPDATE_FAIL_VERIFY_CHECKSUM
 	"image firmware size does not match device",			// UPDATE_FAIL_VERIFY_FIRMWARE_SIZE
 	"image config size does not match device",			// UPDATE_FAIL_VERIFY_CONFIG_SIZE
+	"image product ID does not match device",			// UPDATE_FAIL_VERIFY_IMAGE_PRODUCTID_NOT_MATCH
 	"image version is unsupported",					// UPDATE_FAIL_UNSUPPORTED_IMAGE_VERSION
 	"failed to find F01 on device",					// UPDATE_FAIL_NO_FUNCTION_01
 	"failed to find F34 on device",					// UPDATE_FAIL_NO_FUNCTION_34
@@ -51,6 +52,7 @@
 	"the firmware image is older then the firmware on the device",	// UPDATE_FAIL_FIRMWARE_IMAGE_IS_OLDER
 	"invalid parameter",						// UPDATE_FAIL_INVALID_PARAMETER
 	"failed to open firmware image file",				// UPDATE_FAIL_OPEN_FIRMWARE_IMAGE
+	"write protection is activated",			// UPDATE_FAIL_WRITE_PROTECTED
 };
 
 const char * update_err_to_string(int err)
diff --git a/rmi4update/updateutil.h b/rmi4update/updateutil.h
index 59f1a08..e59d690 100644
--- a/rmi4update/updateutil.h
+++ b/rmi4update/updateutil.h
@@ -26,6 +26,7 @@
 	UPDATE_FAIL_VERIFY_CHECKSUM,
 	UPDATE_FAIL_VERIFY_FIRMWARE_SIZE,
 	UPDATE_FAIL_VERIFY_CONFIG_SIZE,
+	UPDATE_FAIL_VERIFY_IMAGE_PRODUCTID_NOT_MATCH,
 	UPDATE_FAIL_UNSUPPORTED_IMAGE_VERSION,
 	UPDATE_FAIL_NO_FUNCTION_01,
 	UPDATE_FAIL_NO_FUNCTION_34,
@@ -50,6 +51,8 @@
 	UPDATE_FAIL_FIRMWARE_IMAGE_IS_OLDER,
 	UPDATE_FAIL_INVALID_PARAMETER,
 	UPDATE_FAIL_OPEN_FIRMWARE_IMAGE,
+	UPDATE_FAIL_WRITE_PROTECTED,
+	UPDATE_FAIL_MSL_CHECKING,
 };
 
 const char * update_err_to_string(int err);
diff --git a/rmidevice/Makefile b/rmidevice/Makefile
index d9f32cc..4ce6b39 100644
--- a/rmidevice/Makefile
+++ b/rmidevice/Makefile
@@ -2,6 +2,7 @@
 AR ?= ar
 RANLIB ?= ranlib
 CPPFLAGS += -I../include -I./include
+CPPFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
 CXXFLAGS += -fPIC -Wall
 RMIDEVICESRC = rmifunction.cpp rmidevice.cpp hiddevice.cpp util.cpp
 RMIDEVICEOBJ = $(RMIDEVICESRC:.cpp=.o)
diff --git a/rmidevice/hiddevice.cpp b/rmidevice/hiddevice.cpp
index 709559d..b81d70a 100755
--- a/rmidevice/hiddevice.cpp
+++ b/rmidevice/hiddevice.cpp
@@ -40,6 +40,8 @@
 #define RMI_READ_DATA_REPORT_ID             0xb // Input Report
 #define RMI_ATTN_REPORT_ID                  0xc // Input Report
 #define RMI_SET_RMI_MODE_REPORT_ID          0xf // Feature Report
+#define RMI_SET_LID_MODE_REPORT_ID          0xe // Feature Report
+
 
 enum hid_report_type {
 	HID_REPORT_TYPE_UNKNOWN			= 0x0,
@@ -218,6 +220,10 @@
 					continue;
 				}
 
+				if (m_rptDesc.value[i] == RMI_SET_LID_MODE_REPORT_ID) {
+					hasVendorDefineLIDMode = true;
+				}
+
 				if (m_rptDesc.value[i] == HID_REPORT_TYPE_INPUT)
 					hidReportType = HID_REPORT_TYPE_INPUT;
 
@@ -291,16 +297,32 @@
 	size_t bytesToRequest;
 	int reportId;
 	int rc;
+	struct timeval tv;
+	int resendCount = 0;
 
+	tv.tv_sec = 10 / 1000;
+	tv.tv_usec = (10 % 1000) * 1000;
+	
 	if (!m_deviceOpen)
 		return -1;
 
+	if (m_hasDebug) {
+		fprintf(stdout, "R %02x : ", addr);
+	}
+
 	if (m_bytesPerReadRequest)
 		bytesPerRequest = m_bytesPerReadRequest;
 	else
 		bytesPerRequest = len;
 
 	for (totalBytesRead = 0; totalBytesRead < len; totalBytesRead += bytesReadPerRequest) {
+Resend:
+		if (GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) {
+			if (resendCount == 3) {
+				fprintf(stderr, "resend count exceed, return as failure\n");
+				return -1;
+			}
+		}
 		count = 0;
 		if ((len - totalBytesRead) < bytesPerRequest)
 			bytesToRequest = len % bytesPerRequest;
@@ -334,7 +356,13 @@
 
 		bytesReadPerRequest = 0;
 		while (bytesReadPerRequest < bytesToRequest) {
-			rc = GetReport(&reportId);
+			if (GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) {
+				// Add timeout 10 ms for select() called in GetReport().
+				rc = GetReport(&reportId, &tv);
+			} else {
+				// Touch Screen
+				rc = GetReport(&reportId);
+			}
 			if (rc > 0 && reportId == RMI_READ_DATA_REPORT_ID) {
 				if (static_cast<ssize_t>(m_inputReportSize) <
 				    std::max(HID_RMI4_READ_INPUT_COUNT,
@@ -350,10 +378,24 @@
 					bytesInDataReport);
 				bytesReadPerRequest += bytesInDataReport;
 				m_dataBytesRead = 0;
+				if (GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) {
+					// Resend sheme is supported on TP only.
+					resendCount = 0;
+				}
+			} else if (GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) {
+				fprintf(stderr, "Some error with GetReport : rc(%d), reportID(0x%x)\n", rc, reportId);
+				resendCount += 1;
+				goto Resend;
 			}
 		}
 		addr += bytesPerRequest;
 	}
+	if (m_hasDebug) {
+		for (int i=0 ; i<len ; i++) {
+			fprintf(stdout, "%02x ", buf[i]);
+		}
+		fprintf(stdout, "\n");
+	}
 
 	return totalBytesRead;
 }
@@ -374,6 +416,14 @@
 	m_outputReport[HID_RMI4_WRITE_OUTPUT_ADDR + 1] = (addr >> 8) & 0xFF;
 	memcpy(&m_outputReport[HID_RMI4_WRITE_OUTPUT_DATA], buf, len);
 
+	if (m_hasDebug) {
+		fprintf(stdout, "W %02x : ", addr);
+		for (int i=0 ; i<len ; i++) {
+			fprintf(stdout, "%02x ", buf[i]);
+		}
+		fprintf(stdout, "\n");
+	}
+
 	for (;;) {
 		m_bCancel = false;
 		count = write(m_fd, m_outputReport, m_outputReportSize);
@@ -391,11 +441,11 @@
 {
 	int rc;
 	char buf[2];
-
+	
 	if (!m_deviceOpen)
 		return -1;
 
-	buf[0] = 0xF;
+	buf[0] = RMI_SET_RMI_MODE_REPORT_ID;
 	buf[1] = mode;
 	rc = ioctl(m_fd, HIDIOCSFEATURE(2), buf);
 	if (rc < 0) {
@@ -406,6 +456,44 @@
 	return 0;
 }
 
+int HIDDevice::ToggleInterruptMask(bool enable)
+{
+	int rc;
+	char buf[2];
+
+	if (GetDeviceType() != RMI_DEVICE_TYPE_TOUCHPAD) {
+		fprintf(stdout, "Not TP, skip toggle interrupts mask\n");
+		return 0;
+	}
+
+	// We can have information to see whether it exists this feature report currentlt.
+	// However, it might have no action even we set this feature with specific value.
+	// Need FW team's help to query more information about the existence of functions.
+	if (!hasVendorDefineLIDMode) {
+		if (m_hasDebug) {
+			fprintf(stdout, "no LID mode feature, return\n");
+		}
+		return 0;
+	}
+	
+	if (!m_deviceOpen)
+		return -1;
+
+	buf[0] = RMI_SET_LID_MODE_REPORT_ID;
+	if (enable) {
+		buf[1] = 0;
+	} else {
+		buf[1] = 8;
+	}
+	rc = ioctl(m_fd, HIDIOCSFEATURE(2), buf);
+	if (rc < 0) {
+		perror("HIDIOCSFEATURE");
+		return rc;
+	}
+	Sleep(10);
+	return 0;
+}
+
 void HIDDevice::Close()
 {
 	RMIDevice::Close();
@@ -655,11 +743,9 @@
 	int fd=-1;
 	unsigned int type;
 	int abs[6] = {0};
-	int k;
 	struct dirent **namelist;
-	int i, ndev, devnum, match;
-	char *filename;
-	int max_device = 0;
+	int i, ndev;
+
     char input_event_name[PATH_MAX];
 	unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
 
@@ -793,15 +879,8 @@
 
 	if (bus == BUS_I2C) {
 		devicePrefix += "i2c/";
-		// From new patch released on 2020/11, i2c_hid would be renamed as i2c_hid_acpi,
-		// and also need backward compatible.
-		std::string driverPathTemp = devicePrefix + "drivers/i2c_hid/";
-		DIR *driverPathtest = opendir(driverPathTemp.c_str());
-		if(!driverPathtest) {
-			driverPath = devicePrefix + "drivers/i2c_hid_acpi/";
-		} else {
-			driverPath = devicePrefix + "drivers/i2c_hid/";
-		}
+		// The i2c driver module installed on system is vary (i2c_hid, i2c_hid_acpi, i2c_hid_of),
+		// so we will assign driver path until we get device name later.
 	} else {
 		devicePrefix += "usb/";
 		driverPath = devicePrefix + "drivers/usbhid/";
@@ -840,8 +919,25 @@
 		}
 		closedir(devDir);
 
-		if (deviceFound)
+		if (deviceFound) {
+			if (bus == BUS_I2C) {
+				std::fstream ueventfile;
+				std::string ueventfilepath = fullLinkPath + "/uevent";
+				std::string uevent;
+				std::string modulename;
+				ueventfile.open(ueventfilepath.c_str(), std::ios::in);
+				if(ueventfile.is_open()) {
+					getline(ueventfile, uevent);
+					modulename = uevent.substr(uevent.find("=") + 1, std::string::npos);
+					driverPath = devicePrefix + "drivers/";
+					driverPath += modulename;
+					driverPath += "/";
+				}
+				ueventfile.close();
+			}
 			break;
+		}
+			
 	}
 	closedir(devicesDir);
 
diff --git a/rmidevice/hiddevice.h b/rmidevice/hiddevice.h
index b947f62..93b1ed8 100755
--- a/rmidevice/hiddevice.h
+++ b/rmidevice/hiddevice.h
@@ -20,6 +20,7 @@
 
 #include <linux/hidraw.h>
 #include <string>
+#include <fstream>
 #include <stdint.h>
 #include "rmidevice.h"
 
@@ -41,7 +42,8 @@
 		      m_mode(HID_RMI4_MODE_ATTN_REPORTS),
 		      m_initialMode(HID_RMI4_MODE_MOUSE),
 		      m_transportDeviceName(""),
-		      m_driverPath("")
+		      m_driverPath(""),
+		      hasVendorDefineLIDMode(false)
 	{}
 	virtual int Open(const char * filename);
 	virtual int Read(unsigned short addr, unsigned char *buf,
@@ -49,6 +51,7 @@
 	virtual int Write(unsigned short addr, const unsigned char *buf,
 				 unsigned short len);
 	virtual int SetMode(int mode);
+	virtual int ToggleInterruptMask(bool enable);
 	virtual int WaitForAttention(struct timeval * timeout = NULL,
 					unsigned int source_mask = RMI_INTERUPT_SOURCES_ALL_MASK);
 	virtual int GetAttentionReport(struct timeval * timeout, unsigned int source_mask,
@@ -87,6 +90,8 @@
 	std::string m_transportDeviceName;
 	std::string m_driverPath;
 
+	bool hasVendorDefineLIDMode;
+
 	int GetReport(int *reportId, struct timeval * timeout = NULL);
 	void PrintReport(const unsigned char *report);
 	void ParseReportDescriptor();
diff --git a/rmidevice/rmidevice.cpp b/rmidevice/rmidevice.cpp
index 15335f9..029e614 100644
--- a/rmidevice/rmidevice.cpp
+++ b/rmidevice/rmidevice.cpp
@@ -62,7 +62,6 @@
 
 	if (m_page == page)
 		return 0;
-
 	m_page = page;
 	rc = Write(RMI_DEVICE_PAGE_SELECT_REGISTER, &page, 1);
 	if (rc < 0 || rc < 1) {
@@ -327,7 +326,7 @@
 	}
 
 	m_numInterruptRegs = (interruptCount + 7) / 8;
-
+	
 	return 0;
 }
 
diff --git a/rmidevice/rmidevice.h b/rmidevice/rmidevice.h
index 9bfe849..9b8c915 100644
--- a/rmidevice/rmidevice.h
+++ b/rmidevice/rmidevice.h
@@ -38,7 +38,7 @@
 public:
 	RMIDevice() : m_functionList(), m_sensorID(0), m_bCancel(false), m_bytesPerReadRequest(0), m_page(-1),
 		      m_deviceType(RMI_DEVICE_TYPE_ANY)
-	{}
+	{ m_hasDebug = false; }
 	virtual ~RMIDevice() {}
 	virtual int Open(const char * filename) = 0;
 	virtual int Read(unsigned short addr, unsigned char *data,
@@ -46,6 +46,7 @@
 	virtual int Write(unsigned short addr, const unsigned char *data,
 				 unsigned short len) = 0;
 	virtual int SetMode(int mode) { return -1; /* Unsupported */ }
+	virtual int ToggleInterruptMask(bool enable) = 0;
 	virtual int WaitForAttention(struct timeval * timeout = NULL,
 			unsigned int source_mask = RMI_INTERUPT_SOURCES_ALL_MASK) = 0;
 	virtual int GetAttentionReport(struct timeval * timeout, unsigned int source_mask,
@@ -61,6 +62,7 @@
 	int GetFirmwareVersionMajor() { return m_firmwareVersionMajor; }
 	int GetFirmwareVersionMinor() { return m_firmwareVersionMinor; }
 	virtual int QueryBasicProperties();
+	char *GetProductID() { return (char *)m_productID; }
 	
 	int SetRMIPage(unsigned char page);
 	
@@ -81,6 +83,8 @@
 	virtual bool FindDevice(enum RMIDeviceType type = RMI_DEVICE_TYPE_ANY) = 0;
 	enum RMIDeviceType GetDeviceType() { return m_deviceType; }
 
+	bool m_hasDebug;
+
 protected:
 	std::vector<RMIFunction> m_functionList;
 	unsigned char m_manufacturerID;
diff --git a/rmihidtool/Makefile b/rmihidtool/Makefile
index 3553c99..e03fe92 100644
--- a/rmihidtool/Makefile
+++ b/rmihidtool/Makefile
@@ -1,5 +1,6 @@
 CXX ?= g++
 CPPFLAGS += -I../include -I./include -I../rmidevice
+CPPFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
 CXXFLAGS += -Wall
 LDFLAGS += -L.
 LIBS =  -lrmidevice