2 * isdnhdlc.c -- General purpose ISDN HDLC decoder.
5 * 2009 Karsten Keil <keil@b1-systems.de>
6 * 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
7 * 2001 Frode Isaksen <fisaksen@bewan.com>
8 * 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <linux/module.h>
26 #include <linux/init.h>
27 #include <linux/crc-ccitt.h>
28 #include <linux/isdn/hdlc.h>
29 #include <linux/bitrev.h>
31 /*-------------------------------------------------------------------*/
33 MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, "
34 "Frode Isaksen <fisaksen@bewan.com>, "
35 "Kai Germaschewski <kai.germaschewski@gmx.de>");
36 MODULE_DESCRIPTION("General purpose ISDN HDLC decoder");
37 MODULE_LICENSE("GPL");
39 /*-------------------------------------------------------------------*/
42 HDLC_FAST_IDLE
, HDLC_GET_FLAG_B0
, HDLC_GETFLAG_B1A6
, HDLC_GETFLAG_B7
,
43 HDLC_GET_DATA
, HDLC_FAST_FLAG
47 HDLC_SEND_DATA
, HDLC_SEND_CRC1
, HDLC_SEND_FAST_FLAG
,
48 HDLC_SEND_FIRST_FLAG
, HDLC_SEND_CRC2
, HDLC_SEND_CLOSING_FLAG
,
49 HDLC_SEND_IDLE1
, HDLC_SEND_FAST_IDLE
, HDLC_SENDFLAG_B0
,
50 HDLC_SENDFLAG_B1A6
, HDLC_SENDFLAG_B7
, STOPPED
, HDLC_SENDFLAG_ONE
53 void isdnhdlc_rcv_init(struct isdnhdlc_vars
*hdlc
, u32 features
)
55 memset(hdlc
, 0, sizeof(struct isdnhdlc_vars
));
56 hdlc
->state
= HDLC_GET_DATA
;
57 if (features
& HDLC_56KBIT
)
59 if (features
& HDLC_BITREVERSE
)
60 hdlc
->do_bitreverse
= 1;
62 EXPORT_SYMBOL(isdnhdlc_out_init
);
64 void isdnhdlc_out_init(struct isdnhdlc_vars
*hdlc
, u32 features
)
66 memset(hdlc
, 0, sizeof(struct isdnhdlc_vars
));
67 if (features
& HDLC_DCHANNEL
) {
69 hdlc
->state
= HDLC_SEND_FIRST_FLAG
;
72 hdlc
->state
= HDLC_SEND_FAST_FLAG
;
76 if (features
& HDLC_56KBIT
) {
78 hdlc
->state
= HDLC_SENDFLAG_B0
;
81 if (features
& HDLC_BITREVERSE
)
82 hdlc
->do_bitreverse
= 1;
84 EXPORT_SYMBOL(isdnhdlc_rcv_init
);
87 check_frame(struct isdnhdlc_vars
*hdlc
)
91 if (hdlc
->dstpos
< 2) /* too small - framing error */
92 status
= -HDLC_FRAMING_ERROR
;
93 else if (hdlc
->crc
!= 0xf0b8) /* crc error */
94 status
= -HDLC_CRC_ERROR
;
99 status
= hdlc
->dstpos
;
105 isdnhdlc_decode - decodes HDLC frames from a transparent bit stream.
107 The source buffer is scanned for valid HDLC frames looking for
108 flags (01111110) to indicate the start of a frame. If the start of
109 the frame is found, the bit stuffing is removed (0 after 5 1's).
110 When a new flag is found, the complete frame has been received
111 and the CRC is checked.
112 If a valid frame is found, the function returns the frame length
113 excluding the CRC with the bit HDLC_END_OF_FRAME set.
114 If the beginning of a valid frame is found, the function returns
116 If a framing error is found (too many 1s and not a flag) the function
117 returns the length with the bit HDLC_FRAMING_ERROR set.
118 If a CRC error is found the function returns the length with the
119 bit HDLC_CRC_ERROR set.
120 If the frame length exceeds the destination buffer size, the function
121 returns the length with the bit HDLC_LENGTH_ERROR set.
124 slen - source buffer length
125 count - number of bytes removed (decoded) from the source buffer
126 dst _ destination buffer
127 dsize - destination buffer size
128 returns - number of decoded bytes in the destination buffer and status
131 int isdnhdlc_decode(struct isdnhdlc_vars
*hdlc
, const u8
*src
, int slen
,
132 int *count
, u8
*dst
, int dsize
)
136 static const unsigned char fast_flag
[] = {
137 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f
140 static const unsigned char fast_flag_value
[] = {
141 0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f
144 static const unsigned char fast_abort
[] = {
145 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
148 #define handle_fast_flag(h) \
150 if (h->cbin == fast_flag[h->bit_shift]) {\
151 h->ffvalue = fast_flag_value[h->bit_shift];\
152 h->state = HDLC_FAST_FLAG;\
153 h->ffbit_shift = h->bit_shift;\
156 h->state = HDLC_GET_DATA;\
157 h->data_received = 0;\
161 #define handle_abort(h) \
163 h->shift_reg = fast_abort[h->ffbit_shift - 1];\
164 h->hdlc_bits1 = h->ffbit_shift - 2;\
165 if (h->hdlc_bits1 < 0)\
167 h->data_bits = h->ffbit_shift - 1;\
168 h->state = HDLC_GET_DATA;\
169 h->data_received = 0;\
175 if (hdlc
->bit_shift
== 0) {
176 /* the code is for bitreverse streams */
177 if (hdlc
->do_bitreverse
== 0)
178 hdlc
->cbin
= bitrev8(*src
++);
183 if (hdlc
->do_adapt56
)
187 switch (hdlc
->state
) {
191 if (hdlc
->cbin
== 0xff) {
195 hdlc
->state
= HDLC_GET_FLAG_B0
;
196 hdlc
->hdlc_bits1
= 0;
199 case HDLC_GET_FLAG_B0
:
200 if (!(hdlc
->cbin
& 0x80)) {
201 hdlc
->state
= HDLC_GETFLAG_B1A6
;
202 hdlc
->hdlc_bits1
= 0;
204 if ((!hdlc
->do_adapt56
) &&
205 (++hdlc
->hdlc_bits1
>= 8) &&
206 (hdlc
->bit_shift
== 1))
207 hdlc
->state
= HDLC_FAST_IDLE
;
212 case HDLC_GETFLAG_B1A6
:
213 if (hdlc
->cbin
& 0x80) {
215 if (hdlc
->hdlc_bits1
== 6)
216 hdlc
->state
= HDLC_GETFLAG_B7
;
218 hdlc
->hdlc_bits1
= 0;
222 case HDLC_GETFLAG_B7
:
223 if (hdlc
->cbin
& 0x80) {
224 hdlc
->state
= HDLC_GET_FLAG_B0
;
226 hdlc
->state
= HDLC_GET_DATA
;
229 hdlc
->hdlc_bits1
= 0;
231 hdlc
->data_received
= 0;
237 if (hdlc
->cbin
& 0x80) {
239 switch (hdlc
->hdlc_bits1
) {
243 if (hdlc
->data_received
)
245 status
= -HDLC_FRAMING_ERROR
;
246 if (!hdlc
->do_adapt56
) {
247 if (hdlc
->cbin
== fast_abort
248 [hdlc
->bit_shift
+ 1]) {
255 hdlc
->state
= HDLC_GET_FLAG_B0
;
258 hdlc
->shift_reg
>>= 1;
259 hdlc
->shift_reg
|= 0x80;
264 switch (hdlc
->hdlc_bits1
) {
268 if (hdlc
->data_received
)
269 status
= check_frame(hdlc
);
273 if (!hdlc
->do_adapt56
)
274 handle_fast_flag(hdlc
);
276 hdlc
->state
= HDLC_GET_DATA
;
277 hdlc
->data_received
= 0;
281 hdlc
->shift_reg
>>= 1;
285 hdlc
->hdlc_bits1
= 0;
294 if (hdlc
->data_bits
== 8) {
296 hdlc
->data_received
= 1;
297 hdlc
->crc
= crc_ccitt_byte(hdlc
->crc
,
300 /* good byte received */
301 if (hdlc
->dstpos
< dsize
)
302 dst
[hdlc
->dstpos
++] = hdlc
->shift_reg
;
305 status
= -HDLC_LENGTH_ERROR
;
313 if (hdlc
->cbin
== hdlc
->ffvalue
) {
317 if (hdlc
->cbin
== 0xff) {
318 hdlc
->state
= HDLC_FAST_IDLE
;
320 } else if (hdlc
->ffbit_shift
== 8) {
321 hdlc
->state
= HDLC_GETFLAG_B7
;
334 EXPORT_SYMBOL(isdnhdlc_decode
);
336 isdnhdlc_encode - encodes HDLC frames to a transparent bit stream.
338 The bit stream starts with a beginning flag (01111110). After
339 that each byte is added to the bit stream with bit stuffing added
341 When the last byte has been removed from the source buffer, the
342 CRC (2 bytes is added) and the frame terminates with the ending flag.
343 For the dchannel, the idle character (all 1's) is also added at the end.
344 If this function is called with empty source buffer (slen=0), flags or
345 idle character will be generated.
348 slen - source buffer length
349 count - number of bytes removed (encoded) from source buffer
350 dst _ destination buffer
351 dsize - destination buffer size
352 returns - number of encoded bytes in the destination buffer
354 int isdnhdlc_encode(struct isdnhdlc_vars
*hdlc
, const u8
*src
, u16 slen
,
355 int *count
, u8
*dst
, int dsize
)
357 static const unsigned char xfast_flag_value
[] = {
358 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e
365 /* special handling for one byte frames */
366 if ((slen
== 1) && (hdlc
->state
== HDLC_SEND_FAST_FLAG
))
367 hdlc
->state
= HDLC_SENDFLAG_ONE
;
369 if (hdlc
->bit_shift
== 0) {
370 if (slen
&& !hdlc
->do_closing
) {
371 hdlc
->shift_reg
= *src
++;
374 /* closing sequence, CRC + flag(s) */
375 hdlc
->do_closing
= 1;
378 if (hdlc
->state
== HDLC_SEND_DATA
) {
379 if (hdlc
->data_received
) {
380 hdlc
->state
= HDLC_SEND_CRC1
;
385 } else if (!hdlc
->do_adapt56
)
396 switch (hdlc
->state
) {
401 case HDLC_SEND_FAST_FLAG
:
402 hdlc
->do_closing
= 0;
404 /* the code is for bitreverse streams */
405 if (hdlc
->do_bitreverse
== 0)
406 *dst
++ = bitrev8(hdlc
->ffvalue
);
408 *dst
++ = hdlc
->ffvalue
;
414 case HDLC_SENDFLAG_ONE
:
415 if (hdlc
->bit_shift
== 8) {
416 hdlc
->cbin
= hdlc
->ffvalue
>>
417 (8 - hdlc
->data_bits
);
418 hdlc
->state
= HDLC_SEND_DATA
;
420 hdlc
->hdlc_bits1
= 0;
421 hdlc
->data_received
= 1;
424 case HDLC_SENDFLAG_B0
:
425 hdlc
->do_closing
= 0;
428 hdlc
->hdlc_bits1
= 0;
429 hdlc
->state
= HDLC_SENDFLAG_B1A6
;
431 case HDLC_SENDFLAG_B1A6
:
435 if (++hdlc
->hdlc_bits1
== 6)
436 hdlc
->state
= HDLC_SENDFLAG_B7
;
438 case HDLC_SENDFLAG_B7
:
442 hdlc
->state
= HDLC_SENDFLAG_B0
;
445 if (hdlc
->bit_shift
== 8) {
446 hdlc
->state
= HDLC_SEND_DATA
;
448 hdlc
->hdlc_bits1
= 0;
449 hdlc
->data_received
= 1;
452 case HDLC_SEND_FIRST_FLAG
:
453 hdlc
->data_received
= 1;
454 if (hdlc
->data_bits
== 8) {
455 hdlc
->state
= HDLC_SEND_DATA
;
457 hdlc
->hdlc_bits1
= 0;
462 if (hdlc
->shift_reg
& 0x01)
464 hdlc
->shift_reg
>>= 1;
466 if (hdlc
->bit_shift
== 0) {
467 hdlc
->state
= HDLC_SEND_DATA
;
469 hdlc
->hdlc_bits1
= 0;
475 if (hdlc
->hdlc_bits1
== 5) {
476 hdlc
->hdlc_bits1
= 0;
479 if (hdlc
->bit_shift
== 8)
480 hdlc
->crc
= crc_ccitt_byte(hdlc
->crc
,
482 if (hdlc
->shift_reg
& 0x01) {
485 hdlc
->shift_reg
>>= 1;
488 hdlc
->hdlc_bits1
= 0;
489 hdlc
->shift_reg
>>= 1;
496 if (hdlc
->hdlc_bits1
== 5) {
497 hdlc
->hdlc_bits1
= 0;
500 if (hdlc
->shift_reg
& 0x01) {
503 hdlc
->shift_reg
>>= 1;
506 hdlc
->hdlc_bits1
= 0;
507 hdlc
->shift_reg
>>= 1;
510 if (hdlc
->bit_shift
== 0) {
511 hdlc
->shift_reg
= (hdlc
->crc
>> 8);
512 hdlc
->state
= HDLC_SEND_CRC2
;
519 if (hdlc
->hdlc_bits1
== 5) {
520 hdlc
->hdlc_bits1
= 0;
523 if (hdlc
->shift_reg
& 0x01) {
526 hdlc
->shift_reg
>>= 1;
529 hdlc
->hdlc_bits1
= 0;
530 hdlc
->shift_reg
>>= 1;
533 if (hdlc
->bit_shift
== 0) {
534 hdlc
->shift_reg
= 0x7e;
535 hdlc
->state
= HDLC_SEND_CLOSING_FLAG
;
539 case HDLC_SEND_CLOSING_FLAG
:
542 if (hdlc
->hdlc_bits1
== 5) {
543 hdlc
->hdlc_bits1
= 0;
546 if (hdlc
->shift_reg
& 0x01)
548 hdlc
->shift_reg
>>= 1;
550 if (hdlc
->bit_shift
== 0) {
552 xfast_flag_value
[hdlc
->data_bits
];
553 if (hdlc
->dchannel
) {
554 hdlc
->ffvalue
= 0x7e;
555 hdlc
->state
= HDLC_SEND_IDLE1
;
556 hdlc
->bit_shift
= 8-hdlc
->data_bits
;
557 if (hdlc
->bit_shift
== 0)
561 if (!hdlc
->do_adapt56
) {
564 hdlc
->data_received
= 0;
566 hdlc
->state
= HDLC_SENDFLAG_B0
;
567 hdlc
->data_received
= 0;
569 /* Finished this frame, send flags */
575 case HDLC_SEND_IDLE1
:
576 hdlc
->do_closing
= 0;
581 if (hdlc
->bit_shift
== 0) {
582 hdlc
->state
= HDLC_SEND_FAST_IDLE
;
586 case HDLC_SEND_FAST_IDLE
:
587 hdlc
->do_closing
= 0;
590 if (hdlc
->bit_shift
== 8) {
592 hdlc
->state
= HDLC_SEND_FIRST_FLAG
;
594 /* the code is for bitreverse streams */
595 if (hdlc
->do_bitreverse
== 0)
596 *dst
++ = bitrev8(hdlc
->cbin
);
608 if (hdlc
->do_adapt56
) {
609 if (hdlc
->data_bits
== 7) {
615 if (hdlc
->data_bits
== 8) {
616 /* the code is for bitreverse streams */
617 if (hdlc
->do_bitreverse
== 0)
618 *dst
++ = bitrev8(hdlc
->cbin
);
630 EXPORT_SYMBOL(isdnhdlc_encode
);