1 /*
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
18 #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>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <linux/input.h>
28 #include "rmi4update.h"
29
30 #define RMI_F34_QUERY_SIZE 7
31 #define RMI_F34_HAS_NEW_REG_MAP (1 << 0)
32 #define RMI_F34_IS_UNLOCKED (1 << 1)
33 #define RMI_F34_HAS_CONFIG_ID (1 << 2)
34 #define RMI_F34_BLOCK_SIZE_OFFSET 1
35 #define RMI_F34_FW_BLOCKS_OFFSET 3
36 #define RMI_F34_CONFIG_BLOCKS_OFFSET 5
37
38 #define RMI_F34_BLOCK_SIZE_V1_OFFSET 0
39 #define RMI_F34_FW_BLOCKS_V1_OFFSET 0
40 #define RMI_F34_CONFIG_BLOCKS_V1_OFFSET 2
41
42 #define RMI_F34_BLOCK_DATA_OFFSET 2
43 #define RMI_F34_BLOCK_DATA_V1_OFFSET 1
44
45 #define RMI_F34_COMMAND_MASK 0x0F
46 #define RMI_F34_STATUS_MASK 0x07
47 #define RMI_F34_STATUS_SHIFT 4
48 #define RMI_F34_ENABLED_MASK 0x80
49
50 #define RMI_F34_COMMAND_V1_MASK 0x3F
51 #define RMI_F34_STATUS_V1_MASK 0x3F
52 #define RMI_F34_ENABLED_V1_MASK 0x80
53
54 #define RMI_F34_WRITE_FW_BLOCK 0x02
55 #define RMI_F34_ERASE_ALL 0x03
56 #define RMI_F34_WRITE_LOCKDOWN_BLOCK 0x04
57 #define RMI_F34_WRITE_CONFIG_BLOCK 0x06
58 #define RMI_F34_ENABLE_FLASH_PROG 0x0f
59
60 #define RMI_F34_ENABLE_WAIT_MS 300
61 #define RMI_F34_ERASE_WAIT_MS (5 * 1000)
62 #define RMI_F34_ERASE_V8_WAIT_MS (10000)
63 #define RMI_F34_IDLE_WAIT_MS 500
64
65 /* Most recent device status event */
66 #define RMI_F01_STATUS_CODE(status) ((status) & 0x0f)
67 /* Indicates that flash programming is enabled (bootloader mode). */
68 #define RMI_F01_STATUS_BOOTLOADER(status) (!!((status) & 0x40))
69 /* The device has lost its configuration for some reason. */
70 #define RMI_F01_STATUS_UNCONFIGURED(status) (!!((status) & 0x80))
71
72 /* Indicates that flash programming is enabled V7(bootloader mode). */
73 #define RMI_F01_STATUS_BOOTLOADER_v7(status) (!!((status) & 0x80))
74
75 /*
76 * Sleep mode controls power management on the device and affects all
77 * functions of the device.
78 */
79 #define RMI_F01_CTRL0_SLEEP_MODE_MASK 0x03
80
81 #define RMI_SLEEP_MODE_NORMAL 0x00
82 #define RMI_SLEEP_MODE_SENSOR_SLEEP 0x01
83 #define RMI_SLEEP_MODE_RESERVED0 0x02
84 #define RMI_SLEEP_MODE_RESERVED1 0x03
85
86 /*
87 * This bit disables whatever sleep mode may be selected by the sleep_mode
88 * field and forces the device to run at full power without sleeping.
89 */
90 #define RMI_F01_CRTL0_NOSLEEP_BIT (1 << 2)
91
UpdateFirmware(bool force,bool performLockdown)92 int RMI4Update::UpdateFirmware(bool force, bool performLockdown)
93 {
94 struct timespec start;
95 struct timespec end;
96 long long int duration_us = 0;
97 int rc;
98 const unsigned char eraseAll = RMI_F34_ERASE_ALL;
99 rc = FindUpdateFunctions();
100 if (rc != UPDATE_SUCCESS)
101 return rc;
102
103 rc = m_device.QueryBasicProperties();
104 if (rc < 0)
105 return UPDATE_FAIL_QUERY_BASIC_PROPERTIES;
106
107 if (!force && m_firmwareImage.HasIO()) {
108 if (m_firmwareImage.GetFirmwareID() <= m_device.GetFirmwareID()) {
109 fprintf(stderr, "Firmware image (%ld) is not newer then the firmware on the device (%ld)\n",
110 m_firmwareImage.GetFirmwareID(), m_device.GetFirmwareID());
111 rc = UPDATE_FAIL_FIRMWARE_IMAGE_IS_OLDER;
112 return rc;
113 }
114 }
115
116 fprintf(stdout, "Device Properties:\n");
117 m_device.PrintProperties();
118
119 rc = DisableNonessentialInterupts();
120 if (rc != UPDATE_SUCCESS)
121 return rc;
122
123 rc = ReadF34Queries();
124 if (rc != UPDATE_SUCCESS)
125 return rc;
126 rc = m_firmwareImage.VerifyImageMatchesDevice(GetFirmwareSize(), GetConfigSize());
127 if (rc != UPDATE_SUCCESS)
128 return rc;
129
130 if (m_f34.GetFunctionVersion() == 0x02) {
131 fprintf(stdout, "Enable Flash V7+...\n");
132 rc = EnterFlashProgrammingV7();
133 if (rc != UPDATE_SUCCESS) {
134 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
135 goto reset;
136 }
137 fprintf(stdout, "Enable Flash done V7+...\n");
138
139 if (!m_IsErased){
140 fprintf(stdout, "Erasing FW V7+...\n");
141 rc = EraseFirmwareV7();
142 if (rc != UPDATE_SUCCESS) {
143 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
144 goto reset;
145 }
146 fprintf(stdout, "Erasing FW done V7+...\n");
147 }
148 if(m_bootloaderID[1] == 8){
149 if (m_firmwareImage.GetFlashConfigData()) {
150 fprintf(stdout, "Writing flash configuration V8...\n");
151 rc = WriteFlashConfigV7();
152 if (rc != UPDATE_SUCCESS) {
153 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
154 goto reset;
155 }
156 fprintf(stdout, "Writing flash config done V8...\n");
157 }
158 }
159 if (m_firmwareImage.GetFirmwareData()) {
160 fprintf(stdout, "Writing firmware V7+...\n");
161 rc = WriteFirmwareV7();
162 if (rc != UPDATE_SUCCESS) {
163 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
164 goto reset;
165 }
166 fprintf(stdout, "Writing firmware done V7+...\n");
167 }
168 if (m_firmwareImage.GetConfigData()) {
169 fprintf(stdout, "Writing core configuration V7+...\n");
170 rc = WriteCoreConfigV7();
171 if (rc != UPDATE_SUCCESS) {
172 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
173 goto reset;
174 }
175 fprintf(stdout, "Writing core config done V7+...\n");
176 goto reset;
177 }
178
179 } else {
180 rc = EnterFlashProgramming();
181 if (rc != UPDATE_SUCCESS) {
182 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
183 goto reset;
184 }
185 }
186
187 if (performLockdown && m_unlocked) {
188 if (m_firmwareImage.GetLockdownData()) {
189 fprintf(stdout, "Writing lockdown...\n");
190 clock_gettime(CLOCK_MONOTONIC, &start);
191 rc = WriteBlocks(m_firmwareImage.GetLockdownData(),
192 m_firmwareImage.GetLockdownSize() / 0x10,
193 RMI_F34_WRITE_LOCKDOWN_BLOCK);
194 if (rc != UPDATE_SUCCESS) {
195 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
196 goto reset;
197 }
198 clock_gettime(CLOCK_MONOTONIC, &end);
199 duration_us = diff_time(&start, &end);
200 fprintf(stdout, "Done writing lockdown, time: %lld us.\n", duration_us);
201 }
202
203 rc = EnterFlashProgramming();
204 if (rc != UPDATE_SUCCESS) {
205 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
206 goto reset;
207 }
208 }
209
210 rc = WriteBootloaderID();
211 if (rc != UPDATE_SUCCESS) {
212 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
213 goto reset;
214 }
215
216 fprintf(stdout, "Erasing FW...\n");
217 clock_gettime(CLOCK_MONOTONIC, &start);
218 rc = m_device.Write(m_f34StatusAddr, &eraseAll, 1);
219 if (rc != 1) {
220 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(UPDATE_FAIL_ERASE_ALL));
221 rc = UPDATE_FAIL_ERASE_ALL;
222 goto reset;
223 }
224
225 rc = WaitForIdle(RMI_F34_ERASE_WAIT_MS);
226 if (rc != UPDATE_SUCCESS) {
227 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
228 goto reset;
229 }
230 clock_gettime(CLOCK_MONOTONIC, &end);
231 duration_us = diff_time(&start, &end);
232 fprintf(stdout, "Erase complete, time: %lld us.\n", duration_us);
233
234 if (m_firmwareImage.GetFirmwareData()) {
235 fprintf(stdout, "Writing firmware...\n");
236 clock_gettime(CLOCK_MONOTONIC, &start);
237 rc = WriteBlocks(m_firmwareImage.GetFirmwareData(), m_fwBlockCount,
238 RMI_F34_WRITE_FW_BLOCK);
239 if (rc != UPDATE_SUCCESS) {
240 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
241 goto reset;
242 }
243 clock_gettime(CLOCK_MONOTONIC, &end);
244 duration_us = diff_time(&start, &end);
245 fprintf(stdout, "Done writing FW, time: %lld us.\n", duration_us);
246 }
247
248 if (m_firmwareImage.GetConfigData()) {
249 fprintf(stdout, "Writing configuration...\n");
250 clock_gettime(CLOCK_MONOTONIC, &start);
251 rc = WriteBlocks(m_firmwareImage.GetConfigData(), m_configBlockCount,
252 RMI_F34_WRITE_CONFIG_BLOCK);
253 if (rc != UPDATE_SUCCESS) {
254 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
255 goto reset;
256 }
257 clock_gettime(CLOCK_MONOTONIC, &end);
258 duration_us = diff_time(&start, &end);
259 fprintf(stdout, "Done writing config, time: %lld us.\n", duration_us);
260 }
261
262 reset:
263 m_device.Reset();
264 rebind:
265 m_device.RebindDriver();
266 if(!m_device.CheckABSEvent())
267 {
268 goto rebind;
269 }
270
271 // In order to print out new PR
272 rc = FindUpdateFunctions();
273 if (rc != UPDATE_SUCCESS)
274 return rc;
275
276 rc = m_device.QueryBasicProperties();
277 if (rc < 0)
278 return UPDATE_FAIL_QUERY_BASIC_PROPERTIES;
279 fprintf(stdout, "Device Properties:\n");
280 m_device.PrintProperties();
281
282 return rc;
283
284 }
285
DisableNonessentialInterupts()286 int RMI4Update::DisableNonessentialInterupts()
287 {
288 int rc;
289 unsigned char interruptEnabeMask = m_f34.GetInterruptMask() | m_f01.GetInterruptMask();
290
291 rc = m_device.Write(m_f01.GetControlBase() + 1, &interruptEnabeMask, 1);
292 if (rc != 1)
293 return rc;
294
295 return UPDATE_SUCCESS;
296 }
297
FindUpdateFunctions()298 int RMI4Update::FindUpdateFunctions()
299 {
300 if (0 > m_device.ScanPDT())
301 return UPDATE_FAIL_SCAN_PDT;
302
303 if (!m_device.GetFunction(m_f01, 0x01))
304 return UPDATE_FAIL_NO_FUNCTION_01;
305
306 if (!m_device.GetFunction(m_f34, 0x34))
307 return UPDATE_FAIL_NO_FUNCTION_34;
308
309 return UPDATE_SUCCESS;
310 }
311
rmi4update_poll()312 int RMI4Update::rmi4update_poll()
313 {
314 unsigned char f34_status;
315 unsigned short dataAddr = m_f34.GetDataBase();
316 int rc;
317
318 rc = m_device.Read(dataAddr, &f34_status, sizeof(unsigned char));
319 if (rc != sizeof(unsigned char))
320 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
321
322 m_flashStatus = f34_status & 0x1F;
323 m_inBLmode = f34_status & 0x80;
324 if(!m_flashStatus)
325 rc = m_device.Read(dataAddr + 4, &m_flashCmd, sizeof(unsigned char));
326
327 return 0;
328 }
329
ReadFlashConfig()330 int RMI4Update::ReadFlashConfig()
331 {
332 int rc;
333 int transaction_count, remain_block;
334 unsigned char *flash_cfg;
335 int transfer_leng = 0;
336 int read_leng = 0;
337 int offset = 0;
338 unsigned char trans_leng_buf[2];
339 unsigned char cmd_buf[1];
340 unsigned char off[2] = {0, 0};
341 unsigned char partition_id = FLASH_CONFIG_PARTITION;
342 unsigned short dataAddr = m_f34.GetDataBase();
343 int i;
344 int retry = 0;
345 unsigned char *data_temp;
346 struct partition_tbl *partition_temp;
347
348 flash_cfg = (unsigned char *)malloc(m_blockSize * m_flashConfigLength);
349 memset(flash_cfg, 0, m_blockSize * m_flashConfigLength);
350 partition_temp = (partition_tbl *)malloc(sizeof(struct partition_tbl));
351 memset(partition_temp, 0, sizeof(struct partition_tbl));
352 /* calculate the count */
353 remain_block = (m_flashConfigLength % m_payloadLength);
354 transaction_count = (m_flashConfigLength / m_payloadLength);
355
356 if (remain_block > 0)
357 transaction_count++;
358
359 /* set partition id for bootloader 7 */
360 rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
361 if (rc != sizeof(partition_id))
362 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
363 rc = m_device.Write(dataAddr + 2, off, sizeof(off));
364 if (rc != sizeof(off))
365 return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
366
367 for (i = 0; i < transaction_count; i++)
368 {
369 if ((i == (transaction_count -1)) && (remain_block > 0))
370 transfer_leng = remain_block;
371 else
372 transfer_leng = m_payloadLength;
373
374 // Set Transfer Length
375 trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
376 trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
377 rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
378 if (rc != sizeof(trans_leng_buf))
379 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
380
381 // Set Command to Read
382 cmd_buf[0] = (unsigned char)CMD_V7_READ;
383 rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
384 if (rc != sizeof(cmd_buf))
385 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
386
387 //Wait for completion
388 do {
389 Sleep(20);
390 rmi4update_poll();
391 if (m_flashStatus == SUCCESS){
392 break;
393 }
394 retry++;
395 } while(retry < 20);
396
397 read_leng = transfer_leng * m_blockSize;
398 data_temp = (unsigned char *) malloc(sizeof(char) * read_leng);
399 rc = m_device.Read(dataAddr + 5, data_temp, sizeof(char) * read_leng);
400 if (rc != ((ssize_t)sizeof(char) * read_leng))
401 return UPDATE_FAIL_READ_F34_QUERIES;
402
403 memcpy(flash_cfg + offset, data_temp, sizeof(char) * read_leng);
404 offset += read_leng;
405 free(data_temp);
406 }
407
408 // Initialize as NULL here to avoid segmentation fault.
409 m_partitionConfig = NULL;
410 m_partitionCore = NULL;
411 m_partitionGuest = NULL;
412
413 /* parse the config length */
414 for (i = 2; i < m_blockSize * m_flashConfigLength; i = i + 8)
415 {
416 memcpy(partition_temp->data ,flash_cfg + i, sizeof(struct partition_tbl));
417 if (partition_temp->partition_id == CORE_CONFIG_PARTITION)
418 {
419 m_partitionConfig = (partition_tbl *) malloc(sizeof(struct partition_tbl));
420 memcpy(m_partitionConfig ,partition_temp, sizeof(struct partition_tbl));
421 memset(partition_temp, 0, sizeof(struct partition_tbl));
422 fprintf(stdout, "CORE_CONFIG_PARTITION is found\n");
423 }
424 else if (partition_temp->partition_id == CORE_CODE_PARTITION)
425 {
426 m_partitionCore = (partition_tbl *) malloc(sizeof(struct partition_tbl));
427 memcpy(m_partitionCore ,partition_temp, sizeof(struct partition_tbl));
428 memset(partition_temp, 0, sizeof(struct partition_tbl));
429 fprintf(stdout, "CORE_CODE_PARTITION is found\n");
430 }
431 else if (partition_temp->partition_id == GUEST_CODE_PARTITION)
432 {
433 m_partitionGuest = (partition_tbl *) malloc(sizeof(struct partition_tbl));
434 memcpy(m_partitionGuest ,partition_temp, sizeof(struct partition_tbl));
435 memset(partition_temp, 0, sizeof(struct partition_tbl));
436 fprintf(stdout, "GUEST_CODE_PARTITION is found\n");
437 }
438 else if (partition_temp->partition_id == NONE_PARTITION)
439 break;
440 }
441
442 if (flash_cfg)
443 free(flash_cfg);
444
445 if (partition_temp)
446 free(partition_temp);
447
448 m_fwBlockCount = m_partitionCore ? m_partitionCore->partition_len : 0;
449 m_configBlockCount = m_partitionConfig ? m_partitionConfig->partition_len : 0;
450 m_guestBlockCount = m_partitionGuest ? m_partitionGuest->partition_len : 0;
451 fprintf(stdout, "F34 fw blocks: %d\n", m_fwBlockCount);
452 fprintf(stdout, "F34 config blocks: %d\n", m_configBlockCount);
453 fprintf(stdout, "F34 guest blocks: %d\n", m_guestBlockCount);
454 fprintf(stdout, "\n");
455
456 m_guestData = (unsigned char *) malloc(m_guestBlockCount * m_blockSize);
457 memset(m_guestData, 0, m_guestBlockCount * m_blockSize);
458 memset(m_guestData + m_guestBlockCount * m_blockSize -4, 0, 4);
459 return UPDATE_SUCCESS;
460 }
461
ReadF34QueriesV7()462 int RMI4Update::ReadF34QueriesV7()
463 {
464 int rc;
465 struct f34_v7_query_0 query_0;
466 struct f34_v7_query_1_7 query_1_7;
467 unsigned char idStr[3];
468 unsigned short queryAddr = m_f34.GetQueryBase();
469 unsigned char offset;
470
471 rc = m_device.Read(queryAddr, query_0.data, sizeof(query_0.data));
472 if (rc != sizeof(query_0.data))
473 return UPDATE_FAIL_READ_BOOTLOADER_ID;
474
475 offset = query_0.subpacket_1_size + 1;
476 rc = m_device.Read(queryAddr + offset, query_1_7.data, sizeof(query_1_7.data));
477 if (rc != sizeof(query_1_7.data))
478 return UPDATE_FAIL_READ_BOOTLOADER_ID;
479
480 m_bootloaderID[0] = query_1_7.bl_minor_revision;
481 m_bootloaderID[1] = query_1_7.bl_major_revision;
482 m_hasConfigID = query_0.has_config_id;
483 m_blockSize = query_1_7.block_size_15_8 << 8 |
484 query_1_7.block_size_7_0;
485 m_flashConfigLength = query_1_7.flash_config_length_15_8 << 8 |
486 query_1_7.flash_config_length_7_0;
487 m_payloadLength = query_1_7.payload_length_15_8 << 8 |
488 query_1_7.payload_length_7_0;
489 m_buildID = query_1_7.bl_fw_id_7_0 |
490 query_1_7.bl_fw_id_15_8 << 8 |
491 query_1_7.bl_fw_id_23_16 << 16 |
492 query_1_7.bl_fw_id_31_24 << 24;
493
494 idStr[0] = m_bootloaderID[0];
495 idStr[1] = m_bootloaderID[1];
496 idStr[2] = 0;
497
498 fprintf(stdout, "F34 bootloader id: %s (%#04x %#04x)\n", idStr, m_bootloaderID[0],
499 m_bootloaderID[1]);
500 fprintf(stdout, "F34 has config id: %d\n", m_hasConfigID);
501 fprintf(stdout, "F34 unlocked: %d\n", m_unlocked);
502 fprintf(stdout, "F34 block size: %d\n", m_blockSize);
503 fprintf(stdout, "F34 flash cfg leng:%d\n", m_flashConfigLength);
504 fprintf(stdout, "F34 payload length:%d\n", m_payloadLength);
505 fprintf(stdout, "F34 build id: %lu\n", m_buildID);
506
507 return ReadFlashConfig();
508 }
509
ReadF34Queries()510 int RMI4Update::ReadF34Queries()
511 {
512 int rc;
513 unsigned char idStr[3];
514 unsigned char buf[8];
515 unsigned short queryAddr = m_f34.GetQueryBase();
516 unsigned short f34Version = m_f34.GetFunctionVersion();
517 unsigned short querySize;
518
519 if (f34Version == 0x2)
520 return ReadF34QueriesV7();
521 else if (f34Version == 0x1)
522 querySize = 8;
523 else
524 querySize = 2;
525
526 rc = m_device.Read(queryAddr, m_bootloaderID, RMI_BOOTLOADER_ID_SIZE);
527 if (rc != RMI_BOOTLOADER_ID_SIZE)
528 return UPDATE_FAIL_READ_BOOTLOADER_ID;
529
530 if (f34Version == 0x1)
531 ++queryAddr;
532 else
533 queryAddr += querySize;
534
535 if (f34Version == 0x1) {
536 rc = m_device.Read(queryAddr, buf, 1);
537 if (rc != 1)
538 return UPDATE_FAIL_READ_F34_QUERIES;
539
540 m_hasNewRegmap = buf[0] & RMI_F34_HAS_NEW_REG_MAP;
541 m_unlocked = buf[0] & RMI_F34_IS_UNLOCKED;;
542 m_hasConfigID = buf[0] & RMI_F34_HAS_CONFIG_ID;
543
544 ++queryAddr;
545
546 rc = m_device.Read(queryAddr, buf, 2);
547 if (rc != 2)
548 return UPDATE_FAIL_READ_F34_QUERIES;
549
550 m_blockSize = extract_short(buf + RMI_F34_BLOCK_SIZE_V1_OFFSET);
551
552 ++queryAddr;
553
554 rc = m_device.Read(queryAddr, buf, 8);
555 if (rc != 8)
556 return UPDATE_FAIL_READ_F34_QUERIES;
557
558 m_fwBlockCount = extract_short(buf + RMI_F34_FW_BLOCKS_V1_OFFSET);
559 m_configBlockCount = extract_short(buf + RMI_F34_CONFIG_BLOCKS_V1_OFFSET);
560 } else {
561 rc = m_device.Read(queryAddr, buf, RMI_F34_QUERY_SIZE);
562 if (rc != RMI_F34_QUERY_SIZE)
563 return UPDATE_FAIL_READ_F34_QUERIES;
564
565 m_hasNewRegmap = buf[0] & RMI_F34_HAS_NEW_REG_MAP;
566 m_unlocked = buf[0] & RMI_F34_IS_UNLOCKED;;
567 m_hasConfigID = buf[0] & RMI_F34_HAS_CONFIG_ID;
568 m_blockSize = extract_short(buf + RMI_F34_BLOCK_SIZE_OFFSET);
569 m_fwBlockCount = extract_short(buf + RMI_F34_FW_BLOCKS_OFFSET);
570 m_configBlockCount = extract_short(buf + RMI_F34_CONFIG_BLOCKS_OFFSET);
571 }
572
573 idStr[0] = m_bootloaderID[0];
574 idStr[1] = m_bootloaderID[1];
575 idStr[2] = 0;
576
577 fprintf(stdout, "F34 bootloader id: %s (%#04x %#04x)\n", idStr, m_bootloaderID[0],
578 m_bootloaderID[1]);
579 fprintf(stdout, "F34 has config id: %d\n", m_hasConfigID);
580 fprintf(stdout, "F34 unlocked: %d\n", m_unlocked);
581 fprintf(stdout, "F34 new reg map: %d\n", m_hasNewRegmap);
582 fprintf(stdout, "F34 block size: %d\n", m_blockSize);
583 fprintf(stdout, "F34 fw blocks: %d\n", m_fwBlockCount);
584 fprintf(stdout, "F34 config blocks: %d\n", m_configBlockCount);
585 fprintf(stdout, "\n");
586
587 if (f34Version == 0x1)
588 m_f34StatusAddr = m_f34.GetDataBase() + 2;
589 else
590 m_f34StatusAddr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_OFFSET + m_blockSize;
591
592 return UPDATE_SUCCESS;
593 }
594
ReadF34Controls()595 int RMI4Update::ReadF34Controls()
596 {
597 int rc;
598 unsigned char buf[2];
599
600 if (m_f34.GetFunctionVersion() == 0x1) {
601 rc = m_device.Read(m_f34StatusAddr, buf, 2);
602 if (rc != 2)
603 return UPDATE_FAIL_READ_F34_CONTROLS;
604
605 m_f34Command = buf[0] & RMI_F34_COMMAND_V1_MASK;
606 m_f34Status = buf[1] & RMI_F34_STATUS_V1_MASK;
607 m_programEnabled = !!(buf[1] & RMI_F34_ENABLED_MASK);
608
609 } else {
610 rc = m_device.Read(m_f34StatusAddr, buf, 1);
611 if (rc != 1)
612 return UPDATE_FAIL_READ_F34_CONTROLS;
613
614 m_f34Command = buf[0] & RMI_F34_COMMAND_MASK;
615 m_f34Status = (buf[0] >> RMI_F34_STATUS_SHIFT) & RMI_F34_STATUS_MASK;
616 m_programEnabled = !!(buf[0] & RMI_F34_ENABLED_MASK);
617 }
618
619 return UPDATE_SUCCESS;
620 }
621
WriteBootloaderID()622 int RMI4Update::WriteBootloaderID()
623 {
624 int rc;
625 int blockDataOffset = RMI_F34_BLOCK_DATA_OFFSET;
626
627 if (m_f34.GetFunctionVersion() == 0x1)
628 blockDataOffset = RMI_F34_BLOCK_DATA_V1_OFFSET;
629
630 rc = m_device.Write(m_f34.GetDataBase() + blockDataOffset,
631 m_bootloaderID, RMI_BOOTLOADER_ID_SIZE);
632 if (rc != RMI_BOOTLOADER_ID_SIZE)
633 return UPDATE_FAIL_WRITE_BOOTLOADER_ID;
634
635 return UPDATE_SUCCESS;
636 }
637
WriteFirmwareV7()638 int RMI4Update::WriteFirmwareV7()
639 {
640 int transaction_count, remain_block;
641 int transfer_leng = 0;
642 int offset = 0;
643 unsigned char trans_leng_buf[2];
644 unsigned char cmd_buf[1];
645 unsigned char off[2] = {0, 0};
646 unsigned char partition_id;
647 int i;
648 int retry = 0;
649 unsigned char *data_temp;
650 int rc;
651 unsigned short left_bytes;
652 unsigned short write_size;
653 unsigned short max_write_size;
654 unsigned short dataAddr = m_f34.GetDataBase();
655
656 /* calculate the count */
657 partition_id = CORE_CODE_PARTITION;
658 remain_block = (m_fwBlockCount % m_payloadLength);
659 transaction_count = (m_fwBlockCount / m_payloadLength);
660 if (remain_block > 0)
661 transaction_count++;
662
663 /* set partition id for bootloader 7 */
664 rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
665 if (rc != sizeof(partition_id))
666 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
667
668 rc = m_device.Write(dataAddr + 2, off, sizeof(off));
669 if (rc != sizeof(off))
670 return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
671
672 for (i = 0; i < transaction_count; i++)
673 {
674 if ((i == (transaction_count -1)) && (remain_block > 0))
675 transfer_leng = remain_block;
676 else
677 transfer_leng = m_payloadLength;
678
679 // Set Transfer Length
680 trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
681 trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
682
683 rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
684 if (rc != sizeof(trans_leng_buf))
685 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
686
687 // Set Command to Write
688 cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
689 rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
690 if (rc != sizeof(cmd_buf))
691 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
692
693 max_write_size = 16;
694 if (max_write_size >= transfer_leng * m_blockSize)
695 max_write_size = transfer_leng * m_blockSize;
696 else if (max_write_size > m_blockSize)
697 max_write_size -= max_write_size % m_blockSize;
698 else
699 max_write_size = m_blockSize;
700
701 left_bytes = transfer_leng * m_blockSize;
702 do {
703 if (left_bytes / max_write_size)
704 write_size = max_write_size;
705 else
706 write_size = left_bytes;
707
708 data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
709 memcpy(data_temp, m_firmwareImage.GetFirmwareData() + offset, sizeof(char) * write_size);
710 rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
711 if (rc != ((ssize_t)sizeof(char) * write_size)) {
712 fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
713 return UPDATE_FAIL_READ_F34_QUERIES;
714 }
715
716 offset += write_size;
717 left_bytes -= write_size;
718 free(data_temp);
719 } while (left_bytes);
720
721 // Sleep 100 ms and wait for attention.
722 Sleep(100);
723 rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
724 if (rc != UPDATE_SUCCESS) {
725 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
726 return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
727 }
728
729 //Wait for completion
730 do {
731 Sleep(20);
732 rmi4update_poll();
733 if (m_flashStatus == SUCCESS){
734 break;
735
736 }
737 retry++;
738 } while(retry < 20);
739
740 if (m_flashStatus != SUCCESS) {
741 fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
742 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
743 }
744
745 }
746 return UPDATE_SUCCESS;
747 }
748
WriteCoreConfigV7()749 int RMI4Update::WriteCoreConfigV7()
750 {
751 int transaction_count, remain_block;
752 int transfer_leng = 0;
753 int offset = 0;
754 unsigned char trans_leng_buf[2];
755 unsigned char cmd_buf[1];
756 unsigned char off[2] = {0, 0};
757 unsigned char partition_id;
758 unsigned short dataAddr = m_f34.GetDataBase();
759 unsigned short left_bytes;
760 unsigned short write_size;
761 unsigned short max_write_size;
762 int rc;
763 int i;
764 int retry = 0;
765 unsigned char *data_temp;
766
767 /* calculate the count */
768 partition_id = CORE_CONFIG_PARTITION;
769 remain_block = (m_configBlockCount % m_payloadLength);
770 transaction_count = (m_configBlockCount / m_payloadLength);
771 if (remain_block > 0)
772 transaction_count++;
773
774 /* set partition id for bootloader 7 */
775 rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
776 if (rc != sizeof(partition_id))
777 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
778
779 rc = m_device.Write(dataAddr + 2, off, sizeof(off));
780 if (rc != sizeof(off))
781 return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
782
783 for (i = 0; i < transaction_count; i++)
784 {
785 if ((i == (transaction_count -1)) && (remain_block > 0))
786 transfer_leng = remain_block;
787 else
788 transfer_leng = m_payloadLength;
789
790 // Set Transfer Length
791 trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
792 trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
793
794 rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
795 if (rc != sizeof(trans_leng_buf))
796 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
797
798 // Set Command to Write
799 cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
800 rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
801 if (rc != sizeof(cmd_buf))
802 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
803
804 max_write_size = 16;
805 if (max_write_size >= transfer_leng * m_blockSize)
806 max_write_size = transfer_leng * m_blockSize;
807 else if (max_write_size > m_blockSize)
808 max_write_size -= max_write_size % m_blockSize;
809 else
810 max_write_size = m_blockSize;
811
812 left_bytes = transfer_leng * m_blockSize;
813
814 do {
815 if (left_bytes / max_write_size)
816 write_size = max_write_size;
817 else
818 write_size = left_bytes;
819
820 data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
821 memcpy(data_temp, m_firmwareImage.GetConfigData() + offset, sizeof(char) * write_size);
822 rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
823 if (rc != ((ssize_t)sizeof(char) * write_size)) {
824 return UPDATE_FAIL_READ_F34_QUERIES;
825 }
826
827 offset += write_size;
828 left_bytes -= write_size;
829 free(data_temp);
830 } while (left_bytes);
831
832 // Wait for attention.
833 rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
834 if (rc != UPDATE_SUCCESS) {
835 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
836 return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
837 }
838
839 //Wait for completion
840 do {
841 Sleep(20);
842 rmi4update_poll();
843 if (m_flashStatus == SUCCESS){
844 break;
845 }
846 retry++;
847 } while(retry < 20);
848
849 if (m_flashStatus != SUCCESS) {
850 fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
851 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
852 }
853
854 }
855 return UPDATE_SUCCESS;
856 }
857
WriteFlashConfigV7()858 int RMI4Update::WriteFlashConfigV7()
859 {
860 int transaction_count, remain_block;
861 int transfer_leng = 0;
862 int offset = 0;
863 unsigned char trans_leng_buf[2];
864 unsigned char cmd_buf[1];
865 unsigned char off[2] = {0, 0};
866 unsigned char partition_id;
867 unsigned short dataAddr = m_f34.GetDataBase();
868 unsigned short left_bytes;
869 unsigned short write_size;
870 unsigned short max_write_size;
871 int rc;
872 int i;
873 int retry = 0;
874 unsigned char *data_temp;
875 unsigned short FlashConfigBlockCount;
876
877 /* calculate the count */
878 partition_id = FLASH_CONFIG_PARTITION;
879
880 FlashConfigBlockCount = m_firmwareImage.GetFlashConfigSize() / m_blockSize;
881
882 remain_block = (FlashConfigBlockCount % m_payloadLength);
883 transaction_count = (FlashConfigBlockCount / m_payloadLength);
884 if (remain_block > 0)
885 transaction_count++;
886
887 /* set partition id for bootloader 7 */
888 rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
889 if (rc != sizeof(partition_id))
890 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
891
892 rc = m_device.Write(dataAddr + 2, off, sizeof(off));
893 if (rc != sizeof(off))
894 return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
895
896 for (i = 0; i < transaction_count; i++)
897 {
898 if ((i == (transaction_count -1)) && (remain_block > 0))
899 transfer_leng = remain_block;
900 else
901 transfer_leng = m_payloadLength;
902
903 // Set Transfer Length
904 trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
905 trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
906
907 rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
908 if (rc != sizeof(trans_leng_buf))
909 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
910
911 // Set Command to Write
912 cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
913 rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
914 if (rc != sizeof(cmd_buf))
915 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
916
917 max_write_size = 16;
918 if (max_write_size >= transfer_leng * m_blockSize)
919 max_write_size = transfer_leng * m_blockSize;
920 else if (max_write_size > m_blockSize)
921 max_write_size -= max_write_size % m_blockSize;
922 else
923 max_write_size = m_blockSize;
924
925 left_bytes = transfer_leng * m_blockSize;
926
927 do {
928 if (left_bytes / max_write_size)
929 write_size = max_write_size;
930 else
931 write_size = left_bytes;
932
933 data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
934 memcpy(data_temp, m_firmwareImage.GetFlashConfigData() + offset, sizeof(char) * write_size);
935 rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
936 if (rc != ((ssize_t)sizeof(char) * write_size)) {
937 fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
938 return UPDATE_FAIL_READ_F34_QUERIES;
939 }
940
941 offset += write_size;
942 left_bytes -= write_size;
943 free(data_temp);
944 } while (left_bytes);
945
946 // Wair for attention.
947 rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
948 if (rc != UPDATE_SUCCESS) {
949 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
950 return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
951 }
952
953 //Wait for completion
954 do {
955 Sleep(20);
956 rmi4update_poll();
957 if (m_flashStatus == SUCCESS){
958 break;
959 }
960 retry++;
961 } while(retry < 20);
962
963 if (m_flashStatus != SUCCESS) {
964 fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
965 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
966 }
967
968 }
969 return UPDATE_SUCCESS;
970 }
971
EraseFirmwareV7()972 int RMI4Update::EraseFirmwareV7()
973 {
974 unsigned char erase_cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
975 int retry = 0;
976 int rc;
977
978 /* set partition id for bootloader 7 */
979 erase_cmd[0] = CORE_CODE_PARTITION;
980 /* write bootloader id */
981 erase_cmd[6] = m_bootloaderID[0];
982 erase_cmd[7] = m_bootloaderID[1];
983 if(m_bootloaderID[1] == 8){
984 /* Set Command to Erase AP for BL8*/
985 erase_cmd[5] = (unsigned char)CMD_V7_ERASE_AP;
986 } else {
987 /* Set Command to Erase AP for BL7*/
988 erase_cmd[5] = (unsigned char)CMD_V7_ERASE;
989 }
990
991 fprintf(stdout, "Erase command : ");
992 for(int i = 0 ;i<8;i++){
993 fprintf(stdout, "%d ", erase_cmd[i]);
994 }
995 fprintf(stdout, "\n");
996
997 rmi4update_poll();
998 if (!m_inBLmode)
999 return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1000 if(m_bootloaderID[1] == 8){
1001 // For BL8 device, we need hold 1 seconds after querying
1002 // F34 status to avoid not get attention by following giving
1003 // erase command.
1004 Sleep(1000);
1005 }
1006
1007 rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
1008 if (rc != sizeof(erase_cmd))
1009 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1010
1011 Sleep(100);
1012
1013 //Wait from ATTN
1014 if(m_bootloaderID[1] == 8){
1015 // Wait for attention for BL8 device.
1016 rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
1017 if (rc != UPDATE_SUCCESS) {
1018 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1019 return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1020 }
1021 }
1022 do {
1023 Sleep(20);
1024 rmi4update_poll();
1025 if (m_flashStatus == SUCCESS){
1026 break;
1027 }
1028 retry++;
1029 } while(retry < 20);
1030
1031 if (m_flashStatus != SUCCESS) {
1032 fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1033 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1034 }
1035
1036 if(m_bootloaderID[1] == 7){
1037 // For BL7, we need erase config partition.
1038 fprintf(stdout, "Start to erase config\n");
1039 erase_cmd[0] = CORE_CONFIG_PARTITION;
1040 erase_cmd[6] = m_bootloaderID[0];
1041 erase_cmd[7] = m_bootloaderID[1];
1042 erase_cmd[5] = (unsigned char)CMD_V7_ERASE;
1043
1044 Sleep(100);
1045 rmi4update_poll();
1046 if (!m_inBLmode)
1047 return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1048
1049 rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
1050 if (rc != sizeof(erase_cmd))
1051 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1052
1053 //Wait from ATTN
1054 Sleep(100);
1055
1056 rc = WaitForIdle(RMI_F34_ERASE_WAIT_MS, true);
1057 if (rc != UPDATE_SUCCESS) {
1058 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1059 return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1060 }
1061
1062
1063 do {
1064 Sleep(20);
1065 rmi4update_poll();
1066 if (m_flashStatus == SUCCESS){
1067 break;
1068 }
1069 retry++;
1070 } while(retry < 20);
1071
1072 if (m_flashStatus != SUCCESS) {
1073 fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1074 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1075 }
1076 }
1077
1078 return UPDATE_SUCCESS;
1079 }
1080
EnterFlashProgrammingV7()1081 int RMI4Update::EnterFlashProgrammingV7()
1082 {
1083 int rc;
1084 unsigned char f34_status;
1085 rc = m_device.Read(m_f34.GetDataBase(), &f34_status, sizeof(unsigned char));
1086 m_inBLmode = f34_status & 0x80;
1087 if(!m_inBLmode){
1088 fprintf(stdout, "Not in BL mode, going to BL mode...\n");
1089 unsigned char EnterCmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1090 int retry = 0;
1091
1092 /* set partition id for bootloader 7 */
1093 EnterCmd[0] = BOOTLOADER_PARTITION;
1094
1095 /* write bootloader id */
1096 EnterCmd[6] = m_bootloaderID[0];
1097 EnterCmd[7] = m_bootloaderID[1];
1098
1099 // Set Command to EnterBL
1100 EnterCmd[5] = (unsigned char)CMD_V7_ENTER_BL;
1101
1102 rc = m_device.Write(m_f34.GetDataBase() + 1, EnterCmd, sizeof(EnterCmd));
1103 if (rc != sizeof(EnterCmd))
1104 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1105
1106 rc = WaitForIdle(RMI_F34_ENABLE_WAIT_MS, false);
1107 if (rc != UPDATE_SUCCESS) {
1108 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1109 return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1110 }
1111
1112 //Wait from ATTN
1113 do {
1114 Sleep(20);
1115 rmi4update_poll();
1116 if (m_flashStatus == SUCCESS){
1117 break;
1118 }
1119 retry++;
1120 } while(retry < 20);
1121
1122 if (m_flashStatus != SUCCESS) {
1123 fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1124 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1125 }
1126
1127 Sleep(RMI_F34_ENABLE_WAIT_MS);
1128
1129 fprintf(stdout, "%s\n", __func__);
1130 rmi4update_poll();
1131 if (!m_inBLmode)
1132 return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1133
1134 } else
1135 fprintf(stdout, "Already in BL mode, skip...\n");
1136
1137 if(m_device.GetDeviceType() != RMI_DEVICE_TYPE_TOUCHPAD) {
1138 // workaround for touchscreen only
1139 fprintf(stdout, "Erase in BL mode\n");
1140 rc = EraseFirmwareV7();
1141 if (rc != UPDATE_SUCCESS) {
1142 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1143 return UPDATE_FAIL_ERASE_ALL;
1144 }
1145 fprintf(stdout, "Erase in BL mode end\n");
1146 m_device.RebindDriver();
1147 }
1148
1149 Sleep(RMI_F34_ENABLE_WAIT_MS);
1150
1151 rc = FindUpdateFunctions();
1152 if (rc != UPDATE_SUCCESS)
1153 return rc;
1154
1155 rc = ReadF34Queries();
1156 if (rc != UPDATE_SUCCESS)
1157 return rc;
1158
1159 return UPDATE_SUCCESS;
1160 }
1161
EnterFlashProgramming()1162 int RMI4Update::EnterFlashProgramming()
1163 {
1164 int rc;
1165 unsigned char f01Control_0;
1166 const unsigned char enableProg = RMI_F34_ENABLE_FLASH_PROG;
1167
1168 rc = WriteBootloaderID();
1169 if (rc != UPDATE_SUCCESS)
1170 return rc;
1171
1172 fprintf(stdout, "Enabling flash programming.\n");
1173 rc = m_device.Write(m_f34StatusAddr, &enableProg, 1);
1174 if (rc != 1)
1175 return UPDATE_FAIL_ENABLE_FLASH_PROGRAMMING;
1176
1177 Sleep(RMI_F34_ENABLE_WAIT_MS);
1178 if(m_device.GetDeviceType() != RMI_DEVICE_TYPE_TOUCHPAD) {
1179 fprintf(stdout, "not TouchPad, rebind driver here\n");
1180 m_device.RebindDriver();
1181 }
1182 rc = WaitForIdle(0);
1183 if (rc != UPDATE_SUCCESS)
1184 return UPDATE_FAIL_NOT_IN_IDLE_STATE;
1185
1186 if (!m_programEnabled)
1187 return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED;
1188
1189 fprintf(stdout, "Programming is enabled.\n");
1190 rc = FindUpdateFunctions();
1191 if (rc != UPDATE_SUCCESS)
1192 return rc;
1193
1194 rc = m_device.Read(m_f01.GetDataBase(), &m_deviceStatus, 1);
1195 if (rc != 1)
1196 return UPDATE_FAIL_READ_DEVICE_STATUS;
1197
1198 if(m_f34.GetFunctionVersion() > 0x1){
1199 if (!RMI_F01_STATUS_BOOTLOADER_v7(m_deviceStatus))
1200 return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1201 fprintf(stdout, "Already in BL mode V7\n");
1202 } else {
1203 if (!RMI_F01_STATUS_BOOTLOADER(m_deviceStatus))
1204 return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1205 fprintf(stdout, "Already in BL mode\n");
1206 }
1207
1208 rc = ReadF34Queries();
1209 if (rc != UPDATE_SUCCESS)
1210 return rc;
1211
1212 rc = m_device.Read(m_f01.GetControlBase(), &f01Control_0, 1);
1213 if (rc != 1)
1214 return UPDATE_FAIL_READ_F01_CONTROL_0;
1215
1216 f01Control_0 |= RMI_F01_CRTL0_NOSLEEP_BIT;
1217 f01Control_0 = (f01Control_0 & ~RMI_F01_CTRL0_SLEEP_MODE_MASK) | RMI_SLEEP_MODE_NORMAL;
1218
1219 rc = m_device.Write(m_f01.GetControlBase(), &f01Control_0, 1);
1220 if (rc != 1)
1221 return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1222
1223 return UPDATE_SUCCESS;
1224 }
1225
WriteBlocks(unsigned char * block,unsigned short count,unsigned char cmd)1226 int RMI4Update::WriteBlocks(unsigned char *block, unsigned short count, unsigned char cmd)
1227 {
1228 int blockNum;
1229 unsigned char zeros[] = { 0, 0 };
1230 int rc;
1231 unsigned short addr;
1232 unsigned char *blockWithCmd = (unsigned char *)alloca(m_blockSize + 1);
1233
1234 if (m_f34.GetFunctionVersion() == 0x1)
1235 addr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_V1_OFFSET;
1236 else
1237 addr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_OFFSET;
1238
1239 rc = m_device.Write(m_f34.GetDataBase(), zeros, 2);
1240 if (rc != 2)
1241 return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1242
1243 for (blockNum = 0; blockNum < count; ++blockNum) {
1244 if (m_writeBlockWithCmd) {
1245 memcpy(blockWithCmd, block, m_blockSize);
1246 blockWithCmd[m_blockSize] = cmd;
1247
1248 rc = m_device.Write(addr, blockWithCmd, m_blockSize + 1);
1249 if (rc != m_blockSize + 1) {
1250 fprintf(stderr, "failed to write block %d\n", blockNum);
1251 return UPDATE_FAIL_WRITE_BLOCK;
1252 }
1253 } else {
1254 rc = m_device.Write(addr, block, m_blockSize);
1255 if (rc != m_blockSize) {
1256 fprintf(stderr, "failed to write block %d\n", blockNum);
1257 return UPDATE_FAIL_WRITE_BLOCK;
1258 }
1259
1260 rc = m_device.Write(m_f34StatusAddr, &cmd, 1);
1261 if (rc != 1) {
1262 fprintf(stderr, "failed to write command for block %d\n", blockNum);
1263 return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1264 }
1265 }
1266
1267 rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, !m_writeBlockWithCmd);
1268 if (rc != UPDATE_SUCCESS) {
1269 fprintf(stderr, "failed to go into idle after writing block %d\n", blockNum);
1270 return UPDATE_FAIL_NOT_IN_IDLE_STATE;
1271 }
1272
1273 block += m_blockSize;
1274 }
1275
1276 return UPDATE_SUCCESS;
1277 }
1278
1279 /*
1280 * This is a limited implementation of WaitForIdle which assumes WaitForAttention is supported
1281 * this will be true for HID, but other protocols will need to revert polling. Polling
1282 * is not implemented yet.
1283 */
WaitForIdle(int timeout_ms,bool readF34OnSucess)1284 int RMI4Update::WaitForIdle(int timeout_ms, bool readF34OnSucess)
1285 {
1286 int rc = 0;
1287 struct timeval tv;
1288
1289 if (timeout_ms > 0) {
1290 tv.tv_sec = timeout_ms / 1000;
1291 tv.tv_usec = (timeout_ms % 1000) * 1000;
1292
1293 rc = m_device.WaitForAttention(&tv, m_f34.GetInterruptMask());
1294 if (rc == -ETIMEDOUT){
1295 /*
1296 * If for some reason we are not getting attention reports for HID devices
1297 * then we can still continue after the timeout and read F34 status
1298 * but if we have to wait for the timeout to ellapse everytime then this
1299 * will be slow. If this message shows up a lot then something is wrong
1300 * with receiving attention reports and that should be fixed.
1301 */
1302 fprintf(stderr, "RMI4Update::WaitForIdle Timed out waiting for attn report\n");
1303 }
1304 }
1305
1306 if (rc <= 0 || readF34OnSucess) {
1307 rc = ReadF34Controls();
1308 if (rc != UPDATE_SUCCESS)
1309 return rc;
1310
1311 if (!m_f34Status && !m_f34Command) {
1312 if (!m_programEnabled) {
1313 fprintf(stderr, "RMI4Update::WaitForIdle Bootloader is idle but program_enabled bit isn't set.\n");
1314 return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED;
1315 } else {
1316 return UPDATE_SUCCESS;
1317 }
1318 }
1319 fprintf(stderr, "RMI4Update::WaitForIdle\n");
1320 fprintf(stderr, " ERROR: Waiting for idle status.\n");
1321 fprintf(stderr, " Command: %#04x\n", m_f34Command);
1322 fprintf(stderr, " Status: %#04x\n", m_f34Status);
1323 fprintf(stderr, " Enabled: %d\n", m_programEnabled);
1324 fprintf(stderr, " Idle: %d\n", !m_f34Command && !m_f34Status);
1325
1326 return UPDATE_FAIL_NOT_IN_IDLE_STATE;
1327 }
1328
1329 return UPDATE_SUCCESS;
1330 }
1331