• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * isdnhdlc.c  --  General purpose ISDN HDLC decoder.
4  *
5  * Copyright (C)
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>
10  */
11 
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/crc-ccitt.h>
15 #include <linux/bitrev.h>
16 #include "isdnhdlc.h"
17 
18 /*-------------------------------------------------------------------*/
19 
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");
25 
26 /*-------------------------------------------------------------------*/
27 
28 enum {
29 	HDLC_FAST_IDLE, HDLC_GET_FLAG_B0, HDLC_GETFLAG_B1A6, HDLC_GETFLAG_B7,
30 	HDLC_GET_DATA, HDLC_FAST_FLAG
31 };
32 
33 enum {
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
38 };
39 
isdnhdlc_rcv_init(struct isdnhdlc_vars * hdlc,u32 features)40 void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, u32 features)
41 {
42 	memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
43 	hdlc->state = HDLC_GET_DATA;
44 	if (features & HDLC_56KBIT)
45 		hdlc->do_adapt56 = 1;
46 	if (features & HDLC_BITREVERSE)
47 		hdlc->do_bitreverse = 1;
48 }
49 EXPORT_SYMBOL(isdnhdlc_out_init);
50 
isdnhdlc_out_init(struct isdnhdlc_vars * hdlc,u32 features)51 void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, u32 features)
52 {
53 	memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
54 	if (features & HDLC_DCHANNEL) {
55 		hdlc->dchannel = 1;
56 		hdlc->state = HDLC_SEND_FIRST_FLAG;
57 	} else {
58 		hdlc->dchannel = 0;
59 		hdlc->state = HDLC_SEND_FAST_FLAG;
60 		hdlc->ffvalue = 0x7e;
61 	}
62 	hdlc->cbin = 0x7e;
63 	if (features & HDLC_56KBIT) {
64 		hdlc->do_adapt56 = 1;
65 		hdlc->state = HDLC_SENDFLAG_B0;
66 	} else
67 		hdlc->data_bits = 8;
68 	if (features & HDLC_BITREVERSE)
69 		hdlc->do_bitreverse = 1;
70 }
71 EXPORT_SYMBOL(isdnhdlc_rcv_init);
72 
73 static int
check_frame(struct isdnhdlc_vars * hdlc)74 check_frame(struct isdnhdlc_vars *hdlc)
75 {
76 	int status;
77 
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;
82 	else {
83 		/* remove CRC */
84 		hdlc->dstpos -= 2;
85 		/* good frame */
86 		status = hdlc->dstpos;
87 	}
88 	return status;
89 }
90 
91 /*
92   isdnhdlc_decode - decodes HDLC frames from a transparent bit stream.
93 
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
102   the length.
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.
109 
110   src - source buffer
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
116   flag.
117 */
isdnhdlc_decode(struct isdnhdlc_vars * hdlc,const u8 * src,int slen,int * count,u8 * dst,int dsize)118 int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen,
119 		    int *count, u8 *dst, int dsize)
120 {
121 	int status = 0;
122 
123 	static const unsigned char fast_flag[] = {
124 		0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f
125 	};
126 
127 	static const unsigned char fast_flag_value[] = {
128 		0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f
129 	};
130 
131 	static const unsigned char fast_abort[] = {
132 		0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
133 	};
134 
135 #define handle_fast_flag(h)						\
136 	do {								\
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;			\
141 			h->bit_shift = 1;				\
142 		} else {						\
143 			h->state = HDLC_GET_DATA;			\
144 			h->data_received = 0;				\
145 		}							\
146 	} while (0)
147 
148 #define handle_abort(h)						\
149 	do {							\
150 		h->shift_reg = fast_abort[h->ffbit_shift - 1];	\
151 		h->hdlc_bits1 = h->ffbit_shift - 2;		\
152 		if (h->hdlc_bits1 < 0)				\
153 			h->hdlc_bits1 = 0;			\
154 		h->data_bits = h->ffbit_shift - 1;		\
155 		h->state = HDLC_GET_DATA;			\
156 		h->data_received = 0;				\
157 	} while (0)
158 
159 	*count = slen;
160 
161 	while (slen > 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++);
166 			else
167 				hdlc->cbin = *src++;
168 			slen--;
169 			hdlc->bit_shift = 8;
170 			if (hdlc->do_adapt56)
171 				hdlc->bit_shift--;
172 		}
173 
174 		switch (hdlc->state) {
175 		case STOPPED:
176 			return 0;
177 		case HDLC_FAST_IDLE:
178 			if (hdlc->cbin == 0xff) {
179 				hdlc->bit_shift = 0;
180 				break;
181 			}
182 			hdlc->state = HDLC_GET_FLAG_B0;
183 			hdlc->hdlc_bits1 = 0;
184 			hdlc->bit_shift = 8;
185 			break;
186 		case HDLC_GET_FLAG_B0:
187 			if (!(hdlc->cbin & 0x80)) {
188 				hdlc->state = HDLC_GETFLAG_B1A6;
189 				hdlc->hdlc_bits1 = 0;
190 			} else {
191 				if ((!hdlc->do_adapt56) &&
192 				    (++hdlc->hdlc_bits1 >= 8) &&
193 				    (hdlc->bit_shift == 1))
194 					hdlc->state = HDLC_FAST_IDLE;
195 			}
196 			hdlc->cbin <<= 1;
197 			hdlc->bit_shift--;
198 			break;
199 		case HDLC_GETFLAG_B1A6:
200 			if (hdlc->cbin & 0x80) {
201 				hdlc->hdlc_bits1++;
202 				if (hdlc->hdlc_bits1 == 6)
203 					hdlc->state = HDLC_GETFLAG_B7;
204 			} else
205 				hdlc->hdlc_bits1 = 0;
206 			hdlc->cbin <<= 1;
207 			hdlc->bit_shift--;
208 			break;
209 		case HDLC_GETFLAG_B7:
210 			if (hdlc->cbin & 0x80) {
211 				hdlc->state = HDLC_GET_FLAG_B0;
212 			} else {
213 				hdlc->state = HDLC_GET_DATA;
214 				hdlc->crc = 0xffff;
215 				hdlc->shift_reg = 0;
216 				hdlc->hdlc_bits1 = 0;
217 				hdlc->data_bits = 0;
218 				hdlc->data_received = 0;
219 			}
220 			hdlc->cbin <<= 1;
221 			hdlc->bit_shift--;
222 			break;
223 		case HDLC_GET_DATA:
224 			if (hdlc->cbin & 0x80) {
225 				hdlc->hdlc_bits1++;
226 				switch (hdlc->hdlc_bits1) {
227 				case 6:
228 					break;
229 				case 7:
230 					if (hdlc->data_received)
231 						/* bad frame */
232 						status = -HDLC_FRAMING_ERROR;
233 					if (!hdlc->do_adapt56) {
234 						if (hdlc->cbin == fast_abort
235 						    [hdlc->bit_shift + 1]) {
236 							hdlc->state =
237 								HDLC_FAST_IDLE;
238 							hdlc->bit_shift = 1;
239 							break;
240 						}
241 					} else
242 						hdlc->state = HDLC_GET_FLAG_B0;
243 					break;
244 				default:
245 					hdlc->shift_reg >>= 1;
246 					hdlc->shift_reg |= 0x80;
247 					hdlc->data_bits++;
248 					break;
249 				}
250 			} else {
251 				switch (hdlc->hdlc_bits1) {
252 				case 5:
253 					break;
254 				case 6:
255 					if (hdlc->data_received)
256 						status = check_frame(hdlc);
257 					hdlc->crc = 0xffff;
258 					hdlc->shift_reg = 0;
259 					hdlc->data_bits = 0;
260 					if (!hdlc->do_adapt56)
261 						handle_fast_flag(hdlc);
262 					else {
263 						hdlc->state = HDLC_GET_DATA;
264 						hdlc->data_received = 0;
265 					}
266 					break;
267 				default:
268 					hdlc->shift_reg >>= 1;
269 					hdlc->data_bits++;
270 					break;
271 				}
272 				hdlc->hdlc_bits1 = 0;
273 			}
274 			if (status) {
275 				hdlc->dstpos = 0;
276 				*count -= slen;
277 				hdlc->cbin <<= 1;
278 				hdlc->bit_shift--;
279 				return status;
280 			}
281 			if (hdlc->data_bits == 8) {
282 				hdlc->data_bits = 0;
283 				hdlc->data_received = 1;
284 				hdlc->crc = crc_ccitt_byte(hdlc->crc,
285 							   hdlc->shift_reg);
286 
287 				/* good byte received */
288 				if (hdlc->dstpos < dsize)
289 					dst[hdlc->dstpos++] = hdlc->shift_reg;
290 				else {
291 					/* frame too long */
292 					status = -HDLC_LENGTH_ERROR;
293 					hdlc->dstpos = 0;
294 				}
295 			}
296 			hdlc->cbin <<= 1;
297 			hdlc->bit_shift--;
298 			break;
299 		case HDLC_FAST_FLAG:
300 			if (hdlc->cbin == hdlc->ffvalue) {
301 				hdlc->bit_shift = 0;
302 				break;
303 			} else {
304 				if (hdlc->cbin == 0xff) {
305 					hdlc->state = HDLC_FAST_IDLE;
306 					hdlc->bit_shift = 0;
307 				} else if (hdlc->ffbit_shift == 8) {
308 					hdlc->state = HDLC_GETFLAG_B7;
309 					break;
310 				} else
311 					handle_abort(hdlc);
312 			}
313 			break;
314 		default:
315 			break;
316 		}
317 	}
318 	*count -= slen;
319 	return 0;
320 }
321 EXPORT_SYMBOL(isdnhdlc_decode);
322 /*
323   isdnhdlc_encode - encodes HDLC frames to a transparent bit stream.
324 
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
327   (0 after 5 1's).
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.
333 
334   src - source buffer
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
340 */
isdnhdlc_encode(struct isdnhdlc_vars * hdlc,const u8 * src,u16 slen,int * count,u8 * dst,int dsize)341 int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen,
342 		    int *count, u8 *dst, int dsize)
343 {
344 	static const unsigned char xfast_flag_value[] = {
345 		0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e
346 	};
347 
348 	int len = 0;
349 
350 	*count = slen;
351 
352 	/* special handling for one byte frames */
353 	if ((slen == 1) && (hdlc->state == HDLC_SEND_FAST_FLAG))
354 		hdlc->state = HDLC_SENDFLAG_ONE;
355 	while (dsize > 0) {
356 		if (hdlc->bit_shift == 0) {
357 			if (slen && !hdlc->do_closing) {
358 				hdlc->shift_reg = *src++;
359 				slen--;
360 				if (slen == 0)
361 					/* closing sequence, CRC + flag(s) */
362 					hdlc->do_closing = 1;
363 				hdlc->bit_shift = 8;
364 			} else {
365 				if (hdlc->state == HDLC_SEND_DATA) {
366 					if (hdlc->data_received) {
367 						hdlc->state = HDLC_SEND_CRC1;
368 						hdlc->crc ^= 0xffff;
369 						hdlc->bit_shift = 8;
370 						hdlc->shift_reg =
371 							hdlc->crc & 0xff;
372 					} else if (!hdlc->do_adapt56)
373 						hdlc->state =
374 							HDLC_SEND_FAST_FLAG;
375 					else
376 						hdlc->state =
377 							HDLC_SENDFLAG_B0;
378 				}
379 
380 			}
381 		}
382 
383 		switch (hdlc->state) {
384 		case STOPPED:
385 			while (dsize--)
386 				*dst++ = 0xff;
387 			return dsize;
388 		case HDLC_SEND_FAST_FLAG:
389 			hdlc->do_closing = 0;
390 			if (slen == 0) {
391 				/* the code is for bitreverse streams */
392 				if (hdlc->do_bitreverse == 0)
393 					*dst++ = bitrev8(hdlc->ffvalue);
394 				else
395 					*dst++ = hdlc->ffvalue;
396 				len++;
397 				dsize--;
398 				break;
399 			}
400 			fallthrough;
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;
406 				hdlc->crc = 0xffff;
407 				hdlc->hdlc_bits1 = 0;
408 				hdlc->data_received = 1;
409 			}
410 			break;
411 		case HDLC_SENDFLAG_B0:
412 			hdlc->do_closing = 0;
413 			hdlc->cbin <<= 1;
414 			hdlc->data_bits++;
415 			hdlc->hdlc_bits1 = 0;
416 			hdlc->state = HDLC_SENDFLAG_B1A6;
417 			break;
418 		case HDLC_SENDFLAG_B1A6:
419 			hdlc->cbin <<= 1;
420 			hdlc->data_bits++;
421 			hdlc->cbin++;
422 			if (++hdlc->hdlc_bits1 == 6)
423 				hdlc->state = HDLC_SENDFLAG_B7;
424 			break;
425 		case HDLC_SENDFLAG_B7:
426 			hdlc->cbin <<= 1;
427 			hdlc->data_bits++;
428 			if (slen == 0) {
429 				hdlc->state = HDLC_SENDFLAG_B0;
430 				break;
431 			}
432 			if (hdlc->bit_shift == 8) {
433 				hdlc->state = HDLC_SEND_DATA;
434 				hdlc->crc = 0xffff;
435 				hdlc->hdlc_bits1 = 0;
436 				hdlc->data_received = 1;
437 			}
438 			break;
439 		case HDLC_SEND_FIRST_FLAG:
440 			hdlc->data_received = 1;
441 			if (hdlc->data_bits == 8) {
442 				hdlc->state = HDLC_SEND_DATA;
443 				hdlc->crc = 0xffff;
444 				hdlc->hdlc_bits1 = 0;
445 				break;
446 			}
447 			hdlc->cbin <<= 1;
448 			hdlc->data_bits++;
449 			if (hdlc->shift_reg & 0x01)
450 				hdlc->cbin++;
451 			hdlc->shift_reg >>= 1;
452 			hdlc->bit_shift--;
453 			if (hdlc->bit_shift == 0) {
454 				hdlc->state = HDLC_SEND_DATA;
455 				hdlc->crc = 0xffff;
456 				hdlc->hdlc_bits1 = 0;
457 			}
458 			break;
459 		case HDLC_SEND_DATA:
460 			hdlc->cbin <<= 1;
461 			hdlc->data_bits++;
462 			if (hdlc->hdlc_bits1 == 5) {
463 				hdlc->hdlc_bits1 = 0;
464 				break;
465 			}
466 			if (hdlc->bit_shift == 8)
467 				hdlc->crc = crc_ccitt_byte(hdlc->crc,
468 							   hdlc->shift_reg);
469 			if (hdlc->shift_reg & 0x01) {
470 				hdlc->hdlc_bits1++;
471 				hdlc->cbin++;
472 				hdlc->shift_reg >>= 1;
473 				hdlc->bit_shift--;
474 			} else {
475 				hdlc->hdlc_bits1 = 0;
476 				hdlc->shift_reg >>= 1;
477 				hdlc->bit_shift--;
478 			}
479 			break;
480 		case HDLC_SEND_CRC1:
481 			hdlc->cbin <<= 1;
482 			hdlc->data_bits++;
483 			if (hdlc->hdlc_bits1 == 5) {
484 				hdlc->hdlc_bits1 = 0;
485 				break;
486 			}
487 			if (hdlc->shift_reg & 0x01) {
488 				hdlc->hdlc_bits1++;
489 				hdlc->cbin++;
490 				hdlc->shift_reg >>= 1;
491 				hdlc->bit_shift--;
492 			} else {
493 				hdlc->hdlc_bits1 = 0;
494 				hdlc->shift_reg >>= 1;
495 				hdlc->bit_shift--;
496 			}
497 			if (hdlc->bit_shift == 0) {
498 				hdlc->shift_reg = (hdlc->crc >> 8);
499 				hdlc->state = HDLC_SEND_CRC2;
500 				hdlc->bit_shift = 8;
501 			}
502 			break;
503 		case HDLC_SEND_CRC2:
504 			hdlc->cbin <<= 1;
505 			hdlc->data_bits++;
506 			if (hdlc->hdlc_bits1 == 5) {
507 				hdlc->hdlc_bits1 = 0;
508 				break;
509 			}
510 			if (hdlc->shift_reg & 0x01) {
511 				hdlc->hdlc_bits1++;
512 				hdlc->cbin++;
513 				hdlc->shift_reg >>= 1;
514 				hdlc->bit_shift--;
515 			} else {
516 				hdlc->hdlc_bits1 = 0;
517 				hdlc->shift_reg >>= 1;
518 				hdlc->bit_shift--;
519 			}
520 			if (hdlc->bit_shift == 0) {
521 				hdlc->shift_reg = 0x7e;
522 				hdlc->state = HDLC_SEND_CLOSING_FLAG;
523 				hdlc->bit_shift = 8;
524 			}
525 			break;
526 		case HDLC_SEND_CLOSING_FLAG:
527 			hdlc->cbin <<= 1;
528 			hdlc->data_bits++;
529 			if (hdlc->hdlc_bits1 == 5) {
530 				hdlc->hdlc_bits1 = 0;
531 				break;
532 			}
533 			if (hdlc->shift_reg & 0x01)
534 				hdlc->cbin++;
535 			hdlc->shift_reg >>= 1;
536 			hdlc->bit_shift--;
537 			if (hdlc->bit_shift == 0) {
538 				hdlc->ffvalue =
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)
545 						hdlc->state =
546 							HDLC_SEND_FAST_IDLE;
547 				} else {
548 					if (!hdlc->do_adapt56) {
549 						hdlc->state =
550 							HDLC_SEND_FAST_FLAG;
551 						hdlc->data_received = 0;
552 					} else {
553 						hdlc->state = HDLC_SENDFLAG_B0;
554 						hdlc->data_received = 0;
555 					}
556 					/* Finished this frame, send flags */
557 					if (dsize > 1)
558 						dsize = 1;
559 				}
560 			}
561 			break;
562 		case HDLC_SEND_IDLE1:
563 			hdlc->do_closing = 0;
564 			hdlc->cbin <<= 1;
565 			hdlc->cbin++;
566 			hdlc->data_bits++;
567 			hdlc->bit_shift--;
568 			if (hdlc->bit_shift == 0) {
569 				hdlc->state = HDLC_SEND_FAST_IDLE;
570 				hdlc->bit_shift = 0;
571 			}
572 			break;
573 		case HDLC_SEND_FAST_IDLE:
574 			hdlc->do_closing = 0;
575 			hdlc->cbin = 0xff;
576 			hdlc->data_bits = 8;
577 			if (hdlc->bit_shift == 8) {
578 				hdlc->cbin = 0x7e;
579 				hdlc->state = HDLC_SEND_FIRST_FLAG;
580 			} else {
581 				/* the code is for bitreverse streams */
582 				if (hdlc->do_bitreverse == 0)
583 					*dst++ = bitrev8(hdlc->cbin);
584 				else
585 					*dst++ = hdlc->cbin;
586 				hdlc->bit_shift = 0;
587 				hdlc->data_bits = 0;
588 				len++;
589 				dsize = 0;
590 			}
591 			break;
592 		default:
593 			break;
594 		}
595 		if (hdlc->do_adapt56) {
596 			if (hdlc->data_bits == 7) {
597 				hdlc->cbin <<= 1;
598 				hdlc->cbin++;
599 				hdlc->data_bits++;
600 			}
601 		}
602 		if (hdlc->data_bits == 8) {
603 			/* the code is for bitreverse streams */
604 			if (hdlc->do_bitreverse == 0)
605 				*dst++ = bitrev8(hdlc->cbin);
606 			else
607 				*dst++ = hdlc->cbin;
608 			hdlc->data_bits = 0;
609 			len++;
610 			dsize--;
611 		}
612 	}
613 	*count -= slen;
614 
615 	return len;
616 }
617 EXPORT_SYMBOL(isdnhdlc_encode);
618