1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * isdnhdlc.c -- General purpose ISDN HDLC decoder.
6 * 2009 Karsten Keil <keil@b1-systems.de>
7 * 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
8 * 2001 Frode Isaksen <fisaksen@bewan.com>
9 * 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/crc-ccitt.h>
15 #include <linux/bitrev.h>
18 /*-------------------------------------------------------------------*/
20 MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, "
21 "Frode Isaksen <fisaksen@bewan.com>, "
22 "Kai Germaschewski <kai.germaschewski@gmx.de>");
23 MODULE_DESCRIPTION("General purpose ISDN HDLC decoder");
24 MODULE_LICENSE("GPL");
26 /*-------------------------------------------------------------------*/
29 HDLC_FAST_IDLE
, HDLC_GET_FLAG_B0
, HDLC_GETFLAG_B1A6
, HDLC_GETFLAG_B7
,
30 HDLC_GET_DATA
, HDLC_FAST_FLAG
34 HDLC_SEND_DATA
, HDLC_SEND_CRC1
, HDLC_SEND_FAST_FLAG
,
35 HDLC_SEND_FIRST_FLAG
, HDLC_SEND_CRC2
, HDLC_SEND_CLOSING_FLAG
,
36 HDLC_SEND_IDLE1
, HDLC_SEND_FAST_IDLE
, HDLC_SENDFLAG_B0
,
37 HDLC_SENDFLAG_B1A6
, HDLC_SENDFLAG_B7
, STOPPED
, HDLC_SENDFLAG_ONE
40 void isdnhdlc_rcv_init(struct isdnhdlc_vars
*hdlc
, u32 features
)
42 memset(hdlc
, 0, sizeof(struct isdnhdlc_vars
));
43 hdlc
->state
= HDLC_GET_DATA
;
44 if (features
& HDLC_56KBIT
)
46 if (features
& HDLC_BITREVERSE
)
47 hdlc
->do_bitreverse
= 1;
49 EXPORT_SYMBOL(isdnhdlc_out_init
);
51 void isdnhdlc_out_init(struct isdnhdlc_vars
*hdlc
, u32 features
)
53 memset(hdlc
, 0, sizeof(struct isdnhdlc_vars
));
54 if (features
& HDLC_DCHANNEL
) {
56 hdlc
->state
= HDLC_SEND_FIRST_FLAG
;
59 hdlc
->state
= HDLC_SEND_FAST_FLAG
;
63 if (features
& HDLC_56KBIT
) {
65 hdlc
->state
= HDLC_SENDFLAG_B0
;
68 if (features
& HDLC_BITREVERSE
)
69 hdlc
->do_bitreverse
= 1;
71 EXPORT_SYMBOL(isdnhdlc_rcv_init
);
74 check_frame(struct isdnhdlc_vars
*hdlc
)
78 if (hdlc
->dstpos
< 2) /* too small - framing error */
79 status
= -HDLC_FRAMING_ERROR
;
80 else if (hdlc
->crc
!= 0xf0b8) /* crc error */
81 status
= -HDLC_CRC_ERROR
;
86 status
= hdlc
->dstpos
;
92 isdnhdlc_decode - decodes HDLC frames from a transparent bit stream.
94 The source buffer is scanned for valid HDLC frames looking for
95 flags (01111110) to indicate the start of a frame. If the start of
96 the frame is found, the bit stuffing is removed (0 after 5 1's).
97 When a new flag is found, the complete frame has been received
98 and the CRC is checked.
99 If a valid frame is found, the function returns the frame length
100 excluding the CRC with the bit HDLC_END_OF_FRAME set.
101 If the beginning of a valid frame is found, the function returns
103 If a framing error is found (too many 1s and not a flag) the function
104 returns the length with the bit HDLC_FRAMING_ERROR set.
105 If a CRC error is found the function returns the length with the
106 bit HDLC_CRC_ERROR set.
107 If the frame length exceeds the destination buffer size, the function
108 returns the length with the bit HDLC_LENGTH_ERROR set.
111 slen - source buffer length
112 count - number of bytes removed (decoded) from the source buffer
113 dst _ destination buffer
114 dsize - destination buffer size
115 returns - number of decoded bytes in the destination buffer and status
118 int isdnhdlc_decode(struct isdnhdlc_vars
*hdlc
, const u8
*src
, int slen
,
119 int *count
, u8
*dst
, int dsize
)
123 static const unsigned char fast_flag
[] = {
124 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f
127 static const unsigned char fast_flag_value
[] = {
128 0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f
131 static const unsigned char fast_abort
[] = {
132 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
135 #define handle_fast_flag(h) \
137 if (h->cbin == fast_flag[h->bit_shift]) { \
138 h->ffvalue = fast_flag_value[h->bit_shift]; \
139 h->state = HDLC_FAST_FLAG; \
140 h->ffbit_shift = h->bit_shift; \
143 h->state = HDLC_GET_DATA; \
144 h->data_received = 0; \
148 #define handle_abort(h) \
150 h->shift_reg = fast_abort[h->ffbit_shift - 1]; \
151 h->hdlc_bits1 = h->ffbit_shift - 2; \
152 if (h->hdlc_bits1 < 0) \
154 h->data_bits = h->ffbit_shift - 1; \
155 h->state = HDLC_GET_DATA; \
156 h->data_received = 0; \
162 if (hdlc
->bit_shift
== 0) {
163 /* the code is for bitreverse streams */
164 if (hdlc
->do_bitreverse
== 0)
165 hdlc
->cbin
= bitrev8(*src
++);
170 if (hdlc
->do_adapt56
)
174 switch (hdlc
->state
) {
178 if (hdlc
->cbin
== 0xff) {
182 hdlc
->state
= HDLC_GET_FLAG_B0
;
183 hdlc
->hdlc_bits1
= 0;
186 case HDLC_GET_FLAG_B0
:
187 if (!(hdlc
->cbin
& 0x80)) {
188 hdlc
->state
= HDLC_GETFLAG_B1A6
;
189 hdlc
->hdlc_bits1
= 0;
191 if ((!hdlc
->do_adapt56
) &&
192 (++hdlc
->hdlc_bits1
>= 8) &&
193 (hdlc
->bit_shift
== 1))
194 hdlc
->state
= HDLC_FAST_IDLE
;
199 case HDLC_GETFLAG_B1A6
:
200 if (hdlc
->cbin
& 0x80) {
202 if (hdlc
->hdlc_bits1
== 6)
203 hdlc
->state
= HDLC_GETFLAG_B7
;
205 hdlc
->hdlc_bits1
= 0;
209 case HDLC_GETFLAG_B7
:
210 if (hdlc
->cbin
& 0x80) {
211 hdlc
->state
= HDLC_GET_FLAG_B0
;
213 hdlc
->state
= HDLC_GET_DATA
;
216 hdlc
->hdlc_bits1
= 0;
218 hdlc
->data_received
= 0;
224 if (hdlc
->cbin
& 0x80) {
226 switch (hdlc
->hdlc_bits1
) {
230 if (hdlc
->data_received
)
232 status
= -HDLC_FRAMING_ERROR
;
233 if (!hdlc
->do_adapt56
) {
234 if (hdlc
->cbin
== fast_abort
235 [hdlc
->bit_shift
+ 1]) {
242 hdlc
->state
= HDLC_GET_FLAG_B0
;
245 hdlc
->shift_reg
>>= 1;
246 hdlc
->shift_reg
|= 0x80;
251 switch (hdlc
->hdlc_bits1
) {
255 if (hdlc
->data_received
)
256 status
= check_frame(hdlc
);
260 if (!hdlc
->do_adapt56
)
261 handle_fast_flag(hdlc
);
263 hdlc
->state
= HDLC_GET_DATA
;
264 hdlc
->data_received
= 0;
268 hdlc
->shift_reg
>>= 1;
272 hdlc
->hdlc_bits1
= 0;
281 if (hdlc
->data_bits
== 8) {
283 hdlc
->data_received
= 1;
284 hdlc
->crc
= crc_ccitt_byte(hdlc
->crc
,
287 /* good byte received */
288 if (hdlc
->dstpos
< dsize
)
289 dst
[hdlc
->dstpos
++] = hdlc
->shift_reg
;
292 status
= -HDLC_LENGTH_ERROR
;
300 if (hdlc
->cbin
== hdlc
->ffvalue
) {
304 if (hdlc
->cbin
== 0xff) {
305 hdlc
->state
= HDLC_FAST_IDLE
;
307 } else if (hdlc
->ffbit_shift
== 8) {
308 hdlc
->state
= HDLC_GETFLAG_B7
;
321 EXPORT_SYMBOL(isdnhdlc_decode
);
323 isdnhdlc_encode - encodes HDLC frames to a transparent bit stream.
325 The bit stream starts with a beginning flag (01111110). After
326 that each byte is added to the bit stream with bit stuffing added
328 When the last byte has been removed from the source buffer, the
329 CRC (2 bytes is added) and the frame terminates with the ending flag.
330 For the dchannel, the idle character (all 1's) is also added at the end.
331 If this function is called with empty source buffer (slen=0), flags or
332 idle character will be generated.
335 slen - source buffer length
336 count - number of bytes removed (encoded) from source buffer
337 dst _ destination buffer
338 dsize - destination buffer size
339 returns - number of encoded bytes in the destination buffer
341 int isdnhdlc_encode(struct isdnhdlc_vars
*hdlc
, const u8
*src
, u16 slen
,
342 int *count
, u8
*dst
, int dsize
)
344 static const unsigned char xfast_flag_value
[] = {
345 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e
352 /* special handling for one byte frames */
353 if ((slen
== 1) && (hdlc
->state
== HDLC_SEND_FAST_FLAG
))
354 hdlc
->state
= HDLC_SENDFLAG_ONE
;
356 if (hdlc
->bit_shift
== 0) {
357 if (slen
&& !hdlc
->do_closing
) {
358 hdlc
->shift_reg
= *src
++;
361 /* closing sequence, CRC + flag(s) */
362 hdlc
->do_closing
= 1;
365 if (hdlc
->state
== HDLC_SEND_DATA
) {
366 if (hdlc
->data_received
) {
367 hdlc
->state
= HDLC_SEND_CRC1
;
372 } else if (!hdlc
->do_adapt56
)
383 switch (hdlc
->state
) {
388 case HDLC_SEND_FAST_FLAG
:
389 hdlc
->do_closing
= 0;
391 /* the code is for bitreverse streams */
392 if (hdlc
->do_bitreverse
== 0)
393 *dst
++ = bitrev8(hdlc
->ffvalue
);
395 *dst
++ = hdlc
->ffvalue
;
401 case HDLC_SENDFLAG_ONE
:
402 if (hdlc
->bit_shift
== 8) {
403 hdlc
->cbin
= hdlc
->ffvalue
>>
404 (8 - hdlc
->data_bits
);
405 hdlc
->state
= HDLC_SEND_DATA
;
407 hdlc
->hdlc_bits1
= 0;
408 hdlc
->data_received
= 1;
411 case HDLC_SENDFLAG_B0
:
412 hdlc
->do_closing
= 0;
415 hdlc
->hdlc_bits1
= 0;
416 hdlc
->state
= HDLC_SENDFLAG_B1A6
;
418 case HDLC_SENDFLAG_B1A6
:
422 if (++hdlc
->hdlc_bits1
== 6)
423 hdlc
->state
= HDLC_SENDFLAG_B7
;
425 case HDLC_SENDFLAG_B7
:
429 hdlc
->state
= HDLC_SENDFLAG_B0
;
432 if (hdlc
->bit_shift
== 8) {
433 hdlc
->state
= HDLC_SEND_DATA
;
435 hdlc
->hdlc_bits1
= 0;
436 hdlc
->data_received
= 1;
439 case HDLC_SEND_FIRST_FLAG
:
440 hdlc
->data_received
= 1;
441 if (hdlc
->data_bits
== 8) {
442 hdlc
->state
= HDLC_SEND_DATA
;
444 hdlc
->hdlc_bits1
= 0;
449 if (hdlc
->shift_reg
& 0x01)
451 hdlc
->shift_reg
>>= 1;
453 if (hdlc
->bit_shift
== 0) {
454 hdlc
->state
= HDLC_SEND_DATA
;
456 hdlc
->hdlc_bits1
= 0;
462 if (hdlc
->hdlc_bits1
== 5) {
463 hdlc
->hdlc_bits1
= 0;
466 if (hdlc
->bit_shift
== 8)
467 hdlc
->crc
= crc_ccitt_byte(hdlc
->crc
,
469 if (hdlc
->shift_reg
& 0x01) {
472 hdlc
->shift_reg
>>= 1;
475 hdlc
->hdlc_bits1
= 0;
476 hdlc
->shift_reg
>>= 1;
483 if (hdlc
->hdlc_bits1
== 5) {
484 hdlc
->hdlc_bits1
= 0;
487 if (hdlc
->shift_reg
& 0x01) {
490 hdlc
->shift_reg
>>= 1;
493 hdlc
->hdlc_bits1
= 0;
494 hdlc
->shift_reg
>>= 1;
497 if (hdlc
->bit_shift
== 0) {
498 hdlc
->shift_reg
= (hdlc
->crc
>> 8);
499 hdlc
->state
= HDLC_SEND_CRC2
;
506 if (hdlc
->hdlc_bits1
== 5) {
507 hdlc
->hdlc_bits1
= 0;
510 if (hdlc
->shift_reg
& 0x01) {
513 hdlc
->shift_reg
>>= 1;
516 hdlc
->hdlc_bits1
= 0;
517 hdlc
->shift_reg
>>= 1;
520 if (hdlc
->bit_shift
== 0) {
521 hdlc
->shift_reg
= 0x7e;
522 hdlc
->state
= HDLC_SEND_CLOSING_FLAG
;
526 case HDLC_SEND_CLOSING_FLAG
:
529 if (hdlc
->hdlc_bits1
== 5) {
530 hdlc
->hdlc_bits1
= 0;
533 if (hdlc
->shift_reg
& 0x01)
535 hdlc
->shift_reg
>>= 1;
537 if (hdlc
->bit_shift
== 0) {
539 xfast_flag_value
[hdlc
->data_bits
];
540 if (hdlc
->dchannel
) {
541 hdlc
->ffvalue
= 0x7e;
542 hdlc
->state
= HDLC_SEND_IDLE1
;
543 hdlc
->bit_shift
= 8-hdlc
->data_bits
;
544 if (hdlc
->bit_shift
== 0)
548 if (!hdlc
->do_adapt56
) {
551 hdlc
->data_received
= 0;
553 hdlc
->state
= HDLC_SENDFLAG_B0
;
554 hdlc
->data_received
= 0;
556 /* Finished this frame, send flags */
562 case HDLC_SEND_IDLE1
:
563 hdlc
->do_closing
= 0;
568 if (hdlc
->bit_shift
== 0) {
569 hdlc
->state
= HDLC_SEND_FAST_IDLE
;
573 case HDLC_SEND_FAST_IDLE
:
574 hdlc
->do_closing
= 0;
577 if (hdlc
->bit_shift
== 8) {
579 hdlc
->state
= HDLC_SEND_FIRST_FLAG
;
581 /* the code is for bitreverse streams */
582 if (hdlc
->do_bitreverse
== 0)
583 *dst
++ = bitrev8(hdlc
->cbin
);
595 if (hdlc
->do_adapt56
) {
596 if (hdlc
->data_bits
== 7) {
602 if (hdlc
->data_bits
== 8) {
603 /* the code is for bitreverse streams */
604 if (hdlc
->do_bitreverse
== 0)
605 *dst
++ = bitrev8(hdlc
->cbin
);
617 EXPORT_SYMBOL(isdnhdlc_encode
);