code wiki / (root) / nx_tuya_emit_a64.nx

nx_tuya_emit_a64.nx source

↩ module page · 116 lines · 4963 B

1// nx_tuya_emit_a64.nx -- SOVEREIGN emitter: NishiLang -> aarch64 .s for the TUYA smartconfig 2// broadcaster that runs ON the GL.iNet router (the 2.4GHz AP). Same send-loop shortcut as the 3// ESP-Touch one, but uses the GATED nx_tuya_bcast encoding (broadcast_head [1,3,6,10] + body) and 4// Tuya's port 30011. Sends UDP packets of each length to 192.168.10.255:30011 (subnet-directed bcast 5// out the IoT bridge -> 2.4GHz air), 5ms gap, outer-looped. tuya-convert proves AP-broadcast reaches 6// an unassociated sniffing device, so the router-AP IS a valid sender for Tuya (our earlier ESP-Touch 7// failure was protocol, not RF). aarch64 syscalls: socket=198 setsockopt=208 sendto=206 nanosleep=101. 8// NEVER-BRICK #26: reversible Wi-Fi creds only. license_tier: ORIGINAL 9import "nx_tuya_smartconfig.nx" 10const K_MAGIC_30011: i64 = 30011 11 12func e_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 13func e_nl() -> i64 { let b: *u8 = sys_mmap(1); b[0] = 10 as u8; sys_write(1, b, 1); return 0 } 14func e_n(v: i64) -> i64 { 15 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 16 let d: *u8 = sys_mmap(24); var m: i64 = v; var k: i64 = 0 17 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 18 let o: *u8 = sys_mmap(24); var i: i64 = 0 19 while i < k { o[i] = d[k - 1 - i]; i = i + 1 } 20 sys_write(1, o, k); return 0 21} 22func e_line(s: *u8) -> i64 { e_w(s); e_nl(); return 0 } 23 24func main() -> i64 { 25 let ssid: *u8 = "GL-BE9300-558-IoT" as *u8 26 let ssid_n: i64 = 17 27 let pwd: *u8 = "goodlife" as *u8 28 let pwd_n: i64 = 8 29 let tok: *u8 = "00000000000000" as *u8 // placeholder token_group: device joins SSID regardless (token is cloud-reg only) 30 let tok_n: i64 = 14 31 32 let seq: *i64 = sys_mmap(512 * 8) as *i64 33 seq[0] = 1; seq[1] = 3; seq[2] = 6; seq[3] = 10 // broadcast_head 34 let bodyout: *i64 = ((seq as i64) + 32) as *i64 35 let bn: i64 = nx_tuya_bcast(pwd, pwd_n, ssid, ssid_n, tok, tok_n, bodyout, 504) 36 if bn < 0 { e_line("// ENCODE FAILED" as *u8); return 1 } 37 let n: i64 = 4 + bn 38 39 e_line("// auto-emitted by nx_tuya_emit_a64 -- TUYA smartconfig broadcaster for the IoT AP" as *u8) 40 e_line("main:" as *u8) 41 e_line(" sub sp, sp, #1280" as *u8) 42 e_line(" mov x0, #2" as *u8) 43 e_line(" mov x1, #2" as *u8) 44 e_line(" mov x2, #0" as *u8) 45 e_line(" mov x8, #198" as *u8) 46 e_line(" svc" as *u8) 47 e_line(" mov x19, x0" as *u8) 48 // sockaddr_in @ [sp]: family=2, port=30011 (BE 0x753B), addr=192.168.10.255 49 e_line(" movz x1, #2" as *u8) 50 e_line(" movk x1, #15221, lsl #16" as *u8) // 0x3B75 -> port K_MAGIC_30011 51 e_line(" movk x1, #43200, lsl #32" as *u8) // 0xA8C0 -> 192.168 52 e_line(" movk x1, #65290, lsl #48" as *u8) // 0xFF0A -> .10.255 53 e_line(" str x1, [sp]" as *u8) 54 e_line(" mov x1, #0" as *u8) 55 e_line(" str x1, [sp, #8]" as *u8) 56 e_line(" mov x21, sp" as *u8) 57 e_line(" add x20, sp, #16" as *u8) 58 // setsockopt SO_BROADCAST 59 e_line(" mov x9, #1" as *u8) 60 e_line(" str x9, [sp, #1056]" as *u8) 61 e_line(" mov x0, x19" as *u8) 62 e_line(" mov x1, #1" as *u8) 63 e_line(" mov x2, #6" as *u8) 64 e_line(" add x3, sp, #1056" as *u8) 65 e_line(" mov x4, #4" as *u8) 66 e_line(" mov x8, #208" as *u8) 67 e_line(" svc" as *u8) 68 // timespec {0, 5000000ns} 69 e_line(" mov x9, #0" as *u8) 70 e_line(" str x9, [sp, #1040]" as *u8) 71 e_line(" movz x9, #19264" as *u8) 72 e_line(" movk x9, #76, lsl #16" as *u8) 73 e_line(" str x9, [sp, #1048]" as *u8) 74 e_line(" add x22, sp, #1040" as *u8) 75 // HEADER PHASE: broadcast_head [1,3,6,10] x40 (pure guide -> device locks), per smartconfig.py 76 e_line(" mov x26, #0" as *u8) 77 e_line("hphase:" as *u8) 78 var hi: i64 = 0 79 while hi < 4 { 80 e_w(" mov x2, #" as *u8); e_n(seq[hi]); e_nl() 81 e_line(" bl snd" as *u8) 82 hi = hi + 1 83 } 84 e_line(" add x26, x26, #1" as *u8) 85 e_line(" cmp x26, #40" as *u8) 86 e_line(" b.lt hphase" as *u8) 87 // BODY PHASE: broadcast_body x30 (the data, after lock) 88 e_line(" mov x26, #0" as *u8) 89 e_line("bphase:" as *u8) 90 var bi: i64 = 4 91 while bi < n { 92 e_w(" mov x2, #" as *u8); e_n(seq[bi]); e_nl() 93 e_line(" bl snd" as *u8) 94 bi = bi + 1 95 } 96 e_line(" add x26, x26, #1" as *u8) 97 e_line(" cmp x26, #10" as *u8) 98 e_line(" b.lt bphase" as *u8) 99 e_line(" mov x0, #0" as *u8) 100 e_line(" mov x8, #93" as *u8) 101 e_line(" svc" as *u8) 102 e_line("snd:" as *u8) 103 e_line(" mov x0, x19" as *u8) 104 e_line(" mov x1, x20" as *u8) 105 e_line(" mov x3, #0" as *u8) 106 e_line(" mov x4, x21" as *u8) 107 e_line(" mov x5, #16" as *u8) 108 e_line(" mov x8, #206" as *u8) 109 e_line(" svc" as *u8) 110 e_line(" mov x0, x22" as *u8) 111 e_line(" mov x1, #0" as *u8) 112 e_line(" mov x8, #101" as *u8) 113 e_line(" svc" as *u8) 114 e_line(" ret" as *u8) 115 return 0 116}