This source file includes following definitions.
- isdnhdlc_rcv_init
- isdnhdlc_out_init
- check_frame
- isdnhdlc_decode
- isdnhdlc_encode
1
2
3
4
5
6
7
8
9
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
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
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
74 check_frame(struct isdnhdlc_vars *hdlc)
75 {
76 int status;
77
78 if (hdlc->dstpos < 2)
79 status = -HDLC_FRAMING_ERROR;
80 else if (hdlc->crc != 0xf0b8)
81 status = -HDLC_CRC_ERROR;
82 else {
83
84 hdlc->dstpos -= 2;
85
86 status = hdlc->dstpos;
87 }
88 return status;
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
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
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
288 if (hdlc->dstpos < dsize)
289 dst[hdlc->dstpos++] = hdlc->shift_reg;
290 else {
291
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
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
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
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
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
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
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
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
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
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);