// File: /workspace/github_cpp_makefile_star2_O2/goodix[P]gdix_hid_firmware_update/gtx2/gtx2_update.cpp
// Function: GTx2Update::fw_update(unsigned int)
int GTx2Update::fw_update(unsigned int firmware_flag)
{
	int retry;
	int ret, i;
	unsigned char temp_buf[65];
	unsigned char *fw_data = NULL;
	unsigned char buf_switch_to_patch[] = {0x00, 0x10, 0x00, 0x00, 0x01, 0x01};
	unsigned char buf_start_update[] = {0x00, 0x11, 0x00, 0x00, 0x01, 0x01};
	unsigned char buf_restart[] = {0x0E, 0x13, 0x00, 0x00, 0x01, 0x01};

	int sub_fw_num = 0;
	unsigned char sub_fw_type;
	unsigned int sub_fw_len;
	unsigned int sub_fw_flash_addr;
	unsigned int sub_fw_info_pos =
		image->GetFirmwareSubFwInfoOffset(); // SUB_FW_INFO_OFFSET;
	unsigned int fw_image_offset =
		image->GetFirmwareSubFwDataOffset(); // SUB_FW_DATA_OFFSET;

	ret = dev->Write(buf_switch_to_patch, sizeof(buf_switch_to_patch));
	if (ret < 0) {
		gdix_err("Failed switch to patch\n");
		return ret;
	}

	usleep(250000);
	retry = GDIX_RETRY_TIMES;
	do {
		ret = dev->Read(BL_STATE_ADDR, temp_buf, 1);
		gdix_dbg("BL_STATE_ADDR\n");
		if (ret < 0) {
			gdix_err("Failed read 0x%x, ret = %d\n", BL_STATE_ADDR, ret);
			goto update_err;
		}
		if (temp_buf[0] == 0xDD)
			break;
		gdix_info("0x%x value is 0x%x != 0xDD, retry\n", BL_STATE_ADDR,
				  temp_buf[0]);
		usleep(30000);
	} while (--retry);

	if (!retry) {
		gdix_err("Reg 0x%x != 0xDD\n", BL_STATE_ADDR);
		ret = -2;
		goto update_err;
	}

	/* Start update */
	ret = dev->Write(buf_start_update, sizeof(buf_start_update));
	if (ret < 0) {
		gdix_err("Failed start update, ret=%d\n", ret);
		goto update_err;
	}
	usleep(100000);

	/* Start load firmware */
	fw_data = image->GetFirmwareData();
	if (!fw_data) {
		gdix_err("No valid fw data \n");
		ret = -4;
		goto update_err;
	}

	sub_fw_num =
		image->GetFirmwareSubFwNum(); // fw_data[FW_IMAGE_SUB_FWNUM_OFFSET];
	// sub_fw_info_pos = image->GetFirmwareSubFwInfoOffset();//
	// SUB_FW_INFO_OFFSET; fw_image_offset = image->GetFirmwareSubFwDataOffset()
	// ; //SUB_FW_DATA_OFFSET;
	gdix_dbg("load sub firmware, sub_fw_num=%d\n", sub_fw_num);
	for (i = 0; i < sub_fw_num; i++) {
		sub_fw_type = fw_data[sub_fw_info_pos];
		gdix_dbg("load sub firmware, sub_fw_type=0x%x\n", sub_fw_type);
		/*sub_fw_len = (fw_data[sub_fw_info_pos + 1] << 24) |
					 (fw_data[sub_fw_info_pos + 2] << 16) |
					 (fw_data[sub_fw_info_pos + 3] << 8) |
					 fw_data[sub_fw_info_pos + 4];*/
		sub_fw_len =
			(fw_data[sub_fw_info_pos + 1] << 8) | fw_data[sub_fw_info_pos + 2];

		sub_fw_flash_addr =
			(fw_data[sub_fw_info_pos + 3] << 8) | fw_data[sub_fw_info_pos + 4];
		sub_fw_flash_addr = sub_fw_flash_addr << 8;
		if (!(firmware_flag & (0x01 << sub_fw_type))) {
			gdix_info("Sub firmware type does not math:type=%d\n", sub_fw_type);
			fw_image_offset += sub_fw_len;
			sub_fw_info_pos += 8;
			continue;
		}
		ret = load_sub_firmware(sub_fw_flash_addr, &fw_data[fw_image_offset],
								sub_fw_len);
		if (ret < 0) {
			gdix_dbg("Failed load sub firmware, ret=%d\n", ret);
			goto update_err;
		}
		fw_image_offset += sub_fw_len;
		sub_fw_info_pos += 8;
	}
	if (sub_fw_num == 0)
		return -5;
	/* reset IC */
	gdix_dbg("reset ic\n");
	retry = 3;
	do {
		ret = dev->Write(buf_restart, sizeof(buf_restart));
		if (ret < 0)
			gdix_dbg("Failed write restart command, ret=%d\n", ret);
		usleep(20000);
	} while (--retry);
	usleep(300000);
	return 0;

update_err:
	gdix_dbg("reset ic\n");
	retry = 3;
	do {
		if (dev->Write(buf_restart, sizeof(buf_restart)) < 0)
			gdix_dbg("Failed write restart command\n");
		usleep(20000);
	} while (--retry);
	usleep(300000);
	return ret;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movl %esi, 0x1c(%rsp)
movq %rdi, %r13
movw $0x101, %ax             # imm = 0x101
leaq 0x38(%rsp), %r15
movw %ax, 0x4(%r15)
movl $0x1000, (%r15)         # imm = 0x1000
movw %ax, 0x24(%rsp)
movl $0x1100, 0x20(%rsp)     # imm = 0x1100
movw %ax, 0x4(%rsp)
movl $0x130e, (%rsp)         # imm = 0x130E
movq 0x10(%rdi), %rdi
movq (%rdi), %rax
callq *0x60(%rax)
movq %rax, 0x28(%rsp)
movq 0x10(%r13), %rdi
movq (%rdi), %rax
callq *0x68(%rax)
movl %eax, 0x18(%rsp)
movq 0x8(%r13), %rdi
movq (%rdi), %rax
pushq $0x6
popq %rdx
movq %r15, %rsi
callq *0x38(%rax)
testl %eax, %eax
js 0x9969
movl $0x3d090, %edi          # imm = 0x3D090
callq 0x5170
pushq $-0x6
popq %r14
leaq 0x40(%rsp), %r12
pushq $0x1
popq %rbp
leaq 0xe94a(%rip), %r15      # 0x181d6
movq 0x8(%r13), %rdi
movq (%rdi), %rax
movl $0x5095, %esi           # imm = 0x5095
movq %r12, %rdx
movl %ebp, %ecx
callq *0x20(%rax)
movl %eax, %ebx
leaq 0x169e8(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x98ce
movq 0x16703(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
leaq 0xd4b9(%rip), %rsi      # 0x16d78
movq %r15, %rdx
movl $0xf4, %ecx
xorl %eax, %eax
callq 0x5180
testl %ebx, %ebx
js 0x99a4
movzbl 0x40(%rsp), %r9d
cmpl $0xdd, %r9d
je 0x99e6
leaq 0x169a1(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x991b
movq 0x166bc(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
leaq 0xc934(%rip), %rsi      # 0x1623a
movq %r15, %rdx
movl $0xfc, %ecx
movl $0x5095, %r8d           # imm = 0x5095
xorl %eax, %eax
callq 0x5180
movl $0x7530, %edi           # imm = 0x7530
callq 0x5170
incl %r14d
jne 0x988c
pushq $-0x2
popq %rbx
leaq 0x16959(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9cc6
movq 0x16690(%rip), %rax     # 0x1ffd8
movq (%rax), %rdi
leaq 0xc91c(%rip), %rsi      # 0x1626e
leaq 0xe87d(%rip), %rdx      # 0x181d6
movl $0x101, %ecx            # imm = 0x101
movl $0x5095, %r8d           # imm = 0x5095
jmp 0x9b95
movl %eax, %ebx
leaq 0x1691f(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9d5f
movq 0x16656(%rip), %rax     # 0x1ffd8
movq (%rax), %rdi
leaq 0xc80d(%rip), %rsi      # 0x16199
leaq 0xe843(%rip), %rdx      # 0x181d6
movl $0xec, %ecx
xorl %eax, %eax
callq 0x5180
jmp 0x9d5f
leaq 0x168e6(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9cc6
movq 0x1661d(%rip), %rax     # 0x1ffd8
movq (%rax), %rdi
leaq 0xc848(%rip), %rsi      # 0x1620d
leaq 0xe80a(%rip), %rdx      # 0x181d6
movl $0xf6, %ecx
movl $0x5095, %r8d           # imm = 0x5095
movl %ebx, %r9d
xorl %eax, %eax
callq 0x5180
jmp 0x9cc6
movq 0x8(%r13), %rdi
movq (%rdi), %rax
leaq 0x20(%rsp), %rsi
pushq $0x6
popq %rdx
callq *0x38(%rax)
testl %eax, %eax
js 0x9b63
movl $0x186a0, %edi          # imm = 0x186A0
callq 0x5170
movq 0x10(%r13), %rdi
movq (%rdi), %rax
callq *0x38(%rax)
testq %rax, %rax
je 0x9c57
movq %rax, %rbx
movq %r13, 0x8(%rsp)
movq 0x10(%r13), %rdi
movq (%rdi), %rax
callq *0x58(%rax)
movl %eax, %ebp
leaq 0x16859(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9a64
movq 0x16574(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
leaq 0xc895(%rip), %rsi      # 0x162e3
leaq 0xe781(%rip), %rdx      # 0x181d6
movl $0x11b, %ecx            # imm = 0x11B
movl %ebp, %r8d
xorl %eax, %eax
callq 0x5180
testl %ebp, %ebp
movl $0x0, %r14d
movl %ebp, 0x14(%rsp)
cmovgl %ebp, %r14d
movq 0x28(%rsp), %r12
movl 0x18(%rsp), %r13d
movq %rbx, 0x30(%rsp)
subl $0x1, %r14d
jb 0x9ba1
movl %r12d, %eax
movzbl (%rbx,%rax), %r15d
leaq 0x167f5(%rip), %rax     # 0x20291
cmpb $0x0, (%rax)
je 0x9ac8
movq 0x16510(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
leaq 0xc864(%rip), %rsi      # 0x16316
leaq 0xe71d(%rip), %rdx      # 0x181d6
movl $0x11e, %ecx            # imm = 0x11E
movl %r15d, %r8d
xorl %eax, %eax
callq 0x5180
leal 0x1(%r12), %eax
movzbl (%rbx,%rax), %eax
shll $0x8, %eax
leal 0x2(%r12), %ecx
movzbl (%rbx,%rcx), %ebp
orl %eax, %ebp
movl 0x1c(%rsp), %eax
btl %r15d, %eax
jae 0x9b1f
leal 0x4(%r12), %eax
movzbl (%rbx,%rax), %esi
leal 0x3(%r12), %eax
movzbl (%rbx,%rax), %eax
shll $0x10, %eax
shll $0x8, %esi
orl %eax, %esi
movl %r13d, %edx
addq %rbx, %rdx
movq 0x8(%rsp), %rdi
movq (%rdi), %rax
movl %ebp, %ecx
callq *0x28(%rax)
testl %eax, %eax
jns 0x9b52
jmp 0x9c8c
leaq 0x1676b(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9b52
movq 0x16486(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
leaq 0xc810(%rip), %rsi      # 0x1634c
leaq 0xe693(%rip), %rdx      # 0x181d6
movl $0x12a, %ecx            # imm = 0x12A
movl %r15d, %r8d
xorl %eax, %eax
callq 0x5180
addl %ebp, %r13d
addl $0x8, %r12d
movq 0x30(%rsp), %rbx
jmp 0x9a83
movl %eax, %ebx
leaq 0x16725(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9cc6
movq 0x1645c(%rip), %rax     # 0x1ffd8
movq (%rax), %rdi
leaq 0xc70b(%rip), %rsi      # 0x16291
leaq 0xe649(%rip), %rdx      # 0x181d6
movl $0x109, %ecx            # imm = 0x109
movl %ebx, %r8d
xorl %eax, %eax
callq 0x5180
jmp 0x9cc6
cmpl $0x0, 0x14(%rsp)
je 0x9d73
leaq 0x166de(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9bdc
movq 0x163f9(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
leaq 0xc88a(%rip), %rsi      # 0x16453
leaq 0xe606(%rip), %rdx      # 0x181d6
movl $0x13b, %ecx            # imm = 0x13B
xorl %eax, %eax
callq 0x5180
pushq $-0x3
popq %r13
movq %rsp, %r14
pushq $0x6
popq %rbp
leaq 0xc881(%rip), %r15      # 0x1646e
leaq 0xe5e2(%rip), %r12      # 0x181d6
movq 0x8(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
movq %r14, %rsi
movl %ebp, %edx
callq *0x38(%rax)
testl %eax, %eax
jns 0x9c37
leaq 0x1667e(%rip), %rcx     # 0x20291
cmpb $0x1, (%rcx)
jne 0x9c37
movq 0x16399(%rip), %rcx     # 0x1ffb8
movq (%rcx), %rdi
movq %r15, %rsi
movq %r12, %rdx
movl $0x140, %ecx            # imm = 0x140
movl %eax, %r8d
xorl %eax, %eax
callq 0x5180
movl $0x4e20, %edi           # imm = 0x4E20
callq 0x5170
incl %r13d
jne 0x9bf4
movl $0x493e0, %edi          # imm = 0x493E0
callq 0x5170
xorl %ebx, %ebx
jmp 0x9d5f
pushq $-0x4
popq %rbx
leaq 0x16630(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9cc6
movq 0x1636b(%rip), %rax     # 0x1ffd8
movq (%rax), %rdi
leaq 0xc648(%rip), %rsi      # 0x162bf
leaq 0xe558(%rip), %rdx      # 0x181d6
movl $0x111, %ecx            # imm = 0x111
xorl %eax, %eax
callq 0x5180
jmp 0x9cc6
movl %eax, %ebx
leaq 0x165fc(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9cc1
movq 0x16317(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
leaq 0xc712(%rip), %rsi      # 0x163bd
leaq 0xe524(%rip), %rdx      # 0x181d6
movl $0x132, %ecx            # imm = 0x132
movl %ebx, %r8d
xorl %eax, %eax
callq 0x5180
movq 0x8(%rsp), %r13
leaq 0x165c4(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9cf6
movq 0x162df(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
leaq 0xc770(%rip), %rsi      # 0x16453
leaq 0xe4ec(%rip), %rdx      # 0x181d6
movl $0x147, %ecx            # imm = 0x147
xorl %eax, %eax
callq 0x5180
pushq $-0x3
popq %r15
movq %rsp, %r14
pushq $0x6
popq %rbp
leaq 0xe4cf(%rip), %r12      # 0x181d6
movq 0x8(%r13), %rdi
movq (%rdi), %rax
movq %r14, %rsi
movl %ebp, %edx
callq *0x38(%rax)
testl %eax, %eax
jns 0x9d46
leaq 0x16570(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x9d46
movq 0x1628b(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
leaq 0xd061(%rip), %rsi      # 0x16d98
movq %r12, %rdx
movl $0x14b, %ecx            # imm = 0x14B
xorl %eax, %eax
callq 0x5180
movl $0x4e20, %edi           # imm = 0x4E20
callq 0x5170
incl %r15d
jne 0x9d07
movl $0x493e0, %edi          # imm = 0x493E0
callq 0x5170
movl %ebx, %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $-0x5
popq %rbx
jmp 0x9d5f