2 * Copyright (c) 2000 Hans Petter Selasky. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * i4b_hdlc.h - software-HDLC header file
28 * --------------------------------------
30 * $Id: i4b_hdlc.h,v 1.5 2000/08/28 07:41:19 hm Exp $
32 * $FreeBSD: src/sys/i4b/layer1/i4b_hdlc.h,v 1.4.2.1 2001/08/10 14:08:36 obrien Exp $
33 * $DragonFly: src/sys/net/i4b/layer1/i4b_hdlc.h,v 1.2 2003/06/17 04:28:39 dillon Exp $
35 * last edit-date: [Wed Jul 19 09:41:13 2000]
37 *---------------------------------------------------------------------------*/
42 /*---------------------------------------------------------------------------*
46 * crc = (HDLC_FCS_TAB[(u_char)(crc ^ byte of data)] ^ (u_char)(crc >> 8));
48 * For more information see RFC 1662 (p. 10)
49 *---------------------------------------------------------------------------*/
50 const u_short HDLC_FCS_TAB[256] = { 0x0000,
51 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48,
52 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081,
53 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9,
54 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102,
55 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a,
56 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183,
57 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb,
58 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204,
59 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c,
60 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285,
61 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd,
62 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306,
63 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e,
64 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387,
65 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf,
66 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408,
67 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840,
68 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489,
69 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1,
70 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a,
71 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942,
72 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b,
73 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3,
74 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c,
75 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44,
76 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d,
77 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5,
78 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e,
79 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46,
80 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f,
81 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7,
82 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
85 /*---------------------------------------------------------------------------*
89 * bits[0..3]: A value which tells how many set bits there are at the
90 * beginning of the byte.
92 * bits[4..7]: Special bytes like 0x7e, 0x7d, 0xfd ... are flagged here
93 * NOTE: Special bytes also means 'abort' bytes (7 or more
94 * continuous set bits)
96 * bits[8..11]: A copy of bits[0..3] but only incremented by one.
97 * NOTE: 0x7e has value '8' instead of '0'. Internal reasons.
99 * bits[12..15]: A value which tells how many set bits there are at the
101 * NOTE: 0xff has both '8' incoming and '8' outgoing bits.
103 *---------------------------------------------------------------------------*/
104 const u_short HDLC_BIT_TAB[256] = { 0x0100,
105 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
106 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
107 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
108 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0605, 0x0100,
109 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
110 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
111 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
112 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0160, 0x0706, 0x0100,
113 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
114 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
115 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
116 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0605, 0x0100,
117 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
118 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
119 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
120 0x0201, 0x0100, 0x0302, 0x01a0, 0x02a1, 0x0860, 0x0807, 0x1100,
121 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
122 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1504, 0x1100,
123 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
124 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1605, 0x1100,
125 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
126 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1504, 0x1100,
127 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
128 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1160, 0x1706, 0x2100,
129 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2403, 0x2100,
130 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2504, 0x2100,
131 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2403, 0x2100,
132 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2605, 0x3100,
133 0x3201, 0x3100, 0x3302, 0x3100, 0x3201, 0x3100, 0x3403, 0x3100,
134 0x3201, 0x3100, 0x3302, 0x3100, 0x3201, 0x3100, 0x3504, 0x4100,
135 0x4201, 0x4100, 0x4302, 0x4100, 0x4201, 0x4100, 0x4403, 0x5100,
136 0x5201, 0x5100, 0x5302, 0x6180, 0x6281, 0x7150, 0x8908
139 /*---------------------------------------------------------------------------*
143 * u_char: flag, blevel
144 * u_short: crc, ib, tmp, tmp2, len
146 * next: 'continue' or 'goto xxx'
148 * cfr: complete frame
150 * NOTE: must setup 'len' and 'dst', so that 'dst' may be written
151 * at most 'len' times.
154 * rdd: read data (read byte is stored in 'tmp2')
159 * NOTE: setting flag to '0' and len to '0' => recover from rdu
160 * NOTE: bits[8 .. ] of tmp2 may be used to store custom data/flags
161 * NOTE: these variables have to be 'suspended' / 'resumed' somehow:
162 * flag, blevel, crc, ib, tmp, len
163 * NOTE: zero is default value for all variables.
164 * NOTE: each time 'dst' is written, 'len' is decreased by one.
165 *---------------------------------------------------------------------------*/
167 #define HDLC_DECODE(dst, len, tmp, tmp2, blevel, ib, crc, flag, rddcmd, nfrcmd, \
168 cfrcmd, rabcmd, rdocmd, nextcmd, d) \
172 ib += HDLC_BIT_TAB[(u_char)tmp2]; \
174 if ((u_char)ib >= 5) \
176 if (ib & 0x20) /* de-stuff (msb) */ \
178 if ((u_char)tmp2 == 0x7e) goto j0##d; \
179 tmp2 += tmp2 & 0x7f; \
182 if ((ib += 0x100) & 0xc) tmp2 |= 1; /* */ \
187 if ((u_char)ib == 6) /* flag seq (lsb) */ \
189 j0##d: if (flag >= 2) \
191 len += (4 - flag) & 3; /* remove CRC bytes */ \
199 blevel = (ib >> 8) & 0xf; \
200 tmp = ((u_char)tmp2) >> blevel; \
201 blevel = 8 - blevel; \
207 if ((u_char)ib >= 7) /* abort (msb & lsb) */ \
221 if ((u_char)ib == 5) /* de-stuff (lsb) */ \
223 tmp2 = (tmp2 | (tmp2 + 1)) & ~0x1; \
226 if (blevel > 7) /* EO - bits */ \
228 tmp |= (u_char)tmp2 >> (8 - (blevel &= 7)); \
236 tmp |= (u_char)tmp2 << blevel; \
242 if (!flag++) { flag--; goto j5##d;} /* hunt mode */ \
245 { case 2: /* new frame */ \
248 if (!len--) { len++; flag++; goto j4##d; } \
250 case 3: /* CRC (lsb's) */ \
251 case 4: /* CRC (msb's) */ \
261 j3##d: dst = (u_char)tmp; \
262 j4##d: crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8)); \
268 /*------ end of HDLC_DECODE -------------------------------------------------*/
271 /*---------------------------------------------------------------------------*
276 * u_short: tmp2, blevel, ib, crc, len
279 * gfr: This is the place where you free the last [mbuf] chain, and get
280 * the next one. If a mbuf is available the code should setup 'len'
281 * and 'src' so that 'src' may be read 'len' times. If no mbuf is
282 * available leave 'len' and 'src' untouched.
284 * wrd: write data (output = (u_char)tmp)
288 * NOTE: setting flag to '-2' and len to '0' => abort bytes will be sent
289 * NOTE: these variables have to be 'suspended' / 'resumed' somehow:
290 * flag, blevel, crc, ib, tmp, len
291 * NOTE: zero is default value for all variables.
292 * NOTE: each time 'src' is read, 'len' is decreased by one.
293 * NOTE: neither cmd's should exit through 'goto' or 'break' statements.
294 *---------------------------------------------------------------------------*/
296 #define HDLC_ENCODE(src, len, tmp, tmp2, blevel, ib, crc, flag, gfrcmd, wrdcmd, d) \
298 if (blevel >= 0x800) { blevel -= 0x800; goto j4##d; } \
305 { default: /* abort */ \
306 tmp = blevel = 0; /* zero is default */ \
309 case 1: /* 1st time FS */ \
310 case 2: /* 2nd time FS */ \
314 gfrcmd; /* get new frame */ \
318 flag--; /* don't proceed */ \
320 goto j3##d; /* final FS */ \
326 goto j1##d; /* first byte */ \
330 tmp2 = (u_char)crc; \
331 goto j2##d; /* CRC (lsb's) */ \
333 tmp2 = (u_char)(crc >> 8); \
335 goto j2##d; /* CRC (msb's) */ \
340 tmp2 = (u_char)src; \
341 crc =(HDLC_FCS_TAB[(u_char)(crc ^ tmp2)] ^ (u_char)(crc >> 8)); \
345 ib += HDLC_BIT_TAB[(u_char)tmp2]; \
347 if ((u_char)ib >= 5) /* stuffing */ \
351 if (ib & 0xc0) /* bit stuff (msb) */ \
353 tmp2 += tmp2 & (0xff * (ib & 0xc0)); \
360 if ((u_char)ib >= 5) /* bit stuff (lsb) */ \
362 tmp2 += tmp2 & ~0x1f >> ((ib - (ib >> 8) + 1) \
366 if ((u_char)ib >= 10) /* bit stuff (msb) */ \
368 tmp2 += tmp2 & ~0x7ff >> ((ib - \
369 (ib >> 8) + 1) & 7); \
372 if (ib & 0x8000) /* bit walk */ \
374 ib = ((u_char)ib % 5) << 12; \
378 tmp |= tmp2 << (u_char)(blevel >> 8); \
379 blevel += (u_char)blevel << 8; \
381 else /* no stuffing */ \
383 j3##d:tmp |= tmp2 << (u_char)(blevel >> 8); \
390 /*------ end of HDLC_ENCODE -------------------------------------------------*/
393 #endif /* _I4B_HDLC_H_ */