Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
isdnhdlc.c
Go to the documentation of this file.
1 /*
2  * isdnhdlc.c -- General purpose ISDN HDLC decoder.
3  *
4  * Copyright (C)
5  * 2009 Karsten Keil <[email protected]>
6  * 2002 Wolfgang Mües <[email protected]>
7  * 2001 Frode Isaksen <[email protected]>
8  * 2001 Kai Germaschewski <[email protected]>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 
33 MODULE_AUTHOR("Wolfgang Mües <[email protected]>, "
34  "Frode Isaksen <[email protected]>, "
35  "Kai Germaschewski <[email protected]>");
36 MODULE_DESCRIPTION("General purpose ISDN HDLC decoder");
37 MODULE_LICENSE("GPL");
38 
39 /*-------------------------------------------------------------------*/
40 
41 enum {
44 };
45 
46 enum {
51 };
52 
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 }
63 
65 {
66  memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
67  if (features & HDLC_DCHANNEL) {
68  hdlc->dchannel = 1;
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 }
85 
86 static int
87 check_frame(struct isdnhdlc_vars *hdlc)
88 {
89  int status;
90 
91  if (hdlc->dstpos < 2) /* too small - framing error */
92  status = -HDLC_FRAMING_ERROR;
93  else if (hdlc->crc != 0xf0b8) /* crc error */
94  status = -HDLC_CRC_ERROR;
95  else {
96  /* remove CRC */
97  hdlc->dstpos -= 2;
98  /* good frame */
99  status = hdlc->dstpos;
100  }
101  return status;
102 }
103 
104 /*
105  isdnhdlc_decode - decodes HDLC frames from a transparent bit stream.
106 
107  The source buffer is scanned for valid HDLC frames looking for
108  flags (01111110) to indicate the start of a frame. If the start of
109  the frame is found, the bit stuffing is removed (0 after 5 1's).
110  When a new flag is found, the complete frame has been received
111  and the CRC is checked.
112  If a valid frame is found, the function returns the frame length
113  excluding the CRC with the bit HDLC_END_OF_FRAME set.
114  If the beginning of a valid frame is found, the function returns
115  the length.
116  If a framing error is found (too many 1s and not a flag) the function
117  returns the length with the bit HDLC_FRAMING_ERROR set.
118  If a CRC error is found the function returns the length with the
119  bit HDLC_CRC_ERROR set.
120  If the frame length exceeds the destination buffer size, the function
121  returns the length with the bit HDLC_LENGTH_ERROR set.
122 
123  src - source buffer
124  slen - source buffer length
125  count - number of bytes removed (decoded) from the source buffer
126  dst _ destination buffer
127  dsize - destination buffer size
128  returns - number of decoded bytes in the destination buffer and status
129  flag.
130 */
131 int 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  /* the code is for bitreverse streams */
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  /* bad frame */
245  status = -HDLC_FRAMING_ERROR;
246  if (!hdlc->do_adapt56) {
247  if (hdlc->cbin == fast_abort
248  [hdlc->bit_shift + 1]) {
249  hdlc->state =
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  /* good byte received */
301  if (hdlc->dstpos < dsize)
302  dst[hdlc->dstpos++] = hdlc->shift_reg;
303  else {
304  /* frame too long */
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 }
335 /*
336  isdnhdlc_encode - encodes HDLC frames to a transparent bit stream.
337 
338  The bit stream starts with a beginning flag (01111110). After
339  that each byte is added to the bit stream with bit stuffing added
340  (0 after 5 1's).
341  When the last byte has been removed from the source buffer, the
342  CRC (2 bytes is added) and the frame terminates with the ending flag.
343  For the dchannel, the idle character (all 1's) is also added at the end.
344  If this function is called with empty source buffer (slen=0), flags or
345  idle character will be generated.
346 
347  src - source buffer
348  slen - source buffer length
349  count - number of bytes removed (encoded) from source buffer
350  dst _ destination buffer
351  dsize - destination buffer size
352  returns - number of encoded bytes in the destination buffer
353 */
354 int 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  /* special handling for one byte frames */
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  /* closing sequence, CRC + flag(s) */
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 =
388  else
389  hdlc->state =
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  /* the code is for bitreverse streams */
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  /* fall through */
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;
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;
536  hdlc->bit_shift = 8;
537  }
538  break;
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 =
560  } else {
561  if (!hdlc->do_adapt56) {
562  hdlc->state =
564  hdlc->data_received = 0;
565  } else {
566  hdlc->state = HDLC_SENDFLAG_B0;
567  hdlc->data_received = 0;
568  }
569  /* Finished this frame, send flags */
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  /* the code is for bitreverse streams */
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  /* the code is for bitreverse streams */
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 }