1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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>
30
31
32
33MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, "
34 "Frode Isaksen <fisaksen@bewan.com>, "
35 "Kai Germaschewski <kai.germaschewski@gmx.de>");
36MODULE_DESCRIPTION("General purpose ISDN HDLC decoder");
37MODULE_LICENSE("GPL");
38
39
40
41enum {
42 HDLC_FAST_IDLE, HDLC_GET_FLAG_B0, HDLC_GETFLAG_B1A6, HDLC_GETFLAG_B7,
43 HDLC_GET_DATA, HDLC_FAST_FLAG
44};
45
46enum {
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
51};
52
53void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, u32 features)
54{
55 memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
56 hdlc->state = HDLC_GET_DATA;
57 if (features & HDLC_56KBIT)
58 hdlc->do_adapt56 = 1;
59 if (features & HDLC_BITREVERSE)
60 hdlc->do_bitreverse = 1;
61}
62EXPORT_SYMBOL(isdnhdlc_out_init);
63
64void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, u32 features)
65{
66 memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
67 if (features & HDLC_DCHANNEL) {
68 hdlc->dchannel = 1;
69 hdlc->state = HDLC_SEND_FIRST_FLAG;
70 } else {
71 hdlc->dchannel = 0;
72 hdlc->state = HDLC_SEND_FAST_FLAG;
73 hdlc->ffvalue = 0x7e;
74 }
75 hdlc->cbin = 0x7e;
76 if (features & HDLC_56KBIT) {
77 hdlc->do_adapt56 = 1;
78 hdlc->state = HDLC_SENDFLAG_B0;
79 } else
80 hdlc->data_bits = 8;
81 if (features & HDLC_BITREVERSE)
82 hdlc->do_bitreverse = 1;
83}
84EXPORT_SYMBOL(isdnhdlc_rcv_init);
85
86static int
87check_frame(struct isdnhdlc_vars *hdlc)
88{
89 int status;
90
91 if (hdlc->dstpos < 2)
92 status = -HDLC_FRAMING_ERROR;
93 else if (hdlc->crc != 0xf0b8)
94 status = -HDLC_CRC_ERROR;
95 else {
96
97 hdlc->dstpos -= 2;
98
99 status = hdlc->dstpos;
100 }
101 return status;
102}
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen,
132 int *count, u8 *dst, int dsize)
133{
134 int status = 0;
135
136 static const unsigned char fast_flag[] = {
137 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f
138 };
139
140 static const unsigned char fast_flag_value[] = {
141 0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f
142 };
143
144 static const unsigned char fast_abort[] = {
145 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
146 };
147
148#define handle_fast_flag(h) \
149 do { \
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; \
154 h->bit_shift = 1; \
155 } else { \
156 h->state = HDLC_GET_DATA; \
157 h->data_received = 0; \
158 } \
159 } while (0)
160
161#define handle_abort(h) \
162 do { \
163 h->shift_reg = fast_abort[h->ffbit_shift - 1]; \
164 h->hdlc_bits1 = h->ffbit_shift - 2; \
165 if (h->hdlc_bits1 < 0) \
166 h->hdlc_bits1 = 0; \
167 h->data_bits = h->ffbit_shift - 1; \
168 h->state = HDLC_GET_DATA; \
169 h->data_received = 0; \
170 } while (0)
171
172 *count = slen;
173
174 while (slen > 0) {
175 if (hdlc->bit_shift == 0) {
176
177 if (hdlc->do_bitreverse == 0)
178 hdlc->cbin = bitrev8(*src++);
179 else
180 hdlc->cbin = *src++;
181 slen--;
182 hdlc->bit_shift = 8;
183 if (hdlc->do_adapt56)
184 hdlc->bit_shift--;
185 }
186
187 switch (hdlc->state) {
188 case STOPPED:
189 return 0;
190 case HDLC_FAST_IDLE:
191 if (hdlc->cbin == 0xff) {
192 hdlc->bit_shift = 0;
193 break;
194 }
195 hdlc->state = HDLC_GET_FLAG_B0;
196 hdlc->hdlc_bits1 = 0;
197 hdlc->bit_shift = 8;
198 break;
199 case HDLC_GET_FLAG_B0:
200 if (!(hdlc->cbin & 0x80)) {
201 hdlc->state = HDLC_GETFLAG_B1A6;
202 hdlc->hdlc_bits1 = 0;
203 } else {
204 if ((!hdlc->do_adapt56) &&
205 (++hdlc->hdlc_bits1 >= 8) &&
206 (hdlc->bit_shift == 1))
207 hdlc->state = HDLC_FAST_IDLE;
208 }
209 hdlc->cbin <<= 1;
210 hdlc->bit_shift--;
211 break;
212 case HDLC_GETFLAG_B1A6:
213 if (hdlc->cbin & 0x80) {
214 hdlc->hdlc_bits1++;
215 if (hdlc->hdlc_bits1 == 6)
216 hdlc->state = HDLC_GETFLAG_B7;
217 } else
218 hdlc->hdlc_bits1 = 0;
219 hdlc->cbin <<= 1;
220 hdlc->bit_shift--;
221 break;
222 case HDLC_GETFLAG_B7:
223 if (hdlc->cbin & 0x80) {
224 hdlc->state = HDLC_GET_FLAG_B0;
225 } else {
226 hdlc->state = HDLC_GET_DATA;
227 hdlc->crc = 0xffff;
228 hdlc->shift_reg = 0;
229 hdlc->hdlc_bits1 = 0;
230 hdlc->data_bits = 0;
231 hdlc->data_received = 0;
232 }
233 hdlc->cbin <<= 1;
234 hdlc->bit_shift--;
235 break;
236 case HDLC_GET_DATA:
237 if (hdlc->cbin & 0x80) {
238 hdlc->hdlc_bits1++;
239 switch (hdlc->hdlc_bits1) {
240 case 6:
241 break;
242 case 7:
243 if (hdlc->data_received)
244
245 status = -HDLC_FRAMING_ERROR;
246 if (!hdlc->do_adapt56) {
247 if (hdlc->cbin == fast_abort
248 [hdlc->bit_shift + 1]) {
249 hdlc->state =
250 HDLC_FAST_IDLE;
251 hdlc->bit_shift = 1;
252 break;
253 }
254 } else
255 hdlc->state = HDLC_GET_FLAG_B0;
256 break;
257 default:
258 hdlc->shift_reg >>= 1;
259 hdlc->shift_reg |= 0x80;
260 hdlc->data_bits++;
261 break;
262 }
263 } else {
264 switch (hdlc->hdlc_bits1) {
265 case 5:
266 break;
267 case 6:
268 if (hdlc->data_received)
269 status = check_frame(hdlc);
270 hdlc->crc = 0xffff;
271 hdlc->shift_reg = 0;
272 hdlc->data_bits = 0;
273 if (!hdlc->do_adapt56)
274 handle_fast_flag(hdlc);
275 else {
276 hdlc->state = HDLC_GET_DATA;
277 hdlc->data_received = 0;
278 }
279 break;
280 default:
281 hdlc->shift_reg >>= 1;
282 hdlc->data_bits++;
283 break;
284 }
285 hdlc->hdlc_bits1 = 0;
286 }
287 if (status) {
288 hdlc->dstpos = 0;
289 *count -= slen;
290 hdlc->cbin <<= 1;
291 hdlc->bit_shift--;
292 return status;
293 }
294 if (hdlc->data_bits == 8) {
295 hdlc->data_bits = 0;
296 hdlc->data_received = 1;
297 hdlc->crc = crc_ccitt_byte(hdlc->crc,
298 hdlc->shift_reg);
299
300
301 if (hdlc->dstpos < dsize)
302 dst[hdlc->dstpos++] = hdlc->shift_reg;
303 else {
304
305 status = -HDLC_LENGTH_ERROR;
306 hdlc->dstpos = 0;
307 }
308 }
309 hdlc->cbin <<= 1;
310 hdlc->bit_shift--;
311 break;
312 case HDLC_FAST_FLAG:
313 if (hdlc->cbin == hdlc->ffvalue) {
314 hdlc->bit_shift = 0;
315 break;
316 } else {
317 if (hdlc->cbin == 0xff) {
318 hdlc->state = HDLC_FAST_IDLE;
319 hdlc->bit_shift = 0;
320 } else if (hdlc->ffbit_shift == 8) {
321 hdlc->state = HDLC_GETFLAG_B7;
322 break;
323 } else
324 handle_abort(hdlc);
325 }
326 break;
327 default:
328 break;
329 }
330 }
331 *count -= slen;
332 return 0;
333}
334EXPORT_SYMBOL(isdnhdlc_decode);
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen,
355 int *count, u8 *dst, int dsize)
356{
357 static const unsigned char xfast_flag_value[] = {
358 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e
359 };
360
361 int len = 0;
362
363 *count = slen;
364
365
366 if ((slen == 1) && (hdlc->state == HDLC_SEND_FAST_FLAG))
367 hdlc->state = HDLC_SENDFLAG_ONE;
368 while (dsize > 0) {
369 if (hdlc->bit_shift == 0) {
370 if (slen && !hdlc->do_closing) {
371 hdlc->shift_reg = *src++;
372 slen--;
373 if (slen == 0)
374
375 hdlc->do_closing = 1;
376 hdlc->bit_shift = 8;
377 } else {
378 if (hdlc->state == HDLC_SEND_DATA) {
379 if (hdlc->data_received) {
380 hdlc->state = HDLC_SEND_CRC1;
381 hdlc->crc ^= 0xffff;
382 hdlc->bit_shift = 8;
383 hdlc->shift_reg =
384 hdlc->crc & 0xff;
385 } else if (!hdlc->do_adapt56)
386 hdlc->state =
387 HDLC_SEND_FAST_FLAG;
388 else
389 hdlc->state =
390 HDLC_SENDFLAG_B0;
391 }
392
393 }
394 }
395
396 switch (hdlc->state) {
397 case STOPPED:
398 while (dsize--)
399 *dst++ = 0xff;
400 return dsize;
401 case HDLC_SEND_FAST_FLAG:
402 hdlc->do_closing = 0;
403 if (slen == 0) {
404
405 if (hdlc->do_bitreverse == 0)
406 *dst++ = bitrev8(hdlc->ffvalue);
407 else
408 *dst++ = hdlc->ffvalue;
409 len++;
410 dsize--;
411 break;
412 }
413
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;
419 hdlc->crc = 0xffff;
420 hdlc->hdlc_bits1 = 0;
421 hdlc->data_received = 1;
422 }
423 break;
424 case HDLC_SENDFLAG_B0:
425 hdlc->do_closing = 0;
426 hdlc->cbin <<= 1;
427 hdlc->data_bits++;
428 hdlc->hdlc_bits1 = 0;
429 hdlc->state = HDLC_SENDFLAG_B1A6;
430 break;
431 case HDLC_SENDFLAG_B1A6:
432 hdlc->cbin <<= 1;
433 hdlc->data_bits++;
434 hdlc->cbin++;
435 if (++hdlc->hdlc_bits1 == 6)
436 hdlc->state = HDLC_SENDFLAG_B7;
437 break;
438 case HDLC_SENDFLAG_B7:
439 hdlc->cbin <<= 1;
440 hdlc->data_bits++;
441 if (slen == 0) {
442 hdlc->state = HDLC_SENDFLAG_B0;
443 break;
444 }
445 if (hdlc->bit_shift == 8) {
446 hdlc->state = HDLC_SEND_DATA;
447 hdlc->crc = 0xffff;
448 hdlc->hdlc_bits1 = 0;
449 hdlc->data_received = 1;
450 }
451 break;
452 case HDLC_SEND_FIRST_FLAG:
453 hdlc->data_received = 1;
454 if (hdlc->data_bits == 8) {
455 hdlc->state = HDLC_SEND_DATA;
456 hdlc->crc = 0xffff;
457 hdlc->hdlc_bits1 = 0;
458 break;
459 }
460 hdlc->cbin <<= 1;
461 hdlc->data_bits++;
462 if (hdlc->shift_reg & 0x01)
463 hdlc->cbin++;
464 hdlc->shift_reg >>= 1;
465 hdlc->bit_shift--;
466 if (hdlc->bit_shift == 0) {
467 hdlc->state = HDLC_SEND_DATA;
468 hdlc->crc = 0xffff;
469 hdlc->hdlc_bits1 = 0;
470 }
471 break;
472 case HDLC_SEND_DATA:
473 hdlc->cbin <<= 1;
474 hdlc->data_bits++;
475 if (hdlc->hdlc_bits1 == 5) {
476 hdlc->hdlc_bits1 = 0;
477 break;
478 }
479 if (hdlc->bit_shift == 8)
480 hdlc->crc = crc_ccitt_byte(hdlc->crc,
481 hdlc->shift_reg);
482 if (hdlc->shift_reg & 0x01) {
483 hdlc->hdlc_bits1++;
484 hdlc->cbin++;
485 hdlc->shift_reg >>= 1;
486 hdlc->bit_shift--;
487 } else {
488 hdlc->hdlc_bits1 = 0;
489 hdlc->shift_reg >>= 1;
490 hdlc->bit_shift--;
491 }
492 break;
493 case HDLC_SEND_CRC1:
494 hdlc->cbin <<= 1;
495 hdlc->data_bits++;
496 if (hdlc->hdlc_bits1 == 5) {
497 hdlc->hdlc_bits1 = 0;
498 break;
499 }
500 if (hdlc->shift_reg & 0x01) {
501 hdlc->hdlc_bits1++;
502 hdlc->cbin++;
503 hdlc->shift_reg >>= 1;
504 hdlc->bit_shift--;
505 } else {
506 hdlc->hdlc_bits1 = 0;
507 hdlc->shift_reg >>= 1;
508 hdlc->bit_shift--;
509 }
510 if (hdlc->bit_shift == 0) {
511 hdlc->shift_reg = (hdlc->crc >> 8);
512 hdlc->state = HDLC_SEND_CRC2;
513 hdlc->bit_shift = 8;
514 }
515 break;
516 case HDLC_SEND_CRC2:
517 hdlc->cbin <<= 1;
518 hdlc->data_bits++;
519 if (hdlc->hdlc_bits1 == 5) {
520 hdlc->hdlc_bits1 = 0;
521 break;
522 }
523 if (hdlc->shift_reg & 0x01) {
524 hdlc->hdlc_bits1++;
525 hdlc->cbin++;
526 hdlc->shift_reg >>= 1;
527 hdlc->bit_shift--;
528 } else {
529 hdlc->hdlc_bits1 = 0;
530 hdlc->shift_reg >>= 1;
531 hdlc->bit_shift--;
532 }
533 if (hdlc->bit_shift == 0) {
534 hdlc->shift_reg = 0x7e;
535 hdlc->state = HDLC_SEND_CLOSING_FLAG;
536 hdlc->bit_shift = 8;
537 }
538 break;
539 case HDLC_SEND_CLOSING_FLAG:
540 hdlc->cbin <<= 1;
541 hdlc->data_bits++;
542 if (hdlc->hdlc_bits1 == 5) {
543 hdlc->hdlc_bits1 = 0;
544 break;
545 }
546 if (hdlc->shift_reg & 0x01)
547 hdlc->cbin++;
548 hdlc->shift_reg >>= 1;
549 hdlc->bit_shift--;
550 if (hdlc->bit_shift == 0) {
551 hdlc->ffvalue =
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)
558 hdlc->state =
559 HDLC_SEND_FAST_IDLE;
560 } else {
561 if (!hdlc->do_adapt56) {
562 hdlc->state =
563 HDLC_SEND_FAST_FLAG;
564 hdlc->data_received = 0;
565 } else {
566 hdlc->state = HDLC_SENDFLAG_B0;
567 hdlc->data_received = 0;
568 }
569
570 if (dsize > 1)
571 dsize = 1;
572 }
573 }
574 break;
575 case HDLC_SEND_IDLE1:
576 hdlc->do_closing = 0;
577 hdlc->cbin <<= 1;
578 hdlc->cbin++;
579 hdlc->data_bits++;
580 hdlc->bit_shift--;
581 if (hdlc->bit_shift == 0) {
582 hdlc->state = HDLC_SEND_FAST_IDLE;
583 hdlc->bit_shift = 0;
584 }
585 break;
586 case HDLC_SEND_FAST_IDLE:
587 hdlc->do_closing = 0;
588 hdlc->cbin = 0xff;
589 hdlc->data_bits = 8;
590 if (hdlc->bit_shift == 8) {
591 hdlc->cbin = 0x7e;
592 hdlc->state = HDLC_SEND_FIRST_FLAG;
593 } else {
594
595 if (hdlc->do_bitreverse == 0)
596 *dst++ = bitrev8(hdlc->cbin);
597 else
598 *dst++ = hdlc->cbin;
599 hdlc->bit_shift = 0;
600 hdlc->data_bits = 0;
601 len++;
602 dsize = 0;
603 }
604 break;
605 default:
606 break;
607 }
608 if (hdlc->do_adapt56) {
609 if (hdlc->data_bits == 7) {
610 hdlc->cbin <<= 1;
611 hdlc->cbin++;
612 hdlc->data_bits++;
613 }
614 }
615 if (hdlc->data_bits == 8) {
616
617 if (hdlc->do_bitreverse == 0)
618 *dst++ = bitrev8(hdlc->cbin);
619 else
620 *dst++ = hdlc->cbin;
621 hdlc->data_bits = 0;
622 len++;
623 dsize--;
624 }
625 }
626 *count -= slen;
627
628 return len;
629}
630EXPORT_SYMBOL(isdnhdlc_encode);
631