Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / isdn / hisax / isdnhdlc.c
1 /*
2  * isdnhdlc.c  --  General purpose ISDN HDLC decoder.
3  *
4  *Copyright (C) 2002    Wolfgang Mües      <wolfgang@iksw-muees.de>
5  *              2001    Frode Isaksen      <fisaksen@bewan.com>
6  *              2001    Kai Germaschewski  <kai.germaschewski@gmx.de>
7  *
8  *      This program is free software; you can redistribute it and/or modify
9  *      it under the terms of the GNU General Public License as published by
10  *      the Free Software Foundation; either version 2 of the License, or
11  *      (at your option) any later version.
12  *
13  *      This program is distributed in the hope that it will be useful,
14  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *      GNU General Public License for more details.
17  *
18  *      You should have received a copy of the GNU General Public License
19  *      along with this program; if not, write to the Free Software
20  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/crc-ccitt.h>
26 #include "isdnhdlc.h"
27
28 /*-------------------------------------------------------------------*/
29
30 MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, "
31               "Frode Isaksen <fisaksen@bewan.com>, "
32               "Kai Germaschewski <kai.germaschewski@gmx.de>");
33 MODULE_DESCRIPTION("General purpose ISDN HDLC decoder");
34 MODULE_LICENSE("GPL");
35
36 /*-------------------------------------------------------------------*/
37
38 /* bit swap table.
39  * Very handy for devices with different bit order,
40  * and neccessary for each transparent B-channel access for all
41  * devices which works with this HDLC decoder without bit reversal.
42  */
43 const unsigned char isdnhdlc_bit_rev_tab[256] = {
44         0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
45         0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
46         0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
47         0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
48         0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
49         0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
50         0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
51         0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
52         0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
53         0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
54         0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
55         0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
56         0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
57         0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
58         0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
59         0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
60 };
61
62 enum {
63         HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7,
64         HDLC_GET_DATA,HDLC_FAST_FLAG
65 };
66
67 enum {
68         HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG,
69         HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG,
70         HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0,
71         HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED
72 };
73
74 void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56)
75 {
76         hdlc->bit_shift = 0;
77         hdlc->hdlc_bits1 = 0;
78         hdlc->data_bits = 0;
79         hdlc->ffbit_shift = 0;
80         hdlc->data_received = 0;
81         hdlc->state = HDLC_GET_DATA;
82         hdlc->do_adapt56 = do_adapt56;
83         hdlc->dchannel = 0;
84         hdlc->crc = 0;
85         hdlc->cbin = 0;
86         hdlc->shift_reg = 0;
87         hdlc->ffvalue = 0;
88         hdlc->dstpos = 0;
89 }
90
91 void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56)
92 {
93         hdlc->bit_shift = 0;
94         hdlc->hdlc_bits1 = 0;
95         hdlc->data_bits = 0;
96         hdlc->ffbit_shift = 0;
97         hdlc->data_received = 0;
98         hdlc->do_closing = 0;
99         hdlc->ffvalue = 0;
100         if (is_d_channel) {
101                 hdlc->dchannel = 1;
102                 hdlc->state = HDLC_SEND_FIRST_FLAG;
103         } else {
104                 hdlc->dchannel = 0;
105                 hdlc->state = HDLC_SEND_FAST_FLAG;
106                 hdlc->ffvalue = 0x7e;
107         }
108         hdlc->cbin = 0x7e;
109         hdlc->bit_shift = 0;
110         if(do_adapt56){
111                 hdlc->do_adapt56 = 1;
112                 hdlc->data_bits = 0;
113                 hdlc->state = HDLC_SENDFLAG_B0;
114         } else {
115                 hdlc->do_adapt56 = 0;
116                 hdlc->data_bits = 8;
117         }
118         hdlc->shift_reg = 0;
119 }
120
121 /*
122   isdnhdlc_decode - decodes HDLC frames from a transparent bit stream.
123
124   The source buffer is scanned for valid HDLC frames looking for
125   flags (01111110) to indicate the start of a frame. If the start of
126   the frame is found, the bit stuffing is removed (0 after 5 1's).
127   When a new flag is found, the complete frame has been received
128   and the CRC is checked.
129   If a valid frame is found, the function returns the frame length
130   excluding the CRC with the bit HDLC_END_OF_FRAME set.
131   If the beginning of a valid frame is found, the function returns
132   the length.
133   If a framing error is found (too many 1s and not a flag) the function
134   returns the length with the bit HDLC_FRAMING_ERROR set.
135   If a CRC error is found the function returns the length with the
136   bit HDLC_CRC_ERROR set.
137   If the frame length exceeds the destination buffer size, the function
138   returns the length with the bit HDLC_LENGTH_ERROR set.
139
140   src - source buffer
141   slen - source buffer length
142   count - number of bytes removed (decoded) from the source buffer
143   dst _ destination buffer
144   dsize - destination buffer size
145   returns - number of decoded bytes in the destination buffer and status
146   flag.
147  */
148 int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
149                      int slen, int *count, unsigned char *dst, int dsize)
150 {
151         int status=0;
152
153         static const unsigned char fast_flag[]={
154                 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f
155         };
156
157         static const unsigned char fast_flag_value[]={
158                 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f
159         };
160
161         static const unsigned char fast_abort[]={
162                 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff
163         };
164
165         *count = slen;
166
167         while(slen > 0){
168                 if(hdlc->bit_shift==0){
169                         hdlc->cbin = *src++;
170                         slen--;
171                         hdlc->bit_shift = 8;
172                         if(hdlc->do_adapt56){
173                                 hdlc->bit_shift --;
174                         }
175                 }
176
177                 switch(hdlc->state){
178                 case STOPPED:
179                         return 0;
180                 case HDLC_FAST_IDLE:
181                         if(hdlc->cbin == 0xff){
182                                 hdlc->bit_shift = 0;
183                                 break;
184                         }
185                         hdlc->state = HDLC_GET_FLAG_B0;
186                         hdlc->hdlc_bits1 = 0;
187                         hdlc->bit_shift = 8;
188                         break;
189                 case HDLC_GET_FLAG_B0:
190                         if(!(hdlc->cbin & 0x80)) {
191                                 hdlc->state = HDLC_GETFLAG_B1A6;
192                                 hdlc->hdlc_bits1 = 0;
193                         } else {
194                                 if(!hdlc->do_adapt56){
195                                         if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1)
196                                                 hdlc->state = HDLC_FAST_IDLE;
197                                 }
198                         }
199                         hdlc->cbin<<=1;
200                         hdlc->bit_shift --;
201                         break;
202                 case HDLC_GETFLAG_B1A6:
203                         if(hdlc->cbin & 0x80){
204                                 hdlc->hdlc_bits1++;
205                                 if(hdlc->hdlc_bits1==6){
206                                         hdlc->state = HDLC_GETFLAG_B7;
207                                 }
208                         } else {
209                                 hdlc->hdlc_bits1 = 0;
210                         }
211                         hdlc->cbin<<=1;
212                         hdlc->bit_shift --;
213                         break;
214                 case HDLC_GETFLAG_B7:
215                         if(hdlc->cbin & 0x80) {
216                                 hdlc->state = HDLC_GET_FLAG_B0;
217                         } else {
218                                 hdlc->state = HDLC_GET_DATA;
219                                 hdlc->crc = 0xffff;
220                                 hdlc->shift_reg = 0;
221                                 hdlc->hdlc_bits1 = 0;
222                                 hdlc->data_bits = 0;
223                                 hdlc->data_received = 0;
224                         }
225                         hdlc->cbin<<=1;
226                         hdlc->bit_shift --;
227                         break;
228                 case HDLC_GET_DATA:
229                         if(hdlc->cbin & 0x80){
230                                 hdlc->hdlc_bits1++;
231                                 switch(hdlc->hdlc_bits1){
232                                 case 6:
233                                         break;
234                                 case 7:
235                                         if(hdlc->data_received) {
236                                                 // bad frame
237                                                 status = -HDLC_FRAMING_ERROR;
238                                         }
239                                         if(!hdlc->do_adapt56){
240                                                 if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){
241                                                         hdlc->state = HDLC_FAST_IDLE;
242                                                         hdlc->bit_shift=1;
243                                                         break;
244                                                 }
245                                         } else {
246                                                 hdlc->state = HDLC_GET_FLAG_B0;
247                                         }
248                                         break;
249                                 default:
250                                         hdlc->shift_reg>>=1;
251                                         hdlc->shift_reg |= 0x80;
252                                         hdlc->data_bits++;
253                                         break;
254                                 }
255                         } else {
256                                 switch(hdlc->hdlc_bits1){
257                                 case 5:
258                                         break;
259                                 case 6:
260                                         if(hdlc->data_received){
261                                                 if (hdlc->dstpos < 2) {
262                                                         status = -HDLC_FRAMING_ERROR;
263                                                 } else if (hdlc->crc != 0xf0b8){
264                                                         // crc error
265                                                         status = -HDLC_CRC_ERROR;
266                                                 } else {
267                                                         // remove CRC
268                                                         hdlc->dstpos -= 2;
269                                                         // good frame
270                                                         status = hdlc->dstpos;
271                                                 }
272                                         }
273                                         hdlc->crc = 0xffff;
274                                         hdlc->shift_reg = 0;
275                                         hdlc->data_bits = 0;
276                                         if(!hdlc->do_adapt56){
277                                                 if(hdlc->cbin==fast_flag[hdlc->bit_shift]){
278                                                         hdlc->ffvalue = fast_flag_value[hdlc->bit_shift];
279                                                         hdlc->state = HDLC_FAST_FLAG;
280                                                         hdlc->ffbit_shift = hdlc->bit_shift;
281                                                         hdlc->bit_shift = 1;
282                                                 } else {
283                                                         hdlc->state = HDLC_GET_DATA;
284                                                         hdlc->data_received = 0;
285                                                 }
286                                         } else {
287                                                 hdlc->state = HDLC_GET_DATA;
288                                                 hdlc->data_received = 0;
289                                         }
290                                         break;
291                                 default:
292                                         hdlc->shift_reg>>=1;
293                                         hdlc->data_bits++;
294                                         break;
295                                 }
296                                 hdlc->hdlc_bits1 = 0;
297                         }
298                         if (status) {
299                                 hdlc->dstpos = 0;
300                                 *count -= slen;
301                                 hdlc->cbin <<= 1;
302                                 hdlc->bit_shift--;
303                                 return status;
304                         }
305                         if(hdlc->data_bits==8){
306                                 hdlc->data_bits = 0;
307                                 hdlc->data_received = 1;
308                                 hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
309
310                                 // good byte received
311                                 if (hdlc->dstpos < dsize) {
312                                         dst[hdlc->dstpos++] = hdlc->shift_reg;
313                                 } else {
314                                         // frame too long
315                                         status = -HDLC_LENGTH_ERROR;
316                                         hdlc->dstpos = 0;
317                                 }
318                         }
319                         hdlc->cbin <<= 1;
320                         hdlc->bit_shift--;
321                         break;
322                 case HDLC_FAST_FLAG:
323                         if(hdlc->cbin==hdlc->ffvalue){
324                                 hdlc->bit_shift = 0;
325                                 break;
326                         } else {
327                                 if(hdlc->cbin == 0xff){
328                                         hdlc->state = HDLC_FAST_IDLE;
329                                         hdlc->bit_shift=0;
330                                 } else if(hdlc->ffbit_shift==8){
331                                         hdlc->state = HDLC_GETFLAG_B7;
332                                         break;
333                                 } else {
334                                         hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1];
335                                         hdlc->hdlc_bits1 = hdlc->ffbit_shift-2;
336                                         if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0;
337                                         hdlc->data_bits = hdlc->ffbit_shift-1;
338                                         hdlc->state = HDLC_GET_DATA;
339                                         hdlc->data_received = 0;
340                                 }
341                         }
342                         break;
343                 default:
344                         break;
345                 }
346         }
347         *count -= slen;
348         return 0;
349 }
350
351 /*
352   isdnhdlc_encode - encodes HDLC frames to a transparent bit stream.
353
354   The bit stream starts with a beginning flag (01111110). After
355   that each byte is added to the bit stream with bit stuffing added
356   (0 after 5 1's).
357   When the last byte has been removed from the source buffer, the
358   CRC (2 bytes is added) and the frame terminates with the ending flag.
359   For the dchannel, the idle character (all 1's) is also added at the end.
360   If this function is called with empty source buffer (slen=0), flags or
361   idle character will be generated.
362
363   src - source buffer
364   slen - source buffer length
365   count - number of bytes removed (encoded) from source buffer
366   dst _ destination buffer
367   dsize - destination buffer size
368   returns - number of encoded bytes in the destination buffer
369 */
370 int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
371                 unsigned short slen, int *count,
372                 unsigned char *dst, int dsize)
373 {
374         static const unsigned char xfast_flag_value[] = {
375                 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e
376         };
377
378         int len = 0;
379
380         *count = slen;
381
382         while (dsize > 0) {
383                 if(hdlc->bit_shift==0){
384                         if(slen && !hdlc->do_closing){
385                                 hdlc->shift_reg = *src++;
386                                 slen--;
387                                 if (slen == 0)
388                                         hdlc->do_closing = 1;  /* closing sequence, CRC + flag(s) */
389                                 hdlc->bit_shift = 8;
390                         } else {
391                                 if(hdlc->state == HDLC_SEND_DATA){
392                                         if(hdlc->data_received){
393                                                 hdlc->state = HDLC_SEND_CRC1;
394                                                 hdlc->crc ^= 0xffff;
395                                                 hdlc->bit_shift = 8;
396                                                 hdlc->shift_reg = hdlc->crc & 0xff;
397                                         } else if(!hdlc->do_adapt56){
398                                                 hdlc->state = HDLC_SEND_FAST_FLAG;
399                                         } else {
400                                                 hdlc->state = HDLC_SENDFLAG_B0;
401                                         }
402                                 }
403
404                         }
405                 }
406
407                 switch(hdlc->state){
408                 case STOPPED:
409                         while (dsize--)
410                                 *dst++ = 0xff;
411
412                         return dsize;
413                 case HDLC_SEND_FAST_FLAG:
414                         hdlc->do_closing = 0;
415                         if(slen == 0){
416                                 *dst++ = hdlc->ffvalue;
417                                 len++;
418                                 dsize--;
419                                 break;
420                         }
421                         if(hdlc->bit_shift==8){
422                                 hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits);
423                                 hdlc->state = HDLC_SEND_DATA;
424                                 hdlc->crc = 0xffff;
425                                 hdlc->hdlc_bits1 = 0;
426                                 hdlc->data_received = 1;
427                         }
428                         break;
429                 case HDLC_SENDFLAG_B0:
430                         hdlc->do_closing = 0;
431                         hdlc->cbin <<= 1;
432                         hdlc->data_bits++;
433                         hdlc->hdlc_bits1 = 0;
434                         hdlc->state = HDLC_SENDFLAG_B1A6;
435                         break;
436                 case HDLC_SENDFLAG_B1A6:
437                         hdlc->cbin <<= 1;
438                         hdlc->data_bits++;
439                         hdlc->cbin++;
440                         if(++hdlc->hdlc_bits1 == 6)
441                                 hdlc->state = HDLC_SENDFLAG_B7;
442                         break;
443                 case HDLC_SENDFLAG_B7:
444                         hdlc->cbin <<= 1;
445                         hdlc->data_bits++;
446                         if(slen == 0){
447                                 hdlc->state = HDLC_SENDFLAG_B0;
448                                 break;
449                         }
450                         if(hdlc->bit_shift==8){
451                                 hdlc->state = HDLC_SEND_DATA;
452                                 hdlc->crc = 0xffff;
453                                 hdlc->hdlc_bits1 = 0;
454                                 hdlc->data_received = 1;
455                         }
456                         break;
457                 case HDLC_SEND_FIRST_FLAG:
458                         hdlc->data_received = 1;
459                         if(hdlc->data_bits==8){
460                                 hdlc->state = HDLC_SEND_DATA;
461                                 hdlc->crc = 0xffff;
462                                 hdlc->hdlc_bits1 = 0;
463                                 break;
464                         }
465                         hdlc->cbin <<= 1;
466                         hdlc->data_bits++;
467                         if(hdlc->shift_reg & 0x01)
468                                 hdlc->cbin++;
469                         hdlc->shift_reg >>= 1;
470                         hdlc->bit_shift--;
471                         if(hdlc->bit_shift==0){
472                                 hdlc->state = HDLC_SEND_DATA;
473                                 hdlc->crc = 0xffff;
474                                 hdlc->hdlc_bits1 = 0;
475                         }
476                         break;
477                 case HDLC_SEND_DATA:
478                         hdlc->cbin <<= 1;
479                         hdlc->data_bits++;
480                         if(hdlc->hdlc_bits1 == 5){
481                                 hdlc->hdlc_bits1 = 0;
482                                 break;
483                         }
484                         if(hdlc->bit_shift==8){
485                                 hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
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                         break;
498                 case HDLC_SEND_CRC1:
499                         hdlc->cbin <<= 1;
500                         hdlc->data_bits++;
501                         if(hdlc->hdlc_bits1 == 5){
502                                 hdlc->hdlc_bits1 = 0;
503                                 break;
504                         }
505                         if(hdlc->shift_reg & 0x01){
506                                 hdlc->hdlc_bits1++;
507                                 hdlc->cbin++;
508                                 hdlc->shift_reg >>= 1;
509                                 hdlc->bit_shift--;
510                         } else {
511                                 hdlc->hdlc_bits1 = 0;
512                                 hdlc->shift_reg >>= 1;
513                                 hdlc->bit_shift--;
514                         }
515                         if(hdlc->bit_shift==0){
516                                 hdlc->shift_reg = (hdlc->crc >> 8);
517                                 hdlc->state = HDLC_SEND_CRC2;
518                                 hdlc->bit_shift = 8;
519                         }
520                         break;
521                 case HDLC_SEND_CRC2:
522                         hdlc->cbin <<= 1;
523                         hdlc->data_bits++;
524                         if(hdlc->hdlc_bits1 == 5){
525                                 hdlc->hdlc_bits1 = 0;
526                                 break;
527                         }
528                         if(hdlc->shift_reg & 0x01){
529                                 hdlc->hdlc_bits1++;
530                                 hdlc->cbin++;
531                                 hdlc->shift_reg >>= 1;
532                                 hdlc->bit_shift--;
533                         } else {
534                                 hdlc->hdlc_bits1 = 0;
535                                 hdlc->shift_reg >>= 1;
536                                 hdlc->bit_shift--;
537                         }
538                         if(hdlc->bit_shift==0){
539                                 hdlc->shift_reg = 0x7e;
540                                 hdlc->state = HDLC_SEND_CLOSING_FLAG;
541                                 hdlc->bit_shift = 8;
542                         }
543                         break;
544                 case HDLC_SEND_CLOSING_FLAG:
545                         hdlc->cbin <<= 1;
546                         hdlc->data_bits++;
547                         if(hdlc->hdlc_bits1 == 5){
548                                 hdlc->hdlc_bits1 = 0;
549                                 break;
550                         }
551                         if(hdlc->shift_reg & 0x01){
552                                 hdlc->cbin++;
553                         }
554                         hdlc->shift_reg >>= 1;
555                         hdlc->bit_shift--;
556                         if(hdlc->bit_shift==0){
557                                 hdlc->ffvalue = xfast_flag_value[hdlc->data_bits];
558                                 if(hdlc->dchannel){
559                                         hdlc->ffvalue = 0x7e;
560                                         hdlc->state = HDLC_SEND_IDLE1;
561                                         hdlc->bit_shift = 8-hdlc->data_bits;
562                                         if(hdlc->bit_shift==0)
563                                                 hdlc->state = HDLC_SEND_FAST_IDLE;
564                                 } else {
565                                         if(!hdlc->do_adapt56){
566                                                 hdlc->state = HDLC_SEND_FAST_FLAG;
567                                                 hdlc->data_received = 0;
568                                         } else {
569                                                 hdlc->state = HDLC_SENDFLAG_B0;
570                                                 hdlc->data_received = 0;
571                                         }
572                                         // Finished with this frame, send flags
573                                         if (dsize > 1) dsize = 1;
574                                 }
575                         }
576                         break;
577                 case HDLC_SEND_IDLE1:
578                         hdlc->do_closing = 0;
579                         hdlc->cbin <<= 1;
580                         hdlc->cbin++;
581                         hdlc->data_bits++;
582                         hdlc->bit_shift--;
583                         if(hdlc->bit_shift==0){
584                                 hdlc->state = HDLC_SEND_FAST_IDLE;
585                                 hdlc->bit_shift = 0;
586                         }
587                         break;
588                 case HDLC_SEND_FAST_IDLE:
589                         hdlc->do_closing = 0;
590                         hdlc->cbin = 0xff;
591                         hdlc->data_bits = 8;
592                         if(hdlc->bit_shift == 8){
593                                 hdlc->cbin = 0x7e;
594                                 hdlc->state = HDLC_SEND_FIRST_FLAG;
595                         } else {
596                                 *dst++ = hdlc->cbin;
597                                 hdlc->bit_shift = hdlc->data_bits = 0;
598                                 len++;
599                                 dsize = 0;
600                         }
601                         break;
602                 default:
603                         break;
604                 }
605                 if(hdlc->do_adapt56){
606                         if(hdlc->data_bits==7){
607                                 hdlc->cbin <<= 1;
608                                 hdlc->cbin++;
609                                 hdlc->data_bits++;
610                         }
611                 }
612                 if(hdlc->data_bits==8){
613                         *dst++ = hdlc->cbin;
614                         hdlc->data_bits = 0;
615                         len++;
616                         dsize--;
617                 }
618         }
619         *count -= slen;
620
621         return len;
622 }
623
624 EXPORT_SYMBOL(isdnhdlc_bit_rev_tab);
625 EXPORT_SYMBOL(isdnhdlc_rcv_init);
626 EXPORT_SYMBOL(isdnhdlc_decode);
627 EXPORT_SYMBOL(isdnhdlc_out_init);
628 EXPORT_SYMBOL(isdnhdlc_encode);