Merge tag 'block-5.11-2021-01-10' of git://git.kernel.dk/linux-block
[linux/fpc-iii.git] / drivers / isdn / hardware / mISDN / isdnhdlc.c
blob985367e6711d4d8b4a22785f077a72874cac48af
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * isdnhdlc.c -- General purpose ISDN HDLC decoder.
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>
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"
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 /*-------------------------------------------------------------------*/
28 enum {
29 HDLC_FAST_IDLE, HDLC_GET_FLAG_B0, HDLC_GETFLAG_B1A6, HDLC_GETFLAG_B7,
30 HDLC_GET_DATA, HDLC_FAST_FLAG
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
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)
45 hdlc->do_adapt56 = 1;
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) {
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;
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;
71 EXPORT_SYMBOL(isdnhdlc_rcv_init);
73 static int
74 check_frame(struct isdnhdlc_vars *hdlc)
76 int status;
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;
88 return status;
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
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.
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.
118 int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen,
119 int *count, u8 *dst, int dsize)
121 int status = 0;
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) \
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; \
146 } while (0)
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)
159 *count = slen;
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--;
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;
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;
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;
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;
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;
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;
266 break;
267 default:
268 hdlc->shift_reg >>= 1;
269 hdlc->data_bits++;
270 break;
272 hdlc->hdlc_bits1 = 0;
274 if (status) {
275 hdlc->dstpos = 0;
276 *count -= slen;
277 hdlc->cbin <<= 1;
278 hdlc->bit_shift--;
279 return status;
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);
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;
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);
313 break;
314 default:
315 break;
318 *count -= slen;
319 return 0;
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
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.
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
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
348 int len = 0;
350 *count = slen;
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;
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;
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;
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;
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;
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;
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;
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;
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--;
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;
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--;
497 if (hdlc->bit_shift == 0) {
498 hdlc->shift_reg = (hdlc->crc >> 8);
499 hdlc->state = HDLC_SEND_CRC2;
500 hdlc->bit_shift = 8;
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;
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--;
520 if (hdlc->bit_shift == 0) {
521 hdlc->shift_reg = 0x7e;
522 hdlc->state = HDLC_SEND_CLOSING_FLAG;
523 hdlc->bit_shift = 8;
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;
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;
556 /* Finished this frame, send flags */
557 if (dsize > 1)
558 dsize = 1;
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;
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;
591 break;
592 default:
593 break;
595 if (hdlc->do_adapt56) {
596 if (hdlc->data_bits == 7) {
597 hdlc->cbin <<= 1;
598 hdlc->cbin++;
599 hdlc->data_bits++;
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--;
613 *count -= slen;
615 return len;
617 EXPORT_SYMBOL(isdnhdlc_encode);