1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/voicemail/test/marionette/pdu_builder.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,149 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + * http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 +"use strict"; 1.7 + 1.8 +let RIL = {}; 1.9 +SpecialPowers.Cu.import("resource://gre/modules/ril_consts.js", RIL); 1.10 + 1.11 +// Only bring in what we need from ril_worker/RadioInterfaceLayer here. Reusing 1.12 +// that code turns out to be a nightmare, so there is some code duplication. 1.13 +let PDUBuilder = { 1.14 + toHexString: function(n, length) { 1.15 + let str = n.toString(16); 1.16 + if (str.length < length) { 1.17 + for (let i = 0; i < length - str.length; i++) { 1.18 + str = "0" + str; 1.19 + } 1.20 + } 1.21 + return str.toUpperCase(); 1.22 + }, 1.23 + 1.24 + writeUint16: function(value) { 1.25 + this.buf += (value & 0xff).toString(16).toUpperCase(); 1.26 + this.buf += ((value >> 8) & 0xff).toString(16).toUpperCase(); 1.27 + }, 1.28 + 1.29 + writeHexOctet: function(octet) { 1.30 + this.buf += this.toHexString(octet, 2); 1.31 + }, 1.32 + 1.33 + writeSwappedNibbleBCD: function(data) { 1.34 + data = data.toString(); 1.35 + let zeroCharCode = '0'.charCodeAt(0); 1.36 + 1.37 + for (let i = 0; i < data.length; i += 2) { 1.38 + let low = data.charCodeAt(i) - zeroCharCode; 1.39 + let high; 1.40 + if (i + 1 < data.length) { 1.41 + high = data.charCodeAt(i + 1) - zeroCharCode; 1.42 + } else { 1.43 + high = 0xF; 1.44 + } 1.45 + 1.46 + this.writeHexOctet((high << 4) | low); 1.47 + } 1.48 + }, 1.49 + 1.50 + writeStringAsSeptets: function(message, paddingBits, langIndex, 1.51 + langShiftIndex) { 1.52 + const langTable = RIL.PDU_NL_LOCKING_SHIFT_TABLES[langIndex]; 1.53 + const langShiftTable = RIL.PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex]; 1.54 + 1.55 + let dataBits = paddingBits; 1.56 + let data = 0; 1.57 + for (let i = 0; i < message.length; i++) { 1.58 + let septet = langTable.indexOf(message[i]); 1.59 + if (septet == RIL.PDU_NL_EXTENDED_ESCAPE) { 1.60 + continue; 1.61 + } 1.62 + 1.63 + if (septet >= 0) { 1.64 + data |= septet << dataBits; 1.65 + dataBits += 7; 1.66 + } else { 1.67 + septet = langShiftTable.indexOf(message[i]); 1.68 + if (septet == -1) { 1.69 + throw new Error(message[i] + " not in 7 bit alphabet " 1.70 + + langIndex + ":" + langShiftIndex + "!"); 1.71 + } 1.72 + 1.73 + if (septet == RIL.PDU_NL_RESERVED_CONTROL) { 1.74 + continue; 1.75 + } 1.76 + 1.77 + data |= RIL.PDU_NL_EXTENDED_ESCAPE << dataBits; 1.78 + dataBits += 7; 1.79 + data |= septet << dataBits; 1.80 + dataBits += 7; 1.81 + } 1.82 + 1.83 + for (; dataBits >= 8; dataBits -= 8) { 1.84 + this.writeHexOctet(data & 0xFF); 1.85 + data >>>= 8; 1.86 + } 1.87 + } 1.88 + 1.89 + if (dataBits != 0) { 1.90 + this.writeHexOctet(data & 0xFF); 1.91 + } 1.92 + }, 1.93 + 1.94 + buildAddress: function(address) { 1.95 + let addressFormat = RIL.PDU_TOA_ISDN; // 81 1.96 + if (address[0] == '+') { 1.97 + addressFormat = RIL.PDU_TOA_INTERNATIONAL | RIL.PDU_TOA_ISDN; // 91 1.98 + address = address.substring(1); 1.99 + } 1.100 + 1.101 + this.buf = ""; 1.102 + this.writeHexOctet(address.length); 1.103 + this.writeHexOctet(addressFormat); 1.104 + this.writeSwappedNibbleBCD(address); 1.105 + 1.106 + return this.buf; 1.107 + }, 1.108 + 1.109 + // assumes 7 bit encoding 1.110 + buildUserData: function(options) { 1.111 + let headerLength = 0; 1.112 + this.buf = ""; 1.113 + if (options.headers) { 1.114 + for each (let header in options.headers) { 1.115 + headerLength += 2; // id + length octets 1.116 + if (header.octets) { 1.117 + headerLength += header.octets.length; 1.118 + } 1.119 + }; 1.120 + } 1.121 + 1.122 + let encodedBodyLength = options.body.length; 1.123 + let headerOctets = (headerLength ? headerLength + 1 : 0); 1.124 + 1.125 + let paddingBits; 1.126 + let userDataLengthInSeptets; 1.127 + let headerSeptets = Math.ceil(headerOctets * 8 / 7); 1.128 + userDataLengthInSeptets = headerSeptets + encodedBodyLength; 1.129 + paddingBits = headerSeptets * 7 - headerOctets * 8; 1.130 + 1.131 + this.writeHexOctet(userDataLengthInSeptets); 1.132 + if (options.headers) { 1.133 + this.writeHexOctet(headerLength); 1.134 + 1.135 + for each (let header in options.headers) { 1.136 + this.writeHexOctet(header.id); 1.137 + this.writeHexOctet(header.length); 1.138 + 1.139 + if (header.octets) { 1.140 + for each (let octet in header.octets) { 1.141 + this.writeHexOctet(octet); 1.142 + } 1.143 + } 1.144 + } 1.145 + } 1.146 + 1.147 + this.writeStringAsSeptets(options.body, paddingBits, 1.148 + RIL.PDU_NL_IDENTIFIER_DEFAULT, 1.149 + RIL.PDU_NL_IDENTIFIER_DEFAULT); 1.150 + return this.buf; 1.151 + } 1.152 +};