xref: /aosp_15_r20/external/rmi4utils/rmi4update/rmi4update.cpp (revision a248dafd7653b99fc45f9d29e5f139b04f2f28bc)
1*a248dafdSChristopher Ferris /*
2*a248dafdSChristopher Ferris  * Copyright (C) 2014 Andrew Duggan
3*a248dafdSChristopher Ferris  * Copyright (C) 2014 Synaptics Inc
4*a248dafdSChristopher Ferris  *
5*a248dafdSChristopher Ferris  * Licensed under the Apache License, Version 2.0 (the "License");
6*a248dafdSChristopher Ferris  * you may not use this file except in compliance with the License.
7*a248dafdSChristopher Ferris  * You may obtain a copy of the License at
8*a248dafdSChristopher Ferris  *
9*a248dafdSChristopher Ferris  *      http://www.apache.org/licenses/LICENSE-2.0
10*a248dafdSChristopher Ferris  *
11*a248dafdSChristopher Ferris  * Unless required by applicable law or agreed to in writing, software
12*a248dafdSChristopher Ferris  * distributed under the License is distributed on an "AS IS" BASIS,
13*a248dafdSChristopher Ferris  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*a248dafdSChristopher Ferris  * See the License for the specific language governing permissions and
15*a248dafdSChristopher Ferris  * limitations under the License.
16*a248dafdSChristopher Ferris  */
17*a248dafdSChristopher Ferris 
18*a248dafdSChristopher Ferris #include <alloca.h>
19*a248dafdSChristopher Ferris #include <time.h>
20*a248dafdSChristopher Ferris #include <stdint.h>
21*a248dafdSChristopher Ferris #include <stdio.h>
22*a248dafdSChristopher Ferris #include <unistd.h>
23*a248dafdSChristopher Ferris #include <string.h>
24*a248dafdSChristopher Ferris #include <stdlib.h>
25*a248dafdSChristopher Ferris #include <errno.h>
26*a248dafdSChristopher Ferris #include <fcntl.h>
27*a248dafdSChristopher Ferris #include <linux/input.h>
28*a248dafdSChristopher Ferris #include "rmi4update.h"
29*a248dafdSChristopher Ferris 
30*a248dafdSChristopher Ferris #define RMI_F34_QUERY_SIZE		7
31*a248dafdSChristopher Ferris #define RMI_F34_HAS_NEW_REG_MAP		(1 << 0)
32*a248dafdSChristopher Ferris #define RMI_F34_IS_UNLOCKED		(1 << 1)
33*a248dafdSChristopher Ferris #define RMI_F34_HAS_CONFIG_ID		(1 << 2)
34*a248dafdSChristopher Ferris #define RMI_F34_BLOCK_SIZE_OFFSET	1
35*a248dafdSChristopher Ferris #define RMI_F34_FW_BLOCKS_OFFSET	3
36*a248dafdSChristopher Ferris #define RMI_F34_CONFIG_BLOCKS_OFFSET	5
37*a248dafdSChristopher Ferris 
38*a248dafdSChristopher Ferris #define RMI_F34_BLOCK_SIZE_V1_OFFSET	0
39*a248dafdSChristopher Ferris #define RMI_F34_FW_BLOCKS_V1_OFFSET	0
40*a248dafdSChristopher Ferris #define RMI_F34_CONFIG_BLOCKS_V1_OFFSET	2
41*a248dafdSChristopher Ferris 
42*a248dafdSChristopher Ferris #define RMI_F34_BLOCK_DATA_OFFSET	2
43*a248dafdSChristopher Ferris #define RMI_F34_BLOCK_DATA_V1_OFFSET	1
44*a248dafdSChristopher Ferris 
45*a248dafdSChristopher Ferris #define RMI_F34_COMMAND_MASK		0x0F
46*a248dafdSChristopher Ferris #define RMI_F34_STATUS_MASK		0x07
47*a248dafdSChristopher Ferris #define RMI_F34_STATUS_SHIFT		4
48*a248dafdSChristopher Ferris #define RMI_F34_ENABLED_MASK		0x80
49*a248dafdSChristopher Ferris 
50*a248dafdSChristopher Ferris #define RMI_F34_COMMAND_V1_MASK		0x3F
51*a248dafdSChristopher Ferris #define RMI_F34_STATUS_V1_MASK		0x3F
52*a248dafdSChristopher Ferris #define RMI_F34_ENABLED_V1_MASK		0x80
53*a248dafdSChristopher Ferris 
54*a248dafdSChristopher Ferris #define RMI_F34_WRITE_FW_BLOCK        0x02
55*a248dafdSChristopher Ferris #define RMI_F34_ERASE_ALL             0x03
56*a248dafdSChristopher Ferris #define RMI_F34_WRITE_LOCKDOWN_BLOCK  0x04
57*a248dafdSChristopher Ferris #define RMI_F34_WRITE_CONFIG_BLOCK    0x06
58*a248dafdSChristopher Ferris #define RMI_F34_ENABLE_FLASH_PROG     0x0f
59*a248dafdSChristopher Ferris 
60*a248dafdSChristopher Ferris #define RMI_F34_ENABLE_WAIT_MS 300
61*a248dafdSChristopher Ferris #define RMI_F34_ERASE_WAIT_MS (5 * 1000)
62*a248dafdSChristopher Ferris #define RMI_F34_ERASE_V8_WAIT_MS (10000)
63*a248dafdSChristopher Ferris #define RMI_F34_IDLE_WAIT_MS 500
64*a248dafdSChristopher Ferris #define RMI_F34_PARTITION_READ_WAIT_MS 20
65*a248dafdSChristopher Ferris 
66*a248dafdSChristopher Ferris /* Most recent device status event */
67*a248dafdSChristopher Ferris #define RMI_F01_STATUS_CODE(status)		((status) & 0x0f)
68*a248dafdSChristopher Ferris /* Indicates that flash programming is enabled (bootloader mode). */
69*a248dafdSChristopher Ferris #define RMI_F01_STATUS_BOOTLOADER(status)	(!!((status) & 0x40))
70*a248dafdSChristopher Ferris /* The device has lost its configuration for some reason. */
71*a248dafdSChristopher Ferris #define RMI_F01_STATUS_UNCONFIGURED(status)	(!!((status) & 0x80))
72*a248dafdSChristopher Ferris 
73*a248dafdSChristopher Ferris /* Indicates that flash programming is enabled V7(bootloader mode). */
74*a248dafdSChristopher Ferris #define RMI_F01_STATUS_BOOTLOADER_v7(status) (!!((status) & 0x80))
75*a248dafdSChristopher Ferris 
76*a248dafdSChristopher Ferris /*
77*a248dafdSChristopher Ferris  * Sleep mode controls power management on the device and affects all
78*a248dafdSChristopher Ferris  * functions of the device.
79*a248dafdSChristopher Ferris  */
80*a248dafdSChristopher Ferris #define RMI_F01_CTRL0_SLEEP_MODE_MASK	0x03
81*a248dafdSChristopher Ferris 
82*a248dafdSChristopher Ferris #define RMI_SLEEP_MODE_NORMAL		0x00
83*a248dafdSChristopher Ferris #define RMI_SLEEP_MODE_SENSOR_SLEEP	0x01
84*a248dafdSChristopher Ferris #define RMI_SLEEP_MODE_RESERVED0	0x02
85*a248dafdSChristopher Ferris #define RMI_SLEEP_MODE_RESERVED1	0x03
86*a248dafdSChristopher Ferris 
87*a248dafdSChristopher Ferris /*
88*a248dafdSChristopher Ferris  * This bit disables whatever sleep mode may be selected by the sleep_mode
89*a248dafdSChristopher Ferris  * field and forces the device to run at full power without sleeping.
90*a248dafdSChristopher Ferris  */
91*a248dafdSChristopher Ferris #define RMI_F01_CRTL0_NOSLEEP_BIT	(1 << 2)
92*a248dafdSChristopher Ferris 
UpdateFirmware(bool force,bool performLockdown)93*a248dafdSChristopher Ferris int RMI4Update::UpdateFirmware(bool force, bool performLockdown)
94*a248dafdSChristopher Ferris {
95*a248dafdSChristopher Ferris 	struct timespec start;
96*a248dafdSChristopher Ferris 	struct timespec end;
97*a248dafdSChristopher Ferris 	long long int duration_us = 0;
98*a248dafdSChristopher Ferris 	int rc;
99*a248dafdSChristopher Ferris 	const unsigned char eraseAll = RMI_F34_ERASE_ALL;
100*a248dafdSChristopher Ferris 
101*a248dafdSChristopher Ferris 	// Clear all interrupts before parsing to avoid unexpected interrupts.
102*a248dafdSChristopher Ferris 	m_device.ToggleInterruptMask(false);
103*a248dafdSChristopher Ferris 	rc = FindUpdateFunctions();
104*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS) {
105*a248dafdSChristopher Ferris 		m_device.ToggleInterruptMask(true);
106*a248dafdSChristopher Ferris 		return rc;
107*a248dafdSChristopher Ferris 	}
108*a248dafdSChristopher Ferris 
109*a248dafdSChristopher Ferris 	rc = m_device.QueryBasicProperties();
110*a248dafdSChristopher Ferris 	if (rc < 0) {
111*a248dafdSChristopher Ferris 		m_device.ToggleInterruptMask(true);
112*a248dafdSChristopher Ferris 		return UPDATE_FAIL_QUERY_BASIC_PROPERTIES;
113*a248dafdSChristopher Ferris 	}
114*a248dafdSChristopher Ferris 	// Restore the interrupts
115*a248dafdSChristopher Ferris 	m_device.ToggleInterruptMask(true);
116*a248dafdSChristopher Ferris 
117*a248dafdSChristopher Ferris 	if (!force && m_firmwareImage.HasIO()) {
118*a248dafdSChristopher Ferris 		if (m_firmwareImage.GetFirmwareID() <= m_device.GetFirmwareID()) {
119*a248dafdSChristopher Ferris 			fprintf(stderr, "Firmware image (%ld) is not newer then the firmware on the device (%ld)\n",
120*a248dafdSChristopher Ferris 				m_firmwareImage.GetFirmwareID(), m_device.GetFirmwareID());
121*a248dafdSChristopher Ferris 			rc = UPDATE_FAIL_FIRMWARE_IMAGE_IS_OLDER;
122*a248dafdSChristopher Ferris 			return rc;
123*a248dafdSChristopher Ferris 		}
124*a248dafdSChristopher Ferris 	}
125*a248dafdSChristopher Ferris 
126*a248dafdSChristopher Ferris 	fprintf(stdout, "Device Properties:\n");
127*a248dafdSChristopher Ferris 	m_device.PrintProperties();
128*a248dafdSChristopher Ferris 	if (m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) {
129*a248dafdSChristopher Ferris 		rc = m_firmwareImage.VerifyImageProductID(m_device.GetProductID());
130*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS)
131*a248dafdSChristopher Ferris 			return rc;
132*a248dafdSChristopher Ferris 	} else {
133*a248dafdSChristopher Ferris 		fprintf(stdout, "not touchpad, skip checking product ID\n");
134*a248dafdSChristopher Ferris 	}
135*a248dafdSChristopher Ferris 
136*a248dafdSChristopher Ferris 
137*a248dafdSChristopher Ferris 	rc = DisableNonessentialInterupts();
138*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS)
139*a248dafdSChristopher Ferris 		return rc;
140*a248dafdSChristopher Ferris 
141*a248dafdSChristopher Ferris 	rc = ReadF34Queries();
142*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS)
143*a248dafdSChristopher Ferris 		return rc;
144*a248dafdSChristopher Ferris 
145*a248dafdSChristopher Ferris 	if (m_bootloaderID[1] < 10) {
146*a248dafdSChristopher Ferris 		// Checking size alignment for the device prior to BL v10.
147*a248dafdSChristopher Ferris 		rc = m_firmwareImage.VerifyImageMatchesDevice(GetFirmwareSize(), GetConfigSize());
148*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS)
149*a248dafdSChristopher Ferris 			return rc;
150*a248dafdSChristopher Ferris 	}
151*a248dafdSChristopher Ferris 
152*a248dafdSChristopher Ferris 	if (m_f34.GetFunctionVersion() == 0x02) {
153*a248dafdSChristopher Ferris 		fprintf(stdout, "Enable Flash V7+...\n");
154*a248dafdSChristopher Ferris 		rc = EnterFlashProgrammingV7();
155*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS) {
156*a248dafdSChristopher Ferris 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
157*a248dafdSChristopher Ferris 			goto reset;
158*a248dafdSChristopher Ferris 		}
159*a248dafdSChristopher Ferris 		fprintf(stdout, "Enable Flash done V7+...\n");
160*a248dafdSChristopher Ferris 
161*a248dafdSChristopher Ferris 		if (IsBLv87()) {
162*a248dafdSChristopher Ferris 			if (m_firmwareImage.IsImageHasFirmwareVersion()) {
163*a248dafdSChristopher Ferris 				rc = ReadMSL();
164*a248dafdSChristopher Ferris 				if (rc != UPDATE_SUCCESS) {
165*a248dafdSChristopher Ferris 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
166*a248dafdSChristopher Ferris 					goto reset;
167*a248dafdSChristopher Ferris 				}
168*a248dafdSChristopher Ferris 				fprintf(stdout, "MSL : 0x%x\n", m_MSL);
169*a248dafdSChristopher Ferris 				if (m_MSL > m_firmwareImage.GetFirmwareVersion()) {
170*a248dafdSChristopher Ferris 					fprintf(stdout, "MSL checking failed. device(0x%x) > image(0x%x)\n",
171*a248dafdSChristopher Ferris 						m_MSL, m_firmwareImage.GetFirmwareVersion());
172*a248dafdSChristopher Ferris 					rc = UPDATE_FAIL_MSL_CHECKING;
173*a248dafdSChristopher Ferris 					goto reset;
174*a248dafdSChristopher Ferris 				} else {
175*a248dafdSChristopher Ferris 					fprintf(stdout, "Passing MSL checking\n");
176*a248dafdSChristopher Ferris 				}
177*a248dafdSChristopher Ferris 			}
178*a248dafdSChristopher Ferris 		}
179*a248dafdSChristopher Ferris 
180*a248dafdSChristopher Ferris 		if (m_bootloaderID[1] >= 10) {
181*a248dafdSChristopher Ferris 			fprintf(stdout, "Writing FLD V10...\n");
182*a248dafdSChristopher Ferris 			rc = WriteFLDV7();
183*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
184*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
185*a248dafdSChristopher Ferris 				goto reset;
186*a248dafdSChristopher Ferris 			}
187*a248dafdSChristopher Ferris 			fprintf(stdout, "Writing FLD done V10...\n");
188*a248dafdSChristopher Ferris 
189*a248dafdSChristopher Ferris 			fprintf(stdout, "Erasing Flash Config V10...\n");
190*a248dafdSChristopher Ferris 			rc = EraseFlashConfigV10();
191*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
192*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
193*a248dafdSChristopher Ferris 				goto reset;
194*a248dafdSChristopher Ferris 			}
195*a248dafdSChristopher Ferris 			fprintf(stdout, "Erasing Flash Config done V10...\n");
196*a248dafdSChristopher Ferris 
197*a248dafdSChristopher Ferris 			if (m_firmwareImage.GetFlashConfigData()) {
198*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing flash configuration V10...\n");
199*a248dafdSChristopher Ferris 				rc = WriteFlashConfigV7();
200*a248dafdSChristopher Ferris 				if (rc != UPDATE_SUCCESS) {
201*a248dafdSChristopher Ferris 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
202*a248dafdSChristopher Ferris 					goto reset;
203*a248dafdSChristopher Ferris 				}
204*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing flash config done V10...\n");
205*a248dafdSChristopher Ferris 			}
206*a248dafdSChristopher Ferris 
207*a248dafdSChristopher Ferris 			fprintf(stdout, "Erasing Core Code V10...\n");
208*a248dafdSChristopher Ferris 			rc = EraseCoreCodeV10();
209*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
210*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
211*a248dafdSChristopher Ferris 				goto reset;
212*a248dafdSChristopher Ferris 			}
213*a248dafdSChristopher Ferris 			fprintf(stdout, "Erasing Core Code done V10...\n");
214*a248dafdSChristopher Ferris 
215*a248dafdSChristopher Ferris 			if (m_firmwareImage.GetFirmwareData()) {
216*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing Core Code V10...\n");
217*a248dafdSChristopher Ferris 				rc = WriteFirmwareV7();
218*a248dafdSChristopher Ferris 				if (rc != UPDATE_SUCCESS) {
219*a248dafdSChristopher Ferris 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
220*a248dafdSChristopher Ferris 					goto reset;
221*a248dafdSChristopher Ferris 				}
222*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing Core Code done V10...\n");
223*a248dafdSChristopher Ferris 			}
224*a248dafdSChristopher Ferris 
225*a248dafdSChristopher Ferris 			if (m_firmwareImage.GetConfigData()) {
226*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing Core Config V10...\n");
227*a248dafdSChristopher Ferris 				rc = WriteCoreConfigV7();
228*a248dafdSChristopher Ferris 				if (rc != UPDATE_SUCCESS) {
229*a248dafdSChristopher Ferris 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
230*a248dafdSChristopher Ferris 					goto reset;
231*a248dafdSChristopher Ferris 				}
232*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing Core Config done V10...\n");
233*a248dafdSChristopher Ferris 				goto reset;
234*a248dafdSChristopher Ferris 			}
235*a248dafdSChristopher Ferris 
236*a248dafdSChristopher Ferris 			if (m_firmwareImage.GetGlobalParametersSize() && m_hasGlobalParameters) {
237*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing Global Parameters V10...\n");
238*a248dafdSChristopher Ferris 				rc = WriteGlobalParametersV7();
239*a248dafdSChristopher Ferris 				if (rc != UPDATE_SUCCESS) {
240*a248dafdSChristopher Ferris 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
241*a248dafdSChristopher Ferris 					goto reset;
242*a248dafdSChristopher Ferris 				}
243*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing Global Parameters done V10...\n");
244*a248dafdSChristopher Ferris 				goto reset;
245*a248dafdSChristopher Ferris 			}
246*a248dafdSChristopher Ferris 
247*a248dafdSChristopher Ferris 
248*a248dafdSChristopher Ferris 		} else {
249*a248dafdSChristopher Ferris 			if (!m_IsErased){
250*a248dafdSChristopher Ferris 				fprintf(stdout, "Erasing FW V7+...\n");
251*a248dafdSChristopher Ferris 				rc = EraseFirmwareV7();
252*a248dafdSChristopher Ferris 				if (rc != UPDATE_SUCCESS) {
253*a248dafdSChristopher Ferris 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
254*a248dafdSChristopher Ferris 					goto reset;
255*a248dafdSChristopher Ferris 				}
256*a248dafdSChristopher Ferris 				fprintf(stdout, "Erasing FW done V7+...\n");
257*a248dafdSChristopher Ferris 			}
258*a248dafdSChristopher Ferris 			if(m_bootloaderID[1] == 8){
259*a248dafdSChristopher Ferris 				if (m_firmwareImage.GetFlashConfigData()) {
260*a248dafdSChristopher Ferris 					fprintf(stdout, "Writing flash configuration V8...\n");
261*a248dafdSChristopher Ferris 					rc = WriteFlashConfigV7();
262*a248dafdSChristopher Ferris 					if (rc != UPDATE_SUCCESS) {
263*a248dafdSChristopher Ferris 						fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
264*a248dafdSChristopher Ferris 						goto reset;
265*a248dafdSChristopher Ferris 					}
266*a248dafdSChristopher Ferris 					fprintf(stdout, "Writing flash config done V8...\n");
267*a248dafdSChristopher Ferris 				}
268*a248dafdSChristopher Ferris 			}
269*a248dafdSChristopher Ferris 			if (m_firmwareImage.GetFirmwareData()) {
270*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing firmware V7+...\n");
271*a248dafdSChristopher Ferris 				rc = WriteFirmwareV7();
272*a248dafdSChristopher Ferris 				if (rc != UPDATE_SUCCESS) {
273*a248dafdSChristopher Ferris 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
274*a248dafdSChristopher Ferris 					goto reset;
275*a248dafdSChristopher Ferris 				}
276*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing firmware done V7+...\n");
277*a248dafdSChristopher Ferris 			}
278*a248dafdSChristopher Ferris 			if (m_firmwareImage.GetConfigData()) {
279*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing core configuration V7+...\n");
280*a248dafdSChristopher Ferris 				rc = WriteCoreConfigV7();
281*a248dafdSChristopher Ferris 				if (rc != UPDATE_SUCCESS) {
282*a248dafdSChristopher Ferris 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
283*a248dafdSChristopher Ferris 					goto reset;
284*a248dafdSChristopher Ferris 				}
285*a248dafdSChristopher Ferris 				fprintf(stdout, "Writing core config done V7+...\n");
286*a248dafdSChristopher Ferris 				goto reset;
287*a248dafdSChristopher Ferris 			}
288*a248dafdSChristopher Ferris 		}
289*a248dafdSChristopher Ferris 
290*a248dafdSChristopher Ferris 
291*a248dafdSChristopher Ferris 	} else {
292*a248dafdSChristopher Ferris 		rc = EnterFlashProgramming();
293*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS) {
294*a248dafdSChristopher Ferris 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
295*a248dafdSChristopher Ferris 			goto reset;
296*a248dafdSChristopher Ferris 		}
297*a248dafdSChristopher Ferris 	}
298*a248dafdSChristopher Ferris 
299*a248dafdSChristopher Ferris 	if (performLockdown && m_unlocked) {
300*a248dafdSChristopher Ferris 		if (m_firmwareImage.GetLockdownData()) {
301*a248dafdSChristopher Ferris 			fprintf(stdout, "Writing lockdown...\n");
302*a248dafdSChristopher Ferris 			clock_gettime(CLOCK_MONOTONIC, &start);
303*a248dafdSChristopher Ferris 			rc = WriteBlocks(m_firmwareImage.GetLockdownData(),
304*a248dafdSChristopher Ferris 					m_firmwareImage.GetLockdownSize() / 0x10,
305*a248dafdSChristopher Ferris 					RMI_F34_WRITE_LOCKDOWN_BLOCK);
306*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
307*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
308*a248dafdSChristopher Ferris 				goto reset;
309*a248dafdSChristopher Ferris 			}
310*a248dafdSChristopher Ferris 			clock_gettime(CLOCK_MONOTONIC, &end);
311*a248dafdSChristopher Ferris 			duration_us = diff_time(&start, &end);
312*a248dafdSChristopher Ferris 			fprintf(stdout, "Done writing lockdown, time: %lld us.\n", duration_us);
313*a248dafdSChristopher Ferris 		}
314*a248dafdSChristopher Ferris 
315*a248dafdSChristopher Ferris 		rc = EnterFlashProgramming();
316*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS) {
317*a248dafdSChristopher Ferris 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
318*a248dafdSChristopher Ferris 			goto reset;
319*a248dafdSChristopher Ferris 		}
320*a248dafdSChristopher Ferris 	}
321*a248dafdSChristopher Ferris 
322*a248dafdSChristopher Ferris 	rc = WriteBootloaderID();
323*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS) {
324*a248dafdSChristopher Ferris 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
325*a248dafdSChristopher Ferris 		goto reset;
326*a248dafdSChristopher Ferris 	}
327*a248dafdSChristopher Ferris 
328*a248dafdSChristopher Ferris 	fprintf(stdout, "Erasing FW...\n");
329*a248dafdSChristopher Ferris 	clock_gettime(CLOCK_MONOTONIC, &start);
330*a248dafdSChristopher Ferris 	rc = m_device.Write(m_f34StatusAddr, &eraseAll, 1);
331*a248dafdSChristopher Ferris 	if (rc != 1) {
332*a248dafdSChristopher Ferris 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(UPDATE_FAIL_ERASE_ALL));
333*a248dafdSChristopher Ferris 		rc = UPDATE_FAIL_ERASE_ALL;
334*a248dafdSChristopher Ferris 		goto reset;
335*a248dafdSChristopher Ferris 	}
336*a248dafdSChristopher Ferris 
337*a248dafdSChristopher Ferris 	rc = WaitForIdle(RMI_F34_ERASE_WAIT_MS);
338*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS) {
339*a248dafdSChristopher Ferris 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
340*a248dafdSChristopher Ferris 		goto reset;
341*a248dafdSChristopher Ferris 	}
342*a248dafdSChristopher Ferris 	clock_gettime(CLOCK_MONOTONIC, &end);
343*a248dafdSChristopher Ferris 	duration_us = diff_time(&start, &end);
344*a248dafdSChristopher Ferris 	fprintf(stdout, "Erase complete, time: %lld us.\n", duration_us);
345*a248dafdSChristopher Ferris 
346*a248dafdSChristopher Ferris 	if (m_firmwareImage.GetFirmwareData()) {
347*a248dafdSChristopher Ferris 		fprintf(stdout, "Writing firmware...\n");
348*a248dafdSChristopher Ferris 		clock_gettime(CLOCK_MONOTONIC, &start);
349*a248dafdSChristopher Ferris 		rc = WriteBlocks(m_firmwareImage.GetFirmwareData(), m_fwBlockCount,
350*a248dafdSChristopher Ferris 						RMI_F34_WRITE_FW_BLOCK);
351*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS) {
352*a248dafdSChristopher Ferris 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
353*a248dafdSChristopher Ferris 			goto reset;
354*a248dafdSChristopher Ferris 		}
355*a248dafdSChristopher Ferris 		clock_gettime(CLOCK_MONOTONIC, &end);
356*a248dafdSChristopher Ferris 		duration_us = diff_time(&start, &end);
357*a248dafdSChristopher Ferris 		fprintf(stdout, "Done writing FW, time: %lld us.\n", duration_us);
358*a248dafdSChristopher Ferris 	}
359*a248dafdSChristopher Ferris 
360*a248dafdSChristopher Ferris 	if (m_firmwareImage.GetConfigData()) {
361*a248dafdSChristopher Ferris 		fprintf(stdout, "Writing configuration...\n");
362*a248dafdSChristopher Ferris 		clock_gettime(CLOCK_MONOTONIC, &start);
363*a248dafdSChristopher Ferris 		rc = WriteBlocks(m_firmwareImage.GetConfigData(), m_configBlockCount,
364*a248dafdSChristopher Ferris 				RMI_F34_WRITE_CONFIG_BLOCK);
365*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS) {
366*a248dafdSChristopher Ferris 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
367*a248dafdSChristopher Ferris 			goto reset;
368*a248dafdSChristopher Ferris 		}
369*a248dafdSChristopher Ferris 		clock_gettime(CLOCK_MONOTONIC, &end);
370*a248dafdSChristopher Ferris 		duration_us = diff_time(&start, &end);
371*a248dafdSChristopher Ferris 		fprintf(stdout, "Done writing config, time: %lld us.\n", duration_us);
372*a248dafdSChristopher Ferris 	}
373*a248dafdSChristopher Ferris 
374*a248dafdSChristopher Ferris reset:
375*a248dafdSChristopher Ferris 	m_device.Reset();
376*a248dafdSChristopher Ferris rebind:
377*a248dafdSChristopher Ferris 	if (m_bootloaderID[1] >= 10) {
378*a248dafdSChristopher Ferris 		Sleep(5000);
379*a248dafdSChristopher Ferris 	}
380*a248dafdSChristopher Ferris 	m_device.RebindDriver();
381*a248dafdSChristopher Ferris 	if(!m_device.CheckABSEvent())
382*a248dafdSChristopher Ferris 	{
383*a248dafdSChristopher Ferris 		goto rebind;
384*a248dafdSChristopher Ferris 	}
385*a248dafdSChristopher Ferris 
386*a248dafdSChristopher Ferris 	// In order to print out new PR
387*a248dafdSChristopher Ferris 	rc = FindUpdateFunctions();
388*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS)
389*a248dafdSChristopher Ferris 		return rc;
390*a248dafdSChristopher Ferris 
391*a248dafdSChristopher Ferris 	rc = m_device.QueryBasicProperties();
392*a248dafdSChristopher Ferris 	if (rc < 0)
393*a248dafdSChristopher Ferris 		return UPDATE_FAIL_QUERY_BASIC_PROPERTIES;
394*a248dafdSChristopher Ferris 	fprintf(stdout, "Device Properties:\n");
395*a248dafdSChristopher Ferris 	m_device.PrintProperties();
396*a248dafdSChristopher Ferris 
397*a248dafdSChristopher Ferris 	return rc;
398*a248dafdSChristopher Ferris 
399*a248dafdSChristopher Ferris }
400*a248dafdSChristopher Ferris 
DisableNonessentialInterupts()401*a248dafdSChristopher Ferris int RMI4Update::DisableNonessentialInterupts()
402*a248dafdSChristopher Ferris {
403*a248dafdSChristopher Ferris 	int rc;
404*a248dafdSChristopher Ferris 	unsigned char interruptEnabeMask = m_f34.GetInterruptMask() | m_f01.GetInterruptMask();
405*a248dafdSChristopher Ferris 
406*a248dafdSChristopher Ferris 	rc = m_device.Write(m_f01.GetControlBase() + 1, &interruptEnabeMask, 1);
407*a248dafdSChristopher Ferris 	if (rc != 1)
408*a248dafdSChristopher Ferris 		return rc;
409*a248dafdSChristopher Ferris 
410*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
411*a248dafdSChristopher Ferris }
412*a248dafdSChristopher Ferris 
FindUpdateFunctions()413*a248dafdSChristopher Ferris int RMI4Update::FindUpdateFunctions()
414*a248dafdSChristopher Ferris {
415*a248dafdSChristopher Ferris 	if (0 > m_device.ScanPDT())
416*a248dafdSChristopher Ferris 		return UPDATE_FAIL_SCAN_PDT;
417*a248dafdSChristopher Ferris 
418*a248dafdSChristopher Ferris 	if (!m_device.GetFunction(m_f01, 0x01))
419*a248dafdSChristopher Ferris 		return UPDATE_FAIL_NO_FUNCTION_01;
420*a248dafdSChristopher Ferris 
421*a248dafdSChristopher Ferris 	if (!m_device.GetFunction(m_f34, 0x34))
422*a248dafdSChristopher Ferris 		return UPDATE_FAIL_NO_FUNCTION_34;
423*a248dafdSChristopher Ferris 
424*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
425*a248dafdSChristopher Ferris }
426*a248dafdSChristopher Ferris 
rmi4update_poll()427*a248dafdSChristopher Ferris int RMI4Update::rmi4update_poll()
428*a248dafdSChristopher Ferris {
429*a248dafdSChristopher Ferris 	unsigned char f34_status;
430*a248dafdSChristopher Ferris 	unsigned short dataAddr = m_f34.GetDataBase();
431*a248dafdSChristopher Ferris 	int rc;
432*a248dafdSChristopher Ferris 
433*a248dafdSChristopher Ferris 	rc = m_device.Read(dataAddr, &f34_status, sizeof(unsigned char));
434*a248dafdSChristopher Ferris 	if (rc != sizeof(unsigned char))
435*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
436*a248dafdSChristopher Ferris 
437*a248dafdSChristopher Ferris 	m_flashStatus = f34_status & 0x1F;
438*a248dafdSChristopher Ferris 	m_inBLmode = f34_status & 0x80;
439*a248dafdSChristopher Ferris 	if(!m_flashStatus)
440*a248dafdSChristopher Ferris 		rc = m_device.Read(dataAddr + 4, &m_flashCmd, sizeof(unsigned char));
441*a248dafdSChristopher Ferris 
442*a248dafdSChristopher Ferris 	return 0;
443*a248dafdSChristopher Ferris }
444*a248dafdSChristopher Ferris 
ReadFlashConfig()445*a248dafdSChristopher Ferris int RMI4Update::ReadFlashConfig()
446*a248dafdSChristopher Ferris {
447*a248dafdSChristopher Ferris 	int rc;
448*a248dafdSChristopher Ferris 	int transaction_count, remain_block;
449*a248dafdSChristopher Ferris 	unsigned char *flash_cfg;
450*a248dafdSChristopher Ferris 	int transfer_leng = 0;
451*a248dafdSChristopher Ferris 	int read_leng = 0;
452*a248dafdSChristopher Ferris 	int offset = 0;
453*a248dafdSChristopher Ferris 	unsigned char trans_leng_buf[2];
454*a248dafdSChristopher Ferris 	unsigned char cmd_buf[1];
455*a248dafdSChristopher Ferris 	unsigned char off[2] = {0, 0};
456*a248dafdSChristopher Ferris 	unsigned char partition_id = FLASH_CONFIG_PARTITION;
457*a248dafdSChristopher Ferris 	unsigned short dataAddr = m_f34.GetDataBase();
458*a248dafdSChristopher Ferris 	int i;
459*a248dafdSChristopher Ferris 	int retry = 0;
460*a248dafdSChristopher Ferris 	unsigned char *data_temp;
461*a248dafdSChristopher Ferris 	struct partition_tbl *partition_temp;
462*a248dafdSChristopher Ferris 
463*a248dafdSChristopher Ferris 	flash_cfg = (unsigned char *)malloc(m_blockSize * m_flashConfigLength);
464*a248dafdSChristopher Ferris 	memset(flash_cfg, 0, m_blockSize * m_flashConfigLength);
465*a248dafdSChristopher Ferris 	partition_temp = (partition_tbl *)malloc(sizeof(struct partition_tbl));
466*a248dafdSChristopher Ferris 	memset(partition_temp, 0, sizeof(struct partition_tbl));
467*a248dafdSChristopher Ferris 	/* calculate the count */
468*a248dafdSChristopher Ferris 	remain_block = (m_flashConfigLength % m_payloadLength);
469*a248dafdSChristopher Ferris 	transaction_count = (m_flashConfigLength / m_payloadLength);
470*a248dafdSChristopher Ferris 
471*a248dafdSChristopher Ferris 	if (remain_block > 0)
472*a248dafdSChristopher Ferris 		transaction_count++;
473*a248dafdSChristopher Ferris 
474*a248dafdSChristopher Ferris 	/* set partition id for bootloader 7 */
475*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
476*a248dafdSChristopher Ferris 	if (rc != sizeof(partition_id))
477*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
478*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
479*a248dafdSChristopher Ferris 	if (rc != sizeof(off))
480*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
481*a248dafdSChristopher Ferris 
482*a248dafdSChristopher Ferris 	for (i = 0; i < transaction_count; i++)
483*a248dafdSChristopher Ferris 	{
484*a248dafdSChristopher Ferris 		if ((i == (transaction_count -1)) && (remain_block > 0))
485*a248dafdSChristopher Ferris 			transfer_leng = remain_block;
486*a248dafdSChristopher Ferris 		else
487*a248dafdSChristopher Ferris 			transfer_leng = m_payloadLength;
488*a248dafdSChristopher Ferris 
489*a248dafdSChristopher Ferris 		// Set Transfer Length
490*a248dafdSChristopher Ferris 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
491*a248dafdSChristopher Ferris 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
492*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
493*a248dafdSChristopher Ferris 		if (rc != sizeof(trans_leng_buf))
494*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
495*a248dafdSChristopher Ferris 
496*a248dafdSChristopher Ferris 		// Set Command to Read
497*a248dafdSChristopher Ferris 		cmd_buf[0] = (unsigned char)CMD_V7_READ;
498*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
499*a248dafdSChristopher Ferris 		if (rc != sizeof(cmd_buf))
500*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
501*a248dafdSChristopher Ferris 
502*a248dafdSChristopher Ferris 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
503*a248dafdSChristopher Ferris 			// Sleep 20 ms and wait for attention for touchpad only.
504*a248dafdSChristopher Ferris 			Sleep(20);
505*a248dafdSChristopher Ferris 			rc = WaitForIdle(RMI_F34_PARTITION_READ_WAIT_MS, false);
506*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
507*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
508*a248dafdSChristopher Ferris 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
509*a248dafdSChristopher Ferris 			}
510*a248dafdSChristopher Ferris 			fprintf(stdout, "Got attention\n");
511*a248dafdSChristopher Ferris 		}
512*a248dafdSChristopher Ferris 
513*a248dafdSChristopher Ferris 		//Wait for completion
514*a248dafdSChristopher Ferris 		do {
515*a248dafdSChristopher Ferris 			Sleep(20);
516*a248dafdSChristopher Ferris 			rmi4update_poll();
517*a248dafdSChristopher Ferris 			if (m_flashStatus == SUCCESS){
518*a248dafdSChristopher Ferris 				break;
519*a248dafdSChristopher Ferris 			}
520*a248dafdSChristopher Ferris 			retry++;
521*a248dafdSChristopher Ferris 		} while(retry < 20);
522*a248dafdSChristopher Ferris 
523*a248dafdSChristopher Ferris 		read_leng = transfer_leng * m_blockSize;
524*a248dafdSChristopher Ferris 		data_temp = (unsigned char *) malloc(sizeof(char) * read_leng);
525*a248dafdSChristopher Ferris 		rc = m_device.Read(dataAddr + 5, data_temp, sizeof(char) * read_leng);
526*a248dafdSChristopher Ferris 		if (rc != ((ssize_t)sizeof(char) * read_leng))
527*a248dafdSChristopher Ferris 			return UPDATE_FAIL_READ_F34_QUERIES;
528*a248dafdSChristopher Ferris 
529*a248dafdSChristopher Ferris 		memcpy(flash_cfg + offset, data_temp, sizeof(char) * read_leng);
530*a248dafdSChristopher Ferris 		offset += read_leng;
531*a248dafdSChristopher Ferris 		free(data_temp);
532*a248dafdSChristopher Ferris 	}
533*a248dafdSChristopher Ferris 
534*a248dafdSChristopher Ferris 	// Initialize as NULL here to avoid segmentation fault.
535*a248dafdSChristopher Ferris 	m_partitionConfig = NULL;
536*a248dafdSChristopher Ferris 	m_partitionCore = NULL;
537*a248dafdSChristopher Ferris 	m_partitionGuest = NULL;
538*a248dafdSChristopher Ferris 
539*a248dafdSChristopher Ferris 	/* parse the config length */
540*a248dafdSChristopher Ferris 	for (i = 2; i < m_blockSize * m_flashConfigLength; i = i + 8)
541*a248dafdSChristopher Ferris 	{
542*a248dafdSChristopher Ferris 		memcpy(partition_temp->data ,flash_cfg + i, sizeof(struct partition_tbl));
543*a248dafdSChristopher Ferris 		if (partition_temp->partition_id == CORE_CONFIG_PARTITION)
544*a248dafdSChristopher Ferris 		{
545*a248dafdSChristopher Ferris 			m_partitionConfig = (partition_tbl *) malloc(sizeof(struct partition_tbl));
546*a248dafdSChristopher Ferris 			memcpy(m_partitionConfig ,partition_temp, sizeof(struct partition_tbl));
547*a248dafdSChristopher Ferris 			memset(partition_temp, 0, sizeof(struct partition_tbl));
548*a248dafdSChristopher Ferris 			fprintf(stdout, "CORE_CONFIG_PARTITION is found\n");
549*a248dafdSChristopher Ferris 		}
550*a248dafdSChristopher Ferris 		else if (partition_temp->partition_id == CORE_CODE_PARTITION)
551*a248dafdSChristopher Ferris 		{
552*a248dafdSChristopher Ferris 			m_partitionCore = (partition_tbl *) malloc(sizeof(struct partition_tbl));
553*a248dafdSChristopher Ferris 			memcpy(m_partitionCore ,partition_temp, sizeof(struct partition_tbl));
554*a248dafdSChristopher Ferris 			memset(partition_temp, 0, sizeof(struct partition_tbl));
555*a248dafdSChristopher Ferris 			fprintf(stdout, "CORE_CODE_PARTITION is found\n");
556*a248dafdSChristopher Ferris 		}
557*a248dafdSChristopher Ferris 		else if (partition_temp->partition_id == GUEST_CODE_PARTITION)
558*a248dafdSChristopher Ferris 		{
559*a248dafdSChristopher Ferris 			m_partitionGuest = (partition_tbl *) malloc(sizeof(struct partition_tbl));
560*a248dafdSChristopher Ferris 			memcpy(m_partitionGuest ,partition_temp, sizeof(struct partition_tbl));
561*a248dafdSChristopher Ferris 			memset(partition_temp, 0, sizeof(struct partition_tbl));
562*a248dafdSChristopher Ferris 			fprintf(stdout, "GUEST_CODE_PARTITION is found\n");
563*a248dafdSChristopher Ferris 		}
564*a248dafdSChristopher Ferris 		else if (partition_temp->partition_id == NONE_PARTITION)
565*a248dafdSChristopher Ferris 			break;
566*a248dafdSChristopher Ferris 	}
567*a248dafdSChristopher Ferris 
568*a248dafdSChristopher Ferris 	if (flash_cfg)
569*a248dafdSChristopher Ferris 		free(flash_cfg);
570*a248dafdSChristopher Ferris 
571*a248dafdSChristopher Ferris 	if (partition_temp)
572*a248dafdSChristopher Ferris 		free(partition_temp);
573*a248dafdSChristopher Ferris 
574*a248dafdSChristopher Ferris 	m_fwBlockCount = m_partitionCore ? m_partitionCore->partition_len : 0;
575*a248dafdSChristopher Ferris 	m_configBlockCount = m_partitionConfig ? m_partitionConfig->partition_len : 0;
576*a248dafdSChristopher Ferris 	m_guestBlockCount = m_partitionGuest ? m_partitionGuest->partition_len : 0;
577*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 fw blocks:     %d\n", m_fwBlockCount);
578*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 config blocks: %d\n", m_configBlockCount);
579*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 guest blocks:     %d\n", m_guestBlockCount);
580*a248dafdSChristopher Ferris 	fprintf(stdout, "\n");
581*a248dafdSChristopher Ferris 
582*a248dafdSChristopher Ferris 	m_guestData = (unsigned char *) malloc(m_guestBlockCount * m_blockSize);
583*a248dafdSChristopher Ferris 	memset(m_guestData, 0, m_guestBlockCount * m_blockSize);
584*a248dafdSChristopher Ferris 	memset(m_guestData + m_guestBlockCount * m_blockSize -4, 0, 4);
585*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
586*a248dafdSChristopher Ferris }
587*a248dafdSChristopher Ferris 
ReadF34QueriesV7()588*a248dafdSChristopher Ferris int RMI4Update::ReadF34QueriesV7()
589*a248dafdSChristopher Ferris {
590*a248dafdSChristopher Ferris 	int rc;
591*a248dafdSChristopher Ferris 	struct f34_v7_query_0 query_0;
592*a248dafdSChristopher Ferris 	struct f34_v7_query_1_7 query_1_7;
593*a248dafdSChristopher Ferris 	unsigned char idStr[3];
594*a248dafdSChristopher Ferris 	unsigned short queryAddr = m_f34.GetQueryBase();
595*a248dafdSChristopher Ferris 	unsigned char offset;
596*a248dafdSChristopher Ferris 
597*a248dafdSChristopher Ferris 	rc = m_device.Read(queryAddr, query_0.data, sizeof(query_0.data));
598*a248dafdSChristopher Ferris 	if (rc != sizeof(query_0.data))
599*a248dafdSChristopher Ferris 		return UPDATE_FAIL_READ_BOOTLOADER_ID;
600*a248dafdSChristopher Ferris 
601*a248dafdSChristopher Ferris 	offset = query_0.subpacket_1_size + 1;
602*a248dafdSChristopher Ferris 	rc = m_device.Read(queryAddr + offset, query_1_7.data, sizeof(query_1_7.data));
603*a248dafdSChristopher Ferris 	if (rc != sizeof(query_1_7.data))
604*a248dafdSChristopher Ferris 		return UPDATE_FAIL_READ_BOOTLOADER_ID;
605*a248dafdSChristopher Ferris 
606*a248dafdSChristopher Ferris 	m_bootloaderID[0] = query_1_7.bl_minor_revision;
607*a248dafdSChristopher Ferris 	m_bootloaderID[1] = query_1_7.bl_major_revision;
608*a248dafdSChristopher Ferris 	m_hasConfigID = query_0.has_config_id;
609*a248dafdSChristopher Ferris 	m_blockSize = query_1_7.block_size_15_8 << 8 |
610*a248dafdSChristopher Ferris 			query_1_7.block_size_7_0;
611*a248dafdSChristopher Ferris 	m_flashConfigLength = query_1_7.flash_config_length_15_8 << 8 |
612*a248dafdSChristopher Ferris 				query_1_7.flash_config_length_7_0;
613*a248dafdSChristopher Ferris 	m_payloadLength = query_1_7.payload_length_15_8 << 8 |
614*a248dafdSChristopher Ferris 			query_1_7.payload_length_7_0;
615*a248dafdSChristopher Ferris 	m_buildID = query_1_7.bl_fw_id_7_0 |
616*a248dafdSChristopher Ferris 			query_1_7.bl_fw_id_15_8 << 8 |
617*a248dafdSChristopher Ferris 			query_1_7.bl_fw_id_23_16 << 16 |
618*a248dafdSChristopher Ferris 			query_1_7.bl_fw_id_31_24 << 24;
619*a248dafdSChristopher Ferris 
620*a248dafdSChristopher Ferris 	idStr[0] = m_bootloaderID[0];
621*a248dafdSChristopher Ferris 	idStr[1] = m_bootloaderID[1];
622*a248dafdSChristopher Ferris 	idStr[2] = 0;
623*a248dafdSChristopher Ferris 
624*a248dafdSChristopher Ferris 	m_hasCoreCode = query_1_7.has_core_code;
625*a248dafdSChristopher Ferris 	m_hasCoreConfig = query_1_7.has_core_config;
626*a248dafdSChristopher Ferris 	m_hasFlashConfig = query_1_7.has_flash_config;
627*a248dafdSChristopher Ferris 	m_hasFLD = query_1_7.has_fld;
628*a248dafdSChristopher Ferris 	m_hasGlobalParameters = query_1_7.has_global_parameters;
629*a248dafdSChristopher Ferris 
630*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 has CoreCode: %d\n", m_hasCoreCode);
631*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 has CoreConfig: %d\n", m_hasCoreConfig);
632*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 has FlashConfig: %d\n", m_hasFlashConfig);
633*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 has FLD: %d\n", m_hasFLD);
634*a248dafdSChristopher Ferris 
635*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 bootloader id: %s (%#04x %#04x)\n", idStr, m_bootloaderID[0],
636*a248dafdSChristopher Ferris 		m_bootloaderID[1]);
637*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 has config id: %d\n", m_hasConfigID);
638*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 unlocked:      %d\n", m_unlocked);
639*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 block size:    %d\n", m_blockSize);
640*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 flash cfg leng:%d\n", m_flashConfigLength);
641*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 payload length:%d\n", m_payloadLength);
642*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 build id:      %lu\n", m_buildID);
643*a248dafdSChristopher Ferris 
644*a248dafdSChristopher Ferris 	if ((m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) && (m_bootloaderID[1] == 10)) {
645*a248dafdSChristopher Ferris 		// FW size would be different from the one in image file in bootloader v10,
646*a248dafdSChristopher Ferris 		// we use size parsing in image file instead.
647*a248dafdSChristopher Ferris 		return UPDATE_SUCCESS;
648*a248dafdSChristopher Ferris 	} else
649*a248dafdSChristopher Ferris 		return ReadFlashConfig();
650*a248dafdSChristopher Ferris }
651*a248dafdSChristopher Ferris 
ReadF34Queries()652*a248dafdSChristopher Ferris int RMI4Update::ReadF34Queries()
653*a248dafdSChristopher Ferris {
654*a248dafdSChristopher Ferris 	int rc;
655*a248dafdSChristopher Ferris 	unsigned char idStr[3];
656*a248dafdSChristopher Ferris 	unsigned char buf[8];
657*a248dafdSChristopher Ferris 	unsigned short queryAddr = m_f34.GetQueryBase();
658*a248dafdSChristopher Ferris 	unsigned short f34Version = m_f34.GetFunctionVersion();
659*a248dafdSChristopher Ferris 	unsigned short querySize;
660*a248dafdSChristopher Ferris 
661*a248dafdSChristopher Ferris 	if (f34Version == 0x2)
662*a248dafdSChristopher Ferris 		return ReadF34QueriesV7();
663*a248dafdSChristopher Ferris 	else if (f34Version == 0x1)
664*a248dafdSChristopher Ferris 		querySize = 8;
665*a248dafdSChristopher Ferris 	else
666*a248dafdSChristopher Ferris 		querySize = 2;
667*a248dafdSChristopher Ferris 
668*a248dafdSChristopher Ferris 	rc = m_device.Read(queryAddr, m_bootloaderID, RMI_BOOTLOADER_ID_SIZE);
669*a248dafdSChristopher Ferris 	if (rc != RMI_BOOTLOADER_ID_SIZE)
670*a248dafdSChristopher Ferris 		return UPDATE_FAIL_READ_BOOTLOADER_ID;
671*a248dafdSChristopher Ferris 
672*a248dafdSChristopher Ferris 	if (f34Version == 0x1)
673*a248dafdSChristopher Ferris 		++queryAddr;
674*a248dafdSChristopher Ferris 	else
675*a248dafdSChristopher Ferris 		queryAddr += querySize;
676*a248dafdSChristopher Ferris 
677*a248dafdSChristopher Ferris 	if (f34Version == 0x1) {
678*a248dafdSChristopher Ferris 		rc = m_device.Read(queryAddr, buf, 1);
679*a248dafdSChristopher Ferris 		if (rc != 1)
680*a248dafdSChristopher Ferris 			return UPDATE_FAIL_READ_F34_QUERIES;
681*a248dafdSChristopher Ferris 
682*a248dafdSChristopher Ferris 		m_hasNewRegmap = buf[0] & RMI_F34_HAS_NEW_REG_MAP;
683*a248dafdSChristopher Ferris 		m_unlocked = buf[0] & RMI_F34_IS_UNLOCKED;;
684*a248dafdSChristopher Ferris 		m_hasConfigID = buf[0] & RMI_F34_HAS_CONFIG_ID;
685*a248dafdSChristopher Ferris 
686*a248dafdSChristopher Ferris 		++queryAddr;
687*a248dafdSChristopher Ferris 
688*a248dafdSChristopher Ferris 		rc = m_device.Read(queryAddr, buf, 2);
689*a248dafdSChristopher Ferris 		if (rc != 2)
690*a248dafdSChristopher Ferris 			return UPDATE_FAIL_READ_F34_QUERIES;
691*a248dafdSChristopher Ferris 
692*a248dafdSChristopher Ferris 		m_blockSize = extract_short(buf + RMI_F34_BLOCK_SIZE_V1_OFFSET);
693*a248dafdSChristopher Ferris 
694*a248dafdSChristopher Ferris 		++queryAddr;
695*a248dafdSChristopher Ferris 
696*a248dafdSChristopher Ferris 		rc = m_device.Read(queryAddr, buf, 8);
697*a248dafdSChristopher Ferris 		if (rc != 8)
698*a248dafdSChristopher Ferris 			return UPDATE_FAIL_READ_F34_QUERIES;
699*a248dafdSChristopher Ferris 
700*a248dafdSChristopher Ferris 		m_fwBlockCount = extract_short(buf + RMI_F34_FW_BLOCKS_V1_OFFSET);
701*a248dafdSChristopher Ferris 		m_configBlockCount = extract_short(buf + RMI_F34_CONFIG_BLOCKS_V1_OFFSET);
702*a248dafdSChristopher Ferris 	} else {
703*a248dafdSChristopher Ferris 		rc = m_device.Read(queryAddr, buf, RMI_F34_QUERY_SIZE);
704*a248dafdSChristopher Ferris 		if (rc != RMI_F34_QUERY_SIZE)
705*a248dafdSChristopher Ferris 			return UPDATE_FAIL_READ_F34_QUERIES;
706*a248dafdSChristopher Ferris 
707*a248dafdSChristopher Ferris 		m_hasNewRegmap = buf[0] & RMI_F34_HAS_NEW_REG_MAP;
708*a248dafdSChristopher Ferris 		m_unlocked = buf[0] & RMI_F34_IS_UNLOCKED;;
709*a248dafdSChristopher Ferris 		m_hasConfigID = buf[0] & RMI_F34_HAS_CONFIG_ID;
710*a248dafdSChristopher Ferris 		m_blockSize = extract_short(buf + RMI_F34_BLOCK_SIZE_OFFSET);
711*a248dafdSChristopher Ferris 		m_fwBlockCount = extract_short(buf + RMI_F34_FW_BLOCKS_OFFSET);
712*a248dafdSChristopher Ferris 		m_configBlockCount = extract_short(buf + RMI_F34_CONFIG_BLOCKS_OFFSET);
713*a248dafdSChristopher Ferris 	}
714*a248dafdSChristopher Ferris 
715*a248dafdSChristopher Ferris 	idStr[0] = m_bootloaderID[0];
716*a248dafdSChristopher Ferris 	idStr[1] = m_bootloaderID[1];
717*a248dafdSChristopher Ferris 	idStr[2] = 0;
718*a248dafdSChristopher Ferris 
719*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 bootloader id: %s (%#04x %#04x)\n", idStr, m_bootloaderID[0],
720*a248dafdSChristopher Ferris 		m_bootloaderID[1]);
721*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 has config id: %d\n", m_hasConfigID);
722*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 unlocked:      %d\n", m_unlocked);
723*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 new reg map:   %d\n", m_hasNewRegmap);
724*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 block size:    %d\n", m_blockSize);
725*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 fw blocks:     %d\n", m_fwBlockCount);
726*a248dafdSChristopher Ferris 	fprintf(stdout, "F34 config blocks: %d\n", m_configBlockCount);
727*a248dafdSChristopher Ferris 	fprintf(stdout, "\n");
728*a248dafdSChristopher Ferris 
729*a248dafdSChristopher Ferris 	if (f34Version == 0x1)
730*a248dafdSChristopher Ferris 		m_f34StatusAddr = m_f34.GetDataBase() + 2;
731*a248dafdSChristopher Ferris 	else
732*a248dafdSChristopher Ferris 		m_f34StatusAddr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_OFFSET + m_blockSize;
733*a248dafdSChristopher Ferris 
734*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
735*a248dafdSChristopher Ferris }
736*a248dafdSChristopher Ferris 
ReadF34Controls()737*a248dafdSChristopher Ferris int RMI4Update::ReadF34Controls()
738*a248dafdSChristopher Ferris {
739*a248dafdSChristopher Ferris 	int rc;
740*a248dafdSChristopher Ferris 	unsigned char buf[2];
741*a248dafdSChristopher Ferris 
742*a248dafdSChristopher Ferris 	if (m_f34.GetFunctionVersion() == 0x1) {
743*a248dafdSChristopher Ferris 		rc = m_device.Read(m_f34StatusAddr, buf, 2);
744*a248dafdSChristopher Ferris 		if (rc != 2)
745*a248dafdSChristopher Ferris 			return UPDATE_FAIL_READ_F34_CONTROLS;
746*a248dafdSChristopher Ferris 
747*a248dafdSChristopher Ferris 		m_f34Command = buf[0] & RMI_F34_COMMAND_V1_MASK;
748*a248dafdSChristopher Ferris 		m_f34Status = buf[1] & RMI_F34_STATUS_V1_MASK;
749*a248dafdSChristopher Ferris 		m_programEnabled = !!(buf[1] & RMI_F34_ENABLED_MASK);
750*a248dafdSChristopher Ferris 
751*a248dafdSChristopher Ferris 	} else {
752*a248dafdSChristopher Ferris 		rc = m_device.Read(m_f34StatusAddr, buf, 1);
753*a248dafdSChristopher Ferris 		if (rc != 1)
754*a248dafdSChristopher Ferris 			return UPDATE_FAIL_READ_F34_CONTROLS;
755*a248dafdSChristopher Ferris 
756*a248dafdSChristopher Ferris 		m_f34Command = buf[0] & RMI_F34_COMMAND_MASK;
757*a248dafdSChristopher Ferris 		m_f34Status = (buf[0] >> RMI_F34_STATUS_SHIFT) & RMI_F34_STATUS_MASK;
758*a248dafdSChristopher Ferris 		m_programEnabled = !!(buf[0] & RMI_F34_ENABLED_MASK);
759*a248dafdSChristopher Ferris 	}
760*a248dafdSChristopher Ferris 
761*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
762*a248dafdSChristopher Ferris }
763*a248dafdSChristopher Ferris 
WriteBootloaderID()764*a248dafdSChristopher Ferris int RMI4Update::WriteBootloaderID()
765*a248dafdSChristopher Ferris {
766*a248dafdSChristopher Ferris 	int rc;
767*a248dafdSChristopher Ferris 	int blockDataOffset = RMI_F34_BLOCK_DATA_OFFSET;
768*a248dafdSChristopher Ferris 
769*a248dafdSChristopher Ferris 	if (m_f34.GetFunctionVersion() == 0x1)
770*a248dafdSChristopher Ferris 		blockDataOffset = RMI_F34_BLOCK_DATA_V1_OFFSET;
771*a248dafdSChristopher Ferris 
772*a248dafdSChristopher Ferris 	rc = m_device.Write(m_f34.GetDataBase() + blockDataOffset,
773*a248dafdSChristopher Ferris 				m_bootloaderID, RMI_BOOTLOADER_ID_SIZE);
774*a248dafdSChristopher Ferris 	if (rc != RMI_BOOTLOADER_ID_SIZE)
775*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_BOOTLOADER_ID;
776*a248dafdSChristopher Ferris 
777*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
778*a248dafdSChristopher Ferris }
779*a248dafdSChristopher Ferris 
WriteFirmwareV7()780*a248dafdSChristopher Ferris int RMI4Update::WriteFirmwareV7()
781*a248dafdSChristopher Ferris {
782*a248dafdSChristopher Ferris 	int transaction_count, remain_block;
783*a248dafdSChristopher Ferris 	int transfer_leng = 0;
784*a248dafdSChristopher Ferris 	int offset = 0;
785*a248dafdSChristopher Ferris 	unsigned char trans_leng_buf[2];
786*a248dafdSChristopher Ferris 	unsigned char cmd_buf[1];
787*a248dafdSChristopher Ferris 	unsigned char off[2] = {0, 0};
788*a248dafdSChristopher Ferris 	unsigned char partition_id;
789*a248dafdSChristopher Ferris 	int i;
790*a248dafdSChristopher Ferris 	int retry = 0;
791*a248dafdSChristopher Ferris 	unsigned char *data_temp;
792*a248dafdSChristopher Ferris 	int rc;
793*a248dafdSChristopher Ferris 	unsigned short left_bytes;
794*a248dafdSChristopher Ferris 	unsigned short write_size;
795*a248dafdSChristopher Ferris 	unsigned short max_write_size;
796*a248dafdSChristopher Ferris 	unsigned short dataAddr = m_f34.GetDataBase();
797*a248dafdSChristopher Ferris 
798*a248dafdSChristopher Ferris 	if (m_bootloaderID[1] == 10) {
799*a248dafdSChristopher Ferris 		m_fwBlockCount = m_firmwareImage.GetFirmwareSize() / m_blockSize;
800*a248dafdSChristopher Ferris 	}
801*a248dafdSChristopher Ferris 
802*a248dafdSChristopher Ferris 	/* calculate the count */
803*a248dafdSChristopher Ferris 	partition_id = CORE_CODE_PARTITION;
804*a248dafdSChristopher Ferris 
805*a248dafdSChristopher Ferris 	remain_block = (m_fwBlockCount % m_payloadLength);
806*a248dafdSChristopher Ferris 	transaction_count = (m_fwBlockCount / m_payloadLength);
807*a248dafdSChristopher Ferris 
808*a248dafdSChristopher Ferris 	if (remain_block > 0)
809*a248dafdSChristopher Ferris 		transaction_count++;
810*a248dafdSChristopher Ferris 
811*a248dafdSChristopher Ferris 	/* set partition id for bootloader 7 */
812*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
813*a248dafdSChristopher Ferris 	if (rc != sizeof(partition_id))
814*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
815*a248dafdSChristopher Ferris 
816*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
817*a248dafdSChristopher Ferris 	if (rc != sizeof(off))
818*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
819*a248dafdSChristopher Ferris 
820*a248dafdSChristopher Ferris 	for (i = 0; i < transaction_count; i++)
821*a248dafdSChristopher Ferris 	{
822*a248dafdSChristopher Ferris 		if ((i == (transaction_count -1)) && (remain_block > 0))
823*a248dafdSChristopher Ferris 			transfer_leng = remain_block;
824*a248dafdSChristopher Ferris 		else
825*a248dafdSChristopher Ferris 			transfer_leng = m_payloadLength;
826*a248dafdSChristopher Ferris 
827*a248dafdSChristopher Ferris 		// Set Transfer Length
828*a248dafdSChristopher Ferris 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
829*a248dafdSChristopher Ferris 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
830*a248dafdSChristopher Ferris 
831*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
832*a248dafdSChristopher Ferris 		if (rc != sizeof(trans_leng_buf))
833*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
834*a248dafdSChristopher Ferris 
835*a248dafdSChristopher Ferris 		// Set Command to Write
836*a248dafdSChristopher Ferris 		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
837*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
838*a248dafdSChristopher Ferris 		if (rc != sizeof(cmd_buf))
839*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
840*a248dafdSChristopher Ferris 
841*a248dafdSChristopher Ferris 		max_write_size = 16;
842*a248dafdSChristopher Ferris 		if (max_write_size >= transfer_leng * m_blockSize)
843*a248dafdSChristopher Ferris 			max_write_size = transfer_leng * m_blockSize;
844*a248dafdSChristopher Ferris 		else if (max_write_size > m_blockSize)
845*a248dafdSChristopher Ferris 			max_write_size -= max_write_size % m_blockSize;
846*a248dafdSChristopher Ferris 		else
847*a248dafdSChristopher Ferris 			max_write_size = m_blockSize;
848*a248dafdSChristopher Ferris 
849*a248dafdSChristopher Ferris 		left_bytes = transfer_leng * m_blockSize;
850*a248dafdSChristopher Ferris 		do {
851*a248dafdSChristopher Ferris 			if (left_bytes / max_write_size)
852*a248dafdSChristopher Ferris 				write_size = max_write_size;
853*a248dafdSChristopher Ferris 			else
854*a248dafdSChristopher Ferris 				write_size = left_bytes;
855*a248dafdSChristopher Ferris 
856*a248dafdSChristopher Ferris 			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
857*a248dafdSChristopher Ferris 			memcpy(data_temp, m_firmwareImage.GetFirmwareData() + offset, sizeof(char) * write_size);
858*a248dafdSChristopher Ferris 			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
859*a248dafdSChristopher Ferris 			if (rc != ((ssize_t)sizeof(char) * write_size)) {
860*a248dafdSChristopher Ferris 				fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
861*a248dafdSChristopher Ferris 				return UPDATE_FAIL_READ_F34_QUERIES;
862*a248dafdSChristopher Ferris 			}
863*a248dafdSChristopher Ferris 
864*a248dafdSChristopher Ferris 			offset += write_size;
865*a248dafdSChristopher Ferris 			left_bytes -= write_size;
866*a248dafdSChristopher Ferris 			free(data_temp);
867*a248dafdSChristopher Ferris 		} while (left_bytes);
868*a248dafdSChristopher Ferris 
869*a248dafdSChristopher Ferris 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
870*a248dafdSChristopher Ferris 			// Sleep 100 ms and wait for attention for touchpad only.
871*a248dafdSChristopher Ferris 			Sleep(100);
872*a248dafdSChristopher Ferris 			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
873*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
874*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
875*a248dafdSChristopher Ferris 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
876*a248dafdSChristopher Ferris 			}
877*a248dafdSChristopher Ferris 		}
878*a248dafdSChristopher Ferris 
879*a248dafdSChristopher Ferris 
880*a248dafdSChristopher Ferris 		//Wait for completion
881*a248dafdSChristopher Ferris 		do {
882*a248dafdSChristopher Ferris 			Sleep(20);
883*a248dafdSChristopher Ferris 			rmi4update_poll();
884*a248dafdSChristopher Ferris 			if (m_flashStatus == SUCCESS){
885*a248dafdSChristopher Ferris 				break;
886*a248dafdSChristopher Ferris 
887*a248dafdSChristopher Ferris 			}
888*a248dafdSChristopher Ferris 			retry++;
889*a248dafdSChristopher Ferris 		} while(retry < 20);
890*a248dafdSChristopher Ferris 
891*a248dafdSChristopher Ferris 		if (m_flashStatus != SUCCESS) {
892*a248dafdSChristopher Ferris 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
893*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
894*a248dafdSChristopher Ferris 		}
895*a248dafdSChristopher Ferris 
896*a248dafdSChristopher Ferris 	}
897*a248dafdSChristopher Ferris 
898*a248dafdSChristopher Ferris 	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
899*a248dafdSChristopher Ferris 		if (m_firmwareImage.GetSignatureInfo()[BLv7_CORE_CODE].bExisted) {
900*a248dafdSChristopher Ferris 			// Write signature.
901*a248dafdSChristopher Ferris 			rc = WriteSignatureV7(BLv7_CORE_CODE, m_firmwareImage.GetFirmwareData(), offset);
902*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
903*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
904*a248dafdSChristopher Ferris 				return rc;
905*a248dafdSChristopher Ferris 			}
906*a248dafdSChristopher Ferris 		}
907*a248dafdSChristopher Ferris 	}
908*a248dafdSChristopher Ferris 
909*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
910*a248dafdSChristopher Ferris }
911*a248dafdSChristopher Ferris 
WriteCoreConfigV7()912*a248dafdSChristopher Ferris int RMI4Update::WriteCoreConfigV7()
913*a248dafdSChristopher Ferris {
914*a248dafdSChristopher Ferris 	int transaction_count, remain_block;
915*a248dafdSChristopher Ferris 	int transfer_leng = 0;
916*a248dafdSChristopher Ferris 	int offset = 0;
917*a248dafdSChristopher Ferris 	unsigned char trans_leng_buf[2];
918*a248dafdSChristopher Ferris 	unsigned char cmd_buf[1];
919*a248dafdSChristopher Ferris 	unsigned char off[2] = {0, 0};
920*a248dafdSChristopher Ferris 	unsigned char partition_id;
921*a248dafdSChristopher Ferris 	unsigned short dataAddr = m_f34.GetDataBase();
922*a248dafdSChristopher Ferris 	unsigned short left_bytes;
923*a248dafdSChristopher Ferris 	unsigned short write_size;
924*a248dafdSChristopher Ferris 	unsigned short max_write_size;
925*a248dafdSChristopher Ferris 	int rc;
926*a248dafdSChristopher Ferris 	int i;
927*a248dafdSChristopher Ferris 	int retry = 0;
928*a248dafdSChristopher Ferris 	unsigned char *data_temp;
929*a248dafdSChristopher Ferris 	if (m_bootloaderID[1] == 10) {
930*a248dafdSChristopher Ferris 		m_configBlockCount = m_firmwareImage.GetConfigSize() / m_blockSize;
931*a248dafdSChristopher Ferris 	}
932*a248dafdSChristopher Ferris 
933*a248dafdSChristopher Ferris 	/* calculate the count */
934*a248dafdSChristopher Ferris 	partition_id = CORE_CONFIG_PARTITION;
935*a248dafdSChristopher Ferris 
936*a248dafdSChristopher Ferris 	remain_block = (m_configBlockCount % m_payloadLength);
937*a248dafdSChristopher Ferris 	transaction_count = (m_configBlockCount / m_payloadLength);
938*a248dafdSChristopher Ferris 
939*a248dafdSChristopher Ferris 	if (remain_block > 0)
940*a248dafdSChristopher Ferris 		transaction_count++;
941*a248dafdSChristopher Ferris 
942*a248dafdSChristopher Ferris 	/* set partition id for bootloader 7 */
943*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
944*a248dafdSChristopher Ferris 	if (rc != sizeof(partition_id))
945*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
946*a248dafdSChristopher Ferris 
947*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
948*a248dafdSChristopher Ferris 	if (rc != sizeof(off))
949*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
950*a248dafdSChristopher Ferris 
951*a248dafdSChristopher Ferris 	for (i = 0; i < transaction_count; i++)
952*a248dafdSChristopher Ferris 	{
953*a248dafdSChristopher Ferris 		if ((i == (transaction_count -1)) && (remain_block > 0))
954*a248dafdSChristopher Ferris 			transfer_leng = remain_block;
955*a248dafdSChristopher Ferris 		else
956*a248dafdSChristopher Ferris 			transfer_leng = m_payloadLength;
957*a248dafdSChristopher Ferris 
958*a248dafdSChristopher Ferris 		// Set Transfer Length
959*a248dafdSChristopher Ferris 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
960*a248dafdSChristopher Ferris 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
961*a248dafdSChristopher Ferris 
962*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
963*a248dafdSChristopher Ferris 		if (rc != sizeof(trans_leng_buf))
964*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
965*a248dafdSChristopher Ferris 
966*a248dafdSChristopher Ferris 		// Set Command to Write
967*a248dafdSChristopher Ferris 		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
968*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
969*a248dafdSChristopher Ferris 		if (rc != sizeof(cmd_buf))
970*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
971*a248dafdSChristopher Ferris 
972*a248dafdSChristopher Ferris 		max_write_size = 16;
973*a248dafdSChristopher Ferris 		if (max_write_size >= transfer_leng * m_blockSize)
974*a248dafdSChristopher Ferris 			max_write_size = transfer_leng * m_blockSize;
975*a248dafdSChristopher Ferris 		else if (max_write_size > m_blockSize)
976*a248dafdSChristopher Ferris 			max_write_size -= max_write_size % m_blockSize;
977*a248dafdSChristopher Ferris 		else
978*a248dafdSChristopher Ferris 			max_write_size = m_blockSize;
979*a248dafdSChristopher Ferris 
980*a248dafdSChristopher Ferris 		left_bytes = transfer_leng * m_blockSize;
981*a248dafdSChristopher Ferris 
982*a248dafdSChristopher Ferris 		do {
983*a248dafdSChristopher Ferris 			if (left_bytes / max_write_size)
984*a248dafdSChristopher Ferris 				write_size = max_write_size;
985*a248dafdSChristopher Ferris 			else
986*a248dafdSChristopher Ferris 				write_size = left_bytes;
987*a248dafdSChristopher Ferris 
988*a248dafdSChristopher Ferris 			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
989*a248dafdSChristopher Ferris 			memcpy(data_temp, m_firmwareImage.GetConfigData() + offset, sizeof(char) * write_size);
990*a248dafdSChristopher Ferris 			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
991*a248dafdSChristopher Ferris 			if (rc != ((ssize_t)sizeof(char) * write_size)) {
992*a248dafdSChristopher Ferris 				return UPDATE_FAIL_READ_F34_QUERIES;
993*a248dafdSChristopher Ferris 			}
994*a248dafdSChristopher Ferris 
995*a248dafdSChristopher Ferris 			offset += write_size;
996*a248dafdSChristopher Ferris 			left_bytes -= write_size;
997*a248dafdSChristopher Ferris 			free(data_temp);
998*a248dafdSChristopher Ferris 		} while (left_bytes);
999*a248dafdSChristopher Ferris 
1000*a248dafdSChristopher Ferris 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1001*a248dafdSChristopher Ferris 			// Wait for attention for touchpad only.
1002*a248dafdSChristopher Ferris 			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
1003*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
1004*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1005*a248dafdSChristopher Ferris 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1006*a248dafdSChristopher Ferris 			}
1007*a248dafdSChristopher Ferris 		}
1008*a248dafdSChristopher Ferris 
1009*a248dafdSChristopher Ferris 		//Wait for completion
1010*a248dafdSChristopher Ferris 		do {
1011*a248dafdSChristopher Ferris 			Sleep(20);
1012*a248dafdSChristopher Ferris 			rmi4update_poll();
1013*a248dafdSChristopher Ferris 			if (m_flashStatus == SUCCESS){
1014*a248dafdSChristopher Ferris 				break;
1015*a248dafdSChristopher Ferris 			}
1016*a248dafdSChristopher Ferris 			retry++;
1017*a248dafdSChristopher Ferris 		} while(retry < 20);
1018*a248dafdSChristopher Ferris 
1019*a248dafdSChristopher Ferris 		if (m_flashStatus != SUCCESS) {
1020*a248dafdSChristopher Ferris 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1021*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1022*a248dafdSChristopher Ferris 		}
1023*a248dafdSChristopher Ferris 
1024*a248dafdSChristopher Ferris 	}
1025*a248dafdSChristopher Ferris 
1026*a248dafdSChristopher Ferris 	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1027*a248dafdSChristopher Ferris 		if (m_firmwareImage.GetSignatureInfo()[BLv7_CORE_CONFIG].bExisted) {
1028*a248dafdSChristopher Ferris 			// Write signature.
1029*a248dafdSChristopher Ferris 			rc = WriteSignatureV7(BLv7_CORE_CONFIG, m_firmwareImage.GetConfigData(), offset);
1030*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
1031*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1032*a248dafdSChristopher Ferris 				return rc;
1033*a248dafdSChristopher Ferris 			}
1034*a248dafdSChristopher Ferris 		}
1035*a248dafdSChristopher Ferris 	}
1036*a248dafdSChristopher Ferris 
1037*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1038*a248dafdSChristopher Ferris }
1039*a248dafdSChristopher Ferris 
WriteFlashConfigV7()1040*a248dafdSChristopher Ferris int RMI4Update::WriteFlashConfigV7()
1041*a248dafdSChristopher Ferris {
1042*a248dafdSChristopher Ferris 	int transaction_count, remain_block;
1043*a248dafdSChristopher Ferris 	int transfer_leng = 0;
1044*a248dafdSChristopher Ferris 	int offset = 0;
1045*a248dafdSChristopher Ferris 	unsigned char trans_leng_buf[2];
1046*a248dafdSChristopher Ferris 	unsigned char cmd_buf[1];
1047*a248dafdSChristopher Ferris 	unsigned char off[2] = {0, 0};
1048*a248dafdSChristopher Ferris 	unsigned char partition_id;
1049*a248dafdSChristopher Ferris 	unsigned short dataAddr = m_f34.GetDataBase();
1050*a248dafdSChristopher Ferris 	unsigned short left_bytes;
1051*a248dafdSChristopher Ferris 	unsigned short write_size;
1052*a248dafdSChristopher Ferris 	unsigned short max_write_size;
1053*a248dafdSChristopher Ferris 	int rc;
1054*a248dafdSChristopher Ferris 	int i;
1055*a248dafdSChristopher Ferris 	int retry = 0;
1056*a248dafdSChristopher Ferris 	unsigned char *data_temp;
1057*a248dafdSChristopher Ferris 	unsigned short FlashConfigBlockCount;
1058*a248dafdSChristopher Ferris 
1059*a248dafdSChristopher Ferris 	/* calculate the count */
1060*a248dafdSChristopher Ferris 	partition_id = FLASH_CONFIG_PARTITION;
1061*a248dafdSChristopher Ferris 
1062*a248dafdSChristopher Ferris 	FlashConfigBlockCount = m_firmwareImage.GetFlashConfigSize() / m_blockSize;
1063*a248dafdSChristopher Ferris 
1064*a248dafdSChristopher Ferris 	remain_block = (FlashConfigBlockCount % m_payloadLength);
1065*a248dafdSChristopher Ferris 	transaction_count = (FlashConfigBlockCount / m_payloadLength);
1066*a248dafdSChristopher Ferris 	if (remain_block > 0)
1067*a248dafdSChristopher Ferris 		transaction_count++;
1068*a248dafdSChristopher Ferris 
1069*a248dafdSChristopher Ferris 	/* set partition id for bootloader 7 */
1070*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
1071*a248dafdSChristopher Ferris 	if (rc != sizeof(partition_id))
1072*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1073*a248dafdSChristopher Ferris 
1074*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
1075*a248dafdSChristopher Ferris 	if (rc != sizeof(off))
1076*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1077*a248dafdSChristopher Ferris 
1078*a248dafdSChristopher Ferris 	for (i = 0; i < transaction_count; i++)
1079*a248dafdSChristopher Ferris 	{
1080*a248dafdSChristopher Ferris 		if ((i == (transaction_count -1)) && (remain_block > 0))
1081*a248dafdSChristopher Ferris 			transfer_leng = remain_block;
1082*a248dafdSChristopher Ferris 		else
1083*a248dafdSChristopher Ferris 			transfer_leng = m_payloadLength;
1084*a248dafdSChristopher Ferris 
1085*a248dafdSChristopher Ferris 		// Set Transfer Length
1086*a248dafdSChristopher Ferris 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
1087*a248dafdSChristopher Ferris 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
1088*a248dafdSChristopher Ferris 
1089*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
1090*a248dafdSChristopher Ferris 		if (rc != sizeof(trans_leng_buf))
1091*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1092*a248dafdSChristopher Ferris 
1093*a248dafdSChristopher Ferris 		// Set Command to Write
1094*a248dafdSChristopher Ferris 		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
1095*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
1096*a248dafdSChristopher Ferris 		if (rc != sizeof(cmd_buf))
1097*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1098*a248dafdSChristopher Ferris 
1099*a248dafdSChristopher Ferris 		max_write_size = 16;
1100*a248dafdSChristopher Ferris 		if (max_write_size >= transfer_leng * m_blockSize)
1101*a248dafdSChristopher Ferris 			max_write_size = transfer_leng * m_blockSize;
1102*a248dafdSChristopher Ferris 		else if (max_write_size > m_blockSize)
1103*a248dafdSChristopher Ferris 			max_write_size -= max_write_size % m_blockSize;
1104*a248dafdSChristopher Ferris 		else
1105*a248dafdSChristopher Ferris 			max_write_size = m_blockSize;
1106*a248dafdSChristopher Ferris 
1107*a248dafdSChristopher Ferris 		left_bytes = transfer_leng * m_blockSize;
1108*a248dafdSChristopher Ferris 
1109*a248dafdSChristopher Ferris 		do {
1110*a248dafdSChristopher Ferris 			if (left_bytes / max_write_size)
1111*a248dafdSChristopher Ferris 				write_size = max_write_size;
1112*a248dafdSChristopher Ferris 			else
1113*a248dafdSChristopher Ferris 				write_size = left_bytes;
1114*a248dafdSChristopher Ferris 
1115*a248dafdSChristopher Ferris 			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
1116*a248dafdSChristopher Ferris 			memcpy(data_temp, m_firmwareImage.GetFlashConfigData() + offset, sizeof(char) * write_size);
1117*a248dafdSChristopher Ferris 			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
1118*a248dafdSChristopher Ferris 			if (rc != ((ssize_t)sizeof(char) * write_size)) {
1119*a248dafdSChristopher Ferris 				fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
1120*a248dafdSChristopher Ferris 				return UPDATE_FAIL_READ_F34_QUERIES;
1121*a248dafdSChristopher Ferris 			}
1122*a248dafdSChristopher Ferris 
1123*a248dafdSChristopher Ferris 			offset += write_size;
1124*a248dafdSChristopher Ferris 			left_bytes -= write_size;
1125*a248dafdSChristopher Ferris 			free(data_temp);
1126*a248dafdSChristopher Ferris 		} while (left_bytes);
1127*a248dafdSChristopher Ferris 
1128*a248dafdSChristopher Ferris 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1129*a248dafdSChristopher Ferris 			// Wair for attention for touchpad only.
1130*a248dafdSChristopher Ferris 			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
1131*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
1132*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1133*a248dafdSChristopher Ferris 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1134*a248dafdSChristopher Ferris 			}
1135*a248dafdSChristopher Ferris 		}
1136*a248dafdSChristopher Ferris 
1137*a248dafdSChristopher Ferris 		//Wait for completion
1138*a248dafdSChristopher Ferris 		do {
1139*a248dafdSChristopher Ferris 			Sleep(20);
1140*a248dafdSChristopher Ferris 			rmi4update_poll();
1141*a248dafdSChristopher Ferris 			if (IsBLv87()) {
1142*a248dafdSChristopher Ferris 				if (m_flashStatus == WRITE_PROTECTION)
1143*a248dafdSChristopher Ferris 					return UPDATE_FAIL_WRITE_PROTECTED;
1144*a248dafdSChristopher Ferris 			}
1145*a248dafdSChristopher Ferris 			if (m_flashStatus == SUCCESS){
1146*a248dafdSChristopher Ferris 				break;
1147*a248dafdSChristopher Ferris 			}
1148*a248dafdSChristopher Ferris 			retry++;
1149*a248dafdSChristopher Ferris 		} while(retry < 20);
1150*a248dafdSChristopher Ferris 
1151*a248dafdSChristopher Ferris 		if (m_flashStatus != SUCCESS) {
1152*a248dafdSChristopher Ferris 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1153*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1154*a248dafdSChristopher Ferris 		}
1155*a248dafdSChristopher Ferris 
1156*a248dafdSChristopher Ferris 	}
1157*a248dafdSChristopher Ferris 
1158*a248dafdSChristopher Ferris 	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1159*a248dafdSChristopher Ferris 		if (m_firmwareImage.GetSignatureInfo()[BLv7_FLASH_CONFIG].bExisted) {
1160*a248dafdSChristopher Ferris 			// Write signature.
1161*a248dafdSChristopher Ferris 			rc = WriteSignatureV7(BLv7_FLASH_CONFIG, m_firmwareImage.GetFlashConfigData(), offset);
1162*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
1163*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1164*a248dafdSChristopher Ferris 				return rc;
1165*a248dafdSChristopher Ferris 			}
1166*a248dafdSChristopher Ferris 		}
1167*a248dafdSChristopher Ferris 	}
1168*a248dafdSChristopher Ferris 
1169*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1170*a248dafdSChristopher Ferris }
1171*a248dafdSChristopher Ferris 
WriteFLDV7()1172*a248dafdSChristopher Ferris int RMI4Update::WriteFLDV7()
1173*a248dafdSChristopher Ferris {
1174*a248dafdSChristopher Ferris 	int transaction_count, remain_block;
1175*a248dafdSChristopher Ferris 	int transfer_leng = 0;
1176*a248dafdSChristopher Ferris 	int offset = 0;
1177*a248dafdSChristopher Ferris 	unsigned char trans_leng_buf[2];
1178*a248dafdSChristopher Ferris 	unsigned char cmd_buf[1];
1179*a248dafdSChristopher Ferris 	unsigned char off[2] = {0, 0};
1180*a248dafdSChristopher Ferris 	unsigned char partition_id;
1181*a248dafdSChristopher Ferris 	int i;
1182*a248dafdSChristopher Ferris 	int retry = 0;
1183*a248dafdSChristopher Ferris 	unsigned char *data_temp;
1184*a248dafdSChristopher Ferris 	int rc;
1185*a248dafdSChristopher Ferris 	unsigned short left_bytes;
1186*a248dafdSChristopher Ferris 	unsigned short write_size;
1187*a248dafdSChristopher Ferris 	unsigned short max_write_size;
1188*a248dafdSChristopher Ferris 	unsigned short dataAddr = m_f34.GetDataBase();
1189*a248dafdSChristopher Ferris 	unsigned short fldBlockCount = m_firmwareImage.GetFLDSize() / m_blockSize;
1190*a248dafdSChristopher Ferris 
1191*a248dafdSChristopher Ferris 	if (m_bootloaderID[1] < 10) {
1192*a248dafdSChristopher Ferris 		// Not support writing FLD before bootloader v10
1193*a248dafdSChristopher Ferris 		return UPDATE_SUCCESS;
1194*a248dafdSChristopher Ferris 	}
1195*a248dafdSChristopher Ferris 
1196*a248dafdSChristopher Ferris 	/* calculate the count */
1197*a248dafdSChristopher Ferris 	partition_id = FIXED_LOCATION_DATA_PARTITION;
1198*a248dafdSChristopher Ferris 
1199*a248dafdSChristopher Ferris 	remain_block = (fldBlockCount % m_payloadLength);
1200*a248dafdSChristopher Ferris 	transaction_count = (fldBlockCount / m_payloadLength);
1201*a248dafdSChristopher Ferris 
1202*a248dafdSChristopher Ferris 	if (remain_block > 0)
1203*a248dafdSChristopher Ferris 		transaction_count++;
1204*a248dafdSChristopher Ferris 
1205*a248dafdSChristopher Ferris 	/* set partition id for bootloader 7 */
1206*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
1207*a248dafdSChristopher Ferris 	if (rc != sizeof(partition_id))
1208*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1209*a248dafdSChristopher Ferris 
1210*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
1211*a248dafdSChristopher Ferris 	if (rc != sizeof(off))
1212*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1213*a248dafdSChristopher Ferris 
1214*a248dafdSChristopher Ferris 	for (i = 0; i < transaction_count; i++)
1215*a248dafdSChristopher Ferris 	{
1216*a248dafdSChristopher Ferris 		if ((i == (transaction_count -1)) && (remain_block > 0))
1217*a248dafdSChristopher Ferris 			transfer_leng = remain_block;
1218*a248dafdSChristopher Ferris 		else
1219*a248dafdSChristopher Ferris 			transfer_leng = m_payloadLength;
1220*a248dafdSChristopher Ferris 
1221*a248dafdSChristopher Ferris 		// Set Transfer Length
1222*a248dafdSChristopher Ferris 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
1223*a248dafdSChristopher Ferris 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
1224*a248dafdSChristopher Ferris 
1225*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
1226*a248dafdSChristopher Ferris 		if (rc != sizeof(trans_leng_buf))
1227*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1228*a248dafdSChristopher Ferris 
1229*a248dafdSChristopher Ferris 		// Set Command to Write
1230*a248dafdSChristopher Ferris 		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
1231*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
1232*a248dafdSChristopher Ferris 		if (rc != sizeof(cmd_buf))
1233*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1234*a248dafdSChristopher Ferris 
1235*a248dafdSChristopher Ferris 		max_write_size = 16;
1236*a248dafdSChristopher Ferris 		if (max_write_size >= transfer_leng * m_blockSize)
1237*a248dafdSChristopher Ferris 			max_write_size = transfer_leng * m_blockSize;
1238*a248dafdSChristopher Ferris 		else if (max_write_size > m_blockSize)
1239*a248dafdSChristopher Ferris 			max_write_size -= max_write_size % m_blockSize;
1240*a248dafdSChristopher Ferris 		else
1241*a248dafdSChristopher Ferris 			max_write_size = m_blockSize;
1242*a248dafdSChristopher Ferris 
1243*a248dafdSChristopher Ferris 		left_bytes = transfer_leng * m_blockSize;
1244*a248dafdSChristopher Ferris 		do {
1245*a248dafdSChristopher Ferris 			if (left_bytes / max_write_size)
1246*a248dafdSChristopher Ferris 				write_size = max_write_size;
1247*a248dafdSChristopher Ferris 			else
1248*a248dafdSChristopher Ferris 				write_size = left_bytes;
1249*a248dafdSChristopher Ferris 
1250*a248dafdSChristopher Ferris 			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
1251*a248dafdSChristopher Ferris 			memcpy(data_temp, m_firmwareImage.GetFLDData() + offset, sizeof(char) * write_size);
1252*a248dafdSChristopher Ferris 			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
1253*a248dafdSChristopher Ferris 			if (rc != ((ssize_t)sizeof(char) * write_size)) {
1254*a248dafdSChristopher Ferris 				fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
1255*a248dafdSChristopher Ferris 				return UPDATE_FAIL_READ_F34_QUERIES;
1256*a248dafdSChristopher Ferris 			}
1257*a248dafdSChristopher Ferris 
1258*a248dafdSChristopher Ferris 			offset += write_size;
1259*a248dafdSChristopher Ferris 			left_bytes -= write_size;
1260*a248dafdSChristopher Ferris 			free(data_temp);
1261*a248dafdSChristopher Ferris 		} while (left_bytes);
1262*a248dafdSChristopher Ferris 
1263*a248dafdSChristopher Ferris 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1264*a248dafdSChristopher Ferris 			// Sleep 100 ms and wait for attention for touchpad only.
1265*a248dafdSChristopher Ferris 			Sleep(100);
1266*a248dafdSChristopher Ferris 			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
1267*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
1268*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1269*a248dafdSChristopher Ferris 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1270*a248dafdSChristopher Ferris 			}
1271*a248dafdSChristopher Ferris 		}
1272*a248dafdSChristopher Ferris 
1273*a248dafdSChristopher Ferris 
1274*a248dafdSChristopher Ferris 		//Wait for completion
1275*a248dafdSChristopher Ferris 		do {
1276*a248dafdSChristopher Ferris 			Sleep(20);
1277*a248dafdSChristopher Ferris 			rmi4update_poll();
1278*a248dafdSChristopher Ferris 			if (IsBLv87()) {
1279*a248dafdSChristopher Ferris 				if (m_flashStatus == WRITE_PROTECTION)
1280*a248dafdSChristopher Ferris 					return UPDATE_FAIL_WRITE_PROTECTED;
1281*a248dafdSChristopher Ferris 			}
1282*a248dafdSChristopher Ferris 			if (m_flashStatus == SUCCESS){
1283*a248dafdSChristopher Ferris 				break;
1284*a248dafdSChristopher Ferris 
1285*a248dafdSChristopher Ferris 			}
1286*a248dafdSChristopher Ferris 			retry++;
1287*a248dafdSChristopher Ferris 		} while(retry < 20);
1288*a248dafdSChristopher Ferris 
1289*a248dafdSChristopher Ferris 		if (m_flashStatus != SUCCESS) {
1290*a248dafdSChristopher Ferris 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1291*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1292*a248dafdSChristopher Ferris 		}
1293*a248dafdSChristopher Ferris 
1294*a248dafdSChristopher Ferris 	}
1295*a248dafdSChristopher Ferris 
1296*a248dafdSChristopher Ferris 	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1297*a248dafdSChristopher Ferris 		if (m_firmwareImage.GetSignatureInfo()[BLv7_FLD].bExisted) {
1298*a248dafdSChristopher Ferris 			// Write signature.
1299*a248dafdSChristopher Ferris 			rc = WriteSignatureV7(BLv7_FLD, m_firmwareImage.GetFLDData(), offset);
1300*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
1301*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1302*a248dafdSChristopher Ferris 				return rc;
1303*a248dafdSChristopher Ferris 			}
1304*a248dafdSChristopher Ferris 		}
1305*a248dafdSChristopher Ferris 	}
1306*a248dafdSChristopher Ferris 
1307*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1308*a248dafdSChristopher Ferris }
1309*a248dafdSChristopher Ferris 
WriteGlobalParametersV7()1310*a248dafdSChristopher Ferris int RMI4Update::WriteGlobalParametersV7()
1311*a248dafdSChristopher Ferris {
1312*a248dafdSChristopher Ferris 	int transaction_count, remain_block;
1313*a248dafdSChristopher Ferris 	int transfer_leng = 0;
1314*a248dafdSChristopher Ferris 	int offset = 0;
1315*a248dafdSChristopher Ferris 	unsigned char trans_leng_buf[2];
1316*a248dafdSChristopher Ferris 	unsigned char cmd_buf[1];
1317*a248dafdSChristopher Ferris 	unsigned char off[2] = {0, 0};
1318*a248dafdSChristopher Ferris 	unsigned char partition_id;
1319*a248dafdSChristopher Ferris 	int i;
1320*a248dafdSChristopher Ferris 	int retry = 0;
1321*a248dafdSChristopher Ferris 	unsigned char *data_temp;
1322*a248dafdSChristopher Ferris 	int rc;
1323*a248dafdSChristopher Ferris 	unsigned short left_bytes;
1324*a248dafdSChristopher Ferris 	unsigned short write_size;
1325*a248dafdSChristopher Ferris 	unsigned short max_write_size;
1326*a248dafdSChristopher Ferris 	unsigned short dataAddr = m_f34.GetDataBase();
1327*a248dafdSChristopher Ferris 	unsigned short glpBlockCount = m_firmwareImage.GetGlobalParametersSize() / m_blockSize;
1328*a248dafdSChristopher Ferris 
1329*a248dafdSChristopher Ferris 	/* calculate the count */
1330*a248dafdSChristopher Ferris 	partition_id = GLOBAL_PARAMETERS_PARTITION;
1331*a248dafdSChristopher Ferris 
1332*a248dafdSChristopher Ferris 	remain_block = (glpBlockCount % m_payloadLength);
1333*a248dafdSChristopher Ferris 	transaction_count = (glpBlockCount / m_payloadLength);
1334*a248dafdSChristopher Ferris 
1335*a248dafdSChristopher Ferris 	if (remain_block > 0)
1336*a248dafdSChristopher Ferris 		transaction_count++;
1337*a248dafdSChristopher Ferris 
1338*a248dafdSChristopher Ferris 	/* set partition id for bootloader 7 */
1339*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
1340*a248dafdSChristopher Ferris 	if (rc != sizeof(partition_id))
1341*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1342*a248dafdSChristopher Ferris 
1343*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
1344*a248dafdSChristopher Ferris 	if (rc != sizeof(off))
1345*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1346*a248dafdSChristopher Ferris 
1347*a248dafdSChristopher Ferris 	for (i = 0; i < transaction_count; i++)
1348*a248dafdSChristopher Ferris 	{
1349*a248dafdSChristopher Ferris 		if ((i == (transaction_count -1)) && (remain_block > 0))
1350*a248dafdSChristopher Ferris 			transfer_leng = remain_block;
1351*a248dafdSChristopher Ferris 		else
1352*a248dafdSChristopher Ferris 			transfer_leng = m_payloadLength;
1353*a248dafdSChristopher Ferris 
1354*a248dafdSChristopher Ferris 		// Set Transfer Length
1355*a248dafdSChristopher Ferris 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
1356*a248dafdSChristopher Ferris 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
1357*a248dafdSChristopher Ferris 
1358*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
1359*a248dafdSChristopher Ferris 		if (rc != sizeof(trans_leng_buf))
1360*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1361*a248dafdSChristopher Ferris 
1362*a248dafdSChristopher Ferris 		// Set Command to Write
1363*a248dafdSChristopher Ferris 		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
1364*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
1365*a248dafdSChristopher Ferris 		if (rc != sizeof(cmd_buf))
1366*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1367*a248dafdSChristopher Ferris 
1368*a248dafdSChristopher Ferris 		max_write_size = 16;
1369*a248dafdSChristopher Ferris 		if (max_write_size >= transfer_leng * m_blockSize)
1370*a248dafdSChristopher Ferris 			max_write_size = transfer_leng * m_blockSize;
1371*a248dafdSChristopher Ferris 		else if (max_write_size > m_blockSize)
1372*a248dafdSChristopher Ferris 			max_write_size -= max_write_size % m_blockSize;
1373*a248dafdSChristopher Ferris 		else
1374*a248dafdSChristopher Ferris 			max_write_size = m_blockSize;
1375*a248dafdSChristopher Ferris 
1376*a248dafdSChristopher Ferris 		left_bytes = transfer_leng * m_blockSize;
1377*a248dafdSChristopher Ferris 		do {
1378*a248dafdSChristopher Ferris 			if (left_bytes / max_write_size)
1379*a248dafdSChristopher Ferris 				write_size = max_write_size;
1380*a248dafdSChristopher Ferris 			else
1381*a248dafdSChristopher Ferris 				write_size = left_bytes;
1382*a248dafdSChristopher Ferris 
1383*a248dafdSChristopher Ferris 			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
1384*a248dafdSChristopher Ferris 			memcpy(data_temp, m_firmwareImage.GetFLDData() + offset, sizeof(char) * write_size);
1385*a248dafdSChristopher Ferris 			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
1386*a248dafdSChristopher Ferris 			if (rc != ((ssize_t)sizeof(char) * write_size)) {
1387*a248dafdSChristopher Ferris 				fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
1388*a248dafdSChristopher Ferris 				return UPDATE_FAIL_READ_F34_QUERIES;
1389*a248dafdSChristopher Ferris 			}
1390*a248dafdSChristopher Ferris 
1391*a248dafdSChristopher Ferris 			offset += write_size;
1392*a248dafdSChristopher Ferris 			left_bytes -= write_size;
1393*a248dafdSChristopher Ferris 			free(data_temp);
1394*a248dafdSChristopher Ferris 		} while (left_bytes);
1395*a248dafdSChristopher Ferris 
1396*a248dafdSChristopher Ferris 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1397*a248dafdSChristopher Ferris 			// Sleep 100 ms and wait for attention for touchpad only.
1398*a248dafdSChristopher Ferris 			Sleep(100);
1399*a248dafdSChristopher Ferris 			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
1400*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
1401*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1402*a248dafdSChristopher Ferris 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1403*a248dafdSChristopher Ferris 			}
1404*a248dafdSChristopher Ferris 		}
1405*a248dafdSChristopher Ferris 
1406*a248dafdSChristopher Ferris 
1407*a248dafdSChristopher Ferris 		//Wait for completion
1408*a248dafdSChristopher Ferris 		do {
1409*a248dafdSChristopher Ferris 			Sleep(20);
1410*a248dafdSChristopher Ferris 			rmi4update_poll();
1411*a248dafdSChristopher Ferris 			if (m_flashStatus == SUCCESS){
1412*a248dafdSChristopher Ferris 				break;
1413*a248dafdSChristopher Ferris 
1414*a248dafdSChristopher Ferris 			}
1415*a248dafdSChristopher Ferris 			retry++;
1416*a248dafdSChristopher Ferris 		} while(retry < 20);
1417*a248dafdSChristopher Ferris 
1418*a248dafdSChristopher Ferris 		if (m_flashStatus != SUCCESS) {
1419*a248dafdSChristopher Ferris 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1420*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1421*a248dafdSChristopher Ferris 		}
1422*a248dafdSChristopher Ferris 
1423*a248dafdSChristopher Ferris 	}
1424*a248dafdSChristopher Ferris 
1425*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1426*a248dafdSChristopher Ferris }
1427*a248dafdSChristopher Ferris 
EraseFlashConfigV10()1428*a248dafdSChristopher Ferris int RMI4Update::EraseFlashConfigV10()
1429*a248dafdSChristopher Ferris {
1430*a248dafdSChristopher Ferris 	unsigned char erase_cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1431*a248dafdSChristopher Ferris 	int retry = 0;
1432*a248dafdSChristopher Ferris 	int rc;
1433*a248dafdSChristopher Ferris 
1434*a248dafdSChristopher Ferris 	/* set partition id for bootloader 10 */
1435*a248dafdSChristopher Ferris 	erase_cmd[0] = FLASH_CONFIG_PARTITION;
1436*a248dafdSChristopher Ferris 	/* write bootloader id */
1437*a248dafdSChristopher Ferris 	erase_cmd[6] = m_bootloaderID[0];
1438*a248dafdSChristopher Ferris 	erase_cmd[7] = m_bootloaderID[1];
1439*a248dafdSChristopher Ferris 	erase_cmd[5] = (unsigned char)CMD_V7_ERASE;
1440*a248dafdSChristopher Ferris 
1441*a248dafdSChristopher Ferris 	fprintf(stdout, "Erase command : ");
1442*a248dafdSChristopher Ferris 	for(int i = 0 ;i<8;i++){
1443*a248dafdSChristopher Ferris 		fprintf(stdout, "%d ", erase_cmd[i]);
1444*a248dafdSChristopher Ferris 	}
1445*a248dafdSChristopher Ferris 	fprintf(stdout, "\n");
1446*a248dafdSChristopher Ferris 
1447*a248dafdSChristopher Ferris 	rmi4update_poll();
1448*a248dafdSChristopher Ferris 	if (!m_inBLmode)
1449*a248dafdSChristopher Ferris 		return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1450*a248dafdSChristopher Ferris 
1451*a248dafdSChristopher Ferris 	// For BL8 device, we need hold 1 seconds after querying
1452*a248dafdSChristopher Ferris 	// F34 status to avoid not get attention by following giving
1453*a248dafdSChristopher Ferris 	// erase command.
1454*a248dafdSChristopher Ferris 	Sleep(1000);
1455*a248dafdSChristopher Ferris 
1456*a248dafdSChristopher Ferris 	rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
1457*a248dafdSChristopher Ferris 	if (rc != sizeof(erase_cmd))
1458*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1459*a248dafdSChristopher Ferris 
1460*a248dafdSChristopher Ferris 	Sleep(100);
1461*a248dafdSChristopher Ferris 
1462*a248dafdSChristopher Ferris 	//Wait from ATTN
1463*a248dafdSChristopher Ferris 	rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
1464*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS) {
1465*a248dafdSChristopher Ferris 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1466*a248dafdSChristopher Ferris 		return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1467*a248dafdSChristopher Ferris 	}
1468*a248dafdSChristopher Ferris 
1469*a248dafdSChristopher Ferris 	do {
1470*a248dafdSChristopher Ferris 		Sleep(20);
1471*a248dafdSChristopher Ferris 		rmi4update_poll();
1472*a248dafdSChristopher Ferris 		if (IsBLv87()) {
1473*a248dafdSChristopher Ferris 			if (m_flashStatus == WRITE_PROTECTION)
1474*a248dafdSChristopher Ferris 				return UPDATE_FAIL_WRITE_PROTECTED;
1475*a248dafdSChristopher Ferris 		}
1476*a248dafdSChristopher Ferris 		if (m_flashStatus == SUCCESS){
1477*a248dafdSChristopher Ferris 			break;
1478*a248dafdSChristopher Ferris 		}
1479*a248dafdSChristopher Ferris 		retry++;
1480*a248dafdSChristopher Ferris 	} while(retry < 20);
1481*a248dafdSChristopher Ferris 
1482*a248dafdSChristopher Ferris 	if (m_flashStatus != SUCCESS) {
1483*a248dafdSChristopher Ferris 		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1484*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1485*a248dafdSChristopher Ferris 	}
1486*a248dafdSChristopher Ferris 
1487*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1488*a248dafdSChristopher Ferris }
1489*a248dafdSChristopher Ferris 
EraseCoreCodeV10()1490*a248dafdSChristopher Ferris int RMI4Update::EraseCoreCodeV10()
1491*a248dafdSChristopher Ferris {
1492*a248dafdSChristopher Ferris 	unsigned char erase_cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1493*a248dafdSChristopher Ferris 	int retry = 0;
1494*a248dafdSChristopher Ferris 	int rc;
1495*a248dafdSChristopher Ferris 
1496*a248dafdSChristopher Ferris 	/* set partition id for bootloader 10 */
1497*a248dafdSChristopher Ferris 	erase_cmd[0] = CORE_CODE_PARTITION;
1498*a248dafdSChristopher Ferris 	/* write bootloader id */
1499*a248dafdSChristopher Ferris 	erase_cmd[6] = m_bootloaderID[0];
1500*a248dafdSChristopher Ferris 	erase_cmd[7] = m_bootloaderID[1];
1501*a248dafdSChristopher Ferris 	erase_cmd[5] = (unsigned char)CMD_V7_ERASE_AP;
1502*a248dafdSChristopher Ferris 
1503*a248dafdSChristopher Ferris 	fprintf(stdout, "Erase command : ");
1504*a248dafdSChristopher Ferris 	for(int i = 0 ;i<8;i++){
1505*a248dafdSChristopher Ferris 		fprintf(stdout, "%d ", erase_cmd[i]);
1506*a248dafdSChristopher Ferris 	}
1507*a248dafdSChristopher Ferris 	fprintf(stdout, "\n");
1508*a248dafdSChristopher Ferris 
1509*a248dafdSChristopher Ferris 	rmi4update_poll();
1510*a248dafdSChristopher Ferris 	if (!m_inBLmode)
1511*a248dafdSChristopher Ferris 		return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1512*a248dafdSChristopher Ferris 
1513*a248dafdSChristopher Ferris 	// For BL8 device, we need hold 1 seconds after querying
1514*a248dafdSChristopher Ferris 	// F34 status to avoid not get attention by following giving
1515*a248dafdSChristopher Ferris 	// erase command.
1516*a248dafdSChristopher Ferris 	Sleep(1000);
1517*a248dafdSChristopher Ferris 
1518*a248dafdSChristopher Ferris 	rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
1519*a248dafdSChristopher Ferris 	if (rc != sizeof(erase_cmd))
1520*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1521*a248dafdSChristopher Ferris 
1522*a248dafdSChristopher Ferris 	Sleep(100);
1523*a248dafdSChristopher Ferris 
1524*a248dafdSChristopher Ferris 	//Wait from ATTN
1525*a248dafdSChristopher Ferris 	rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
1526*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS) {
1527*a248dafdSChristopher Ferris 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1528*a248dafdSChristopher Ferris 		return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1529*a248dafdSChristopher Ferris 	}
1530*a248dafdSChristopher Ferris 
1531*a248dafdSChristopher Ferris 	do {
1532*a248dafdSChristopher Ferris 		Sleep(20);
1533*a248dafdSChristopher Ferris 		rmi4update_poll();
1534*a248dafdSChristopher Ferris 		if (m_flashStatus == SUCCESS){
1535*a248dafdSChristopher Ferris 			break;
1536*a248dafdSChristopher Ferris 		}
1537*a248dafdSChristopher Ferris 		retry++;
1538*a248dafdSChristopher Ferris 	} while(retry < 20);
1539*a248dafdSChristopher Ferris 
1540*a248dafdSChristopher Ferris 	if (m_flashStatus != SUCCESS) {
1541*a248dafdSChristopher Ferris 		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1542*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1543*a248dafdSChristopher Ferris 	}
1544*a248dafdSChristopher Ferris 
1545*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1546*a248dafdSChristopher Ferris }
1547*a248dafdSChristopher Ferris 
EraseFirmwareV7()1548*a248dafdSChristopher Ferris int RMI4Update::EraseFirmwareV7()
1549*a248dafdSChristopher Ferris {
1550*a248dafdSChristopher Ferris 	unsigned char erase_cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1551*a248dafdSChristopher Ferris 	int retry = 0;
1552*a248dafdSChristopher Ferris 	int rc;
1553*a248dafdSChristopher Ferris 
1554*a248dafdSChristopher Ferris 	/* set partition id for bootloader 7 */
1555*a248dafdSChristopher Ferris 	erase_cmd[0] = CORE_CODE_PARTITION;
1556*a248dafdSChristopher Ferris 	/* write bootloader id */
1557*a248dafdSChristopher Ferris 	erase_cmd[6] = m_bootloaderID[0];
1558*a248dafdSChristopher Ferris 	erase_cmd[7] = m_bootloaderID[1];
1559*a248dafdSChristopher Ferris 	if(m_bootloaderID[1] == 8){
1560*a248dafdSChristopher Ferris 		/* Set Command to Erase AP for BL8*/
1561*a248dafdSChristopher Ferris 		erase_cmd[5] = (unsigned char)CMD_V7_ERASE_AP;
1562*a248dafdSChristopher Ferris 	} else {
1563*a248dafdSChristopher Ferris 		/* Set Command to Erase AP for BL7*/
1564*a248dafdSChristopher Ferris 		erase_cmd[5] = (unsigned char)CMD_V7_ERASE;
1565*a248dafdSChristopher Ferris 	}
1566*a248dafdSChristopher Ferris 
1567*a248dafdSChristopher Ferris 	fprintf(stdout, "Erase command : ");
1568*a248dafdSChristopher Ferris 	for(int i = 0 ;i<8;i++){
1569*a248dafdSChristopher Ferris 		fprintf(stdout, "%d ", erase_cmd[i]);
1570*a248dafdSChristopher Ferris 	}
1571*a248dafdSChristopher Ferris 	fprintf(stdout, "\n");
1572*a248dafdSChristopher Ferris 
1573*a248dafdSChristopher Ferris 	rmi4update_poll();
1574*a248dafdSChristopher Ferris 	if (!m_inBLmode)
1575*a248dafdSChristopher Ferris 		return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1576*a248dafdSChristopher Ferris 	if(m_bootloaderID[1] == 8){
1577*a248dafdSChristopher Ferris 		// For BL8 device, we need hold 1 seconds after querying
1578*a248dafdSChristopher Ferris 		// F34 status to avoid not get attention by following giving
1579*a248dafdSChristopher Ferris 		// erase command.
1580*a248dafdSChristopher Ferris 		Sleep(1000);
1581*a248dafdSChristopher Ferris 	}
1582*a248dafdSChristopher Ferris 
1583*a248dafdSChristopher Ferris 	rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
1584*a248dafdSChristopher Ferris 	if (rc != sizeof(erase_cmd))
1585*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1586*a248dafdSChristopher Ferris 
1587*a248dafdSChristopher Ferris 	Sleep(100);
1588*a248dafdSChristopher Ferris 
1589*a248dafdSChristopher Ferris 	//Wait from ATTN
1590*a248dafdSChristopher Ferris 	if(m_bootloaderID[1] == 8){
1591*a248dafdSChristopher Ferris 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1592*a248dafdSChristopher Ferris 			// Wait for attention for BL8 touchpad.
1593*a248dafdSChristopher Ferris 			rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
1594*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
1595*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1596*a248dafdSChristopher Ferris 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1597*a248dafdSChristopher Ferris 			}
1598*a248dafdSChristopher Ferris 		}
1599*a248dafdSChristopher Ferris 	}
1600*a248dafdSChristopher Ferris 	do {
1601*a248dafdSChristopher Ferris 		Sleep(20);
1602*a248dafdSChristopher Ferris 		rmi4update_poll();
1603*a248dafdSChristopher Ferris 		if (IsBLv87()) {
1604*a248dafdSChristopher Ferris 			if (m_flashStatus == WRITE_PROTECTION)
1605*a248dafdSChristopher Ferris 				return UPDATE_FAIL_WRITE_PROTECTED;
1606*a248dafdSChristopher Ferris 		}
1607*a248dafdSChristopher Ferris 		if (m_flashStatus == SUCCESS){
1608*a248dafdSChristopher Ferris 			break;
1609*a248dafdSChristopher Ferris 		}
1610*a248dafdSChristopher Ferris 		retry++;
1611*a248dafdSChristopher Ferris 	} while(retry < 20);
1612*a248dafdSChristopher Ferris 
1613*a248dafdSChristopher Ferris 	if (m_flashStatus != SUCCESS) {
1614*a248dafdSChristopher Ferris 		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1615*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1616*a248dafdSChristopher Ferris 	}
1617*a248dafdSChristopher Ferris 
1618*a248dafdSChristopher Ferris 	if(m_bootloaderID[1] == 7){
1619*a248dafdSChristopher Ferris 		// For BL7, we need erase config partition.
1620*a248dafdSChristopher Ferris 		fprintf(stdout, "Start to erase config\n");
1621*a248dafdSChristopher Ferris 		erase_cmd[0] = CORE_CONFIG_PARTITION;
1622*a248dafdSChristopher Ferris 		erase_cmd[6] = m_bootloaderID[0];
1623*a248dafdSChristopher Ferris 		erase_cmd[7] = m_bootloaderID[1];
1624*a248dafdSChristopher Ferris 		erase_cmd[5] = (unsigned char)CMD_V7_ERASE;
1625*a248dafdSChristopher Ferris 
1626*a248dafdSChristopher Ferris 		Sleep(100);
1627*a248dafdSChristopher Ferris 		rmi4update_poll();
1628*a248dafdSChristopher Ferris 		if (!m_inBLmode)
1629*a248dafdSChristopher Ferris 		  return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1630*a248dafdSChristopher Ferris 
1631*a248dafdSChristopher Ferris 		rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
1632*a248dafdSChristopher Ferris 		if (rc != sizeof(erase_cmd))
1633*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1634*a248dafdSChristopher Ferris 
1635*a248dafdSChristopher Ferris 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1636*a248dafdSChristopher Ferris 			//Wait from ATTN for touchpad only.
1637*a248dafdSChristopher Ferris 			Sleep(100);
1638*a248dafdSChristopher Ferris 
1639*a248dafdSChristopher Ferris 			rc = WaitForIdle(RMI_F34_ERASE_WAIT_MS, true);
1640*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
1641*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1642*a248dafdSChristopher Ferris 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1643*a248dafdSChristopher Ferris 			}
1644*a248dafdSChristopher Ferris 		}
1645*a248dafdSChristopher Ferris 
1646*a248dafdSChristopher Ferris 
1647*a248dafdSChristopher Ferris 		do {
1648*a248dafdSChristopher Ferris 			Sleep(20);
1649*a248dafdSChristopher Ferris 			rmi4update_poll();
1650*a248dafdSChristopher Ferris 			if (m_flashStatus == SUCCESS){
1651*a248dafdSChristopher Ferris 				break;
1652*a248dafdSChristopher Ferris 			}
1653*a248dafdSChristopher Ferris 			retry++;
1654*a248dafdSChristopher Ferris 		} while(retry < 20);
1655*a248dafdSChristopher Ferris 
1656*a248dafdSChristopher Ferris 		if (m_flashStatus != SUCCESS) {
1657*a248dafdSChristopher Ferris 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1658*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1659*a248dafdSChristopher Ferris 		}
1660*a248dafdSChristopher Ferris 	}
1661*a248dafdSChristopher Ferris 
1662*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1663*a248dafdSChristopher Ferris }
1664*a248dafdSChristopher Ferris 
EnterFlashProgrammingV7()1665*a248dafdSChristopher Ferris int RMI4Update::EnterFlashProgrammingV7()
1666*a248dafdSChristopher Ferris {
1667*a248dafdSChristopher Ferris 	int rc;
1668*a248dafdSChristopher Ferris 	unsigned char f34_status;
1669*a248dafdSChristopher Ferris 	rc = m_device.Read(m_f34.GetDataBase(), &f34_status, sizeof(unsigned char));
1670*a248dafdSChristopher Ferris 	m_inBLmode = f34_status & 0x80;
1671*a248dafdSChristopher Ferris 	if(!m_inBLmode){
1672*a248dafdSChristopher Ferris 		fprintf(stdout, "Not in BL mode, going to BL mode...\n");
1673*a248dafdSChristopher Ferris 		unsigned char EnterCmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1674*a248dafdSChristopher Ferris 		int retry = 0;
1675*a248dafdSChristopher Ferris 
1676*a248dafdSChristopher Ferris 		/* set partition id for bootloader 7 */
1677*a248dafdSChristopher Ferris 		EnterCmd[0] = BOOTLOADER_PARTITION;
1678*a248dafdSChristopher Ferris 
1679*a248dafdSChristopher Ferris 		/* write bootloader id */
1680*a248dafdSChristopher Ferris 		EnterCmd[6] = m_bootloaderID[0];
1681*a248dafdSChristopher Ferris 		EnterCmd[7] = m_bootloaderID[1];
1682*a248dafdSChristopher Ferris 
1683*a248dafdSChristopher Ferris 		// Set Command to EnterBL
1684*a248dafdSChristopher Ferris 		EnterCmd[5] = (unsigned char)CMD_V7_ENTER_BL;
1685*a248dafdSChristopher Ferris 
1686*a248dafdSChristopher Ferris 		rc = m_device.Write(m_f34.GetDataBase() + 1, EnterCmd, sizeof(EnterCmd));
1687*a248dafdSChristopher Ferris 		if (rc != sizeof(EnterCmd))
1688*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1689*a248dafdSChristopher Ferris 
1690*a248dafdSChristopher Ferris 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1691*a248dafdSChristopher Ferris 			rc = WaitForIdle(RMI_F34_ENABLE_WAIT_MS, false);
1692*a248dafdSChristopher Ferris 			if (rc != UPDATE_SUCCESS) {
1693*a248dafdSChristopher Ferris 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1694*a248dafdSChristopher Ferris 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1695*a248dafdSChristopher Ferris 			}
1696*a248dafdSChristopher Ferris 		}
1697*a248dafdSChristopher Ferris 
1698*a248dafdSChristopher Ferris 		//Wait from ATTN
1699*a248dafdSChristopher Ferris 		do {
1700*a248dafdSChristopher Ferris 			Sleep(20);
1701*a248dafdSChristopher Ferris 			rmi4update_poll();
1702*a248dafdSChristopher Ferris 			if (m_flashStatus == SUCCESS){
1703*a248dafdSChristopher Ferris 				break;
1704*a248dafdSChristopher Ferris 			}
1705*a248dafdSChristopher Ferris 			retry++;
1706*a248dafdSChristopher Ferris 		} while(retry < 20);
1707*a248dafdSChristopher Ferris 
1708*a248dafdSChristopher Ferris 		if (m_flashStatus != SUCCESS) {
1709*a248dafdSChristopher Ferris 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1710*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1711*a248dafdSChristopher Ferris 		}
1712*a248dafdSChristopher Ferris 
1713*a248dafdSChristopher Ferris 		Sleep(RMI_F34_ENABLE_WAIT_MS);
1714*a248dafdSChristopher Ferris 
1715*a248dafdSChristopher Ferris 		fprintf(stdout, "%s\n", __func__);
1716*a248dafdSChristopher Ferris 		rmi4update_poll();
1717*a248dafdSChristopher Ferris 		if (!m_inBLmode)
1718*a248dafdSChristopher Ferris 			return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1719*a248dafdSChristopher Ferris 
1720*a248dafdSChristopher Ferris 	} else
1721*a248dafdSChristopher Ferris 		fprintf(stdout, "Already in BL mode, skip...\n");
1722*a248dafdSChristopher Ferris 
1723*a248dafdSChristopher Ferris 	if(m_device.GetDeviceType() != RMI_DEVICE_TYPE_TOUCHPAD) {
1724*a248dafdSChristopher Ferris 		// workaround for touchscreen only
1725*a248dafdSChristopher Ferris 		fprintf(stdout, "Erase in BL mode\n");
1726*a248dafdSChristopher Ferris 		rc = EraseFirmwareV7();
1727*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS) {
1728*a248dafdSChristopher Ferris 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1729*a248dafdSChristopher Ferris 			return UPDATE_FAIL_ERASE_ALL;
1730*a248dafdSChristopher Ferris 		}
1731*a248dafdSChristopher Ferris 		fprintf(stdout, "Erase in BL mode end\n");
1732*a248dafdSChristopher Ferris 		m_device.RebindDriver();
1733*a248dafdSChristopher Ferris 	}
1734*a248dafdSChristopher Ferris 
1735*a248dafdSChristopher Ferris 	Sleep(RMI_F34_ENABLE_WAIT_MS);
1736*a248dafdSChristopher Ferris 
1737*a248dafdSChristopher Ferris 	rc = FindUpdateFunctions();
1738*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS)
1739*a248dafdSChristopher Ferris 		return rc;
1740*a248dafdSChristopher Ferris 
1741*a248dafdSChristopher Ferris 	rc = ReadF34Queries();
1742*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS)
1743*a248dafdSChristopher Ferris 		return rc;
1744*a248dafdSChristopher Ferris 
1745*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1746*a248dafdSChristopher Ferris }
1747*a248dafdSChristopher Ferris 
EnterFlashProgramming()1748*a248dafdSChristopher Ferris int RMI4Update::EnterFlashProgramming()
1749*a248dafdSChristopher Ferris {
1750*a248dafdSChristopher Ferris 	int rc;
1751*a248dafdSChristopher Ferris 	unsigned char f01Control_0;
1752*a248dafdSChristopher Ferris 	const unsigned char enableProg = RMI_F34_ENABLE_FLASH_PROG;
1753*a248dafdSChristopher Ferris 
1754*a248dafdSChristopher Ferris 	rc = WriteBootloaderID();
1755*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS)
1756*a248dafdSChristopher Ferris 		return rc;
1757*a248dafdSChristopher Ferris 
1758*a248dafdSChristopher Ferris 	fprintf(stdout, "Enabling flash programming.\n");
1759*a248dafdSChristopher Ferris 	rc = m_device.Write(m_f34StatusAddr, &enableProg, 1);
1760*a248dafdSChristopher Ferris 	if (rc != 1)
1761*a248dafdSChristopher Ferris 		return UPDATE_FAIL_ENABLE_FLASH_PROGRAMMING;
1762*a248dafdSChristopher Ferris 
1763*a248dafdSChristopher Ferris 
1764*a248dafdSChristopher Ferris 	if(m_device.GetDeviceType() != RMI_DEVICE_TYPE_TOUCHPAD) {
1765*a248dafdSChristopher Ferris 		fprintf(stdout, "not TouchPad, rebind driver here\n");
1766*a248dafdSChristopher Ferris 		Sleep(RMI_F34_ENABLE_WAIT_MS);
1767*a248dafdSChristopher Ferris 		m_device.RebindDriver();
1768*a248dafdSChristopher Ferris 		rc = WaitForIdle(0);
1769*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS)
1770*a248dafdSChristopher Ferris 			return UPDATE_FAIL_NOT_IN_IDLE_STATE;
1771*a248dafdSChristopher Ferris 	} else {
1772*a248dafdSChristopher Ferris 		// For TouchPad
1773*a248dafdSChristopher Ferris 		rc = WaitForIdle(RMI_F34_ENABLE_WAIT_MS);
1774*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS)
1775*a248dafdSChristopher Ferris 			return UPDATE_FAIL_NOT_IN_IDLE_STATE;
1776*a248dafdSChristopher Ferris 	}
1777*a248dafdSChristopher Ferris 
1778*a248dafdSChristopher Ferris 	if (!m_programEnabled)
1779*a248dafdSChristopher Ferris 		return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED;
1780*a248dafdSChristopher Ferris 
1781*a248dafdSChristopher Ferris 	fprintf(stdout, "Programming is enabled.\n");
1782*a248dafdSChristopher Ferris 	rc = FindUpdateFunctions();
1783*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS)
1784*a248dafdSChristopher Ferris 		return rc;
1785*a248dafdSChristopher Ferris 
1786*a248dafdSChristopher Ferris 	rc = m_device.Read(m_f01.GetDataBase(), &m_deviceStatus, 1);
1787*a248dafdSChristopher Ferris 	if (rc != 1)
1788*a248dafdSChristopher Ferris 		return UPDATE_FAIL_READ_DEVICE_STATUS;
1789*a248dafdSChristopher Ferris 
1790*a248dafdSChristopher Ferris 	if(m_f34.GetFunctionVersion() > 0x1){
1791*a248dafdSChristopher Ferris 		if (!RMI_F01_STATUS_BOOTLOADER_v7(m_deviceStatus))
1792*a248dafdSChristopher Ferris 			return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1793*a248dafdSChristopher Ferris 		fprintf(stdout, "Already in BL mode V7\n");
1794*a248dafdSChristopher Ferris 	} else {
1795*a248dafdSChristopher Ferris 		if (!RMI_F01_STATUS_BOOTLOADER(m_deviceStatus))
1796*a248dafdSChristopher Ferris 			return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1797*a248dafdSChristopher Ferris 		fprintf(stdout, "Already in BL mode\n");
1798*a248dafdSChristopher Ferris 	}
1799*a248dafdSChristopher Ferris 
1800*a248dafdSChristopher Ferris 	rc = ReadF34Queries();
1801*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS)
1802*a248dafdSChristopher Ferris 		return rc;
1803*a248dafdSChristopher Ferris 
1804*a248dafdSChristopher Ferris 	rc = m_device.Read(m_f01.GetControlBase(), &f01Control_0, 1);
1805*a248dafdSChristopher Ferris 	if (rc != 1)
1806*a248dafdSChristopher Ferris 		return UPDATE_FAIL_READ_F01_CONTROL_0;
1807*a248dafdSChristopher Ferris 
1808*a248dafdSChristopher Ferris 	f01Control_0 |= RMI_F01_CRTL0_NOSLEEP_BIT;
1809*a248dafdSChristopher Ferris 	f01Control_0 = (f01Control_0 & ~RMI_F01_CTRL0_SLEEP_MODE_MASK) | RMI_SLEEP_MODE_NORMAL;
1810*a248dafdSChristopher Ferris 
1811*a248dafdSChristopher Ferris 	rc = m_device.Write(m_f01.GetControlBase(), &f01Control_0, 1);
1812*a248dafdSChristopher Ferris 	if (rc != 1)
1813*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1814*a248dafdSChristopher Ferris 
1815*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1816*a248dafdSChristopher Ferris }
1817*a248dafdSChristopher Ferris 
WriteBlocks(unsigned char * block,unsigned short count,unsigned char cmd)1818*a248dafdSChristopher Ferris int RMI4Update::WriteBlocks(unsigned char *block, unsigned short count, unsigned char cmd)
1819*a248dafdSChristopher Ferris {
1820*a248dafdSChristopher Ferris 	int blockNum;
1821*a248dafdSChristopher Ferris 	unsigned char zeros[] = { 0, 0 };
1822*a248dafdSChristopher Ferris 	int rc;
1823*a248dafdSChristopher Ferris 	unsigned short addr;
1824*a248dafdSChristopher Ferris 	unsigned char *blockWithCmd = (unsigned char *)alloca(m_blockSize + 1);
1825*a248dafdSChristopher Ferris 
1826*a248dafdSChristopher Ferris 	if (m_f34.GetFunctionVersion() == 0x1)
1827*a248dafdSChristopher Ferris 		addr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_V1_OFFSET;
1828*a248dafdSChristopher Ferris 	else
1829*a248dafdSChristopher Ferris 		addr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_OFFSET;
1830*a248dafdSChristopher Ferris 
1831*a248dafdSChristopher Ferris 	rc = m_device.Write(m_f34.GetDataBase(), zeros, 2);
1832*a248dafdSChristopher Ferris 	if (rc != 2)
1833*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1834*a248dafdSChristopher Ferris 
1835*a248dafdSChristopher Ferris 	for (blockNum = 0; blockNum < count; ++blockNum) {
1836*a248dafdSChristopher Ferris 		if (m_writeBlockWithCmd) {
1837*a248dafdSChristopher Ferris 			memcpy(blockWithCmd, block, m_blockSize);
1838*a248dafdSChristopher Ferris 			blockWithCmd[m_blockSize] = cmd;
1839*a248dafdSChristopher Ferris 
1840*a248dafdSChristopher Ferris 			rc = m_device.Write(addr, blockWithCmd, m_blockSize + 1);
1841*a248dafdSChristopher Ferris 			if (rc != m_blockSize + 1) {
1842*a248dafdSChristopher Ferris 				fprintf(stderr, "failed to write block %d\n", blockNum);
1843*a248dafdSChristopher Ferris 				return UPDATE_FAIL_WRITE_BLOCK;
1844*a248dafdSChristopher Ferris 			}
1845*a248dafdSChristopher Ferris 		} else {
1846*a248dafdSChristopher Ferris 			rc = m_device.Write(addr, block, m_blockSize);
1847*a248dafdSChristopher Ferris 			if (rc != m_blockSize) {
1848*a248dafdSChristopher Ferris 				fprintf(stderr, "failed to write block %d\n", blockNum);
1849*a248dafdSChristopher Ferris 				return UPDATE_FAIL_WRITE_BLOCK;
1850*a248dafdSChristopher Ferris 			}
1851*a248dafdSChristopher Ferris 
1852*a248dafdSChristopher Ferris 			rc = m_device.Write(m_f34StatusAddr, &cmd, 1);
1853*a248dafdSChristopher Ferris 			if (rc != 1) {
1854*a248dafdSChristopher Ferris 				fprintf(stderr, "failed to write command for block %d\n", blockNum);
1855*a248dafdSChristopher Ferris 				return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1856*a248dafdSChristopher Ferris 			}
1857*a248dafdSChristopher Ferris 		}
1858*a248dafdSChristopher Ferris 
1859*a248dafdSChristopher Ferris 		rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, !m_writeBlockWithCmd);
1860*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS) {
1861*a248dafdSChristopher Ferris 			fprintf(stderr, "failed to go into idle after writing block %d\n", blockNum);
1862*a248dafdSChristopher Ferris 			return UPDATE_FAIL_NOT_IN_IDLE_STATE;
1863*a248dafdSChristopher Ferris 		}
1864*a248dafdSChristopher Ferris 
1865*a248dafdSChristopher Ferris 		block += m_blockSize;
1866*a248dafdSChristopher Ferris 	}
1867*a248dafdSChristopher Ferris 
1868*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1869*a248dafdSChristopher Ferris }
1870*a248dafdSChristopher Ferris 
WriteSignatureV7(enum signature_BLv7 signature_partition,unsigned char * data,int offset)1871*a248dafdSChristopher Ferris int RMI4Update::WriteSignatureV7(enum signature_BLv7 signature_partition, unsigned char* data, int offset)
1872*a248dafdSChristopher Ferris {
1873*a248dafdSChristopher Ferris 	fprintf(stdout, "Write Signature...\n");
1874*a248dafdSChristopher Ferris 	int rc;
1875*a248dafdSChristopher Ferris 	unsigned char off[2] = {0, 0};
1876*a248dafdSChristopher Ferris 	unsigned char cmd_buf[1];
1877*a248dafdSChristopher Ferris 	unsigned short dataAddr = m_f34.GetDataBase();
1878*a248dafdSChristopher Ferris 	int transfer_leng = 0;
1879*a248dafdSChristopher Ferris 	signature_info signature = m_firmwareImage.GetSignatureInfo()[signature_partition];
1880*a248dafdSChristopher Ferris 	unsigned char trans_leng_buf[2];
1881*a248dafdSChristopher Ferris 	unsigned short left_bytes;
1882*a248dafdSChristopher Ferris 	unsigned short write_size;
1883*a248dafdSChristopher Ferris 	unsigned short max_write_size;
1884*a248dafdSChristopher Ferris 	unsigned char *data_temp;
1885*a248dafdSChristopher Ferris 	int retry = 0;
1886*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
1887*a248dafdSChristopher Ferris 	if (rc != sizeof(off))
1888*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1889*a248dafdSChristopher Ferris 
1890*a248dafdSChristopher Ferris 	// Set Transfer Length
1891*a248dafdSChristopher Ferris 	transfer_leng = signature.size / m_blockSize;
1892*a248dafdSChristopher Ferris 	trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
1893*a248dafdSChristopher Ferris 	trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
1894*a248dafdSChristopher Ferris 
1895*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
1896*a248dafdSChristopher Ferris 	if (rc != sizeof(trans_leng_buf))
1897*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1898*a248dafdSChristopher Ferris 
1899*a248dafdSChristopher Ferris 	// Set Command to Signature
1900*a248dafdSChristopher Ferris 	cmd_buf[0] = (unsigned char)CMD_V7_SIGNATURE;
1901*a248dafdSChristopher Ferris 	rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
1902*a248dafdSChristopher Ferris 	if (rc != sizeof(cmd_buf))
1903*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1904*a248dafdSChristopher Ferris 
1905*a248dafdSChristopher Ferris 	max_write_size = 16;
1906*a248dafdSChristopher Ferris 	if (max_write_size >= transfer_leng * m_blockSize)
1907*a248dafdSChristopher Ferris 		max_write_size = transfer_leng * m_blockSize;
1908*a248dafdSChristopher Ferris 	else if (max_write_size > m_blockSize)
1909*a248dafdSChristopher Ferris 		max_write_size -= max_write_size % m_blockSize;
1910*a248dafdSChristopher Ferris 	else
1911*a248dafdSChristopher Ferris 		max_write_size = m_blockSize;
1912*a248dafdSChristopher Ferris 
1913*a248dafdSChristopher Ferris 	left_bytes = transfer_leng * m_blockSize;
1914*a248dafdSChristopher Ferris 
1915*a248dafdSChristopher Ferris 	do {
1916*a248dafdSChristopher Ferris 		if (left_bytes / max_write_size)
1917*a248dafdSChristopher Ferris 			write_size = max_write_size;
1918*a248dafdSChristopher Ferris 		else
1919*a248dafdSChristopher Ferris 			write_size = left_bytes;
1920*a248dafdSChristopher Ferris 
1921*a248dafdSChristopher Ferris 		data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
1922*a248dafdSChristopher Ferris 		memcpy(data_temp, data + offset, sizeof(char) * write_size);
1923*a248dafdSChristopher Ferris 		rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
1924*a248dafdSChristopher Ferris 		if (rc != ((ssize_t)sizeof(char) * write_size)) {
1925*a248dafdSChristopher Ferris 			fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
1926*a248dafdSChristopher Ferris 			return UPDATE_FAIL_WRITE_BLOCK;
1927*a248dafdSChristopher Ferris 		}
1928*a248dafdSChristopher Ferris 
1929*a248dafdSChristopher Ferris 		offset += write_size;
1930*a248dafdSChristopher Ferris 		left_bytes -= write_size;
1931*a248dafdSChristopher Ferris 		free(data_temp);
1932*a248dafdSChristopher Ferris 	} while (left_bytes);
1933*a248dafdSChristopher Ferris 
1934*a248dafdSChristopher Ferris 	// Wair for attention for touchpad only.
1935*a248dafdSChristopher Ferris 	rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
1936*a248dafdSChristopher Ferris 	if (rc != UPDATE_SUCCESS) {
1937*a248dafdSChristopher Ferris 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1938*a248dafdSChristopher Ferris 		return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1939*a248dafdSChristopher Ferris 	}
1940*a248dafdSChristopher Ferris 
1941*a248dafdSChristopher Ferris 	//Wait for completion
1942*a248dafdSChristopher Ferris 	do {
1943*a248dafdSChristopher Ferris 		Sleep(20);
1944*a248dafdSChristopher Ferris 		rmi4update_poll();
1945*a248dafdSChristopher Ferris 		if (m_flashStatus == SUCCESS){
1946*a248dafdSChristopher Ferris 			break;
1947*a248dafdSChristopher Ferris 		}
1948*a248dafdSChristopher Ferris 		retry++;
1949*a248dafdSChristopher Ferris 	} while(retry < 20);
1950*a248dafdSChristopher Ferris 
1951*a248dafdSChristopher Ferris 	if (m_flashStatus != SUCCESS) {
1952*a248dafdSChristopher Ferris 		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1953*a248dafdSChristopher Ferris 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1954*a248dafdSChristopher Ferris 	}
1955*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
1956*a248dafdSChristopher Ferris }
1957*a248dafdSChristopher Ferris 
1958*a248dafdSChristopher Ferris /*
1959*a248dafdSChristopher Ferris  * This is a limited implementation of WaitForIdle which assumes WaitForAttention is supported
1960*a248dafdSChristopher Ferris  * this will be true for HID, but other protocols will need to revert polling. Polling
1961*a248dafdSChristopher Ferris  * is not implemented yet.
1962*a248dafdSChristopher Ferris  */
WaitForIdle(int timeout_ms,bool readF34OnSucess)1963*a248dafdSChristopher Ferris int RMI4Update::WaitForIdle(int timeout_ms, bool readF34OnSucess)
1964*a248dafdSChristopher Ferris {
1965*a248dafdSChristopher Ferris 	int rc = 0;
1966*a248dafdSChristopher Ferris 	struct timeval tv;
1967*a248dafdSChristopher Ferris 
1968*a248dafdSChristopher Ferris 	if (timeout_ms > 0) {
1969*a248dafdSChristopher Ferris 		tv.tv_sec = timeout_ms / 1000;
1970*a248dafdSChristopher Ferris 		tv.tv_usec = (timeout_ms % 1000) * 1000;
1971*a248dafdSChristopher Ferris 
1972*a248dafdSChristopher Ferris 		rc = m_device.WaitForAttention(&tv, m_f34.GetInterruptMask());
1973*a248dafdSChristopher Ferris 		if (rc == -ETIMEDOUT){
1974*a248dafdSChristopher Ferris 			/*
1975*a248dafdSChristopher Ferris 			 * If for some reason we are not getting attention reports for HID devices
1976*a248dafdSChristopher Ferris 			 * then we can still continue after the timeout and read F34 status
1977*a248dafdSChristopher Ferris 			 * but if we have to wait for the timeout to ellapse everytime then this
1978*a248dafdSChristopher Ferris 			 * will be slow. If this message shows up a lot then something is wrong
1979*a248dafdSChristopher Ferris 			 * with receiving attention reports and that should be fixed.
1980*a248dafdSChristopher Ferris 			 */
1981*a248dafdSChristopher Ferris 			fprintf(stderr, "RMI4Update::WaitForIdle Timed out waiting for attn report\n");
1982*a248dafdSChristopher Ferris 		}
1983*a248dafdSChristopher Ferris 	}
1984*a248dafdSChristopher Ferris 
1985*a248dafdSChristopher Ferris 	if (rc <= 0 || readF34OnSucess) {
1986*a248dafdSChristopher Ferris 		rc = ReadF34Controls();
1987*a248dafdSChristopher Ferris 		if (rc != UPDATE_SUCCESS)
1988*a248dafdSChristopher Ferris 			return rc;
1989*a248dafdSChristopher Ferris 
1990*a248dafdSChristopher Ferris 		if (!m_f34Status && !m_f34Command) {
1991*a248dafdSChristopher Ferris 			if (!m_programEnabled) {
1992*a248dafdSChristopher Ferris 				fprintf(stderr, "RMI4Update::WaitForIdle Bootloader is idle but program_enabled bit isn't set.\n");
1993*a248dafdSChristopher Ferris 				return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED;
1994*a248dafdSChristopher Ferris 			} else {
1995*a248dafdSChristopher Ferris 				return UPDATE_SUCCESS;
1996*a248dafdSChristopher Ferris 			}
1997*a248dafdSChristopher Ferris 		}
1998*a248dafdSChristopher Ferris 		fprintf(stderr, "RMI4Update::WaitForIdle\n");
1999*a248dafdSChristopher Ferris 		fprintf(stderr, "  ERROR: Waiting for idle status.\n");
2000*a248dafdSChristopher Ferris 		fprintf(stderr, "  Command: %#04x\n", m_f34Command);
2001*a248dafdSChristopher Ferris 		fprintf(stderr, "  Status:  %#04x\n", m_f34Status);
2002*a248dafdSChristopher Ferris 		fprintf(stderr, "  Enabled: %d\n", m_programEnabled);
2003*a248dafdSChristopher Ferris 		fprintf(stderr, "  Idle:    %d\n", !m_f34Command && !m_f34Status);
2004*a248dafdSChristopher Ferris 
2005*a248dafdSChristopher Ferris 		return UPDATE_FAIL_NOT_IN_IDLE_STATE;
2006*a248dafdSChristopher Ferris 	}
2007*a248dafdSChristopher Ferris 
2008*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
2009*a248dafdSChristopher Ferris }
2010*a248dafdSChristopher Ferris 
IsBLv87()2011*a248dafdSChristopher Ferris bool RMI4Update::IsBLv87()
2012*a248dafdSChristopher Ferris {
2013*a248dafdSChristopher Ferris 	if ((m_bootloaderID[1] >= 10) ||
2014*a248dafdSChristopher Ferris 		((m_bootloaderID[1] == 8) && (m_bootloaderID[0] >= 7))){
2015*a248dafdSChristopher Ferris 		return true;
2016*a248dafdSChristopher Ferris 	} else
2017*a248dafdSChristopher Ferris 		return false;
2018*a248dafdSChristopher Ferris }
2019*a248dafdSChristopher Ferris 
ReadMSL()2020*a248dafdSChristopher Ferris int RMI4Update::ReadMSL()
2021*a248dafdSChristopher Ferris {
2022*a248dafdSChristopher Ferris 	int rc;
2023*a248dafdSChristopher Ferris 	unsigned char idStr[3];
2024*a248dafdSChristopher Ferris 	unsigned short query9Addr = m_f34.GetQueryBase() + 9;
2025*a248dafdSChristopher Ferris 	unsigned char offset;
2026*a248dafdSChristopher Ferris 	unsigned char MSL[2];
2027*a248dafdSChristopher Ferris 
2028*a248dafdSChristopher Ferris 	rc = m_device.Read(query9Addr, MSL, sizeof(MSL));
2029*a248dafdSChristopher Ferris 	if (rc != sizeof(MSL))
2030*a248dafdSChristopher Ferris 		return UPDATE_FAIL_READ_F34_QUERIES;
2031*a248dafdSChristopher Ferris 
2032*a248dafdSChristopher Ferris 	m_MSL = MSL[0] << 8 | MSL[1];
2033*a248dafdSChristopher Ferris 	return UPDATE_SUCCESS;
2034*a248dafdSChristopher Ferris }
2035