to_single_byte(c1)

本文介绍了一个实用的字符串转换函数to_single_byte(),该函数能够将输入的全角字符转化为对应的半角字符,适用于文本规范化处理场景。
to_single_byte(c1)
【功能】将字符串中的全角转化为半角
【参数】c1,字符型
【返回】字符串

【示例】
SQL> select to_multi_byte('高A') text from dual; test ---- 高A

 

 

 

import idaapi import idc import idautils import ida_nalt def analyze_elf_structure(): """Analyze ELF file structure in detail""" print(f"\n{'='*60}") print("ELF Structure Analysis") print(f"{'='*60}") # Get ELF header info inf = idaapi.get_inf_structure() print(f"Processor: {inf.procname}") print(f"File Type: {ida_nalt.get_file_type_name()}") print(f"Image Base: 0x{inf.base:016X}") # List all segments with detailed info print(f"\n{'='*60}") print("Segment Mapping (VA ↔ File Offset)") print(f"{'='*60}") print(f"{'Name':<12} {'Start VA':<16} {'End VA':<16} {'File Off':<12} {'Size':<12}") print(f"{'-'*70}") for n in range(idaapi.get_segm_qty()): seg = idaapi.getnseg(n) if seg: seg_name = idaapi.get_segm_name(seg) start_va = seg.start_ea end_va = seg.end_ea size = end_va - start_va # Try to get file offset file_off = idaapi.get_fileregion_offset(start_va) if file_off == -1: file_off_str = "N/A" else: file_off_str = f"0x{file_off:X}" print(f"{seg_name:<12} 0x{start_va:<14X} 0x{end_va:<14X} {file_off_str:<12} 0x{size:<10X}") def calculate_file_offset_detailed(va_address): """ Calculate file offset with detailed explanation """ print(f"\n{'='*60}") print(f"Detailed File Offset Calculation") print(f"{'='*60}") # Get segment containing the address seg = idaapi.getseg(va_address) if not seg: print(f"❌ Address 0x{va_address:X} not in any segment!") return None seg_name = idaapi.get_segm_name(seg) seg_start = seg.start_ea # Get file offset directly if available file_offset = idaapi.get_fileregion_offset(va_address) print(f"Target VA: 0x{va_address:X}") print(f"In segment: {seg_name}") print(f"Segment start VA: 0x{seg_start:X}") print(f"Offset in segment: 0x{va_address - seg_start:X}") if file_offset != -1: print(f"\n✅ Direct file offset mapping found!") print(f"File offset: 0x{file_offset:X}") # Show the relationship if file_offset == va_address: print(f"\n📌 Special case: File offset equals VA") print(f" This means .text starts at file offset 0x{seg_start:X}") else: print(f"\n📌 Relationship: VA 0x{va_address:X} → File 0x{file_offset:X}") print(f" Delta: 0x{va_address - file_offset:X}") else: # Try to calculate based on common patterns print(f"\n⚠️ No direct file offset mapping") print(f"Trying to calculate based on ELF patterns...") # Common ARM64 patterns if seg_name == ".text": # Pattern 1: .text at 0x28000 in file calc1 = (va_address - seg_start) + 0x28000 # Pattern 2: .text at 0x1000 in file calc2 = (va_address - seg_start) + 0x1000 # Pattern 3: Direct mapping (your case) calc3 = va_address print(f"\nPossible calculations:") print(f" 1. If .text @ file 0x28000: 0x{calc1:X}") print(f" 2. If .text @ file 0x1000: 0x{calc2:X}") print(f" 3. If direct VA=File mapping: 0x{calc3:X}") # Ask user which one to use print(f"\nSelect calculation method:") print(f" [1] Pattern 1 (0x28000 offset)") print(f" [2] Pattern 2 (0x1000 offset)") print(f" [3] Direct mapping") print(f" [4] Custom offset") choice = input("Choice (1-4): ").strip() if choice == "1": file_offset = calc1 elif choice == "2": file_offset = calc2 elif choice == "3": file_offset = calc3 elif choice == "4": custom = input("Enter custom .text file offset (hex): ").strip() try: custom_offset = int(custom, 16) file_offset = (va_address - seg_start) + custom_offset except: print("Invalid offset!") return None else: print("Invalid choice!") return None return file_offset def extract_hex_bytes(va_address, num_bytes=16): """Extract hex bytes from memory""" hex_bytes = [] for i in range(num_bytes): byte = idaapi.get_byte(va_address + i) hex_bytes.append(byte) # Format for MemoryPatch hex_str = " ".join([f"{b:02X}" for b in hex_bytes]) # Also create C array format c_array = ", ".join([f"0x{b:02X}" for b in hex_bytes]) return hex_str, c_array, hex_bytes def generate_patches(va_address, file_offset, hex_str): """Generate different patch formats""" print(f"\n{'='*60}") print("Patch Code Generation") print(f"{'='*60}") # Format 1: MemoryPatch (Android) print(f"\n📱 MemoryPatch (Android):") print(f"{'-'*40}") patch_code = f'MemoryPatch::createWithHex("libanogs.so", 0x{file_offset:X}, "{hex_str}").Modify();' print(patch_code) # Format 2: Direct hex patch print(f"\n🔧 Direct Hex Patch:") print(f"{'-'*40}") print(f"Offset: 0x{file_offset:X}") print(f"Bytes: {hex_str}") # Format 3: Binary patch command print(f"\n💻 Binary Patch Command (xxd):") print(f"{'-'*40}") print(f"printf '{hex_str.replace(' ', '')}' | xxd -r -p | dd of=libanogs.so bs=1 seek=$((0x{file_offset:X})) conv=notrunc") # Format 4: C code for inline patching print(f"\n👨‍💻 C Inline Patching Code:") print(f"{'-'*40}") bytes_list = hex_str.split() c_code = f"""uintptr_t patch_addr = base_address + 0x{va_address:X}; // Or use dlopen+dlsym unsigned char patch_bytes[] = {{{', '.join([f'0x{b}' for b in bytes_list])}}}; memcpy((void*)patch_addr, patch_bytes, sizeof(patch_bytes));""" print(c_code) def interactive_analyzer(): """Interactive analyzer with options""" print(f"\n{'='*60}") print("IDA ELF File Offset Analyzer") print("="*60) while True: print(f"\nOptions:") print(f" 1. Analyze current address") print(f" 2. Enter address manually") print(f" 3. View ELF structure") print(f" 4. Generate patch from current") print(f" 5. Exit") choice = input("\nSelect option: ").strip() if choice == "1": # Current address current_ea = idc.get_screen_ea() if current_ea != idaapi.BADADDR: print(f"\n📍 Current address: 0x{current_ea:X}") analyze_single_address(current_ea) else: print("❌ No valid address at cursor!") elif choice == "2": # Manual address addr_str = input("\nEnter VA (hex): ").strip() try: if addr_str.startswith("0x"): va_address = int(addr_str, 16) else: va_address = int(addr_str, 16) analyze_single_address(va_address) except: print("❌ Invalid address!") elif choice == "3": # ELF structure analyze_elf_structure() elif choice == "4": # Generate patch from current current_ea = idc.get_screen_ea() if current_ea != idaapi.BADADDR: generate_patch_from_address(current_ea) else: print("❌ No valid address at cursor!") elif choice == "5": break else: print("❌ Invalid option!") def analyze_single_address(va_address): """Analyze a single address""" print(f"\n{'='*60}") print(f"Analyzing 0x{va_address:X}") print(f"{'='*60}") # Get disassembly disasm = idc.generate_disasm_line(va_address, 0) print(f"Instruction: {disasm}") # Get function info func = idaapi.get_func(va_address) if func: func_name = idaapi.get_func_name(func.start_ea) print(f"Function: {func_name} (0x{func.start_ea:X}-0x{func.end_ea:X})") # Calculate file offset file_offset = calculate_file_offset_detailed(va_address) if not file_offset: return # Extract hex bytes hex_str, c_array, raw_bytes = extract_hex_bytes(va_address, 16) print(f"\n🔍 Hex Bytes (16 bytes):") print(f" {hex_str}") print(f"\n📊 C Array:") print(f" {{{c_array}}}") # Generate patches generate_patches(va_address, file_offset, hex_str) # Ask to copy to clipboard copy = input(f"\n📋 Copy MemoryPatch code to clipboard? (y/n): ").strip().lower() if copy == 'y': try: import pyperclip patch_code = f'MemoryPatch::createWithHex("libanogs.so", 0x{file_offset:X}, "{hex_str}").Modify();' pyperclip.copy(patch_code) print("✅ Copied to clipboard!") except: print("⚠️ Install pyperclip: pip install pyperclip") def generate_patch_from_address(va_address): """Quick patch generation from address""" file_offset = calculate_file_offset_detailed(va_address) if not file_offset: return hex_str, _, _ = extract_hex_bytes(va_address, 16) print(f"\n✅ Quick Patch Code:") print(f"{'='*40}") print(f'MemoryPatch::createWithHex("libanogs.so", 0x{file_offset:X}, "{hex_str}").Modify();') print(f"{'='*40}") def show_simple_dialog(): """Simple dialog for quick analysis""" import ida_kernwin # Get current address current_ea = idc.get_screen_ea() # Ask for address or use current if current_ea != idaapi.BADADDR: default_addr = f"0x{current_ea:X}" else: default_addr = "0x228654" addr_str = ida_kernwin.ask_str(default_addr, 0, "Enter virtual address (hex):") if not addr_str: return try: if addr_str.startswith("0x"): va_address = int(addr_str, 16) else: va_address = int(addr_str, 16) # Quick analysis file_offset = calculate_file_offset_detailed(va_address) if file_offset: hex_str, _, _ = extract_hex_bytes(va_address, 16) # Show result result = f"""Analysis Complete! Address: 0x{va_address:X} File Offset: 0x{file_offset:X} Hex Bytes: {hex_str} MemoryPatch Code: MemoryPatch::createWithHex("libanogs.so", 0x{file_offset:X}, "{hex_str}").Modify();""" # Display in message box ida_kernwin.msg(result) # Also print to console print(f"\n{result}") except ValueError as e: ida_kernwin.warning(f"Invalid address: {e}") # Run the script if __name__ == "__main__": # Choose your preferred mode: # Mode 1: Simple dialog (recommended for beginners) show_simple_dialog() # Mode 2: Full interactive analyzer # interactive_analyzer() # Mode 3: Quick analysis of current address # current_ea = idc.get_screen_ea() # if current_ea != idaapi.BADADDR: # analyze_single_address(current_ea) Address: 0x228560 File Offset: 0x228560 Hex Bytes: FF 43 01 D1 FD 7B 03 A9 F4 4F 04 A9 FD C3 00 91 MemoryPatch Code: MemoryPatch::createWithHex("libanogs.so", 0x228560, "FF 43 01 D1 FD 7B 03 A9 F4 4F 04 A9 FD C3 00 91").Modify(); this is result getting from script MemoryPatch::createWithHex( "libanogs.so", 0x28654, "E0 03 C0 FF E1 83 C1 B2 E2 07 C2 B2 E3 0B C3 B2" ).Modify(); this result find by ai why both diffrent
12-06
__int64 __fastcall sub_228560(__int64 *a1) { int v2; // w8 __int64 v3; // x20 __int64 v5; // x0 __int64 v6; // x0 __int64 v8; // [xsp+8h] [xbp-28h] __int64 v9; // [xsp+10h] [xbp-20h] _BYTE v10[12]; // [xsp+1Ch] [xbp-14h] BYREF __int64 v11; // [xsp+28h] [xbp-8h] BYREF sub_229134(&unk_A0065, 12, v10); v2 = *((_DWORD *)a1 + 280); *((_DWORD )a1 + 280) = v2 + 1; if ( (v2 | 8) != 0xB || ! ((_BYTE *)a1 + 1129) || (v9 = sub_228668(a1)) == 0 ) { sub_4DF2BC(a1 + 133); if ( !*a1 ) { sub_4DF2EC(a1 + 133); goto LABEL_8; } v3 = *(_QWORD *)(*a1 + 16); v11 = *a1; sub_22871C(a1, &v11); sub_4DF2EC(a1 + 133); v9 = v3; if ( !v3 ) { LABEL_8: v8 = 0; v9 = sub_22878C(a1); if ( !v9 ) return v8; } } v8 = v9; if ( dword_5755A4++ <= 4 ) { v5 = sub_4F6C54(); v8 = v9; if ( (unsigned int)sub_4F7874(v5, 68) ) { v6 = sub_4F6C54(); sub_4F7074(v6, v10, *((unsigned int *)a1 + 280), v9); return v9; } } return v8; } .text:0000000000228560 .text:0000000000228560 ; __int64 __fastcall sub_228560(__int64 *) .text:0000000000228560 sub_228560 ; CODE XREF: .text:00000000001C5EC4↑p .text:0000000000228560 .text:0000000000228560 var_28 = -0x28 .text:0000000000228560 var_20 = -0x20 .text:0000000000228560 var_14 = -0x14 .text:0000000000228560 var_8 = -8 .text:0000000000228560 var_s0 = 0 .text:0000000000228560 var_s10 = 0x10 .text:0000000000228560 .text:0000000000228560 ; __unwind { .text:0000000000228560 SUB SP, SP, #0x50 .text:0000000000228564 STP X29, X30, [SP,#0x30+var_s0] .text:0000000000228568 STP X20, X19, [SP,#0x30+var_s10] .text :000000000022856C ADD X29, SP, #0x30 .text :0000000000228570 MOV .text:000000000022858C ORR W9, W8, #8 .text:0000000000228590 ADD W8, W8, #1 .text:0000000000228594 CMP W9, #0xB .text:0000000000228598 STR W8, [X19,#0x460] .text:000000000022859C B.NE loc_2285B8 .text:00000000002285A0 LDRB W8, [X19,#0x469] .text:00000000002285A4 CBZ W8, loc_2285B8 .text:00000000002285A8 MOV X0, 00000000002285B8 loc_2285B8; sub_228560+44↑j .text : 00000000002285B8 ADD X0 , loc_2285F0 .text : 00000000002285C8 LDR X20, [X8,#0x10] .text : 00000000002285CC SUB X1 , X20, [SP,#0x30+var_20] .text :00000000002285E8 CBNZ .text:00000000002285F0 .text:00000000002285F0 loc_2285F0 ; CODE XREF: sub_228560+64↑j .text : 00000000002285F0 ADD X0, XREF: sub_228560+8C↑j .text:00000000002285F8 MOV X0, X19 .text:00000000002285FC BL sub_22878C .text:0000000000228600 STP [SP,#0x30+var_28] .text:0000000000228604 CBZ .text:0000000000228608 .text :0000000000228608 loc_228608 ; CODE #dword_5755A4@PAGE .text: 000000000022860C LDR STR X20, [SP,#0x30+var_28] .text:0000000000228618 ADD W10, W9, #1 .text:000000000022861C CMP W9, #4 .text:0000000000228620 STR W10, [X8,#dword_5755A4@PAGEOFF] .text:0000000000228624 B.GT loc_228654 .text:0000000000228628 BL sub_4F6C54 .text:000000000022862C MOV W1, #0x44 ; 'D' .text:0000000000228630 BL sub_4F7874 .text:0000000000228634 STR X20, [SP,#0x30+var_28] .text:0000000000228638 CBZ W0, loc_228654 .text:000000000022863C BL sub_4F6C54 .text:0000000000228640 LDR W2, [X19,#0x460] .text:0000000000228644 SUB X1, X29, #-var_14 .text :0000000000228648 MOV X3, loc_228654 ; CODE .text:0000000000228654 LDR X0, [SP,#0x30+var_28] .text :0000000000228658 LDP .text:0000000000228664 RET .text:0000000000228664 ; } // starts at 228560 .text:0000000000228664 ; End of function sub_228560 import idaapi import idc import idautils import ida_nalt def analyze_elf_structure(): """Analyze ELF file structure in detail""" print(f"\n{'='*60}") print("ELF Structure Analysis") print(f"{'='*60}") # Get ELF header info inf = idaapi.get_inf_structure() print(f"Processor: {inf.procname}") print(f"File Type: {ida_nalt.get_file_type_name()}") print(f"Image Base: 0x{inf.base:016X}") # List all segments with detailed info print(f"\n{'='*60}") print("Segment Mapping (VA ↔ File Offset)") print(f"{'='*60}") print(f"{'Name':<12} {'Start VA':<16} {'End VA':<16} {'File Off':<12} {'Size':<12}") print(f"{'-'*70}") for n in range(idaapi.get_segm_qty()): seg = idaapi.getnseg(n) if seg: seg_name = idaapi.get_segm_name(seg) start_va = seg.start_ea end_va = seg.end_ea size = end_va - start_va # Try to get file offset file_off = idaapi.get_fileregion_offset(start_va) if file_off == -1: file_off_str = "N/A" else: file_off_str = f"0x{file_off:X}" print(f"{seg_name:<12} 0x{start_va:<14X} 0x{end_va:<14X} {file_off_str:<12} 0x{size:<10X}") def calculate_file_offset_detailed(va_address): “”” Calculate file offset with detailed explanation “”” print(f"\n{'='*60}") print(f"Detailed File Offset Calculation") print(f"{'='*60}") # Get segment containing the address seg = idaapi.getseg(va_address) if not seg: print(f"❌ Address 0x{va_address:X} not in any segment!") return None seg_name = idaapi.get_segm_name(seg) seg_start = seg.start_ea # Get file offset directly if available file_offset = idaapi.get_fileregion_offset(va_address) print(f"Target VA: 0x{va_address:X}") print(f"In segment: {seg_name}") print(f"Segment start VA: 0x{seg_start:X}") print(f"Offset in segment: 0x{va_address - seg_start:X}") if file_offset != -1: print(f"\n✅ Direct file offset mapping found!") print(f"File offset: 0x{file_offset:X}") # Show the relationship if file_offset == va_address: print(f"\n📌 Special case: File offset equals VA") print(f" This means .text starts at file offset 0x{seg_start:X}") else: print(f"\n📌 Relationship: VA 0x{va_address:X} → File 0x{file_offset:X}") print(f" Delta: 0x{va_address - file_offset:X}") else: # Try to calculate based on common patterns print(f"\n⚠️ No direct file offset mapping") print(f"Trying to calculate based on ELF patterns...") # Common ARM64 patterns if seg_name == ".text": # Pattern 1: .text at 0x28000 in file calc1 = (va_address - seg_start) + 0x28000 # Pattern 2: .text at 0x1000 in file calc2 = (va_address - seg_start) + 0x1000 # Pattern 3: Direct mapping (your case) calc3 = va_address print(f"\nPossible calculations:") print(f" 1. If .text @ file 0x28000: 0x{calc1:X}") print(f" 2. If .text @ file 0x1000: 0x{calc2:X}") print(f" 3. If direct VA=File mapping: 0x{calc3:X}") # Ask user which one to use print(f"\nSelect calculation method:") print(f" [1] Pattern 1 (0x28000 offset)") print(f" [2] Pattern 2 (0x1000 offset)") print(f" [3] Direct mapping") print(f" [4] Custom offset") choice = input("Choice (1-4): ").strip() if choice == "1": file_offset = calc1 elif choice == "2": file_offset = calc2 elif choice == "3": file_offset = calc3 elif choice == "4": custom = input("Enter custom .text file offset (hex): ").strip() try: custom_offset = int(custom, 16) file_offset = (va_address - seg_start) + custom_offset except: print("Invalid offset!") return None else: print("Invalid choice!") return None return file_offset def extract_hex_bytes(va_address, num_bytes=16): """Extract hex bytes from memory""" hex_bytes = [] for i in range(num_bytes): byte = idaapi.get_byte(va_address + i) hex_bytes.append(byte) # Format for MemoryPatch hex_str = " ".join([f"{b:02X}" for b in hex_bytes]) # Also create C array format c_array = ", ".join([f"0x{b:02X}" for b in hex_bytes]) return hex_str, c_array, hex_bytes def generate_patches(va_address, file_offset, hex_str): """Generate different patch formats""" print(f"\n{'='*60}") print("Patch Code Generation") print(f"{'='*60}") # Format 1: MemoryPatch (Android) print(f"\n📱 MemoryPatch (Android):") print(f"{'-'*40}") patch_code = f'MemoryPatch::createWithHex("libanogs.so", 0x{file_offset:X}, "{hex_str}").Modify();' print(patch_code) # Format 2: Direct hex patch print(f"\n🔧 Direct Hex Patch:") print(f"{'-'*40}") print(f"Offset: 0x{file_offset:X}") print(f"Bytes: {hex_str}") # Format 3: Binary patch command print(f"\n💻 Binary Patch Command (xxd):") print(f"{'-'*40}") print(f"printf '{hex_str.replace(' ', '')}' | xxd -r -p | dd of=libanogs.so bs=1 seek=$((0x{file_offset:X})) conv=notrunc") # Format 4: C code for inline patching print(f"\n👨‍💻 C Inline Patching Code:") print(f"{'-'*40}") bytes_list = hex_str.split() c_code = f"""uintptr_t patch_addr = base_address + 0x{va_address:X}; // Or use dlopen+dlsym unsigned char patch_bytes[] = {{{', '.join([f'0x{b}' for b in bytes_list])}}}; memcpy((void*)patch_addr, patch_bytes, sizeof(patch_bytes));""" print(c_code) def interactive_analyzer(): """Interactive analyzer with options""" print(f"\n{'='*60}") print("IDA ELF File Offset Analyzer") print("="*60) while True: print(f"\nOptions:") print(f" 1. Analyze current address") print(f" 2. Enter address manually") print(f" 3. View ELF structure") print(f" 4. Generate patch from current") print(f" 5. Exit") choice = input("\nSelect option: ").strip() if choice == "1": # Current address current_ea = idc.get_screen_ea() if current_ea != idaapi.BADADDR: print(f"\n📍 Current address: 0x{current_ea:X}") analyze_single_address(current_ea) else: print("❌ No valid address at cursor!") elif choice == "2": # Manual address addr_str = input("\nEnter VA (hex): ").strip() try: if addr_str.startswith("0x"): va_address = int(addr_str, 16) else: va_address = int(addr_str, 16) analyze_single_address(va_address) except: print("❌ Invalid address!") elif choice == "3": # ELF structure analyze_elf_structure() elif choice == "4": # Generate patch from current current_ea = idc.get_screen_ea() if current_ea != idaapi.BADADDR: generate_patch_from_address(current_ea) else: print("❌ No valid address at cursor!") elif choice == "5": break else: print("❌ Invalid option!") def analyze_single_address(va_address): """Analyze a single address""" print(f"\n{'='*60}") print(f"Analyzing 0x{va_address:X}") print(f"{'='*60}") # Get disassembly disasm = idc.generate_disasm_line(va_address, 0) print(f"Instruction: {disasm}") # Get function info func = idaapi.get_func(va_address) if func: func_name = idaapi.get_func_name(func.start_ea) print(f"Function: {func_name} (0x{func.start_ea:X}-0x{func.end_ea:X})") # Calculate file offset file_offset = calculate_file_offset_detailed(va_address) if not file_offset: return # Extract hex bytes hex_str, c_array, raw_bytes = extract_hex_bytes(va_address, 16) print(f"\n🔍 Hex Bytes (16 bytes):") print(f" {hex_str}") print(f"\n📊 C Array:") print(f" {{{c_array}}}") # Generate patches generate_patches(va_address, file_offset, hex_str) # Ask to copy to clipboard copy = input(f"\n📋 Copy MemoryPatch code to clipboard? (y/n): ").strip().lower() if copy == 'y': try: import pyperclip patch_code = f'MemoryPatch::createWithHex("libanogs.so", 0x{file_offset:X}, "{hex_str}").Modify();' pyperclip.copy(patch_code) print("✅ Copied to clipboard!") except: print("⚠️ Install pyperclip: pip install pyperclip") def generate_patch_from_address(va_address): """Quick patch generation from address""" file_offset = calculate_file_offset_detailed(va_address) if not file_offset: return hex_str, _, _ = extract_hex_bytes(va_address, 16) print(f"\n✅ Quick Patch Code:") print(f"{'='*40}") print(f'MemoryPatch::createWithHex("libanogs.so", 0x{file_offset:X}, "{hex_str}").Modify();') print(f"{'='*40}") def show_simple_dialog(): """Simple dialog for quick analysis""" import ida_kernwin # Get current address current_ea = idc.get_screen_ea() # Ask for address or use current if current_ea != idaapi.BADADDR: default_addr = f"0x{current_ea:X}" else: default_addr = "0x228654" addr_str = ida_kernwin.ask_str(default_addr, 0, "Enter virtual address (hex):") if not addr_str: return try: if addr_str.startswith("0x"): va_address = int(addr_str, 16) else: va_address = int(addr_str, 16) # Quick analysis file_offset = calculate_file_offset_detailed(va_address) if file_offset: hex_str, _, _ = extract_hex_bytes(va_address, 16) # Show result result = f"""Analysis Complete! Address: 0x{va_address:X} File Offset: 0x Hex Bytes: MemoryPatch Code: MemoryPatch::createWithHex(“ libanogs.so ”, 0x{file_offset:X}, “{hex_str}”).Modify();“”” # Display in message box ida_kernwin.msg(result) # Also print to console print(f"\n{result}") except ValueError as e: ida_kernwin.warning(f"Invalid address: {e}") Run the script if name == " main ": # Choose your preferred mode: # Mode 1: Simple dialog (recommended for beginners) show_simple_dialog() # Mode 2: Full interactive analyzer # interactive_analyzer() # Mode 3: Quick analysis of current address # current_ea = idc.get_screen_ea() # if current_ea != idaapi.BADADDR: # analyze_single_address(current_ea) Address: 0x228560 File Offset: 0x228560 Hex Bytes: FF 43 01 D1 FD 7B 03 A9 F4 4F 04 A9 FD C3 00 91 MemoryPatch Code: MemoryPatch::createWithHex(“ libanogs.so ”, 0x228560, “FF 43 01 D1 FD 7B 03 A9 F4 4F 04 A9 FD C3 00 91).Modify(); this is result getting from script MemoryPatch::createWithHex( " libanogs.so ", 0x28654, "E0 03 C0 FF E1 83 C1 B2 E2 07 C2 B2 E3 0B C3 B2" ).Modify(); this result find by ai why both diffrent
最新发布
12-06
/****************************************************************************** * * Filename: * --------- * gc05a2mipimadrid_Sensor.c * * Project: * -------- * ALPS * * Description: * ------------ * Source code of Sensor driver * * *----------------------------------------------------------------------------- * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! *============================================================================ * * Version: V20220830190306 by GC-S-TEAM * ******************************************************************************/ #include <linux/videodev2.h> #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/cdev.h> #include <linux/uaccess.h> #include <linux/fs.h> #include <linux/atomic.h> #include <linux/types.h> #include "kd_camera_typedef.h" #include "kd_imgsensor.h" #include "kd_imgsensor_define.h" #include "kd_imgsensor_errcode.h" #include "gc05a2mipimadrid_Sensor.h" /************************** Modify Following Strings for Debug **************************/ #define PFX "gc05a2_camera_sensor" #define LOG_1 LOG_INF("GC05A2, MIPI 2LANE\n") /**************************** Modify end *******************************************/ #define GC05A2_DEBUG 1 #if GC05A2_DEBUG #define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __func__, ##args) #else #define LOG_INF(format, args...) #endif #define SN_OFFSET 0x2150 // sn starting address of otp guide #define SN_LENGTH 0x1F // sn length + read offset #define GC05A2_SN_DEBUG 0 static BYTE gc05a2_common_data[200] = { 0 }; static DEFINE_SPINLOCK(imgsensor_drv_lock); static struct imgsensor_info_struct imgsensor_info = { .sensor_id = GC05A2_SENSOR_ID_MADRID, .checksum_value = 0xe5d32119, .pre = { .pclk = 224000000, .linelength = 3616, .framelength = 2064, .startx = 0, .starty = 0, .grabwindow_width = 1296, .grabwindow_height = 972, .mipi_data_lp2hs_settle_dc = 85, .mipi_pixel_rate = 89600000, .max_framerate = 300, }, .cap = { .pclk = 224000000, .linelength = 3664, .framelength = 2032, .startx = 0, .starty = 0, .grabwindow_width = 2592, .grabwindow_height = 1944, .mipi_data_lp2hs_settle_dc = 85, .mipi_pixel_rate = 179200000, .max_framerate = 300, }, .normal_video = { .pclk = 224000000, .linelength = 3616, .framelength = 2064, .startx = 0, .starty = 0, .grabwindow_width = 1296, .grabwindow_height = 972, .mipi_data_lp2hs_settle_dc = 85, .mipi_pixel_rate = 89600000, .max_framerate = 300, }, .hs_video = { .pclk = 224000000, .linelength = 3616, .framelength = 2064, .startx = 0, .starty = 0, .grabwindow_width = 1296, .grabwindow_height = 972, .mipi_data_lp2hs_settle_dc = 85, .mipi_pixel_rate = 89600000, .max_framerate = 300, }, .slim_video = { .pclk = 224000000, .linelength = 3616, .framelength = 2064, .startx = 0, .starty = 0, .grabwindow_width = 1280, .grabwindow_height = 720, .mipi_data_lp2hs_settle_dc = 85, .mipi_pixel_rate = 89600000, .max_framerate = 300, }, .margin = 16, .min_shutter = 4, .max_frame_length = 0xfffe, .ae_shut_delay_frame = 0, .ae_sensor_gain_delay_frame = 0, .ae_ispGain_delay_frame = 2, .ihdr_support = 0, .ihdr_le_firstline = 0, .sensor_mode_num = 5, .cap_delay_frame = 2, .pre_delay_frame = 2, .video_delay_frame = 2, .hs_video_delay_frame = 2, .slim_video_delay_frame = 2, .isp_driving_current = ISP_DRIVING_6MA, .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI, .mipi_sensor_type = MIPI_OPHY_NCSI2, .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO, //#if GC05A2_MIRROR_NORMAL .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_Gr, //#elif GC05A2_MIRROR_H // .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_R, //#elif GC05A2_MIRROR_V // .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_B, //#elif GC05A2_MIRROR_HV // .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_Gb, //#else // .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_Gr, //#endif .mclk = 24, .mipi_lane_num = SENSOR_MIPI_2_LANE, .i2c_addr_table = {0x7e, 0xff}, .i2c_speed = 400, }; static struct imgsensor_struct imgsensor = { .mirror = IMAGE_HV_MIRROR, .sensor_mode = IMGSENSOR_MODE_INIT, .shutter = 0x900, .gain = 0x40, .dummy_pixel = 0, .dummy_line = 0, .current_fps = 300, .autoflicker_en = KAL_FALSE, .test_pattern = KAL_FALSE, .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW, .ihdr_en = 0, .i2c_write_id = 0x7e, }; /* Sensor output window information */ static struct SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = { { 2592, 1944, 0, 0, 2592, 1944, 1296, 972, 0, 0, 1296, 972, 0, 0, 1296, 972}, /* Preview */ { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0, 0, 2592, 1944, 0, 0, 2592, 1944}, /* capture */ { 2592, 1944, 0, 0, 2592, 1944, 1296, 972, 0, 0, 1296, 972, 0, 0, 1296, 972}, /* video */ { 2592, 1944, 0, 0, 2592, 1944, 1296, 972, 0, 0, 1296, 972, 0, 0, 1296, 972}, /* hs video */ { 2592, 1944, 0, 0, 2592, 1944, 1296, 972, 8, 126, 1280, 720, 0, 0, 1280, 720} /* slim video */ }; static kal_uint16 read_cmos_sensor(kal_uint32 addr) { kal_uint16 get_byte = 0; char pu_send_cmd[2] = { (char)((addr >> 8) & 0xff), (char)(addr & 0xff) }; iReadRegI2C(pu_send_cmd, 2, (u8 *)&get_byte, 1, imgsensor.i2c_write_id); return get_byte; } static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) { char pu_send_cmd[4] = { (char)((addr >> 8) & 0xff), (char)(addr & 0xff), (char)((para >> 8) & 0xff), (char)(para & 0xff) }; iWriteRegI2C(pu_send_cmd, 4, imgsensor.i2c_write_id); } static void write_cmos_sensor_8bit(kal_uint32 addr, kal_uint32 para) { char pu_send_cmd[3] = { (char)((addr >> 8) & 0xff), (char)(addr & 0xff), (char)(para & 0xff) }; iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); } static void table_write_cmos_sensor(kal_uint16 *para, kal_uint32 len) { char puSendCmd[I2C_BUFFER_LEN]; kal_uint32 tosend = 0, idx = 0; kal_uint16 addr = 0, data = 0; while (len > idx) { addr = para[idx]; puSendCmd[tosend++] = (char)((addr >> 8) & 0xff); puSendCmd[tosend++] = (char)(addr & 0xff); data = para[idx + 1]; puSendCmd[tosend++] = (char)(data & 0xff); idx += 2; #if MULTI_WRITE if (tosend >= I2C_BUFFER_LEN || idx == len) { iBurstWriteReg_multi(puSendCmd, tosend, imgsensor.i2c_write_id, 3, imgsensor_info.i2c_speed); tosend = 0; } #else iWriteRegI2CTiming(puSendCmd, 3, imgsensor.i2c_write_id, imgsensor_info.i2c_speed); tosend = 0; #endif } } static kal_uint32 return_sensor_id(void) { kal_uint32 sensor_id = 0; sensor_id = (read_cmos_sensor(0x03f0) << 8) | read_cmos_sensor(0x03f1); return sensor_id; } static void set_dummy(void) { LOG_INF("frame length = %d\n", imgsensor.frame_length); write_cmos_sensor(0x0340, imgsensor.frame_length & 0xfffe); } static void set_max_framerate(kal_uint16 framerate, kal_bool min_framelength_en) { kal_uint32 frame_length = imgsensor.frame_length; frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; spin_lock(&imgsensor_drv_lock); imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; if (imgsensor.frame_length > imgsensor_info.max_frame_length) { imgsensor.frame_length = imgsensor_info.max_frame_length; imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; } if (min_framelength_en) imgsensor.min_frame_length = imgsensor.frame_length; spin_unlock(&imgsensor_drv_lock); set_dummy(); } static void set_shutter(kal_uint16 shutter) { unsigned long flags; kal_uint16 realtime_fps = 0; /*kal_uint32 frame_length = 0;*/ spin_lock_irqsave(&imgsensor_drv_lock, flags); imgsensor.shutter = shutter; spin_unlock_irqrestore(&imgsensor_drv_lock, flags); /* if shutter bigger than frame_length, should extend frame length first */ spin_lock(&imgsensor_drv_lock); if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) imgsensor.frame_length = shutter + imgsensor_info.margin; else imgsensor.frame_length = imgsensor.min_frame_length; if (imgsensor.frame_length > imgsensor_info.max_frame_length) imgsensor.frame_length = imgsensor_info.max_frame_length; spin_unlock(&imgsensor_drv_lock); shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; if (imgsensor.autoflicker_en) { if (realtime_fps >= 297 && realtime_fps <= 305) set_max_framerate(296, 0); else if (realtime_fps >= 147 && realtime_fps <= 150) set_max_framerate(146, 0); else write_cmos_sensor(0x0340, imgsensor.frame_length & 0xfffe); } else write_cmos_sensor(0x0340, imgsensor.frame_length & 0xfffe); /* Update Shutter */ write_cmos_sensor(0x0202, shutter); LOG_INF("shutter = %d, framelength = %d\n", shutter, imgsensor.frame_length); } static kal_uint16 gain2reg(kal_uint16 gain) { kal_uint16 reg_gain = gain << 4; reg_gain = (reg_gain < SENSOR_BASE_GAIN) ? SENSOR_BASE_GAIN : reg_gain; reg_gain = (reg_gain > SENSOR_MAX_GAIN) ? SENSOR_MAX_GAIN : reg_gain; return reg_gain; } static kal_uint16 set_gain(kal_uint16 gain) { kal_uint32 reg_gain = 0; reg_gain = gain2reg(gain); LOG_INF("gain = %d, reg_gain = %d\n", gain, reg_gain); write_cmos_sensor(0x0204, reg_gain & 0xffff); return gain; } static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) { LOG_INF("le: 0x%x, se: 0x%x, gain: 0x%x\n", le, se, gain); } static void night_mode(kal_bool enable) { /* No Need to implement this function */ } static kal_uint16 gc05a2_init_addr_data[] = { /*system*/ 0x0315, 0xd4, 0x0d06, 0x01, 0x0a70, 0x80, 0x031a, 0x00, 0x0314, 0x00, 0x0130, 0x08, 0x0132, 0x01, 0x0135, 0x01, 0x0136, 0x38, 0x0137, 0x03, 0x0134, 0x5b, 0x031c, 0xe0, 0x0d82, 0x14, 0x0dd1, 0x56, /*gate_mode*/ 0x0af4, 0x01, 0x0002, 0x10, 0x00c3, 0x34, /*pre_setting*/ 0x0084, 0x21, 0x0d05, 0xcc, 0x0218, 0x00, 0x005e, 0x48, 0x0d06, 0x01, 0x0007, 0x16, 0x0101, GC05A2_MIRROR, /*analog*/ 0x0342, 0x07, 0x0343, 0x28, 0x0220, 0x07, 0x0221, 0xd0, 0x0202, 0x07, 0x0203, 0x32, 0x0340, 0x07, 0x0341, 0xf0, 0x0219, 0x00, 0x0346, 0x00, 0x0347, 0x04, 0x0d14, 0x00, 0x0d13, 0x05, 0x0d16, 0x05, 0x0d15, 0x1d, 0x00c0, 0x0a, 0x00c1, 0x30, 0x034a, 0x07, 0x034b, 0xa8, 0x0e0a, 0x00, 0x0e0b, 0x00, 0x0e0e, 0x03, 0x0e0f, 0x00, 0x0e06, 0x0a, 0x0e23, 0x15, 0x0e24, 0x15, 0x0e2a, 0x10, 0x0e2b, 0x10, 0x0e17, 0x49, 0x0e1b, 0x1c, 0x0e3a, 0x36, 0x0d11, 0x84, 0x0e52, 0x14, 0x000b, 0x10, 0x0008, 0x08, 0x0223, 0x17, 0x0d27, 0x39, 0x0d22, 0x00, 0x03f6, 0x0d, 0x0d04, 0x07, 0x03f3, 0x72, 0x03f4, 0xb8, 0x03f5, 0xbc, 0x0d02, 0x73, /*auto load start*/ 0x00c4, 0x00, 0x00c5, 0x01, 0x0af6, 0x00, 0x0ba0, 0x17, 0x0ba1, 0x00, 0x0ba2, 0x00, 0x0ba3, 0x00, 0x0ba4, 0x03, 0x0ba5, 0x00, 0x0ba6, 0x00, 0x0ba7, 0x00, 0x0ba8, 0x40, 0x0ba9, 0x00, 0x0baa, 0x00, 0x0bab, 0x00, 0x0bac, 0x40, 0x0bad, 0x00, 0x0bae, 0x00, 0x0baf, 0x00, 0x0bb0, 0x02, 0x0bb1, 0x00, 0x0bb2, 0x00, 0x0bb3, 0x00, 0x0bb8, 0x02, 0x0bb9, 0x00, 0x0bba, 0x00, 0x0bbb, 0x00, 0x0a70, 0x80, 0x0a71, 0x00, 0x0a72, 0x00, 0x0a66, 0x00, 0x0a67, 0x80, 0x0a4d, 0x4e, 0x0a50, 0x00, 0x0a4f, 0x0c, 0x0a66, 0x00, 0x00ca, 0x00, 0x00cb, 0x00, 0x00cc, 0x00, 0x00cd, 0x00, 0x0aa1, 0x00, 0x0aa2, 0xe0, 0x0aa3, 0x00, 0x0aa4, 0x40, 0x0a90, 0x03, 0x0a91, 0x0e, 0x0a94, 0x80, /*standby*/ 0x0af6, 0x20, 0x0b00, 0x91, 0x0b01, 0x17, 0x0b02, 0x01, 0x0b03, 0x00, 0x0b04, 0x01, 0x0b05, 0x17, 0x0b06, 0x01, 0x0b07, 0x00, 0x0ae9, 0x01, 0x0aea, 0x02, 0x0ae8, 0x53, 0x0ae8, 0x43, /*gain_partition*/ 0x0af6, 0x30, 0x0b00, 0x08, 0x0b01, 0x0f, 0x0b02, 0x00, 0x0b04, 0x1c, 0x0b05, 0x24, 0x0b06, 0x00, 0x0b08, 0x30, 0x0b09, 0x40, 0x0b0a, 0x00, 0x0b0c, 0x0e, 0x0b0d, 0x2a, 0x0b0e, 0x00, 0x0b10, 0x0e, 0x0b11, 0x2b, 0x0b12, 0x00, 0x0b14, 0x0e, 0x0b15, 0x23, 0x0b16, 0x00, 0x0b18, 0x0e, 0x0b19, 0x24, 0x0b1a, 0x00, 0x0b1c, 0x0c, 0x0b1d, 0x0c, 0x0b1e, 0x00, 0x0b20, 0x03, 0x0b21, 0x03, 0x0b22, 0x00, 0x0b24, 0x0e, 0x0b25, 0x0e, 0x0b26, 0x00, 0x0b28, 0x03, 0x0b29, 0x03, 0x0b2a, 0x00, 0x0b2c, 0x12, 0x0b2d, 0x12, 0x0b2e, 0x00, 0x0b30, 0x08, 0x0b31, 0x08, 0x0b32, 0x00, 0x0b34, 0x14, 0x0b35, 0x14, 0x0b36, 0x00, 0x0b38, 0x10, 0x0b39, 0x10, 0x0b3a, 0x00, 0x0b3c, 0x16, 0x0b3d, 0x16, 0x0b3e, 0x00, 0x0b40, 0x10, 0x0b41, 0x10, 0x0b42, 0x00, 0x0b44, 0x19, 0x0b45, 0x19, 0x0b46, 0x00, 0x0b48, 0x16, 0x0b49, 0x16, 0x0b4a, 0x00, 0x0b4c, 0x19, 0x0b4d, 0x19, 0x0b4e, 0x00, 0x0b50, 0x16, 0x0b51, 0x16, 0x0b52, 0x00, 0x0b80, 0x01, 0x0b81, 0x00, 0x0b82, 0x00, 0x0b84, 0x00, 0x0b85, 0x00, 0x0b86, 0x00, 0x0b88, 0x01, 0x0b89, 0x6a, 0x0b8a, 0x00, 0x0b8c, 0x00, 0x0b8d, 0x01, 0x0b8e, 0x00, 0x0b90, 0x01, 0x0b91, 0xf6, 0x0b92, 0x00, 0x0b94, 0x00, 0x0b95, 0x02, 0x0b96, 0x00, 0x0b98, 0x02, 0x0b99, 0xc4, 0x0b9a, 0x00, 0x0b9c, 0x00, 0x0b9d, 0x03, 0x0b9e, 0x00, 0x0ba0, 0x03, 0x0ba1, 0xd8, 0x0ba2, 0x00, 0x0ba4, 0x00, 0x0ba5, 0x04, 0x0ba6, 0x00, 0x0ba8, 0x05, 0x0ba9, 0x4d, 0x0baa, 0x00, 0x0bac, 0x00, 0x0bad, 0x05, 0x0bae, 0x00, 0x0bb0, 0x07, 0x0bb1, 0x3e, 0x0bb2, 0x00, 0x0bb4, 0x00, 0x0bb5, 0x06, 0x0bb6, 0x00, 0x0bb8, 0x0a, 0x0bb9, 0x1a, 0x0bba, 0x00, 0x0bbc, 0x09, 0x0bbd, 0x36, 0x0bbe, 0x00, 0x0bc0, 0x0e, 0x0bc1, 0x66, 0x0bc2, 0x00, 0x0bc4, 0x10, 0x0bc5, 0x06, 0x0bc6, 0x00, 0x02c1, 0xe0, 0x0207, 0x04, 0x02c2, 0x10, 0x02c3, 0x74, 0x02C5, 0x09, 0x02c1, 0xe0,//20221121 0x0207, 0x04, 0x02c2, 0x10, 0x02c5, 0x09, 0x02c1, 0xe0, 0x0207, 0x04, 0x02c2, 0x10, 0x02c5, 0x09, /*auto load CH_GAIN*/ 0x0aa1, 0x15, 0x0aa2, 0x50, 0x0aa3, 0x00, 0x0aa4, 0x09, 0x0a90, 0x25, 0x0a91, 0x0e, 0x0a94, 0x80, /*ISP*/ 0x0050, 0x00, 0x0089, 0x83, 0x005a, 0x40, 0x00c3, 0x35, 0x00c4, 0x80, 0x0080, 0x10, 0x0040, 0x12, 0x0053, 0x0a, 0x0054, 0x44, 0x0055, 0x32, 0x0058, 0x89, 0x004a, 0x03, 0x0048, 0xf0, 0x0049, 0x0f, 0x0041, 0x20, 0x0043, 0x0a, 0x009d, 0x08, 0x0236, 0x40, /*gain*/ 0x0204, 0x04, 0x0205, 0x00, 0x02b3, 0x00, 0x02b4, 0x00, 0x009e, 0x01, 0x009f, 0x94, /*OUT 2592x1944*/ 0x0350, 0x01, 0x0353, 0x00, 0x0354, 0x08, 0x034c, 0x0a, 0x034d, 0x20, 0x021f, 0x14, /*auto load REG*/ 0x0aa1, 0x10, 0x0aa2, 0xf8, 0x0aa3, 0x00, 0x0aa4, 0x1f, 0x0a90, 0x11, 0x0a91, 0x0e, 0x0a94, 0x80, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00,//20221121 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x0a90, 0x00, 0x0a70, 0x00, 0x0a67, 0x00, 0x0af4, 0x29, /*DPHY */ 0x0d80, 0x07, 0x0dd3, 0x1c, /*MIPI*/ 0x0107, 0x05, 0x0117, 0x01, 0x0d81, 0x00, /*CISCTL_Reset*/ 0x031c, 0x80, 0x03fe, 0x30, 0x0d17, 0x06, 0x03fe, 0x00, 0x0d17, 0x00, 0x031c, 0x93, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x031c, 0x80, 0x03fe, 0x30, 0x0d17, 0x06, 0x03fe, 0x00, 0x0d17, 0x00, 0x031c, 0x93, }; static kal_uint16 gc05a2_1296x972_addr_data[] = { /*system*/ 0x0315, 0xd4, 0x0d06, 0x01, 0x0a70, 0x80, 0x031a, 0x00, 0x0314, 0x00, 0x0130, 0x08, 0x0132, 0x01, 0x0135, 0x05, 0x0136, 0x38, 0x0137, 0x03, 0x0134, 0x5b, 0x031c, 0xe0, 0x0d82, 0x14, 0x0dd1, 0x56, /*gate_mode*/ 0x0af4, 0x01, 0x0002, 0x10, 0x00c3, 0x34, /*pre_setting*/ 0x0084, 0x21, 0x0d05, 0xcc, 0x0218, 0x80, 0x005e, 0x49, 0x0d06, 0x81, 0x0007, 0x16, /*analog */ 0x0342, 0x07, 0x0343, 0x10, 0x0220, 0x0f, 0x0221, 0xe0, 0x0202, 0x03, 0x0203, 0x32, 0x0340, 0x08, 0x0341, 0x10, 0x0346, 0x00, 0x0347, 0x04, 0x0d14, 0x00, 0x0d13, 0x05, 0x0d16, 0x05, 0x0d15, 0x1d, 0x00c0, 0x0a, 0x00c1, 0x30, 0x034a, 0x07, 0x034b, 0xa8, 0x000b, 0x0e, 0x0008, 0x03, 0x0223, 0x16, /*auto load DD*/ 0x00ca, 0x00, 0x00cb, 0x00, 0x00cc, 0x00, 0x00cd, 0x00, /*ISP*/ 0x00c3, 0x35, 0x0053, 0x0a, 0x0054, 0x44, 0x0055, 0x32, /*OUT 1296x972*/ 0x0350, 0x01, 0x0353, 0x00, 0x0354, 0x04, 0x034c, 0x05, 0x034d, 0x10, 0x021f, 0x14, /*MIPI*/ 0x0d84, 0x06, 0x0d85, 0x54, 0x0d86, 0x03, 0x0d87, 0x2b, 0x0db3, 0x03, 0x0db4, 0x04, 0x0db5, 0x0d, 0x0db6, 0x01, 0x0db8, 0x04, 0x0db9, 0x06, 0x0d93, 0x03, 0x0d94, 0x04, 0x0d95, 0x05, 0x0d99, 0x06, 0x0084, 0x01, /*CISCTL_Reset*/ 0x031c, 0x80, 0x03fe, 0x30, 0x0d17, 0x06, 0x03fe, 0x00, 0x0d17, 0x00, 0x031c, 0x93, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x031c, 0x80, 0x03fe, 0x30, 0x0d17, 0x06, 0x03fe, 0x00, 0x0d17, 0x00, 0x031c, 0x93, /*OUT*/ 0x0110, 0x01, }; static kal_uint16 gc05a2_normal_video_addr_data[] = { /*system*/ 0x0315, 0xd4, 0x0d06, 0x01, 0x0a70, 0x80, 0x031a, 0x00, 0x0314, 0x00, 0x0130, 0x08, 0x0132, 0x01, 0x0135, 0x05, 0x0136, 0x38, 0x0137, 0x03, 0x0134, 0x5b, 0x031c, 0xe0, 0x0d82, 0x14, 0x0dd1, 0x56, /*gate_mode*/ 0x0af4, 0x01, 0x0002, 0x10, 0x00c3, 0x34, /*pre_setting*/ 0x0084, 0x21, 0x0d05, 0xcc, 0x0218, 0x80, 0x005e, 0x49, 0x0d06, 0x81, 0x0007, 0x16, /*analog */ 0x0342, 0x07, 0x0343, 0x10, 0x0220, 0x0f, 0x0221, 0xe0, 0x0202, 0x03, 0x0203, 0x32, 0x0340, 0x08, 0x0341, 0x10, 0x0346, 0x00, 0x0347, 0x04, 0x0d14, 0x00, 0x0d13, 0x05, 0x0d16, 0x05, 0x0d15, 0x1d, 0x00c0, 0x0a, 0x00c1, 0x30, 0x034a, 0x07, 0x034b, 0xa8, 0x000b, 0x0e, 0x0008, 0x03, 0x0223, 0x16, /*auto load DD*/ 0x00ca, 0x00, 0x00cb, 0x00, 0x00cc, 0x00, 0x00cd, 0x00, /*ISP*/ 0x00c3, 0x35, 0x0053, 0x0a, 0x0054, 0x44, 0x0055, 0x32, /*OUT 1296x972*/ 0x0350, 0x01, 0x0353, 0x00, 0x0354, 0x04, 0x034c, 0x05, 0x034d, 0x10, 0x021f, 0x14, /*MIPI*/ 0x0d84, 0x06, 0x0d85, 0x54, 0x0d86, 0x03, 0x0d87, 0x2b, 0x0db3, 0x03, 0x0db4, 0x04, 0x0db5, 0x0d, 0x0db6, 0x01, 0x0db8, 0x08, 0x0db9, 0x06, 0x0d93, 0x03, 0x0d94, 0x04, 0x0d95, 0x05, 0x0d99, 0x06, 0x0084, 0x01, /*CISCTL_Reset*/ 0x031c, 0x80, 0x03fe, 0x30, 0x0d17, 0x06, 0x03fe, 0x00, 0x0d17, 0x00, 0x031c, 0x93, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x031c, 0x80, 0x03fe, 0x30, 0x0d17, 0x06, 0x03fe, 0x00, 0x0d17, 0x00, 0x031c, 0x93, /*OUT*/ 0x0110, 0x01, }; static kal_uint16 gc05a2_2592x1944_addr_data[] = { /*system*/ 0x0315, 0xd4, 0x0d06, 0x01, 0x0a70, 0x80, 0x031a, 0x00, 0x0314, 0x00, 0x0130, 0x08, 0x0132, 0x01, 0x0135, 0x01, 0x0136, 0x38, 0x0137, 0x03, 0x0134, 0x5b, 0x031c, 0xe0, 0x0d82, 0x14, 0x0dd1, 0x56, /*gate_mode*/ 0x0af4, 0x01, 0x0002, 0x10, 0x00c3, 0x34, /*pre_setting*/ 0x0084, 0x21, 0x0d05, 0xcc, 0x0218, 0x00, 0x005e, 0x48, 0x0d06, 0x01, 0x0007, 0x16, /*analog*/ 0x0342, 0x07, 0x0343, 0x28, 0x0220, 0x07, 0x0221, 0xd0, 0x0202, 0x07, 0x0203, 0x32, 0x0340, 0x07, 0x0341, 0xf0, 0x0346, 0x00, 0x0347, 0x04, 0x0d14, 0x00, 0x0d13, 0x05, 0x0d16, 0x05, 0x0d15, 0x1d, 0x00c0, 0x0a, 0x00c1, 0x30, 0x034a, 0x07, 0x034b, 0xa8, 0x000b, 0x10, 0x0008, 0x08, 0x0223, 0x17, /* auto load DD*/ 0x00ca, 0x00, 0x00cb, 0x00, 0x00cc, 0x00, 0x00cd, 0x00, /*ISP*/ 0x00c3, 0x35, 0x0053, 0x0a, 0x0054, 0x44, 0x0055, 0x32, /*OUT 2592x1944*/ 0x0350, 0x01, 0x0353, 0x00, 0x0354, 0x08, 0x034c, 0x0a, 0x034d, 0x20, 0x021f, 0x14, /*MIPI*/ 0x0d84, 0x0c, 0x0d85, 0xa8, 0x0d86, 0x06, 0x0d87, 0x55, 0x0db3, 0x06, 0x0db4, 0x08, 0x0db5, 0x1e, 0x0db6, 0x02, 0x0db8, 0x12, 0x0db9, 0x0a, 0x0d93, 0x06, 0x0d94, 0x09, 0x0d95, 0x0d, 0x0d99, 0x0b, 0x0084, 0x01, /* CISCTL_Reset*/ 0x031c, 0x80, 0x03fe, 0x30, 0x0d17, 0x06, 0x03fe, 0x00, 0x0d17, 0x00, 0x031c, 0x93, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x031c, 0x80, 0x03fe, 0x30, 0x0d17, 0x06, 0x03fe, 0x00, 0x0d17, 0x00, 0x031c, 0x93, /*OUT*/ 0x0110, 0x01, }; static kal_uint16 gc05a2_1280x720_addr_data[] = { /*system*/ 0x0315, 0xd4, 0x0d06, 0x01, 0x0a70, 0x80, 0x031a, 0x00, 0x0314, 0x00, 0x0130, 0x08, 0x0132, 0x01, 0x0135, 0x05, 0x0136, 0x38, 0x0137, 0x03, 0x0134, 0x5b, 0x031c, 0xe0, 0x0d82, 0x14, 0x0dd1, 0x56, /*gate_mode*/ 0x0af4, 0x01, 0x0002, 0x10, 0x00c3, 0x34, /*pre_setting*/ 0x0084, 0x21, 0x0d05, 0xcc, 0x0218, 0x80, 0x005e, 0x49, 0x0d06, 0x81, 0x0007, 0x16, /*analog */ 0x0342, 0x07, 0x0343, 0x10, 0x0220, 0x07, 0x0221, 0xd0, 0x0202, 0x03, 0x0203, 0x32, 0x0340, 0x04, 0x0341, 0x08, 0x0346, 0x01, 0x0347, 0x00, 0x0d14, 0x00, 0x0d13, 0x05, 0x0d16, 0x05, 0x0d15, 0x1d, 0x00c0, 0x0a, 0x00c1, 0x30, 0x034a, 0x05, 0x034b, 0xb0, 0x000b, 0x0e, 0x0008, 0x03, 0x0223, 0x16, /*auto load DD*/ 0x00ca, 0x00, 0x00cb, 0xfc, 0x00cc, 0x00, 0x00cd, 0x00, /*ISP*/ 0x00c3, 0x35, 0x0053, 0x0a, 0x0054, 0x44, 0x0055, 0x32, /*OUT 1280x720*/ 0x0350, 0x01, 0x0353, 0x00, 0x0354, 0x0c, 0x034c, 0x05, 0x034d, 0x00, 0x021f, 0x14, /*MIPI*/ 0x0d84, 0x06, 0x0d85, 0x40, 0x0d86, 0x03, 0x0d87, 0x21, 0x0db3, 0x03, 0x0db4, 0x04, 0x0db5, 0x0d, 0x0db6, 0x01, 0x0db8, 0x04, 0x0db9, 0x06, 0x0d93, 0x03, 0x0d94, 0x04, 0x0d95, 0x05, 0x0d99, 0x06, 0x0084, 0x01, /*CISCTL_Reset*/ 0x031c, 0x80, 0x03fe, 0x30, 0x0d17, 0x06, 0x03fe, 0x00, 0x0d17, 0x00, 0x031c, 0x93, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x03fe, 0x00, 0x031c, 0x80, 0x03fe, 0x30, 0x0d17, 0x06, 0x03fe, 0x00, 0x0d17, 0x00, 0x031c, 0x93, /*OUT*/ 0x0110, 0x01, }; static void gc05a2_stream_on(void) { write_cmos_sensor_8bit(0x0100, 0x01); } static void gc05a2_stream_off(void) { write_cmos_sensor_8bit(0x0100, 0x00); } static void sensor_init(void) { table_write_cmos_sensor(gc05a2_init_addr_data, sizeof(gc05a2_init_addr_data)/sizeof(kal_uint16)); } static void preview_setting(void) { gc05a2_stream_off(); table_write_cmos_sensor(gc05a2_1296x972_addr_data, sizeof(gc05a2_1296x972_addr_data)/sizeof(kal_uint16)); gc05a2_stream_on(); } static void capture_setting(void) { gc05a2_stream_off(); table_write_cmos_sensor(gc05a2_2592x1944_addr_data, sizeof(gc05a2_2592x1944_addr_data)/sizeof(kal_uint16)); gc05a2_stream_on(); } static void normal_video_setting(void) { gc05a2_stream_off(); table_write_cmos_sensor(gc05a2_normal_video_addr_data, sizeof(gc05a2_normal_video_addr_data)/sizeof(kal_uint16)); gc05a2_stream_on(); } static void hs_video_setting(void) { gc05a2_stream_off(); table_write_cmos_sensor(gc05a2_1296x972_addr_data, sizeof(gc05a2_1296x972_addr_data)/sizeof(kal_uint16)); gc05a2_stream_on(); } static void slim_video_setting(void) { gc05a2_stream_off(); table_write_cmos_sensor(gc05a2_1280x720_addr_data, sizeof(gc05a2_1280x720_addr_data)/sizeof(kal_uint16)); gc05a2_stream_on(); } static kal_uint32 set_test_pattern_mode(kal_bool enable) { LOG_INF("enable: %d\n", enable); if (enable){ write_cmos_sensor_8bit(0x008c, 0x01); write_cmos_sensor_8bit(0x008d, 0x00); } else { write_cmos_sensor_8bit(0x008c, 0x00); write_cmos_sensor_8bit(0x008d, 0x00); } printk("test_pattern 0x008c=%x 0x008d=%x",read_cmos_sensor(0x008c),read_cmos_sensor(0x008d)); spin_lock(&imgsensor_drv_lock); imgsensor.test_pattern = enable; spin_unlock(&imgsensor_drv_lock); return ERROR_NONE; } static kal_uint32 streaming_control(kal_bool enable) { printk("streaming_enable(0=Sw Standby,1=streaming): %d\n", enable); if (enable) { write_cmos_sensor(0x0100,0x01); mdelay(10);//delay 10ms } else { write_cmos_sensor(0x0100, 0x00); mdelay(10);//delay 10ms } //mdelay(10); return ERROR_NONE; } static void gc05a2_otp_init(void) { #if 1 write_cmos_sensor_8bit(0x031c, 0x60); write_cmos_sensor_8bit(0x0315, 0x80); write_cmos_sensor_8bit(0x0af4, 0x01); write_cmos_sensor_8bit(0x0af6, 0x00); write_cmos_sensor_8bit(0x0b90, 0x10); write_cmos_sensor_8bit(0x0b91, 0x00); write_cmos_sensor_8bit(0x0b92, 0x00); write_cmos_sensor_8bit(0x0ba0, 0x17); write_cmos_sensor_8bit(0x0ba1, 0x00); write_cmos_sensor_8bit(0x0ba2, 0x00); write_cmos_sensor_8bit(0x0ba4, 0x03); write_cmos_sensor_8bit(0x0ba5, 0x00); write_cmos_sensor_8bit(0x0ba6, 0x00); write_cmos_sensor_8bit(0x0ba8, 0x40); write_cmos_sensor_8bit(0x0ba9, 0x00); write_cmos_sensor_8bit(0x0baa, 0x00); write_cmos_sensor_8bit(0x0bac, 0x40); write_cmos_sensor_8bit(0x0bad, 0x00); write_cmos_sensor_8bit(0x0bae, 0x00); write_cmos_sensor_8bit(0x0bb0, 0x02); write_cmos_sensor_8bit(0x0bb1, 0x00); write_cmos_sensor_8bit(0x0bb2, 0x00); write_cmos_sensor_8bit(0x0bb8, 0x02); write_cmos_sensor_8bit(0x0bb9, 0x00); write_cmos_sensor_8bit(0x0bba, 0x00); write_cmos_sensor_8bit(0x0a70, 0x80); write_cmos_sensor_8bit(0x0a71, 0x00); write_cmos_sensor_8bit(0x0a72, 0x00); write_cmos_sensor_8bit(0x0a66, 0x00); write_cmos_sensor_8bit(0x0a67, 0x84); write_cmos_sensor_8bit(0x0a4d, 0x0e); write_cmos_sensor_8bit(0x0a45, 0x02); write_cmos_sensor_8bit(0x0a47, 0x02); write_cmos_sensor_8bit(0x0a50, 0x00); write_cmos_sensor_8bit(0x0a4f, 0x0c); #else //write_cmos_sensor(0x031c, 0x60); //write_cmos_sensor(0x0315, 0x80); //write_cmos_sensor(0x0af4, 0x01); write_cmos_sensor(0x0af6, 0x00); write_cmos_sensor(0x0b90, 0x10); write_cmos_sensor(0x0b91, 0x00); write_cmos_sensor(0x0b92, 0x00); write_cmos_sensor(0x0ba0, 0x17); write_cmos_sensor(0x0ba1, 0x00); write_cmos_sensor(0x0ba2, 0x00); write_cmos_sensor(0x0ba4, 0x03); write_cmos_sensor(0x0ba5, 0x00); write_cmos_sensor(0x0ba6, 0x00); write_cmos_sensor(0x0ba8, 0x40); write_cmos_sensor(0x0ba9, 0x00); write_cmos_sensor(0x0baa, 0x00); write_cmos_sensor(0x0bac, 0x40); write_cmos_sensor(0x0bad, 0x00); write_cmos_sensor(0x0bae, 0x00); write_cmos_sensor(0x0bb0, 0x02); write_cmos_sensor(0x0bb1, 0x00); write_cmos_sensor(0x0bb2, 0x00); write_cmos_sensor(0x0bb8, 0x02); write_cmos_sensor(0x0bb9, 0x00); write_cmos_sensor(0x0bba, 0x00); write_cmos_sensor(0x0a70, 0x80); write_cmos_sensor(0x0a71, 0x00); write_cmos_sensor(0x0a72, 0x00); write_cmos_sensor(0x0a66, 0x00); write_cmos_sensor(0x0a67, 0x84); write_cmos_sensor(0x0a4d, 0x0e); write_cmos_sensor(0x0a45, 0x02); write_cmos_sensor(0x0a47, 0x02); write_cmos_sensor(0x0a50, 0x00); write_cmos_sensor(0x0a4f, 0x0c); #endif mdelay(10); } static void gc05a2_otp_close(void) { #if 1 write_cmos_sensor_8bit(0x0a70, 0x00); write_cmos_sensor_8bit(0x0a67, 0x00); #else write_cmos_sensor(0x0a70, 0x00); write_cmos_sensor(0x0a67, 0x00); #endif } #if 0 static u16 gc05a2_otp_read_group(u16 addr, u8 *data, u16 length) { u16 i = 0; #if 1 //write_cmos_sensor_8bit(0x0a67, 0x84); write_cmos_sensor_8bit(0x0a69, (addr >> 8) & 0xff); write_cmos_sensor_8bit(0x0a6a, addr & 0xff); write_cmos_sensor_8bit(0x0a66, 0x20); write_cmos_sensor_8bit(0x0a66, 0x12); #else write_cmos_sensor(0x0a69, (addr >> 8) & 0xff); write_cmos_sensor(0x0a6a, addr & 0xff); write_cmos_sensor(0x0a66, 0x20); write_cmos_sensor(0x0a66, 0x12); #endif for (i = 0; i < length; i++) { data[i] = read_cmos_sensor(0x0a6c); printk("addr = 0x%x, data = 0x%x\n", addr + i * 8, data[i]); } return 0; } #else static u16 gc05a2_otp_read_single(u16 addr, u8 *data, u16 length) { int result = 0; u16 i = 8; for (i = 8; i < length; i++) { write_cmos_sensor_8bit(0x0a69, (addr >> 8) & 0xff); write_cmos_sensor_8bit(0x0a6a, addr & 0xff); write_cmos_sensor_8bit(0x0a66, 0x20); data[i] = read_cmos_sensor(0x0a6c); addr = addr + 8; #if GC05A2_SN_DEBUG printk("kernel addr = 0x%x, data = 0x%x\n", addr, data[i]); #endif } /* Manufacturer Code */ if (data[8] == 0) result = -1; return result; } #endif static void gc05a2_iReadData(unsigned int ui4_offset, unsigned int ui4_length, unsigned char *pinputdata) { int i4RetValue = 0; printk("gc05a2 otp ui4_offset = 0x%x, ui4_length = %d \n", ui4_offset, ui4_length); gc05a2_otp_init(); mdelay(10); i4RetValue = gc05a2_otp_read_single(ui4_offset, pinputdata, ui4_length); // gc05a2_common_data = pinputdata; if (i4RetValue != 0) { printk("I2C iReadData failed!!\n"); } gc05a2_otp_close(); } // static inkal_uint32t gc05a2madrid_sensor_otp_read_flag() { // } // static kal_uint32 gc05a2madrid_sensor_otp_set_flag() { // } // static kal_uint32 gc05a2madrid_sensor_otp_read_sn() { // } static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) { kal_uint8 i = 0; kal_uint8 retry = 2; gc05a2_iReadData(SN_OFFSET,SN_LENGTH,gc05a2_common_data); while (imgsensor_info.i2c_addr_table[i] != 0xff) { spin_lock(&imgsensor_drv_lock); imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; spin_unlock(&imgsensor_drv_lock); do { *sensor_id = return_sensor_id() + SENSOR_ID_OFFSET_MADRID; gc05a2_iReadData(SN_OFFSET,SN_LENGTH,gc05a2_common_data); if (*sensor_id == imgsensor_info.sensor_id) { pr_debug("[gc05a2_camera_sensor]get_imgsensor_id:i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id, *sensor_id); gc05a2madrid_sensor_otp_read_sn(); return ERROR_NONE; } pr_debug("[gc05a2_camera_sensor]get_imgsensor_id:Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id, *sensor_id); retry--; } while (retry > 0); i++; retry = 2; } if (*sensor_id != imgsensor_info.sensor_id) { /* if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF */ *sensor_id = 0xFFFFFFFF; return ERROR_SENSOR_CONNECT_FAIL; } return ERROR_NONE; } static kal_uint32 open(void) { kal_uint8 i = 0; kal_uint8 retry = 2; kal_uint32 sensor_id = 0; LOG_1; LOG_INF("imgsensor_open\n"); while (imgsensor_info.i2c_addr_table[i] != 0xff) { spin_lock(&imgsensor_drv_lock); imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; spin_unlock(&imgsensor_drv_lock); do { sensor_id = return_sensor_id() + SENSOR_ID_OFFSET_MADRID; if (sensor_id == imgsensor_info.sensor_id) { pr_debug("[gc05a2_camera_sensor]open:i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id, sensor_id); break; } pr_debug("[gc05a2_camera_sensor]open:Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id, sensor_id); retry--; } while (retry > 0); i++; if (sensor_id == imgsensor_info.sensor_id) break; retry = 2; } if (imgsensor_info.sensor_id != sensor_id) return ERROR_SENSOR_CONNECT_FAIL; /* initail sequence write in */ sensor_init(); spin_lock(&imgsensor_drv_lock); imgsensor.autoflicker_en = KAL_FALSE; imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; imgsensor.pclk = imgsensor_info.pre.pclk; imgsensor.frame_length = imgsensor_info.pre.framelength; imgsensor.line_length = imgsensor_info.pre.linelength; imgsensor.min_frame_length = imgsensor_info.pre.framelength; imgsensor.dummy_pixel = 0; imgsensor.dummy_line = 0; imgsensor.ihdr_en = 0; imgsensor.test_pattern = KAL_FALSE; imgsensor.current_fps = imgsensor_info.pre.max_framerate; spin_unlock(&imgsensor_drv_lock); return ERROR_NONE; } static kal_uint32 close(void) { LOG_INF("E\n"); /* No Need to implement this function */ streaming_control(KAL_FALSE); return ERROR_NONE; } static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) { LOG_INF("E\n"); spin_lock(&imgsensor_drv_lock); imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; imgsensor.pclk = imgsensor_info.pre.pclk; /* imgsensor.video_mode = KAL_FALSE; */ imgsensor.line_length = imgsensor_info.pre.linelength; imgsensor.frame_length = imgsensor_info.pre.framelength; imgsensor.min_frame_length = imgsensor_info.pre.framelength; imgsensor.autoflicker_en = KAL_TRUE; spin_unlock(&imgsensor_drv_lock); preview_setting(); return ERROR_NONE; } static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) { LOG_INF("E\n"); spin_lock(&imgsensor_drv_lock); imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n", imgsensor.current_fps, imgsensor_info.cap.max_framerate / 10); imgsensor.pclk = imgsensor_info.cap.pclk; imgsensor.line_length = imgsensor_info.cap.linelength; imgsensor.frame_length = imgsensor_info.cap.framelength; imgsensor.min_frame_length = imgsensor_info.cap.framelength; imgsensor.autoflicker_en = KAL_TRUE; spin_unlock(&imgsensor_drv_lock); capture_setting(); return ERROR_NONE; } static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) { LOG_INF("E\n"); spin_lock(&imgsensor_drv_lock); imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; imgsensor.pclk = imgsensor_info.normal_video.pclk; imgsensor.line_length = imgsensor_info.normal_video.linelength; imgsensor.frame_length = imgsensor_info.normal_video.framelength; imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; /*imgsensor.current_fps = 300*/ imgsensor.autoflicker_en = KAL_TRUE; spin_unlock(&imgsensor_drv_lock); normal_video_setting(); return ERROR_NONE; } static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) { LOG_INF("E\n"); spin_lock(&imgsensor_drv_lock); imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; imgsensor.pclk = imgsensor_info.hs_video.pclk; /* imgsensor.video_mode = KAL_TRUE; */ imgsensor.line_length = imgsensor_info.hs_video.linelength; imgsensor.frame_length = imgsensor_info.hs_video.framelength; imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; imgsensor.dummy_line = 0; imgsensor.dummy_pixel = 0; imgsensor.autoflicker_en = KAL_TRUE; spin_unlock(&imgsensor_drv_lock); hs_video_setting(); return ERROR_NONE; } static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) { LOG_INF("E\n"); spin_lock(&imgsensor_drv_lock); imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; imgsensor.pclk = imgsensor_info.slim_video.pclk; imgsensor.line_length = imgsensor_info.slim_video.linelength; imgsensor.frame_length = imgsensor_info.slim_video.framelength; imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; imgsensor.dummy_line = 0; imgsensor.dummy_pixel = 0; imgsensor.autoflicker_en = KAL_TRUE; spin_unlock(&imgsensor_drv_lock); slim_video_setting(); return ERROR_NONE; } static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) { LOG_INF("E\n"); sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; return ERROR_NONE; } static kal_uint32 get_info(enum MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_INFO_STRUCT *sensor_info, MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) { LOG_INF("scenario_id = %d\n", scenario_id); sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; /* inverse with datasheet */ sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; sensor_info->SensorInterruptDelayLines = 4; /* not use */ sensor_info->SensorResetActiveHigh = FALSE; /* not use */ sensor_info->SensorResetDelayCount = 5; /* not use */ sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; sensor_info->SensorMasterClockSwitch = 0; /* not use */ sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; sensor_info->IHDR_Support = imgsensor_info.ihdr_support; sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; sensor_info->SensorClockFreq = imgsensor_info.mclk; sensor_info->SensorClockDividCount = 3; /* not use */ sensor_info->SensorClockRisingCount = 0; sensor_info->SensorClockFallingCount = 2; /* not use */ sensor_info->SensorPixelClockCount = 3; /* not use */ sensor_info->SensorDataLatchCount = 2; /* not use */ sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; sensor_info->SensorWidthSampling = 0; /* 0 is default 1x */ sensor_info->SensorHightSampling = 0; /* 0 is default 1x */ sensor_info->SensorPacketECCOrder = 1; switch (scenario_id) { case MSDK_SCENARIO_ID_CAMERA_PREVIEW: sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; break; case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; break; case MSDK_SCENARIO_ID_VIDEO_PREVIEW: sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; break; case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; break; case MSDK_SCENARIO_ID_SLIM_VIDEO: sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; break; default: sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; break; } return ERROR_NONE; } static kal_uint32 control(enum MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) { LOG_INF("scenario_id = %d\n", scenario_id); spin_lock(&imgsensor_drv_lock); imgsensor.current_scenario_id = scenario_id; spin_unlock(&imgsensor_drv_lock); switch (scenario_id) { case MSDK_SCENARIO_ID_CAMERA_PREVIEW: preview(image_window, sensor_config_data); break; case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: capture(image_window, sensor_config_data); break; case MSDK_SCENARIO_ID_VIDEO_PREVIEW: normal_video(image_window, sensor_config_data); break; case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: hs_video(image_window, sensor_config_data); break; case MSDK_SCENARIO_ID_SLIM_VIDEO: slim_video(image_window, sensor_config_data); break; default: LOG_INF("Error ScenarioId setting"); preview(image_window, sensor_config_data); return ERROR_INVALID_SCENARIO_ID; } return ERROR_NONE; } static kal_uint32 set_video_mode(UINT16 framerate) { /*This Function not used after ROME*/ LOG_INF("framerate = %d\n ", framerate); /* SetVideoMode Function should fix framerate */ /*********** *if (framerate == 0) //Dynamic frame rate * return ERROR_NONE; *spin_lock(&imgsensor_drv_lock); *if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) * imgsensor.current_fps = 296; *else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) * imgsensor.current_fps = 146; *else * imgsensor.current_fps = framerate; *spin_unlock(&imgsensor_drv_lock); *set_max_framerate(imgsensor.current_fps, 1); ********/ return ERROR_NONE; } static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) { LOG_INF("enable = %d, framerate = %d\n", enable, framerate); spin_lock(&imgsensor_drv_lock); if (enable) /* enable auto flicker */ imgsensor.autoflicker_en = KAL_TRUE; else /* Cancel Auto flick */ imgsensor.autoflicker_en = KAL_FALSE; spin_unlock(&imgsensor_drv_lock); return ERROR_NONE; } static kal_uint32 set_max_framerate_by_scenario(enum MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) { kal_uint32 frame_length; LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); switch (scenario_id) { case MSDK_SCENARIO_ID_CAMERA_PREVIEW: frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; spin_lock(&imgsensor_drv_lock); imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; imgsensor.min_frame_length = imgsensor.frame_length; spin_unlock(&imgsensor_drv_lock); set_dummy(); break; case MSDK_SCENARIO_ID_VIDEO_PREVIEW: if (framerate == 0) return ERROR_NONE; frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; spin_lock(&imgsensor_drv_lock); imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; imgsensor.min_frame_length = imgsensor.frame_length; spin_unlock(&imgsensor_drv_lock); set_dummy(); break; case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n", framerate, imgsensor_info.cap.max_framerate / 10); frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; spin_lock(&imgsensor_drv_lock); imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; imgsensor.min_frame_length = imgsensor.frame_length; spin_unlock(&imgsensor_drv_lock); set_dummy(); break; case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; spin_lock(&imgsensor_drv_lock); imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; imgsensor.min_frame_length = imgsensor.frame_length; spin_unlock(&imgsensor_drv_lock); set_dummy(); break; case MSDK_SCENARIO_ID_SLIM_VIDEO: frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; spin_lock(&imgsensor_drv_lock); imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength) : 0; imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; imgsensor.min_frame_length = imgsensor.frame_length; spin_unlock(&imgsensor_drv_lock); set_dummy(); break; default: frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; spin_lock(&imgsensor_drv_lock); imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; imgsensor.min_frame_length = imgsensor.frame_length; spin_unlock(&imgsensor_drv_lock); set_dummy(); LOG_INF("error scenario_id = %d, we use preview scenario\n", scenario_id); break; } return ERROR_NONE; } static kal_uint32 get_default_framerate_by_scenario(enum MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) { LOG_INF("scenario_id = %d\n", scenario_id); switch (scenario_id) { case MSDK_SCENARIO_ID_CAMERA_PREVIEW: *framerate = imgsensor_info.pre.max_framerate; break; case MSDK_SCENARIO_ID_VIDEO_PREVIEW: *framerate = imgsensor_info.normal_video.max_framerate; break; case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: *framerate = imgsensor_info.cap.max_framerate; break; case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: *framerate = imgsensor_info.hs_video.max_framerate; break; case MSDK_SCENARIO_ID_SLIM_VIDEO: *framerate = imgsensor_info.slim_video.max_framerate; break; default: break; } return ERROR_NONE; } static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, UINT8 *feature_para, UINT32 *feature_para_len) { UINT16 *feature_return_para_16 = (UINT16 *)feature_para; UINT16 *feature_data_16 = (UINT16 *)feature_para; UINT32 *feature_return_para_32 = (UINT32 *)feature_para; UINT32 *feature_data_32 = (UINT32 *)feature_para; unsigned long long *feature_data = (unsigned long long *)feature_para; struct SENSOR_WINSIZE_INFO_STRUCT *wininfo; MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data = (MSDK_SENSOR_REG_INFO_STRUCT *)feature_para; LOG_INF("feature_id = %d\n", feature_id); switch (feature_id) { case SENSOR_FEATURE_GET_PERIOD: *feature_return_para_16++ = imgsensor.line_length; *feature_return_para_16 = imgsensor.frame_length; *feature_para_len = 4; break; case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: *feature_return_para_32 = imgsensor.pclk; *feature_para_len = 4; break; case SENSOR_FEATURE_GET_MIPI_PIXEL_RATE: { kal_uint32 rate; switch (*feature_data) { case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: rate = imgsensor_info.cap.mipi_pixel_rate; break; case MSDK_SCENARIO_ID_VIDEO_PREVIEW: rate = imgsensor_info.normal_video.mipi_pixel_rate; break; case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: rate = imgsensor_info.hs_video.mipi_pixel_rate; break; case MSDK_SCENARIO_ID_SLIM_VIDEO: rate = imgsensor_info.slim_video.mipi_pixel_rate; break; case MSDK_SCENARIO_ID_CAMERA_PREVIEW: default: rate = imgsensor_info.pre.mipi_pixel_rate; break; } *(MUINT32 *)(uintptr_t)(*(feature_data + 1)) = rate; } break; case SENSOR_FEATURE_SET_ESHUTTER: set_shutter(*feature_data); break; case SENSOR_FEATURE_SET_NIGHTMODE: night_mode((BOOL)*feature_data); break; case SENSOR_FEATURE_SET_GAIN: set_gain((UINT16)*feature_data); break; case SENSOR_FEATURE_SET_FLASHLIGHT: break; case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: break; case SENSOR_FEATURE_SET_REGISTER: write_cmos_sensor_8bit(sensor_reg_data->RegAddr, sensor_reg_data->RegData); break; case SENSOR_FEATURE_GET_REGISTER: sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); LOG_INF("adb_i2c_read 0x%x = 0x%x\n", sensor_reg_data->RegAddr, sensor_reg_data->RegData); break; case SENSOR_FEATURE_GET_LENS_DRIVER_ID: /* get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE */ /* if EEPROM does not exist in camera module. */ *feature_return_para_32 = LENS_DRIVER_ID_DO_NOT_CARE; *feature_para_len = 4; break; case SENSOR_FEATURE_SET_VIDEO_MODE: set_video_mode(*feature_data); break; case SENSOR_FEATURE_CHECK_SENSOR_ID: get_imgsensor_id(feature_return_para_32); break; case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: set_auto_flicker_mode((BOOL)*feature_data_16, *(feature_data_16 + 1)); break; case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: set_max_framerate_by_scenario((enum MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data + 1)); break; case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: get_default_framerate_by_scenario((enum MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_SET_TEST_PATTERN: set_test_pattern_mode((BOOL)*feature_data); break; case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: *feature_return_para_32 = imgsensor_info.checksum_value; *feature_para_len = 4; break; case SENSOR_FEATURE_SET_FRAMERATE: LOG_INF("current fps: %d\n", (UINT32)*feature_data); spin_lock(&imgsensor_drv_lock); imgsensor.current_fps = *feature_data; spin_unlock(&imgsensor_drv_lock); break; case SENSOR_FEATURE_SET_HDR: LOG_INF("ihdr enable: %d\n", (BOOL)*feature_data); spin_lock(&imgsensor_drv_lock); imgsensor.ihdr_en = (BOOL)*feature_data; spin_unlock(&imgsensor_drv_lock); break; case SENSOR_FEATURE_GET_EEPROM_COMDATA: memcpy(feature_return_para_32, gc05a2_common_data, CAMERA_EEPPROM_COMDATA_LENGTH); *feature_para_len = CAMERA_EEPPROM_COMDATA_LENGTH; break; case SENSOR_FEATURE_GET_CROP_INFO: LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId: %d\n", (UINT32)*feature_data); wininfo = (struct SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data + 1)); switch (*feature_data_32) { case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: memcpy((void *)wininfo, (void *)&imgsensor_winsize_info[1], sizeof(struct SENSOR_WINSIZE_INFO_STRUCT)); break; case MSDK_SCENARIO_ID_VIDEO_PREVIEW: memcpy((void *)wininfo, (void *)&imgsensor_winsize_info[2], sizeof(struct SENSOR_WINSIZE_INFO_STRUCT)); break; case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: memcpy((void *)wininfo, (void *)&imgsensor_winsize_info[3], sizeof(struct SENSOR_WINSIZE_INFO_STRUCT)); break; case MSDK_SCENARIO_ID_SLIM_VIDEO: memcpy((void *)wininfo, (void *)&imgsensor_winsize_info[4], sizeof(struct SENSOR_WINSIZE_INFO_STRUCT)); break; case MSDK_SCENARIO_ID_CAMERA_PREVIEW: default: memcpy((void *)wininfo, (void *)&imgsensor_winsize_info[0], sizeof(struct SENSOR_WINSIZE_INFO_STRUCT)); break; } break; case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: LOG_INF("SENSOR_SET_SENSOR_IHDR LE = %d, SE = %d, Gain = %d\n", (UINT16)*feature_data, (UINT16)*(feature_data + 1), (UINT16)*(feature_data + 2)); ihdr_write_shutter_gain((UINT16)*feature_data, (UINT16)*(feature_data + 1), (UINT16)*(feature_data + 2)); break; default: break; } return ERROR_NONE; } static struct SENSOR_FUNCTION_STRUCT sensor_func = { open, get_info, get_resolution, feature_control, control, close }; UINT32 GC05A2_MIPI_RAW_MADRID_SensorInit(struct SENSOR_FUNCTION_STRUCT **pfFunc) { /* Check Sensor status here */ if (pfFunc != NULL) *pfFunc = &sensor_func; return ERROR_NONE; } 修改代码,要读sn号
11-07
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值