1let adb_ws; 2let logcat = document.getElementById('logcat'); 3 4let utf8Encoder = new TextEncoder(); 5let utf8Decoder = new TextDecoder(); 6 7const A_CNXN = 0x4e584e43; 8const A_OPEN = 0x4e45504f; 9const A_WRTE = 0x45545257; 10const A_OKAY = 0x59414b4f; 11 12const kLocalChannelId = 666; 13 14function setU32LE(array, offset, x) { 15 array[offset] = x & 0xff; 16 array[offset + 1] = (x >> 8) & 0xff; 17 array[offset + 2] = (x >> 16) & 0xff; 18 array[offset + 3] = x >> 24; 19} 20 21function getU32LE(array, offset) { 22 let x = array[offset] 23 | (array[offset + 1] << 8) 24 | (array[offset + 2] << 16) 25 | (array[offset + 3] << 24); 26 27 return x >>> 0; // convert signed to unsigned if necessary. 28} 29 30function computeChecksum(array) { 31 let sum = 0; 32 let i; 33 for (i = 0; i < array.length; ++i) { 34 sum = ((sum + array[i]) & 0xffffffff) >>> 0; 35 } 36 37 return sum; 38} 39 40function createAdbMessage(command, arg0, arg1, payload) { 41 let arrayBuffer = new ArrayBuffer(24 + payload.length); 42 let array = new Uint8Array(arrayBuffer); 43 setU32LE(array, 0, command); 44 setU32LE(array, 4, arg0); 45 setU32LE(array, 8, arg1); 46 setU32LE(array, 12, payload.length); 47 setU32LE(array, 16, computeChecksum(payload)); 48 setU32LE(array, 20, command ^ 0xffffffff); 49 array.set(payload, 24); 50 51 return arrayBuffer; 52} 53 54function adbOpenConnection() { 55 let systemIdentity = utf8Encoder.encode("Cray_II:1234:whatever"); 56 57 let arrayBuffer = createAdbMessage( 58 A_CNXN, 0x1000000, 256 * 1024, systemIdentity); 59 60 adb_ws.send(arrayBuffer); 61} 62 63function adbOpenChannel() { 64 let destination = utf8Encoder.encode("shell:logcat"); 65 66 let arrayBuffer = createAdbMessage(A_OPEN, kLocalChannelId, 0, destination); 67 adb_ws.send(arrayBuffer); 68} 69 70function adbSendOkay(remoteId) { 71 let payload = new Uint8Array(0); 72 73 let arrayBuffer = createAdbMessage( 74 A_OKAY, kLocalChannelId, remoteId, payload); 75 76 adb_ws.send(arrayBuffer); 77} 78 79function adbOnMessage(ev) { 80 // console.log("adb_ws: onmessage (" + ev.data.byteLength + " bytes)"); 81 82 let arrayBuffer = ev.data; 83 let array = new Uint8Array(arrayBuffer); 84 85 if (array.length < 24) { 86 console.log("adb message too short."); 87 return; 88 } 89 90 let command = getU32LE(array, 0); 91 let magic = getU32LE(array, 20); 92 93 if (command != ((magic ^ 0xffffffff) >>> 0)) { 94 console.log("command = " + command + ", magic = " + magic); 95 console.log("adb message command vs magic failed."); 96 return; 97 } 98 99 let payloadLength = getU32LE(array, 12); 100 101 if (array.length != 24 + payloadLength) { 102 console.log("adb message length mismatch."); 103 return; 104 } 105 106 let payloadChecksum = getU32LE(array, 16); 107 let checksum = computeChecksum(array.slice(24)); 108 109 if (payloadChecksum != checksum) { 110 console.log("adb message checksum mismatch."); 111 return; 112 } 113 114 switch (command) { 115 case A_CNXN: 116 { 117 console.log("connected."); 118 119 adbOpenChannel(); 120 break; 121 } 122 123 case A_OKAY: 124 { 125 let remoteId = getU32LE(array, 4); 126 console.log("channel created w/ remoteId " + remoteId); 127 break; 128 } 129 130 case A_WRTE: 131 { 132 let payloadText = utf8Decoder.decode(array.slice(24)); 133 134 logcat.value += payloadText; 135 136 // Scroll to bottom 137 logcat.scrollTop = logcat.scrollHeight; 138 139 let remoteId = getU32LE(array, 4); 140 adbSendOkay(remoteId); 141 break; 142 } 143 } 144} 145 146function init_logcat() { 147 const wsProtocol = (location.protocol == "http:") ? "ws:" : "wss:"; 148 149 adb_ws = new WebSocket( 150 wsProtocol + "//" + location.host + "/control_adb"); 151 152 adb_ws.binaryType = "arraybuffer"; 153 154 adb_ws.onopen = function() { 155 console.log("adb_ws: onopen"); 156 157 adbOpenConnection(); 158 159 logcat.style.display = "initial"; 160 }; 161 adb_ws.onmessage = adbOnMessage; 162} 163 164