ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / isdn / tpam / tpam_hdlc.c
1 /* $Id: tpam_hdlc.c,v 1.1.2.3 2001/11/06 20:58:30 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  +---------------------------------------------------------------------------*/
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  +---------------------------------------------------------------------------*/
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