|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 "use strict"; |
|
4 |
|
5 let RIL = {}; |
|
6 SpecialPowers.Cu.import("resource://gre/modules/ril_consts.js", RIL); |
|
7 |
|
8 // Only bring in what we need from ril_worker/RadioInterfaceLayer here. Reusing |
|
9 // that code turns out to be a nightmare, so there is some code duplication. |
|
10 let PDUBuilder = { |
|
11 toHexString: function(n, length) { |
|
12 let str = n.toString(16); |
|
13 if (str.length < length) { |
|
14 for (let i = 0; i < length - str.length; i++) { |
|
15 str = "0" + str; |
|
16 } |
|
17 } |
|
18 return str.toUpperCase(); |
|
19 }, |
|
20 |
|
21 writeUint16: function(value) { |
|
22 this.buf += (value & 0xff).toString(16).toUpperCase(); |
|
23 this.buf += ((value >> 8) & 0xff).toString(16).toUpperCase(); |
|
24 }, |
|
25 |
|
26 writeHexOctet: function(octet) { |
|
27 this.buf += this.toHexString(octet, 2); |
|
28 }, |
|
29 |
|
30 writeSwappedNibbleBCD: function(data) { |
|
31 data = data.toString(); |
|
32 let zeroCharCode = '0'.charCodeAt(0); |
|
33 |
|
34 for (let i = 0; i < data.length; i += 2) { |
|
35 let low = data.charCodeAt(i) - zeroCharCode; |
|
36 let high; |
|
37 if (i + 1 < data.length) { |
|
38 high = data.charCodeAt(i + 1) - zeroCharCode; |
|
39 } else { |
|
40 high = 0xF; |
|
41 } |
|
42 |
|
43 this.writeHexOctet((high << 4) | low); |
|
44 } |
|
45 }, |
|
46 |
|
47 writeStringAsSeptets: function(message, paddingBits, langIndex, |
|
48 langShiftIndex) { |
|
49 const langTable = RIL.PDU_NL_LOCKING_SHIFT_TABLES[langIndex]; |
|
50 const langShiftTable = RIL.PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex]; |
|
51 |
|
52 let dataBits = paddingBits; |
|
53 let data = 0; |
|
54 for (let i = 0; i < message.length; i++) { |
|
55 let septet = langTable.indexOf(message[i]); |
|
56 if (septet == RIL.PDU_NL_EXTENDED_ESCAPE) { |
|
57 continue; |
|
58 } |
|
59 |
|
60 if (septet >= 0) { |
|
61 data |= septet << dataBits; |
|
62 dataBits += 7; |
|
63 } else { |
|
64 septet = langShiftTable.indexOf(message[i]); |
|
65 if (septet == -1) { |
|
66 throw new Error(message[i] + " not in 7 bit alphabet " |
|
67 + langIndex + ":" + langShiftIndex + "!"); |
|
68 } |
|
69 |
|
70 if (septet == RIL.PDU_NL_RESERVED_CONTROL) { |
|
71 continue; |
|
72 } |
|
73 |
|
74 data |= RIL.PDU_NL_EXTENDED_ESCAPE << dataBits; |
|
75 dataBits += 7; |
|
76 data |= septet << dataBits; |
|
77 dataBits += 7; |
|
78 } |
|
79 |
|
80 for (; dataBits >= 8; dataBits -= 8) { |
|
81 this.writeHexOctet(data & 0xFF); |
|
82 data >>>= 8; |
|
83 } |
|
84 } |
|
85 |
|
86 if (dataBits != 0) { |
|
87 this.writeHexOctet(data & 0xFF); |
|
88 } |
|
89 }, |
|
90 |
|
91 buildAddress: function(address) { |
|
92 let addressFormat = RIL.PDU_TOA_ISDN; // 81 |
|
93 if (address[0] == '+') { |
|
94 addressFormat = RIL.PDU_TOA_INTERNATIONAL | RIL.PDU_TOA_ISDN; // 91 |
|
95 address = address.substring(1); |
|
96 } |
|
97 |
|
98 this.buf = ""; |
|
99 this.writeHexOctet(address.length); |
|
100 this.writeHexOctet(addressFormat); |
|
101 this.writeSwappedNibbleBCD(address); |
|
102 |
|
103 return this.buf; |
|
104 }, |
|
105 |
|
106 // assumes 7 bit encoding |
|
107 buildUserData: function(options) { |
|
108 let headerLength = 0; |
|
109 this.buf = ""; |
|
110 if (options.headers) { |
|
111 for each (let header in options.headers) { |
|
112 headerLength += 2; // id + length octets |
|
113 if (header.octets) { |
|
114 headerLength += header.octets.length; |
|
115 } |
|
116 }; |
|
117 } |
|
118 |
|
119 let encodedBodyLength = options.body.length; |
|
120 let headerOctets = (headerLength ? headerLength + 1 : 0); |
|
121 |
|
122 let paddingBits; |
|
123 let userDataLengthInSeptets; |
|
124 let headerSeptets = Math.ceil(headerOctets * 8 / 7); |
|
125 userDataLengthInSeptets = headerSeptets + encodedBodyLength; |
|
126 paddingBits = headerSeptets * 7 - headerOctets * 8; |
|
127 |
|
128 this.writeHexOctet(userDataLengthInSeptets); |
|
129 if (options.headers) { |
|
130 this.writeHexOctet(headerLength); |
|
131 |
|
132 for each (let header in options.headers) { |
|
133 this.writeHexOctet(header.id); |
|
134 this.writeHexOctet(header.length); |
|
135 |
|
136 if (header.octets) { |
|
137 for each (let octet in header.octets) { |
|
138 this.writeHexOctet(octet); |
|
139 } |
|
140 } |
|
141 } |
|
142 } |
|
143 |
|
144 this.writeStringAsSeptets(options.body, paddingBits, |
|
145 RIL.PDU_NL_IDENTIFIER_DEFAULT, |
|
146 RIL.PDU_NL_IDENTIFIER_DEFAULT); |
|
147 return this.buf; |
|
148 } |
|
149 }; |