• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/isdn/i4l/
1/*
2 * isdnhdlc.c  --  General purpose ISDN HDLC decoder.
3 *
4 * Copyright (C)
5 *	2009	Karsten Keil		<keil@b1-systems.de>
6 *	2002	Wolfgang M��es		<wolfgang@iksw-muees.de>
7 *	2001	Frode Isaksen		<fisaksen@bewan.com>
8 *      2001	Kai Germaschewski	<kai.germaschewski@gmx.de>
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
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) 	/* 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 */
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			/* 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 =
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				/* 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}
334EXPORT_SYMBOL(isdnhdlc_decode);
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*/
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	/* 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 =
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				/* 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;
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					/* 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}
630EXPORT_SYMBOL(isdnhdlc_encode);
631