blob: f8fe3880ddf2af7782f96822e0557bd79854c9b0 [file] [log] [blame]
Andrew Duggan052556f2014-04-16 11:32:30 -07001/*
2 * Copyright (C) 2014 Andrew Duggan
3 * Copyright (C) 2014 Synaptics Inc
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Andrew Duggan4e811252014-04-03 15:17:57 -070018#include <alloca.h>
19#include <time.h>
20#include <stdint.h>
21#include <stdio.h>
22#include <unistd.h>
23#include <string.h>
24#include <stdlib.h>
Andrew Duggan62137912014-05-06 16:06:19 -070025#include <errno.h>
Andrew Duggan4e811252014-04-03 15:17:57 -070026
27#include "rmi4update.h"
28
29#define RMI_F34_QUERY_SIZE 7
30#define RMI_F34_HAS_NEW_REG_MAP (1 << 0)
31#define RMI_F34_IS_UNLOCKED (1 << 1)
32#define RMI_F34_HAS_CONFIG_ID (1 << 2)
33#define RMI_F34_BLOCK_SIZE_OFFSET 1
34#define RMI_F34_FW_BLOCKS_OFFSET 3
35#define RMI_F34_CONFIG_BLOCKS_OFFSET 5
36
Andrew Duggana90829b2014-05-23 12:34:31 -070037#define RMI_F34_BLOCK_SIZE_V1_OFFSET 0
38#define RMI_F34_FW_BLOCKS_V1_OFFSET 0
39#define RMI_F34_CONFIG_BLOCKS_V1_OFFSET 2
40
Andrew Duggan4e811252014-04-03 15:17:57 -070041#define RMI_F34_BLOCK_DATA_OFFSET 2
Andrew Duggana90829b2014-05-23 12:34:31 -070042#define RMI_F34_BLOCK_DATA_V1_OFFSET 1
Andrew Duggan4e811252014-04-03 15:17:57 -070043
44#define RMI_F34_COMMAND_MASK 0x0F
45#define RMI_F34_STATUS_MASK 0x07
46#define RMI_F34_STATUS_SHIFT 4
47#define RMI_F34_ENABLED_MASK 0x80
48
Andrew Duggana90829b2014-05-23 12:34:31 -070049#define RMI_F34_COMMAND_V1_MASK 0x3F
50#define RMI_F34_STATUS_V1_MASK 0x3F
51#define RMI_F34_ENABLED_V1_MASK 0x80
52
Andrew Duggan4e811252014-04-03 15:17:57 -070053#define RMI_F34_WRITE_FW_BLOCK 0x02
54#define RMI_F34_ERASE_ALL 0x03
55#define RMI_F34_WRITE_LOCKDOWN_BLOCK 0x04
56#define RMI_F34_WRITE_CONFIG_BLOCK 0x06
57#define RMI_F34_ENABLE_FLASH_PROG 0x0f
58
59#define RMI_F34_ENABLE_WAIT_MS 300
60#define RMI_F34_ERASE_WAIT_MS (5 * 1000)
61#define RMI_F34_IDLE_WAIT_MS 500
62
63/* Most recent device status event */
64#define RMI_F01_STATUS_CODE(status) ((status) & 0x0f)
65/* Indicates that flash programming is enabled (bootloader mode). */
66#define RMI_F01_STATUS_BOOTLOADER(status) (!!((status) & 0x40))
67/* The device has lost its configuration for some reason. */
68#define RMI_F01_STATUS_UNCONFIGURED(status) (!!((status) & 0x80))
69
70/*
71 * Sleep mode controls power management on the device and affects all
72 * functions of the device.
73 */
74#define RMI_F01_CTRL0_SLEEP_MODE_MASK 0x03
75
76#define RMI_SLEEP_MODE_NORMAL 0x00
77#define RMI_SLEEP_MODE_SENSOR_SLEEP 0x01
78#define RMI_SLEEP_MODE_RESERVED0 0x02
79#define RMI_SLEEP_MODE_RESERVED1 0x03
80
81/*
82 * This bit disables whatever sleep mode may be selected by the sleep_mode
83 * field and forces the device to run at full power without sleeping.
84 */
85#define RMI_F01_CRTL0_NOSLEEP_BIT (1 << 2)
86
Satoshi Noguchia0b675a2014-09-29 02:38:14 -070087int RMI4Update::UpdateFirmware(bool force, bool performLockdown)
Andrew Duggan4e811252014-04-03 15:17:57 -070088{
89 struct timespec start;
90 struct timespec end;
Andrew Duggan65e55532014-04-04 16:59:54 -070091 long long int duration_us = 0;
Andrew Duggan4e811252014-04-03 15:17:57 -070092 int rc;
93 const unsigned char eraseAll = RMI_F34_ERASE_ALL;
94
95 rc = FindUpdateFunctions();
96 if (rc != UPDATE_SUCCESS)
97 return rc;
98
99 rc = m_device.QueryBasicProperties();
100 if (rc < 0)
101 return UPDATE_FAIL_QUERY_BASIC_PROPERTIES;
102
103 fprintf(stdout, "Device Properties:\n");
104 m_device.PrintProperties();
105
106 rc = ReadF34Queries();
107 if (rc != UPDATE_SUCCESS)
108 return rc;
109
Andrew Duggan050db0e2014-07-29 12:42:49 -0700110 rc = m_firmwareImage.VerifyImageMatchesDevice(GetFirmwareSize(), GetConfigSize());
Andrew Duggan4e811252014-04-03 15:17:57 -0700111 if (rc != UPDATE_SUCCESS)
112 return rc;
113
114 rc = EnterFlashProgramming();
115 if (rc != UPDATE_SUCCESS) {
116 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
117 return rc;
118 }
119
120 if (!force && m_firmwareImage.HasIO()) {
121 if (m_firmwareImage.GetFirmwareID() <= m_device.GetFirmwareID()) {
122 m_device.Reset();
123 return UPDATE_FAIL_FIRMWARE_IMAGE_IS_OLDER;
124 }
125 }
126
Satoshi Noguchia0b675a2014-09-29 02:38:14 -0700127 if (performLockdown && m_unlocked) {
Andrew Duggan4e811252014-04-03 15:17:57 -0700128 if (m_firmwareImage.GetLockdownData()) {
129 fprintf(stdout, "Writing lockdown...\n");
130 clock_gettime(CLOCK_MONOTONIC, &start);
131 rc = WriteBlocks(m_firmwareImage.GetLockdownData(),
132 m_firmwareImage.GetLockdownSize() / 0x10,
133 RMI_F34_WRITE_LOCKDOWN_BLOCK);
134 if (rc != UPDATE_SUCCESS) {
135 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
136 return rc;
137 }
138 clock_gettime(CLOCK_MONOTONIC, &end);
Andrew Duggan65e55532014-04-04 16:59:54 -0700139 duration_us = diff_time(&start, &end);
140 fprintf(stdout, "Done writing lockdown, time: %lld us.\n", duration_us);
Andrew Duggan4e811252014-04-03 15:17:57 -0700141 }
142
143 rc = EnterFlashProgramming();
144 if (rc != UPDATE_SUCCESS) {
145 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
146 return rc;
147 }
148
149 }
150
151 rc = WriteBootloaderID();
152 if (rc != UPDATE_SUCCESS) {
153 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
154 return rc;
155 }
156
157 fprintf(stdout, "Erasing FW...\n");
158 clock_gettime(CLOCK_MONOTONIC, &start);
159 rc = m_device.Write(m_f34StatusAddr, &eraseAll, 1);
160 if (rc < 0) {
161 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(UPDATE_FAIL_ERASE_ALL));
162 return UPDATE_FAIL_ERASE_ALL;
163 }
164
165 rc = WaitForIdle(RMI_F34_ERASE_WAIT_MS);
166 if (rc != UPDATE_SUCCESS) {
167 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
168 return rc;
169 }
170 clock_gettime(CLOCK_MONOTONIC, &end);
Andrew Duggan65e55532014-04-04 16:59:54 -0700171 duration_us = diff_time(&start, &end);
172 fprintf(stdout, "Erase complete, time: %lld us.\n", duration_us);
Andrew Duggan4e811252014-04-03 15:17:57 -0700173
174 if (m_firmwareImage.GetFirmwareData()) {
175 fprintf(stdout, "Writing firmware...\n");
176 clock_gettime(CLOCK_MONOTONIC, &start);
177 rc = WriteBlocks(m_firmwareImage.GetFirmwareData(), m_fwBlockCount,
178 RMI_F34_WRITE_FW_BLOCK);
179 if (rc != UPDATE_SUCCESS) {
180 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
181 return rc;
182 }
183 clock_gettime(CLOCK_MONOTONIC, &end);
Andrew Duggan65e55532014-04-04 16:59:54 -0700184 duration_us = diff_time(&start, &end);
185 fprintf(stdout, "Done writing FW, time: %lld us.\n", duration_us);
Andrew Duggan4e811252014-04-03 15:17:57 -0700186 }
187
188 if (m_firmwareImage.GetConfigData()) {
189 fprintf(stdout, "Writing configuration...\n");
190 clock_gettime(CLOCK_MONOTONIC, &start);
191 rc = WriteBlocks(m_firmwareImage.GetConfigData(), m_configBlockCount,
192 RMI_F34_WRITE_CONFIG_BLOCK);
193 if (rc != UPDATE_SUCCESS) {
194 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
195 return rc;
196 }
197 clock_gettime(CLOCK_MONOTONIC, &end);
Andrew Duggan65e55532014-04-04 16:59:54 -0700198 duration_us = diff_time(&start, &end);
199 fprintf(stdout, "Done writing config, time: %lld us.\n", duration_us);
Andrew Duggan4e811252014-04-03 15:17:57 -0700200 }
201 m_device.Reset();
202
203 return UPDATE_SUCCESS;
204
205}
206
207int RMI4Update::FindUpdateFunctions()
208{
209 if (0 > m_device.ScanPDT())
210 return UPDATE_FAIL_SCAN_PDT;
211
212 if (!m_device.GetFunction(m_f01, 0x01))
213 return UPDATE_FAIL_NO_FUNCTION_01;
214
215 if (!m_device.GetFunction(m_f34, 0x34))
216 return UPDATE_FAIL_NO_FUNCTION_34;
217
218 return UPDATE_SUCCESS;
219}
220
221int RMI4Update::ReadF34Queries()
222{
223 int rc;
224 unsigned char idStr[3];
Andrew Duggana90829b2014-05-23 12:34:31 -0700225 unsigned char buf[8];
Andrew Duggan4e811252014-04-03 15:17:57 -0700226 unsigned short queryAddr = m_f34.GetQueryBase();
Andrew Duggana90829b2014-05-23 12:34:31 -0700227 unsigned short f34Version = m_f34.GetFunctionVersion();
228 unsigned short querySize;
229
230 if (f34Version == 0x1)
231 querySize = 8;
232 else
233 querySize = 2;
Andrew Duggan4e811252014-04-03 15:17:57 -0700234
235 rc = m_device.Read(queryAddr, m_bootloaderID, RMI_BOOTLOADER_ID_SIZE);
236 if (rc < 0)
237 return UPDATE_FAIL_READ_BOOTLOADER_ID;
238
Andrew Duggana90829b2014-05-23 12:34:31 -0700239 if (f34Version == 0x1)
240 ++queryAddr;
241 else
242 queryAddr += querySize;
Andrew Duggan4e811252014-04-03 15:17:57 -0700243
Andrew Duggana90829b2014-05-23 12:34:31 -0700244 if (f34Version == 0x1) {
245 rc = m_device.Read(queryAddr, buf, 1);
246 if (rc < 0)
247 return UPDATE_FAIL_READ_F34_QUERIES;
Andrew Duggan4e811252014-04-03 15:17:57 -0700248
Andrew Duggana90829b2014-05-23 12:34:31 -0700249 m_hasNewRegmap = buf[0] & RMI_F34_HAS_NEW_REG_MAP;
250 m_unlocked = buf[0] & RMI_F34_IS_UNLOCKED;;
251 m_hasConfigID = buf[0] & RMI_F34_HAS_CONFIG_ID;
252
253 ++queryAddr;
254
255 rc = m_device.Read(queryAddr, buf, 2);
256 if (rc < 0)
257 return UPDATE_FAIL_READ_F34_QUERIES;
258
259 m_blockSize = extract_short(buf + RMI_F34_BLOCK_SIZE_V1_OFFSET);
260
261 ++queryAddr;
262
263 rc = m_device.Read(queryAddr, buf, 8);
264 if (rc < 0)
265 return UPDATE_FAIL_READ_F34_QUERIES;
266
267 m_fwBlockCount = extract_short(buf + RMI_F34_FW_BLOCKS_V1_OFFSET);
268 m_configBlockCount = extract_short(buf + RMI_F34_CONFIG_BLOCKS_V1_OFFSET);
269 } else {
270 rc = m_device.Read(queryAddr, buf, RMI_F34_QUERY_SIZE);
271 if (rc < 0)
272 return UPDATE_FAIL_READ_F34_QUERIES;
273
274 m_hasNewRegmap = buf[0] & RMI_F34_HAS_NEW_REG_MAP;
275 m_unlocked = buf[0] & RMI_F34_IS_UNLOCKED;;
276 m_hasConfigID = buf[0] & RMI_F34_HAS_CONFIG_ID;
277 m_blockSize = extract_short(buf + RMI_F34_BLOCK_SIZE_OFFSET);
278 m_fwBlockCount = extract_short(buf + RMI_F34_FW_BLOCKS_OFFSET);
279 m_configBlockCount = extract_short(buf + RMI_F34_CONFIG_BLOCKS_OFFSET);
280 }
Andrew Duggan4e811252014-04-03 15:17:57 -0700281
282 idStr[0] = m_bootloaderID[0];
283 idStr[1] = m_bootloaderID[1];
284 idStr[2] = 0;
285
286 fprintf(stdout, "F34 bootloader id: %s (%#04x %#04x)\n", idStr, m_bootloaderID[0],
287 m_bootloaderID[1]);
288 fprintf(stdout, "F34 has config id: %d\n", m_hasConfigID);
289 fprintf(stdout, "F34 unlocked: %d\n", m_unlocked);
290 fprintf(stdout, "F34 new reg map: %d\n", m_hasNewRegmap);
291 fprintf(stdout, "F34 block size: %d\n", m_blockSize);
292 fprintf(stdout, "F34 fw blocks: %d\n", m_fwBlockCount);
293 fprintf(stdout, "F34 config blocks: %d\n", m_configBlockCount);
294 fprintf(stdout, "\n");
295
Andrew Duggana90829b2014-05-23 12:34:31 -0700296 if (f34Version == 0x1)
297 m_f34StatusAddr = m_f34.GetDataBase() + 2;
298 else
299 m_f34StatusAddr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_OFFSET + m_blockSize;
Andrew Duggan4e811252014-04-03 15:17:57 -0700300
301 return UPDATE_SUCCESS;
302}
303
304int RMI4Update::ReadF34Controls()
305{
306 int rc;
Andrew Duggana90829b2014-05-23 12:34:31 -0700307 unsigned char buf[2];
Andrew Duggan4e811252014-04-03 15:17:57 -0700308
Andrew Duggana90829b2014-05-23 12:34:31 -0700309 if (m_f34.GetFunctionVersion() == 0x1) {
310 rc = m_device.Read(m_f34StatusAddr, buf, 2);
311 if (rc < 0)
312 return UPDATE_FAIL_READ_F34_CONTROLS;
Andrew Duggan4e811252014-04-03 15:17:57 -0700313
Andrew Duggana90829b2014-05-23 12:34:31 -0700314 m_f34Command = buf[0] & RMI_F34_COMMAND_V1_MASK;
315 m_f34Status = buf[1] & RMI_F34_STATUS_V1_MASK;
316 m_programEnabled = !!(buf[1] & RMI_F34_ENABLED_MASK);
317
318 } else {
319 rc = m_device.Read(m_f34StatusAddr, buf, 1);
320 if (rc < 0)
321 return UPDATE_FAIL_READ_F34_CONTROLS;
322
323 m_f34Command = buf[0] & RMI_F34_COMMAND_MASK;
324 m_f34Status = (buf[0] >> RMI_F34_STATUS_SHIFT) & RMI_F34_STATUS_MASK;
325 m_programEnabled = !!(buf[0] & RMI_F34_ENABLED_MASK);
326 }
Andrew Duggan4e811252014-04-03 15:17:57 -0700327
328 return UPDATE_SUCCESS;
329}
330
331int RMI4Update::WriteBootloaderID()
332{
333 int rc;
Andrew Duggana90829b2014-05-23 12:34:31 -0700334 int blockDataOffset = RMI_F34_BLOCK_DATA_OFFSET;
Andrew Duggan4e811252014-04-03 15:17:57 -0700335
Andrew Duggana90829b2014-05-23 12:34:31 -0700336 if (m_f34.GetFunctionVersion() == 0x1)
337 blockDataOffset = RMI_F34_BLOCK_DATA_V1_OFFSET;
338
339 rc = m_device.Write(m_f34.GetDataBase() + blockDataOffset,
Andrew Duggan4e811252014-04-03 15:17:57 -0700340 m_bootloaderID, RMI_BOOTLOADER_ID_SIZE);
341 if (rc < 0)
342 return UPDATE_FAIL_WRITE_BOOTLOADER_ID;
343
344 return UPDATE_SUCCESS;
345}
346
347int RMI4Update::EnterFlashProgramming()
348{
349 int rc;
350 unsigned char f01Control_0;
351 const unsigned char enableProg = RMI_F34_ENABLE_FLASH_PROG;
352
353 rc = WriteBootloaderID();
354 if (rc != UPDATE_SUCCESS)
355 return rc;
356
357 fprintf(stdout, "Enabling flash programming.\n");
358 rc = m_device.Write(m_f34StatusAddr, &enableProg, 1);
359 if (rc < 0)
360 return UPDATE_FAIL_ENABLE_FLASH_PROGRAMMING;
361
362 rc = WaitForIdle(RMI_F34_ENABLE_WAIT_MS);
363 if (rc != UPDATE_SUCCESS)
364 return UPDATE_FAIL_NOT_IN_IDLE_STATE;
365
366 if (!m_programEnabled)
367 return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED;
368
Andrew Duggan62137912014-05-06 16:06:19 -0700369 fprintf(stdout, "Programming is enabled.\n");
Andrew Duggan4e811252014-04-03 15:17:57 -0700370 rc = FindUpdateFunctions();
371 if (rc != UPDATE_SUCCESS)
372 return rc;
373
374 rc = m_device.Read(m_f01.GetDataBase(), &m_deviceStatus, 1);
375 if (rc < 0)
376 return UPDATE_FAIL_READ_DEVICE_STATUS;
377
378 if (!RMI_F01_STATUS_BOOTLOADER(m_deviceStatus))
379 return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
380
381 rc = ReadF34Queries();
382 if (rc != UPDATE_SUCCESS)
383 return rc;
384
385 rc = m_device.Read(m_f01.GetControlBase(), &f01Control_0, 1);
386 if (rc < 0)
387 return UPDATE_FAIL_READ_F01_CONTROL_0;
388
389 f01Control_0 |= RMI_F01_CRTL0_NOSLEEP_BIT;
390 f01Control_0 = (f01Control_0 & ~RMI_F01_CTRL0_SLEEP_MODE_MASK) | RMI_SLEEP_MODE_NORMAL;
391
392 rc = m_device.Write(m_f01.GetControlBase(), &f01Control_0, 1);
393 if (rc < 0)
394 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
395
396 return UPDATE_SUCCESS;
397}
398
399int RMI4Update::WriteBlocks(unsigned char *block, unsigned short count, unsigned char cmd)
400{
401 int blockNum;
402 unsigned char zeros[] = { 0, 0 };
403 int rc;
Andrew Duggana90829b2014-05-23 12:34:31 -0700404 unsigned short addr;
405
406 if (m_f34.GetFunctionVersion() == 0x1)
407 addr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_V1_OFFSET;
408 else
409 addr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_OFFSET;
Andrew Duggan4e811252014-04-03 15:17:57 -0700410
411 rc = m_device.Write(m_f34.GetDataBase(), zeros, 2);
412 if (rc < 0)
413 return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
414
415 for (blockNum = 0; blockNum < count; ++blockNum) {
416 rc = m_device.Write(addr, block, m_blockSize);
417 if (rc < 0) {
418 fprintf(stderr, "failed to write block %d\n", blockNum);
419 return UPDATE_FAIL_WRITE_BLOCK;
420 }
421
Andrew Duggan4e811252014-04-03 15:17:57 -0700422 rc = m_device.Write(m_f34StatusAddr, &cmd, 1);
423 if (rc < 0) {
424 fprintf(stderr, "failed to write command for block %d\n", blockNum);
425 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
426 }
427
428 rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS);
429 if (rc != UPDATE_SUCCESS) {
430 fprintf(stderr, "failed to go into idle after writing block %d\n", blockNum);
431 return UPDATE_FAIL_NOT_IN_IDLE_STATE;
432 }
433
434 block += m_blockSize;
435 }
436
437 return UPDATE_SUCCESS;
438}
439
440/*
441 * This is a limited implementation of WaitForIdle which assumes WaitForAttention is supported
442 * this will be true for HID, but other protocols will need to revert polling. Polling
443 * is not implemented yet.
444 */
445int RMI4Update::WaitForIdle(int timeout_ms)
446{
447 int rc;
448 struct timeval tv;
449
450 tv.tv_sec = timeout_ms / 1000;
451 tv.tv_usec = (timeout_ms % 1000) * 1000;
452
453 rc = m_device.WaitForAttention(&tv);
Andrew Duggan62137912014-05-06 16:06:19 -0700454 if (rc == -ETIMEDOUT)
455 /*
456 * If for some reason we are not getting attention reports for HID devices
457 * then we can still continue after the timeout and read F34 status
458 * but if we have to wait for the timeout to ellapse everytime then this
459 * will be slow. If this message shows up a lot then something is wrong
460 * with receiving attention reports and that should be fixed.
461 */
462 fprintf(stderr, "Timed out waiting for attn report\n");
Andrew Duggan4e811252014-04-03 15:17:57 -0700463
Andrew Duggan62137912014-05-06 16:06:19 -0700464 rc = ReadF34Controls();
465 if (rc != UPDATE_SUCCESS)
466 return rc;
467
468 if (!m_f34Status && !m_f34Command) {
469 if (!m_programEnabled) {
470 fprintf(stderr, "Bootloader is idle but program_enabled bit isn't set.\n");
471 return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED;
472 } else {
473 return UPDATE_SUCCESS;
Andrew Duggan4e811252014-04-03 15:17:57 -0700474 }
Andrew Duggan4e811252014-04-03 15:17:57 -0700475 }
Andrew Duggan62137912014-05-06 16:06:19 -0700476
477 fprintf(stderr, "ERROR: Waiting for idle status.\n");
478 fprintf(stderr, "Command: %#04x\n", m_f34Command);
479 fprintf(stderr, "Status: %#04x\n", m_f34Status);
480 fprintf(stderr, "Enabled: %d\n", m_programEnabled);
481 fprintf(stderr, "Idle: %d\n", !m_f34Command && !m_f34Status);
482
483 return UPDATE_FAIL_NOT_IN_IDLE_STATE;
Andrew Duggan050db0e2014-07-29 12:42:49 -0700484}