1 /* $Id: tpam_hdlc.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
2  *
3  * Turbo PAM ISDN driver for Linux. (Kernel Driver - HDLC encoding)
4  *
5  * Copyright 1998-2000 AUVERTECH T�l�com
6  * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alc�ve
7  *
8  * This software may be used and distributed according to the terms
9  * of the GNU General Public License, incorporated herein by reference.
10  *
11  * For all support questions please contact: <support@auvertech.fr>
12  *
13  */
14 
15 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16 
17 Module Name:
18 
19     hdlc.c
20 
21 Abstract:
22 
23     stuff0 : array necessary for the bit stuffing algorithm
24     stuff1 : array necessary for the bit stuffing algorithm
25     stuff2 : array necessary for the bit stuffing algorithm
26     stuff3 : array necessary for the bit stuffing algorithm
27     stuff4 : array necessary for the bit stuffing algorithm
28     stuff5 : array necessary for the bit stuffing algorithm
29     stuffs[] : array conaining the previous 6 arrays
30     destuff0 : array necessary for the bit destuffing algorithm
31     destuff1 : array necessary for the bit destuffing algorithm
32     destuff2 : array necessary for the bit destuffing algorithm
33     destuff3 : array necessary for the bit destuffing algorithm
34     destuff4 : array necessary for the bit destuffing algorithm
35     destuff5 : array necessary for the bit destuffing algorithm
36     destuffs[] : array conaining the previous 6 arrays
37 
38     tpam_hdlc_encode : bit stuffing of a byte array, with the addition
39                   of a start and end flag, using the bit shift given in
40 		  parameter (which is updated at the end of encoding).
41     tpam_hdlc_decode : bit de-stuffing of a byte array with detection of
42                   possible ABORTs.
43 
44 Revision History:
45 
46 ---------------------------------------------------------------------------*/
47 
48 /* The arrays are used as follows:
49 
50   For the bit stuffing :
51 
52   stuff0 = used if the previous byte ended with '0'
53   stuff1 = used if the previous byte ended with '10'
54   stuff2 = used if the previous byte ended with '110'
55   stuff3 = used if the previous byte ended with '1110'
56   stuff4 = used if the previous byte ended with '11110'
57   stuff5 = used if the previous byte ended with '111110'
58 
59   those arrays are indexed by the byte to stuff.
60 
61   the data of those arrays are of the form (in binary):
62   "bbbbaaaa cccccccc"
63   with "cccccccc" : byte stuffed
64        "aaaa" : "0000" --> no insertion of '0'
65 	            "0100" --> 1 '0' inserted, carry = '0'
66                 "0101" --> 1 '0' inserted, carry = '1'
67                 "1000" --> 2 '0' inserted, carry = '00'
68                 "1001" --> 2 '0' inserted, carry = '01'
69                 "1010" --> 2 '0' inserted, carry = '10'
70                 "1011" --> 2 '0' inserted, carry = '11'
71        "bbbb" : count of '1' at the end of "cccccccc"
72 
73 
74 
75   For the bit de-stuffing :
76 
77   destuff0 = used if the previous byte ended with '0'
78   destuff1 = used if the previous byte ended with '10'
79   destuff2 = used if the previous byte ended with '110'
80   destuff3 = used if the previous byte ended with '1110'
81   destuff4 = used if the previous byte ended with '11110'
82   destuff5 = used if the previous byte ended with '111110'
83 
84   those arrays are indexed by the byte to de-stuff.
85 
86   the data of those arrays are of the form (in binary):
87   "dbbbaaaa cccccccc"
88   with "cccccccc" : byte destuffed
89        "aaaa" : count of '1' at the end of the byte non destuffed
90        "bbb" : count of bits to use in the destuffed byte (8 less the count
91                of '0' deleted) less 1 (can be only 7, 6 or 5)
92 	   "d" : '1' if the byte non destuffed has more than 5 consecutive '1'
93 	         (flag or abort)
94 */
95 
96 #include <linux/types.h>
97 #include "tpam.h"
98 
99 typedef u8	BYTE;
100 typedef u16	WORD;
101 typedef u32	DWORD;
102 typedef u8	BOOL;
103 
104 #define	TRUE			1
105 #define FALSE			0
106 
107 static WORD stuff0[] =
108 {
109 	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
110 	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
111 	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
112 	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x041F,
113 	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
114 	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
115 	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
116 	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x045F,
117 	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
118 	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
119 	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
120 	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x149F,
121 	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
122 	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
123 	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
124 	0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x24DF,
125 	0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
126 	0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
127 	0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
128 	0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x051F,
129 	0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7,
130 	0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x10AF,
131 	0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7,
132 	0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x055F,
133 	0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
134 	0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF,
135 	0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
136 	0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x159F,
137 	0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7,
138 	0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF,
139 	0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7,
140 	0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x25DF,
141 };
142 
143 
144 static WORD stuff1[] =
145 {
146 	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
147 	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x040F,
148 	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
149 	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x042F,
150 	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
151 	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x044F,
152 	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
153 	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x046F,
154 	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
155 	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x148F,
156 	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
157 	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x14AF,
158 	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
159 	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x24CF,
160 	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
161 	0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x34EF,
162 	0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
163 	0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x050F,
164 	0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
165 	0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x052F,
166 	0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7,
167 	0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x054F,
168 	0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7,
169 	0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x056F,
170 	0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
171 	0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x158F,
172 	0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
173 	0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x15AF,
174 	0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7,
175 	0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x25CF,
176 	0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7,
177 	0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x35EF,
178 };
179 
180 
181 static WORD stuff2[] =
182 {
183 	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0407,
184 	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0417,
185 	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0427,
186 	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x0437,
187 	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0447,
188 	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x0457,
189 	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0467,
190 	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x0477,
191 	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x1487,
192 	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x1497,
193 	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x14A7,
194 	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x14B7,
195 	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x24C7,
196 	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x24D7,
197 	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x34E7,
198 	0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x44F7,
199 	0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x0507,
200 	0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x0517,
201 	0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x0527,
202 	0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x0537,
203 	0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x0547,
204 	0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x0557,
205 	0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x0567,
206 	0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x0577,
207 	0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x1587,
208 	0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x1597,
209 	0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x15A7,
210 	0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x15B7,
211 	0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x25C7,
212 	0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x25D7,
213 	0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x35E7,
214 	0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x45F7,
215 };
216 
217 
218 static WORD stuff3[] =
219 {
220 	0x0000, 0x0001, 0x0002, 0x0403, 0x0004, 0x0005, 0x0006, 0x040B,
221 	0x0008, 0x0009, 0x000A, 0x0413, 0x000C, 0x000D, 0x000E, 0x041B,
222 	0x0010, 0x0011, 0x0012, 0x0423, 0x0014, 0x0015, 0x0016, 0x042B,
223 	0x0018, 0x0019, 0x001A, 0x0433, 0x001C, 0x001D, 0x001E, 0x043B,
224 	0x0020, 0x0021, 0x0022, 0x0443, 0x0024, 0x0025, 0x0026, 0x044B,
225 	0x0028, 0x0029, 0x002A, 0x0453, 0x002C, 0x002D, 0x002E, 0x045B,
226 	0x0030, 0x0031, 0x0032, 0x0463, 0x0034, 0x0035, 0x0036, 0x046B,
227 	0x0038, 0x0039, 0x003A, 0x0473, 0x003C, 0x003D, 0x043E, 0x047B,
228 	0x0040, 0x0041, 0x0042, 0x1483, 0x0044, 0x0045, 0x0046, 0x148B,
229 	0x0048, 0x0049, 0x004A, 0x1493, 0x004C, 0x004D, 0x004E, 0x149B,
230 	0x0050, 0x0051, 0x0052, 0x14A3, 0x0054, 0x0055, 0x0056, 0x14AB,
231 	0x0058, 0x0059, 0x005A, 0x14B3, 0x005C, 0x005D, 0x005E, 0x14BB,
232 	0x0060, 0x0061, 0x0062, 0x24C3, 0x0064, 0x0065, 0x0066, 0x24CB,
233 	0x0068, 0x0069, 0x006A, 0x24D3, 0x006C, 0x006D, 0x006E, 0x24DB,
234 	0x0070, 0x0071, 0x0072, 0x34E3, 0x0074, 0x0075, 0x0076, 0x34EB,
235 	0x0078, 0x0079, 0x007A, 0x44F3, 0x047C, 0x047D, 0x14BE, 0x54FB,
236 	0x1080, 0x1081, 0x1082, 0x0503, 0x1084, 0x1085, 0x1086, 0x050B,
237 	0x1088, 0x1089, 0x108A, 0x0513, 0x108C, 0x108D, 0x108E, 0x051B,
238 	0x1090, 0x1091, 0x1092, 0x0523, 0x1094, 0x1095, 0x1096, 0x052B,
239 	0x1098, 0x1099, 0x109A, 0x0533, 0x109C, 0x109D, 0x109E, 0x053B,
240 	0x10A0, 0x10A1, 0x10A2, 0x0543, 0x10A4, 0x10A5, 0x10A6, 0x054B,
241 	0x10A8, 0x10A9, 0x10AA, 0x0553, 0x10AC, 0x10AD, 0x10AE, 0x055B,
242 	0x10B0, 0x10B1, 0x10B2, 0x0563, 0x10B4, 0x10B5, 0x10B6, 0x056B,
243 	0x10B8, 0x10B9, 0x10BA, 0x0573, 0x10BC, 0x10BD, 0x053E, 0x057B,
244 	0x20C0, 0x20C1, 0x20C2, 0x1583, 0x20C4, 0x20C5, 0x20C6, 0x158B,
245 	0x20C8, 0x20C9, 0x20CA, 0x1593, 0x20CC, 0x20CD, 0x20CE, 0x159B,
246 	0x20D0, 0x20D1, 0x20D2, 0x15A3, 0x20D4, 0x20D5, 0x20D6, 0x15AB,
247 	0x20D8, 0x20D9, 0x20DA, 0x15B3, 0x20DC, 0x20DD, 0x20DE, 0x15BB,
248 	0x30E0, 0x30E1, 0x30E2, 0x25C3, 0x30E4, 0x30E5, 0x30E6, 0x25CB,
249 	0x30E8, 0x30E9, 0x30EA, 0x25D3, 0x30EC, 0x30ED, 0x30EE, 0x25DB,
250 	0x40F0, 0x40F1, 0x40F2, 0x35E3, 0x40F4, 0x40F5, 0x40F6, 0x35EB,
251 	0x50F8, 0x50F9, 0x50FA, 0x45F3, 0x057C, 0x057D, 0x15BE, 0x55FB,
252 };
253 
254 
255 static WORD stuff4[] =
256 {
257 	0x0000, 0x0401, 0x0002, 0x0405, 0x0004, 0x0409, 0x0006, 0x040D,
258 	0x0008, 0x0411, 0x000A, 0x0415, 0x000C, 0x0419, 0x000E, 0x041D,
259 	0x0010, 0x0421, 0x0012, 0x0425, 0x0014, 0x0429, 0x0016, 0x042D,
260 	0x0018, 0x0431, 0x001A, 0x0435, 0x001C, 0x0439, 0x001E, 0x043D,
261 	0x0020, 0x0441, 0x0022, 0x0445, 0x0024, 0x0449, 0x0026, 0x044D,
262 	0x0028, 0x0451, 0x002A, 0x0455, 0x002C, 0x0459, 0x002E, 0x045D,
263 	0x0030, 0x0461, 0x0032, 0x0465, 0x0034, 0x0469, 0x0036, 0x046D,
264 	0x0038, 0x0471, 0x003A, 0x0475, 0x003C, 0x0479, 0x043E, 0x087D,
265 	0x0040, 0x1481, 0x0042, 0x1485, 0x0044, 0x1489, 0x0046, 0x148D,
266 	0x0048, 0x1491, 0x004A, 0x1495, 0x004C, 0x1499, 0x004E, 0x149D,
267 	0x0050, 0x14A1, 0x0052, 0x14A5, 0x0054, 0x14A9, 0x0056, 0x14AD,
268 	0x0058, 0x14B1, 0x005A, 0x14B5, 0x005C, 0x14B9, 0x005E, 0x14BD,
269 	0x0060, 0x24C1, 0x0062, 0x24C5, 0x0064, 0x24C9, 0x0066, 0x24CD,
270 	0x0068, 0x24D1, 0x006A, 0x24D5, 0x006C, 0x24D9, 0x006E, 0x24DD,
271 	0x0070, 0x34E1, 0x0072, 0x34E5, 0x0074, 0x34E9, 0x0076, 0x34ED,
272 	0x0078, 0x44F1, 0x007A, 0x44F5, 0x047C, 0x54F9, 0x14BE, 0x097D,
273 	0x1080, 0x0501, 0x1082, 0x0505, 0x1084, 0x0509, 0x1086, 0x050D,
274 	0x1088, 0x0511, 0x108A, 0x0515, 0x108C, 0x0519, 0x108E, 0x051D,
275 	0x1090, 0x0521, 0x1092, 0x0525, 0x1094, 0x0529, 0x1096, 0x052D,
276 	0x1098, 0x0531, 0x109A, 0x0535, 0x109C, 0x0539, 0x109E, 0x053D,
277 	0x10A0, 0x0541, 0x10A2, 0x0545, 0x10A4, 0x0549, 0x10A6, 0x054D,
278 	0x10A8, 0x0551, 0x10AA, 0x0555, 0x10AC, 0x0559, 0x10AE, 0x055D,
279 	0x10B0, 0x0561, 0x10B2, 0x0565, 0x10B4, 0x0569, 0x10B6, 0x056D,
280 	0x10B8, 0x0571, 0x10BA, 0x0575, 0x10BC, 0x0579, 0x053E, 0x0A7D,
281 	0x20C0, 0x1581, 0x20C2, 0x1585, 0x20C4, 0x1589, 0x20C6, 0x158D,
282 	0x20C8, 0x1591, 0x20CA, 0x1595, 0x20CC, 0x1599, 0x20CE, 0x159D,
283 	0x20D0, 0x15A1, 0x20D2, 0x15A5, 0x20D4, 0x15A9, 0x20D6, 0x15AD,
284 	0x20D8, 0x15B1, 0x20DA, 0x15B5, 0x20DC, 0x15B9, 0x20DE, 0x15BD,
285 	0x30E0, 0x25C1, 0x30E2, 0x25C5, 0x30E4, 0x25C9, 0x30E6, 0x25CD,
286 	0x30E8, 0x25D1, 0x30EA, 0x25D5, 0x30EC, 0x25D9, 0x30EE, 0x25DD,
287 	0x40F0, 0x35E1, 0x40F2, 0x35E5, 0x40F4, 0x35E9, 0x40F6, 0x35ED,
288 	0x50F8, 0x45F1, 0x50FA, 0x45F5, 0x057C, 0x55F9, 0x15BE, 0x0B7D,
289 };
290 
291 
292 static WORD stuff5[] =
293 {
294 	0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E,
295 	0x0410, 0x0412, 0x0414, 0x0416, 0x0418, 0x041A, 0x041C, 0x041E,
296 	0x0420, 0x0422, 0x0424, 0x0426, 0x0428, 0x042A, 0x042C, 0x042E,
297 	0x0430, 0x0432, 0x0434, 0x0436, 0x0438, 0x043A, 0x043C, 0x083E,
298 	0x0440, 0x0442, 0x0444, 0x0446, 0x0448, 0x044A, 0x044C, 0x044E,
299 	0x0450, 0x0452, 0x0454, 0x0456, 0x0458, 0x045A, 0x045C, 0x045E,
300 	0x0460, 0x0462, 0x0464, 0x0466, 0x0468, 0x046A, 0x046C, 0x046E,
301 	0x0470, 0x0472, 0x0474, 0x0476, 0x0478, 0x047A, 0x087C, 0x18BE,
302 	0x1480, 0x1482, 0x1484, 0x1486, 0x1488, 0x148A, 0x148C, 0x148E,
303 	0x1490, 0x1492, 0x1494, 0x1496, 0x1498, 0x149A, 0x149C, 0x149E,
304 	0x14A0, 0x14A2, 0x14A4, 0x14A6, 0x14A8, 0x14AA, 0x14AC, 0x14AE,
305 	0x14B0, 0x14B2, 0x14B4, 0x14B6, 0x14B8, 0x14BA, 0x14BC, 0x093E,
306 	0x24C0, 0x24C2, 0x24C4, 0x24C6, 0x24C8, 0x24CA, 0x24CC, 0x24CE,
307 	0x24D0, 0x24D2, 0x24D4, 0x24D6, 0x24D8, 0x24DA, 0x24DC, 0x24DE,
308 	0x34E0, 0x34E2, 0x34E4, 0x34E6, 0x34E8, 0x34EA, 0x34EC, 0x34EE,
309 	0x44F0, 0x44F2, 0x44F4, 0x44F6, 0x54F8, 0x54FA, 0x097C, 0x19BE,
310 	0x0500, 0x0502, 0x0504, 0x0506, 0x0508, 0x050A, 0x050C, 0x050E,
311 	0x0510, 0x0512, 0x0514, 0x0516, 0x0518, 0x051A, 0x051C, 0x051E,
312 	0x0520, 0x0522, 0x0524, 0x0526, 0x0528, 0x052A, 0x052C, 0x052E,
313 	0x0530, 0x0532, 0x0534, 0x0536, 0x0538, 0x053A, 0x053C, 0x0A3E,
314 	0x0540, 0x0542, 0x0544, 0x0546, 0x0548, 0x054A, 0x054C, 0x054E,
315 	0x0550, 0x0552, 0x0554, 0x0556, 0x0558, 0x055A, 0x055C, 0x055E,
316 	0x0560, 0x0562, 0x0564, 0x0566, 0x0568, 0x056A, 0x056C, 0x056E,
317 	0x0570, 0x0572, 0x0574, 0x0576, 0x0578, 0x057A, 0x0A7C, 0x1ABE,
318 	0x1580, 0x1582, 0x1584, 0x1586, 0x1588, 0x158A, 0x158C, 0x158E,
319 	0x1590, 0x1592, 0x1594, 0x1596, 0x1598, 0x159A, 0x159C, 0x159E,
320 	0x15A0, 0x15A2, 0x15A4, 0x15A6, 0x15A8, 0x15AA, 0x15AC, 0x15AE,
321 	0x15B0, 0x15B2, 0x15B4, 0x15B6, 0x15B8, 0x15BA, 0x15BC, 0x0B3E,
322 	0x25C0, 0x25C2, 0x25C4, 0x25C6, 0x25C8, 0x25CA, 0x25CC, 0x25CE,
323 	0x25D0, 0x25D2, 0x25D4, 0x25D6, 0x25D8, 0x25DA, 0x25DC, 0x25DE,
324 	0x35E0, 0x35E2, 0x35E4, 0x35E6, 0x35E8, 0x35EA, 0x35EC, 0x35EE,
325 	0x45F0, 0x45F2, 0x45F4, 0x45F6, 0x55F8, 0x55FA, 0x0B7C, 0x1BBE,
326 };
327 
328 static WORD destuff0[] =
329 {
330 	0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007,
331 	0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0x700F,
332 	0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017,
333 	0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0x601F,
334 	0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x7027,
335 	0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0x702F,
336 	0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x7037,
337 	0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F,
338 	0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047,
339 	0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0x704F,
340 	0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057,
341 	0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0x603F,
342 	0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067,
343 	0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0x706F,
344 	0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x7077,
345 	0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F,
346 	0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x7187,
347 	0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0x718F,
348 	0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x7197,
349 	0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0x615F,
350 	0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x71A7,
351 	0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0x71AF,
352 	0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x71B7,
353 	0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF,
354 	0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x72C7,
355 	0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0x72CF,
356 	0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x72D7,
357 	0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0x627F,
358 	0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x73E7,
359 	0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0x73EF,
360 	0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x74F7,
361 	0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xF8FF,
362 };
363 
364 
365 static WORD destuff1[] =
366 {
367 	0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007,
368 	0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0x600F,
369 	0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017,
370 	0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0xF01F,
371 	0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x7027,
372 	0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0x601F,
373 	0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x7037,
374 	0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F,
375 	0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047,
376 	0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0x602F,
377 	0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057,
378 	0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0xF05F,
379 	0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067,
380 	0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0x603F,
381 	0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x7077,
382 	0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F,
383 	0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x7187,
384 	0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0x614F,
385 	0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x7197,
386 	0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0xF19F,
387 	0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x71A7,
388 	0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0x615F,
389 	0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x71B7,
390 	0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF,
391 	0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x72C7,
392 	0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0x626F,
393 	0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x72D7,
394 	0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0xF2DF,
395 	0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x73E7,
396 	0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0x637F,
397 	0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x74F7,
398 	0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xF9FF,
399 };
400 
401 
402 static WORD destuff2[] =
403 {
404 	0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x6007,
405 	0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0xF00F,
406 	0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x600F,
407 	0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0xF01F,
408 	0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x6017,
409 	0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0xF02F,
410 	0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x601F,
411 	0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F,
412 	0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x6027,
413 	0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0xF04F,
414 	0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x602F,
415 	0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0xF05F,
416 	0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x6037,
417 	0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0xF06F,
418 	0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x603F,
419 	0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F,
420 	0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x6147,
421 	0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0xF18F,
422 	0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x614F,
423 	0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0xF19F,
424 	0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x6157,
425 	0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0xF1AF,
426 	0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x615F,
427 	0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF,
428 	0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x6267,
429 	0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0xF2CF,
430 	0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x626F,
431 	0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0xF2DF,
432 	0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x6377,
433 	0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0xF3EF,
434 	0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x647F,
435 	0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xFAFF,
436 };
437 
438 
439 static WORD destuff3[] =
440 {
441 	0x7000, 0x7001, 0x7002, 0x6003, 0x7004, 0x7005, 0x7006, 0xF007,
442 	0x7008, 0x7009, 0x700A, 0x6007, 0x700C, 0x700D, 0x700E, 0xF00F,
443 	0x7010, 0x7011, 0x7012, 0x600B, 0x7014, 0x7015, 0x7016, 0xF017,
444 	0x7018, 0x7019, 0x701A, 0x600F, 0x701C, 0x701D, 0x701E, 0xF01F,
445 	0x7020, 0x7021, 0x7022, 0x6013, 0x7024, 0x7025, 0x7026, 0xF027,
446 	0x7028, 0x7029, 0x702A, 0x6017, 0x702C, 0x702D, 0x702E, 0xF02F,
447 	0x7030, 0x7031, 0x7032, 0x601B, 0x7034, 0x7035, 0x7036, 0xF037,
448 	0x7038, 0x7039, 0x703A, 0x601F, 0x703C, 0x703D, 0x603E, 0xF03F,
449 	0x7040, 0x7041, 0x7042, 0x6023, 0x7044, 0x7045, 0x7046, 0xF047,
450 	0x7048, 0x7049, 0x704A, 0x6027, 0x704C, 0x704D, 0x704E, 0xF04F,
451 	0x7050, 0x7051, 0x7052, 0x602B, 0x7054, 0x7055, 0x7056, 0xF057,
452 	0x7058, 0x7059, 0x705A, 0x602F, 0x705C, 0x705D, 0x705E, 0xF05F,
453 	0x7060, 0x7061, 0x7062, 0x6033, 0x7064, 0x7065, 0x7066, 0xF067,
454 	0x7068, 0x7069, 0x706A, 0x6037, 0x706C, 0x706D, 0x706E, 0xF06F,
455 	0x7070, 0x7071, 0x7072, 0x603B, 0x7074, 0x7075, 0x7076, 0xF077,
456 	0x7078, 0x7079, 0x707A, 0x603F, 0x607C, 0x607D, 0xF07E, 0xF07F,
457 	0x7180, 0x7181, 0x7182, 0x6143, 0x7184, 0x7185, 0x7186, 0xF187,
458 	0x7188, 0x7189, 0x718A, 0x6147, 0x718C, 0x718D, 0x718E, 0xF18F,
459 	0x7190, 0x7191, 0x7192, 0x614B, 0x7194, 0x7195, 0x7196, 0xF197,
460 	0x7198, 0x7199, 0x719A, 0x614F, 0x719C, 0x719D, 0x719E, 0xF19F,
461 	0x71A0, 0x71A1, 0x71A2, 0x6153, 0x71A4, 0x71A5, 0x71A6, 0xF1A7,
462 	0x71A8, 0x71A9, 0x71AA, 0x6157, 0x71AC, 0x71AD, 0x71AE, 0xF1AF,
463 	0x71B0, 0x71B1, 0x71B2, 0x615B, 0x71B4, 0x71B5, 0x71B6, 0xF1B7,
464 	0x71B8, 0x71B9, 0x71BA, 0x615F, 0x71BC, 0x71BD, 0x617E, 0xF1BF,
465 	0x72C0, 0x72C1, 0x72C2, 0x6263, 0x72C4, 0x72C5, 0x72C6, 0xF2C7,
466 	0x72C8, 0x72C9, 0x72CA, 0x6267, 0x72CC, 0x72CD, 0x72CE, 0xF2CF,
467 	0x72D0, 0x72D1, 0x72D2, 0x626B, 0x72D4, 0x72D5, 0x72D6, 0xF2D7,
468 	0x72D8, 0x72D9, 0x72DA, 0x626F, 0x72DC, 0x72DD, 0x72DE, 0xF2DF,
469 	0x73E0, 0x73E1, 0x73E2, 0x6373, 0x73E4, 0x73E5, 0x73E6, 0xF3E7,
470 	0x73E8, 0x73E9, 0x73EA, 0x6377, 0x73EC, 0x73ED, 0x73EE, 0xF3EF,
471 	0x74F0, 0x74F1, 0x74F2, 0x647B, 0x74F4, 0x74F5, 0x74F6, 0xF4F7,
472 	0x75F8, 0x75F9, 0x75FA, 0x657F, 0xF6FC, 0xF6FD, 0xF7FE, 0xFBFF,
473 };
474 
475 
476 static WORD destuff4[] =
477 {
478 	0x7000, 0x6001, 0x7002, 0xF003, 0x7004, 0x6003, 0x7006, 0xF007,
479 	0x7008, 0x6005, 0x700A, 0xF00B, 0x700C, 0x6007, 0x700E, 0xF00F,
480 	0x7010, 0x6009, 0x7012, 0xF013, 0x7014, 0x600B, 0x7016, 0xF017,
481 	0x7018, 0x600D, 0x701A, 0xF01B, 0x701C, 0x600F, 0x701E, 0xF01F,
482 	0x7020, 0x6011, 0x7022, 0xF023, 0x7024, 0x6013, 0x7026, 0xF027,
483 	0x7028, 0x6015, 0x702A, 0xF02B, 0x702C, 0x6017, 0x702E, 0xF02F,
484 	0x7030, 0x6019, 0x7032, 0xF033, 0x7034, 0x601B, 0x7036, 0xF037,
485 	0x7038, 0x601D, 0x703A, 0xF03B, 0x703C, 0x601F, 0x603E, 0xF03F,
486 	0x7040, 0x6021, 0x7042, 0xF043, 0x7044, 0x6023, 0x7046, 0xF047,
487 	0x7048, 0x6025, 0x704A, 0xF04B, 0x704C, 0x6027, 0x704E, 0xF04F,
488 	0x7050, 0x6029, 0x7052, 0xF053, 0x7054, 0x602B, 0x7056, 0xF057,
489 	0x7058, 0x602D, 0x705A, 0xF05B, 0x705C, 0x602F, 0x705E, 0xF05F,
490 	0x7060, 0x6031, 0x7062, 0xF063, 0x7064, 0x6033, 0x7066, 0xF067,
491 	0x7068, 0x6035, 0x706A, 0xF06B, 0x706C, 0x6037, 0x706E, 0xF06F,
492 	0x7070, 0x6039, 0x7072, 0xF073, 0x7074, 0x603B, 0x7076, 0xF077,
493 	0x7078, 0x603D, 0x707A, 0xF07B, 0x607C, 0x503F, 0xF07E, 0xF07F,
494 	0x7180, 0x6141, 0x7182, 0xF183, 0x7184, 0x6143, 0x7186, 0xF187,
495 	0x7188, 0x6145, 0x718A, 0xF18B, 0x718C, 0x6147, 0x718E, 0xF18F,
496 	0x7190, 0x6149, 0x7192, 0xF193, 0x7194, 0x614B, 0x7196, 0xF197,
497 	0x7198, 0x614D, 0x719A, 0xF19B, 0x719C, 0x614F, 0x719E, 0xF19F,
498 	0x71A0, 0x6151, 0x71A2, 0xF1A3, 0x71A4, 0x6153, 0x71A6, 0xF1A7,
499 	0x71A8, 0x6155, 0x71AA, 0xF1AB, 0x71AC, 0x6157, 0x71AE, 0xF1AF,
500 	0x71B0, 0x6159, 0x71B2, 0xF1B3, 0x71B4, 0x615B, 0x71B6, 0xF1B7,
501 	0x71B8, 0x615D, 0x71BA, 0xF1BB, 0x71BC, 0x615F, 0x617E, 0xF1BF,
502 	0x72C0, 0x6261, 0x72C2, 0xF2C3, 0x72C4, 0x6263, 0x72C6, 0xF2C7,
503 	0x72C8, 0x6265, 0x72CA, 0xF2CB, 0x72CC, 0x6267, 0x72CE, 0xF2CF,
504 	0x72D0, 0x6269, 0x72D2, 0xF2D3, 0x72D4, 0x626B, 0x72D6, 0xF2D7,
505 	0x72D8, 0x626D, 0x72DA, 0xF2DB, 0x72DC, 0x626F, 0x72DE, 0xF2DF,
506 	0x73E0, 0x6371, 0x73E2, 0xF3E3, 0x73E4, 0x6373, 0x73E6, 0xF3E7,
507 	0x73E8, 0x6375, 0x73EA, 0xF3EB, 0x73EC, 0x6377, 0x73EE, 0xF3EF,
508 	0x74F0, 0x6479, 0x74F2, 0xF4F3, 0x74F4, 0x647B, 0x74F6, 0xF4F7,
509 	0x75F8, 0x657D, 0x75FA, 0xF5FB, 0xF6FC, 0xE67F, 0xF7FE, 0xFCFF,
510 };
511 
512 
513 static WORD destuff5[] =
514 {
515 	0x6000, 0xF001, 0x6001, 0xF003, 0x6002, 0xF005, 0x6003, 0xF007,
516 	0x6004, 0xF009, 0x6005, 0xF00B, 0x6006, 0xF00D, 0x6007, 0xF00F,
517 	0x6008, 0xF011, 0x6009, 0xF013, 0x600A, 0xF015, 0x600B, 0xF017,
518 	0x600C, 0xF019, 0x600D, 0xF01B, 0x600E, 0xF01D, 0x600F, 0xF01F,
519 	0x6010, 0xF021, 0x6011, 0xF023, 0x6012, 0xF025, 0x6013, 0xF027,
520 	0x6014, 0xF029, 0x6015, 0xF02B, 0x6016, 0xF02D, 0x6017, 0xF02F,
521 	0x6018, 0xF031, 0x6019, 0xF033, 0x601A, 0xF035, 0x601B, 0xF037,
522 	0x601C, 0xF039, 0x601D, 0xF03B, 0x601E, 0xF03D, 0x501F, 0xF03F,
523 	0x6020, 0xF041, 0x6021, 0xF043, 0x6022, 0xF045, 0x6023, 0xF047,
524 	0x6024, 0xF049, 0x6025, 0xF04B, 0x6026, 0xF04D, 0x6027, 0xF04F,
525 	0x6028, 0xF051, 0x6029, 0xF053, 0x602A, 0xF055, 0x602B, 0xF057,
526 	0x602C, 0xF059, 0x602D, 0xF05B, 0x602E, 0xF05D, 0x602F, 0xF05F,
527 	0x6030, 0xF061, 0x6031, 0xF063, 0x6032, 0xF065, 0x6033, 0xF067,
528 	0x6034, 0xF069, 0x6035, 0xF06B, 0x6036, 0xF06D, 0x6037, 0xF06F,
529 	0x6038, 0xF071, 0x6039, 0xF073, 0x603A, 0xF075, 0x603B, 0xF077,
530 	0x603C, 0xF079, 0x603D, 0xF07B, 0x503E, 0xE07D, 0xE03F, 0xF07F,
531 	0x6140, 0xF181, 0x6141, 0xF183, 0x6142, 0xF185, 0x6143, 0xF187,
532 	0x6144, 0xF189, 0x6145, 0xF18B, 0x6146, 0xF18D, 0x6147, 0xF18F,
533 	0x6148, 0xF191, 0x6149, 0xF193, 0x614A, 0xF195, 0x614B, 0xF197,
534 	0x614C, 0xF199, 0x614D, 0xF19B, 0x614E, 0xF19D, 0x614F, 0xF19F,
535 	0x6150, 0xF1A1, 0x6151, 0xF1A3, 0x6152, 0xF1A5, 0x6153, 0xF1A7,
536 	0x6154, 0xF1A9, 0x6155, 0xF1AB, 0x6156, 0xF1AD, 0x6157, 0xF1AF,
537 	0x6158, 0xF1B1, 0x6159, 0xF1B3, 0x615A, 0xF1B5, 0x615B, 0xF1B7,
538 	0x615C, 0xF1B9, 0x615D, 0xF1BB, 0x615E, 0xF1BD, 0x513F, 0xF1BF,
539 	0x6260, 0xF2C1, 0x6261, 0xF2C3, 0x6262, 0xF2C5, 0x6263, 0xF2C7,
540 	0x6264, 0xF2C9, 0x6265, 0xF2CB, 0x6266, 0xF2CD, 0x6267, 0xF2CF,
541 	0x6268, 0xF2D1, 0x6269, 0xF2D3, 0x626A, 0xF2D5, 0x626B, 0xF2D7,
542 	0x626C, 0xF2D9, 0x626D, 0xF2DB, 0x626E, 0xF2DD, 0x626F, 0xF2DF,
543 	0x6370, 0xF3E1, 0x6371, 0xF3E3, 0x6372, 0xF3E5, 0x6373, 0xF3E7,
544 	0x6374, 0xF3E9, 0x6375, 0xF3EB, 0x6376, 0xF3ED, 0x6377, 0xF3EF,
545 	0x6478, 0xF4F1, 0x6479, 0xF4F3, 0x647A, 0xF4F5, 0x647B, 0xF4F7,
546 	0x657C, 0xF5F9, 0x657D, 0xF5FB, 0xE67E, 0xF6FD, 0xE77F, 0xFDFF,
547 };
548 
549 
550 static WORD * stuffs[] = { stuff0, stuff1, stuff2, stuff3, stuff4, stuff5 };
551 WORD * destuffs[] = { destuff0, destuff1, destuff2, destuff3, destuff4, destuff5 };
552 
553 
554 /*- AuverTech Telecom -------------------------------------------------------+
555  |                                                                           |
556  | @Function  : tpam_hdlc_encode                                             |
557  | @Author    : Cyrille Boudon                                               |
558  |                                                                           |
559  +---------------------------------------------------------------------------+
560  |                                                                           |
561  | @Param     : BYTE *pbyBuffIn        IN,    array of bytes to encode       |
562  | @Param     : BYTE *pbyBuffOut       OUT,   array of bytes encoded         |
563  | @Param     : DWORD *pdwInitialShift INOUT, initial shift                  |
564  | @Param     : DWORD dwLength         IN,    count of bytes to encode       |
565  |                                                                           |
566  | @Return    : DWORD                  count of bytes encoded                |
567  |                                                                           |
568  +------------------------------- @Abstract ---------------------------------+
569  |                                                                           |
570  | Bit stuffing of thz array pbyBuffIn with the insertion of a flag at the   |
571  | beginning and the end, using the initial shift (due to the emission of    |
572  | previous frames). The last byte can be used to insert flags (by outputting|
573  | the flag N times) before the next frame. The initial shift is updated at  |
574  | the end of the algorithm for the next frame. Its signification is: for the|
575  | flags shifted like  "1100111111001111" *pdwInitialShift = 3. At the       |
576  | beginning (for the first frame), the shift must be initialized to 0.      |
577  |                                                                           |
578  +---------------------------------------------------------------------------*/
tpam_hdlc_encode(BYTE * pbyBuffIn,BYTE * pbyBuffOut,DWORD * pdwInitialShift,DWORD dwLength)579 DWORD tpam_hdlc_encode(BYTE *pbyBuffIn, BYTE *pbyBuffOut,
580 		       DWORD *pdwInitialShift, DWORD dwLength)
581 {
582 	DWORD	dwShifter;     // temporary variable
583 	DWORD	dwShiftNb;     // shift due to the insertion of '0'
584 	DWORD	dwState;       // count of '1' at the end of the current byte
585 	DWORD	dwNb;          // length of the encoded array
586 	BYTE	byCarry;       // carry due to the shift
587 	BYTE	byNewCarry;    // temporary variable
588 	BYTE	byCharIn;      // byte being encoded
589 	BYTE	byCarryMSB;    // lost bit of the carry if dwShiftNb=7 and 2 '0' inserted
590 	WORD	woDecal;       // temporary variable
591 	WORD	woInfo;        // data read in the arrays
592 	BOOL	bContinue;     // true until the two last bytes
593 	BOOL	bContinue2;    // true until the last byte
594 
595 	bContinue = TRUE;
596 	bContinue2 = TRUE;
597 	dwShiftNb = 0;
598 	byCarry = 0;
599 	dwState = 0;
600 	woDecal = 0x7E;
601 	byCarryMSB = 0xFF;
602 	dwNb = 1; // length to 1 to account for the first flag
603 
604 	/*-----------------------------
605 	 | insert the flag using the
606 	 | shift given by
607 	 | *pdwInitialShift)
608 	 +-----------------------------*/
609 	* pbyBuffOut ++ = 0x7E7E >> *pdwInitialShift;
610 
611 	/*-----------------------------
612 	 | main loop
613 	 +-----------------------------*/
614 	while (dwLength--)
615 	{
616 		byCharIn = *pbyBuffIn ++;
617 
618 /*-----------------------------
619  | go back here to treat the
620  | carry when its length
621  | is over 7 and for the first
622  | byte (with flag)
623  +-----------------------------*/
624 carry:
625 
626 		dwNb ++;
627 
628 		/*-----------------------------
629 		 | shift the byte to get the
630 		 | byte to encode (without
631 		 | taking into account the
632 		 | initial shift)
633 		 +-----------------------------*/
634 		if (dwShiftNb)
635 		{
636 			dwShifter = byCharIn << dwShiftNb;
637 			byNewCarry = dwShifter >> 8;
638 			byCharIn = dwShifter | byCarry;
639 			byCarry = byNewCarry;
640 		}
641 
642 		/*-----------------------------
643 		 | get the data from the arrays
644 		 | and take into account the
645 		 | initial shift for the byte
646 		 | to encode
647 		 +-----------------------------*/
648 		woInfo = stuffs[dwState][byCharIn];
649 		woDecal |= (woInfo & 0x00FF) << 8;
650 		* pbyBuffOut ++ = woDecal >> *pdwInitialShift;
651 		woDecal = woInfo & 0x00FF;
652 		dwState = woInfo >> 12;
653 
654 		/*-----------------------------
655 		 | treat the lost bit if we had
656 		 | a carry overflow
657 		 +-----------------------------*/
658 		if (byCarryMSB != 0xFF)
659 		{
660 			if (!dwShiftNb)
661 			{
662 				if(byCarryMSB)
663 					byCarry = 1;
664 				dwShiftNb = 1;
665 			}
666 			byCarryMSB = 0xFF;
667 		}
668 
669 		/*-----------------------------
670 		 | if one '0' get inserted, we
671 		 | have to calculate the new
672 		 | carry and the new shift
673 		 +-----------------------------*/
674 		if (woInfo & 0x0F00)
675 		{
676 			byCarryMSB = byCarry & 0x40;
677 			byCarry <<= (woInfo & 0x0C00) >> 10;
678 			byCarry |= (woInfo & 0x0300) >> 8;
679 			dwShiftNb += (woInfo & 0x0C00) >> 10;
680 		}
681 
682 		/*-----------------------------
683 		 | if the carry is a whole byte
684 		 | we use it as a byte to encode
685 		 +-----------------------------*/
686 		if (dwShiftNb > 7)
687 		{
688 			if (dwShiftNb == 8)
689 				byCarryMSB = 0xFF;
690 			dwShiftNb = 0;
691 			byCharIn = byCarry;
692 			byCarry = 0;
693 			goto carry;
694 		}
695 
696 		/*-----------------------------
697 		 | at the end of the array
698 		 +-----------------------------*/
699 		if (!dwLength)
700 		{
701 			/*-----------------------------
702 			 | take into account the bits
703 			 | set in the carry
704 			 +-----------------------------*/
705 			if (bContinue)
706 			{
707 				bContinue = FALSE;
708 				byCharIn = 0;
709 				goto carry;
710 			}
711 
712 			/*-----------------------------
713 			 | treat the last byte if we
714 			 | had a carry overflow
715 			 +-----------------------------*/
716 			if (bContinue2 && ((8 - *pdwInitialShift) + dwShiftNb) > 7)
717 			{
718 				bContinue2 = FALSE;
719 				byCharIn = 0;
720 				goto carry;
721 			}
722 
723 			/*-----------------------------
724 			 | Calculate the new shift
725 			 +-----------------------------*/
726 			*pdwInitialShift = ((8 - *pdwInitialShift) + dwShiftNb)%8;
727 
728 			/*-----------------------------
729 			 | Add a flag at the end of the
730 			 | carry and a full flag
731 			 +-----------------------------*/
732 			pbyBuffOut--;
733 			*pbyBuffOut++ |= 0x7E << *pdwInitialShift;
734 			byCarry = 0x7E7E >> (8 - *pdwInitialShift);
735 			*pbyBuffOut++ = byCarry;
736 			*pbyBuffOut++ = byCarry;
737 			dwNb += 2;
738 		}
739 	}
740 
741 	/*-------------------------------
742 	 | Pad the array to a multiple
743 	 | of 64 bytes.
744 	 +-------------------------------*/
745 	for(;dwNb%64;dwNb++)
746 		*pbyBuffOut ++ = byCarry;
747 
748 	*pdwInitialShift = (8 - *pdwInitialShift)%8;
749 
750 	return dwNb;
751 }
752 
753 
754 
755 /*- AuverTech Telecom -------------------------------------------------------+
756  |                                                                           |
757  | @Function  : tpam_hdlc_decode                                             |
758  | @Author    : Cyrille Boudon                                               |
759  |                                                                           |
760  +---------------------------------------------------------------------------+
761  |                                                                           |
762  | @Param     : BYTE * pbyBuffIn  IN,  array of bytes to decode              |
763  | @Param     : BYTE * pbyBuffOut OUT, array of decoded bytes                |
764  | @Param     : DWORD dwLength    IN,  count of bytes to decode              |
765  |                                                                           |
766  | @Return    : DWORD             count of decoded bytes                     |
767  |                                                                           |
768  +------------------------------- @Abstract ---------------------------------+
769  |                                                                           |
770  | Bit de-stuffing of the array pbyBuffIn. There has to be at least 1 full   |
771  | flag at the beginning. At the end there has to be a flag or an abort (more|
772  | than 6 consecutive '1').                                                  |
773  | If an abort is encountered, the returned count is '0'.                    |
774  |                                                                           |
775  +---------------------------------------------------------------------------*/
tpam_hdlc_decode(BYTE * pbyBuffIn,BYTE * pbyBuffOut,DWORD dwLength)776 DWORD tpam_hdlc_decode(BYTE * pbyBuffIn, BYTE * pbyBuffOut, DWORD dwLength)
777 {
778 	BYTE	byCharIn;    // byte being decoded
779 	BYTE	byCarry;     // current carry
780 	WORD	woInfo;      // data read in the arrays
781 	WORD	woNb1;       // count of '1' at the end of the previous byte
782 	BYTE	byShift;     // shift of the first flag
783 	DWORD	dwInit;      // temporary variable
784 	DWORD	dwLengthOut; // count of the decoded bytes
785 	BYTE	byLgCarry;   // count of used bits in the carry
786 	BYTE	byLgByte;    // count of used bits in the decoded byte
787 
788 	/*-----------------------------
789 	 | Find the 1st flag. At the end
790 	 | of the loop dwShift is the count
791 	 | of bits to reach the 1st bit
792 	 | of the 1st flag.
793 	 +-----------------------------*/
794 	dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8) | (*(pbyBuffIn+2)<<16);
795 	for (byShift=0;byShift<17;byShift++)
796 	{
797 		if (!(((dwInit>>byShift)&0xFF)^0x7E))
798 		{
799 			break;
800 		}
801 	}
802 
803 	/*-----------------------------
804 	 | If at the end of the previous
805 	 | loop dwShift = 17, it means
806 	 | that no flag was found in the
807 	 | first 3 bytes (normally
808 	 | impossible impossible with the
809 	 | DSP algorithm)
810 	 +-----------------------------*/
811 	if (byShift == 17)
812 		return 0;
813 
814 	/*-----------------------------
815 	 | Plase the array pointer after
816 	 | the first flag. Update the
817 	 | shift.
818 	 +-----------------------------*/
819 	pbyBuffIn += byShift/8 + 1;
820 	dwLength -= byShift/8 + 1;
821 	byShift %= 8;
822 
823 	/*-----------------------------
824 	 | Walk through the frame to
825 	 | find the first data byte
826 	 +-----------------------------*/
827 	dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8);
828 	while (!(((dwInit>>byShift)&0xFF)^0x7E))
829 	{
830 		pbyBuffIn ++;
831 		dwLength --;
832 		dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8);
833 	}
834 
835 	dwLengthOut = 0;
836 	byCarry = 0;
837 	byLgCarry = 0;
838 	byLgByte = 0;
839 
840 	/*-------------------------------
841 	 | Treat the first byte
842 	 +-------------------------------*/
843 	byCharIn = (*pbyBuffIn >> byShift) << byShift;
844 	woInfo = destuffs[0][byCharIn];
845 	byLgByte = ((woInfo & 0x7000) >> 12) + 1;
846 	woNb1 = (woInfo & 0x0F00) >> 8;
847 	dwLength --;
848 	pbyBuffIn++;
849 
850 	if (woNb1 > 5)
851 		return 0;
852 
853 	if (byLgByte - byShift == 8)
854 	{
855 		*pbyBuffOut ++ = woInfo;
856 		dwLengthOut ++;
857 	}
858 	else
859 	{
860 		byCarry = woInfo << (8 - byLgByte);
861 		byLgCarry = byLgByte - byShift;
862 	}
863 
864 	/*-------------------------------
865 	 | main loop
866 	 +-------------------------------*/
867 	while(dwLength --)
868 	{
869 		byCharIn = *pbyBuffIn ++;
870 
871 		woInfo = destuffs[woNb1][byCharIn];
872 		byLgByte = ((woInfo & 0x7000) >> 12) + 1;
873 
874 		/*-------------------------------
875 		 | if the used bits in the carry
876 		 | and the current byte makes
877 		 | possible to output a full byte
878 		 +-------------------------------*/
879 		if (byLgByte + byLgCarry >= 8)
880 		{
881 			*pbyBuffOut ++ = ( (woInfo << 8) | byCarry) >> (8 - byLgCarry);
882 			dwLengthOut ++;
883 			byLgCarry += byLgByte - 8;
884 			byCarry = woInfo << (8-byLgByte);
885 		}
886 		/*-------------------------------
887 		 | if the used bits in the carry
888 		 | and the current byte doesn't
889 		 | make possible to output a full
890 		 | byte
891 		 +-------------------------------*/
892 		else
893 		{
894 			dwInit = (woInfo << 8) | byCarry;
895 			byLgCarry += byLgByte;
896 			byCarry = dwInit >> byLgByte;
897 		}
898 
899 		woNb1 = (woInfo & 0x0F00) >> 8;
900 
901 		/*-------------------------------
902 		 | if the current byte contains
903 		 | six or more consecutive '1'
904 		 +-------------------------------*/
905 		if (woInfo & 0x8000)
906 		{
907 			byCarry = ((byCharIn << 8) | *(pbyBuffIn-2)) >> (8 - byLgCarry);
908 			if (byCarry == 0x7E)
909 				return dwLengthOut-1;
910 			else
911 				if (woNb1 > 6)
912 					return 0;
913 				else
914 					if ((!(*pbyBuffIn & 1)) && (byLgCarry == 7))
915 						return dwLengthOut;
916 					else
917 						return 0;
918 		}
919 	}
920 
921 	return dwLengthOut;
922 }
923 
924