Merge branch 'i2c/for-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
[linux-2.6-block.git] / drivers / isdn / i4l / isdnhdlc.c
CommitLineData
1da177e4
LT
1/*
2 * isdnhdlc.c -- General purpose ISDN HDLC decoder.
3 *
6bd4bcd3 4 * Copyright (C)
c38fc3bc 5 * 2009 Karsten Keil <keil@b1-systems.de>
6bd4bcd3
KK
6 * 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
7 * 2001 Frode Isaksen <fisaksen@bewan.com>
8 * 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
1da177e4 9 *
6bd4bcd3
KK
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.
1da177e4 14 *
6bd4bcd3
KK
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.
1da177e4 19 *
6bd4bcd3
KK
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.
1da177e4
LT
23 */
24
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/crc-ccitt.h>
cb3824ba 28#include <linux/isdn/hdlc.h>
c38fc3bc 29#include <linux/bitrev.h>
1da177e4
LT
30
31/*-------------------------------------------------------------------*/
32
96de0e25 33MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, "
1da177e4
LT
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
1da177e4 41enum {
6bd4bcd3
KK
42 HDLC_FAST_IDLE, HDLC_GET_FLAG_B0, HDLC_GETFLAG_B1A6, HDLC_GETFLAG_B7,
43 HDLC_GET_DATA, HDLC_FAST_FLAG
1da177e4
LT
44};
45
46enum {
6bd4bcd3
KK
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,
f3fad223 50 HDLC_SENDFLAG_B1A6, HDLC_SENDFLAG_B7, STOPPED, HDLC_SENDFLAG_ONE
1da177e4
LT
51};
52
c38fc3bc 53void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, u32 features)
1da177e4 54{
c38fc3bc 55 memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
1da177e4 56 hdlc->state = HDLC_GET_DATA;
c38fc3bc
KK
57 if (features & HDLC_56KBIT)
58 hdlc->do_adapt56 = 1;
59 if (features & HDLC_BITREVERSE)
60 hdlc->do_bitreverse = 1;
1da177e4 61}
6bd4bcd3 62EXPORT_SYMBOL(isdnhdlc_out_init);
1da177e4 63
c38fc3bc 64void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, u32 features)
1da177e4 65{
c38fc3bc
KK
66 memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
67 if (features & HDLC_DCHANNEL) {
1da177e4
LT
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;
c38fc3bc 76 if (features & HDLC_56KBIT) {
1da177e4 77 hdlc->do_adapt56 = 1;
1da177e4 78 hdlc->state = HDLC_SENDFLAG_B0;
c38fc3bc 79 } else
1da177e4 80 hdlc->data_bits = 8;
c38fc3bc
KK
81 if (features & HDLC_BITREVERSE)
82 hdlc->do_bitreverse = 1;
1da177e4 83}
6bd4bcd3
KK
84EXPORT_SYMBOL(isdnhdlc_rcv_init);
85
86static int
87check_frame(struct isdnhdlc_vars *hdlc)
88{
89 int status;
90
475be4d8 91 if (hdlc->dstpos < 2) /* too small - framing error */
6bd4bcd3
KK
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}
1da177e4
LT
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.
475be4d8 130*/
6bd4bcd3 131int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen,
475be4d8 132 int *count, u8 *dst, int dsize)
1da177e4 133{
6bd4bcd3 134 int status = 0;
1da177e4 135
6bd4bcd3
KK
136 static const unsigned char fast_flag[] = {
137 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f
1da177e4
LT
138 };
139
6bd4bcd3
KK
140 static const unsigned char fast_flag_value[] = {
141 0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f
1da177e4
LT
142 };
143
6bd4bcd3
KK
144 static const unsigned char fast_abort[] = {
145 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
1da177e4
LT
146 };
147
475be4d8
JP
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 } \
6bd4bcd3
KK
159 } while (0)
160
475be4d8
JP
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; \
6bd4bcd3
KK
170 } while (0)
171
1da177e4
LT
172 *count = slen;
173
6bd4bcd3
KK
174 while (slen > 0) {
175 if (hdlc->bit_shift == 0) {
c38fc3bc
KK
176 /* the code is for bitreverse streams */
177 if (hdlc->do_bitreverse == 0)
178 hdlc->cbin = bitrev8(*src++);
179 else
180 hdlc->cbin = *src++;
1da177e4
LT
181 slen--;
182 hdlc->bit_shift = 8;
6bd4bcd3
KK
183 if (hdlc->do_adapt56)
184 hdlc->bit_shift--;
1da177e4
LT
185 }
186
6bd4bcd3 187 switch (hdlc->state) {
1da177e4
LT
188 case STOPPED:
189 return 0;
190 case HDLC_FAST_IDLE:
6bd4bcd3 191 if (hdlc->cbin == 0xff) {
1da177e4
LT
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:
6bd4bcd3 200 if (!(hdlc->cbin & 0x80)) {
1da177e4
LT
201 hdlc->state = HDLC_GETFLAG_B1A6;
202 hdlc->hdlc_bits1 = 0;
203 } else {
6bd4bcd3
KK
204 if ((!hdlc->do_adapt56) &&
205 (++hdlc->hdlc_bits1 >= 8) &&
206 (hdlc->bit_shift == 1))
475be4d8 207 hdlc->state = HDLC_FAST_IDLE;
1da177e4 208 }
6bd4bcd3
KK
209 hdlc->cbin <<= 1;
210 hdlc->bit_shift--;
1da177e4
LT
211 break;
212 case HDLC_GETFLAG_B1A6:
6bd4bcd3 213 if (hdlc->cbin & 0x80) {
1da177e4 214 hdlc->hdlc_bits1++;
6bd4bcd3 215 if (hdlc->hdlc_bits1 == 6)
1da177e4 216 hdlc->state = HDLC_GETFLAG_B7;
6bd4bcd3 217 } else
1da177e4 218 hdlc->hdlc_bits1 = 0;
6bd4bcd3
KK
219 hdlc->cbin <<= 1;
220 hdlc->bit_shift--;
1da177e4
LT
221 break;
222 case HDLC_GETFLAG_B7:
6bd4bcd3 223 if (hdlc->cbin & 0x80) {
1da177e4
LT
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 }
6bd4bcd3
KK
233 hdlc->cbin <<= 1;
234 hdlc->bit_shift--;
1da177e4
LT
235 break;
236 case HDLC_GET_DATA:
6bd4bcd3 237 if (hdlc->cbin & 0x80) {
1da177e4 238 hdlc->hdlc_bits1++;
6bd4bcd3 239 switch (hdlc->hdlc_bits1) {
1da177e4
LT
240 case 6:
241 break;
242 case 7:
6bd4bcd3
KK
243 if (hdlc->data_received)
244 /* bad frame */
1da177e4 245 status = -HDLC_FRAMING_ERROR;
6bd4bcd3
KK
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;
1da177e4
LT
252 break;
253 }
6bd4bcd3 254 } else
1da177e4 255 hdlc->state = HDLC_GET_FLAG_B0;
1da177e4
LT
256 break;
257 default:
6bd4bcd3 258 hdlc->shift_reg >>= 1;
1da177e4
LT
259 hdlc->shift_reg |= 0x80;
260 hdlc->data_bits++;
261 break;
262 }
263 } else {
6bd4bcd3 264 switch (hdlc->hdlc_bits1) {
1da177e4
LT
265 case 5:
266 break;
267 case 6:
6bd4bcd3
KK
268 if (hdlc->data_received)
269 status = check_frame(hdlc);
1da177e4
LT
270 hdlc->crc = 0xffff;
271 hdlc->shift_reg = 0;
272 hdlc->data_bits = 0;
6bd4bcd3
KK
273 if (!hdlc->do_adapt56)
274 handle_fast_flag(hdlc);
275 else {
1da177e4
LT
276 hdlc->state = HDLC_GET_DATA;
277 hdlc->data_received = 0;
278 }
279 break;
280 default:
6bd4bcd3 281 hdlc->shift_reg >>= 1;
1da177e4
LT
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 }
6bd4bcd3 294 if (hdlc->data_bits == 8) {
1da177e4
LT
295 hdlc->data_bits = 0;
296 hdlc->data_received = 1;
6bd4bcd3 297 hdlc->crc = crc_ccitt_byte(hdlc->crc,
475be4d8 298 hdlc->shift_reg);
1da177e4 299
6bd4bcd3
KK
300 /* good byte received */
301 if (hdlc->dstpos < dsize)
1da177e4 302 dst[hdlc->dstpos++] = hdlc->shift_reg;
6bd4bcd3
KK
303 else {
304 /* frame too long */
1da177e4
LT
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:
6bd4bcd3 313 if (hdlc->cbin == hdlc->ffvalue) {
1da177e4
LT
314 hdlc->bit_shift = 0;
315 break;
316 } else {
6bd4bcd3 317 if (hdlc->cbin == 0xff) {
1da177e4 318 hdlc->state = HDLC_FAST_IDLE;
6bd4bcd3
KK
319 hdlc->bit_shift = 0;
320 } else if (hdlc->ffbit_shift == 8) {
1da177e4
LT
321 hdlc->state = HDLC_GETFLAG_B7;
322 break;
6bd4bcd3
KK
323 } else
324 handle_abort(hdlc);
1da177e4
LT
325 }
326 break;
327 default:
328 break;
329 }
330 }
331 *count -= slen;
332 return 0;
333}
6bd4bcd3 334EXPORT_SYMBOL(isdnhdlc_decode);
1da177e4
LT
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*/
6bd4bcd3 354int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen,
475be4d8 355 int *count, u8 *dst, int dsize)
1da177e4
LT
356{
357 static const unsigned char xfast_flag_value[] = {
6bd4bcd3 358 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e
1da177e4
LT
359 };
360
361 int len = 0;
362
363 *count = slen;
364
f3fad223
KK
365 /* special handling for one byte frames */
366 if ((slen == 1) && (hdlc->state == HDLC_SEND_FAST_FLAG))
367 hdlc->state = HDLC_SENDFLAG_ONE;
1da177e4 368 while (dsize > 0) {
6bd4bcd3
KK
369 if (hdlc->bit_shift == 0) {
370 if (slen && !hdlc->do_closing) {
1da177e4
LT
371 hdlc->shift_reg = *src++;
372 slen--;
373 if (slen == 0)
6bd4bcd3
KK
374 /* closing sequence, CRC + flag(s) */
375 hdlc->do_closing = 1;
1da177e4
LT
376 hdlc->bit_shift = 8;
377 } else {
6bd4bcd3
KK
378 if (hdlc->state == HDLC_SEND_DATA) {
379 if (hdlc->data_received) {
1da177e4
LT
380 hdlc->state = HDLC_SEND_CRC1;
381 hdlc->crc ^= 0xffff;
382 hdlc->bit_shift = 8;
6bd4bcd3
KK
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;
1da177e4
LT
391 }
392
393 }
394 }
395
6bd4bcd3 396 switch (hdlc->state) {
1da177e4
LT
397 case STOPPED:
398 while (dsize--)
399 *dst++ = 0xff;
1da177e4
LT
400 return dsize;
401 case HDLC_SEND_FAST_FLAG:
402 hdlc->do_closing = 0;
6bd4bcd3 403 if (slen == 0) {
c38fc3bc
KK
404 /* the code is for bitreverse streams */
405 if (hdlc->do_bitreverse == 0)
406 *dst++ = bitrev8(hdlc->ffvalue);
407 else
408 *dst++ = hdlc->ffvalue;
1da177e4
LT
409 len++;
410 dsize--;
411 break;
412 }
f3fad223
KK
413 /* fall through */
414 case HDLC_SENDFLAG_ONE:
6bd4bcd3
KK
415 if (hdlc->bit_shift == 8) {
416 hdlc->cbin = hdlc->ffvalue >>
417 (8 - hdlc->data_bits);
1da177e4
LT
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++;
6bd4bcd3 435 if (++hdlc->hdlc_bits1 == 6)
1da177e4
LT
436 hdlc->state = HDLC_SENDFLAG_B7;
437 break;
438 case HDLC_SENDFLAG_B7:
439 hdlc->cbin <<= 1;
440 hdlc->data_bits++;
6bd4bcd3 441 if (slen == 0) {
1da177e4
LT
442 hdlc->state = HDLC_SENDFLAG_B0;
443 break;
444 }
6bd4bcd3 445 if (hdlc->bit_shift == 8) {
1da177e4
LT
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;
6bd4bcd3 454 if (hdlc->data_bits == 8) {
1da177e4
LT
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++;
6bd4bcd3 462 if (hdlc->shift_reg & 0x01)
1da177e4
LT
463 hdlc->cbin++;
464 hdlc->shift_reg >>= 1;
465 hdlc->bit_shift--;
6bd4bcd3 466 if (hdlc->bit_shift == 0) {
1da177e4
LT
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++;
6bd4bcd3 475 if (hdlc->hdlc_bits1 == 5) {
1da177e4
LT
476 hdlc->hdlc_bits1 = 0;
477 break;
478 }
6bd4bcd3
KK
479 if (hdlc->bit_shift == 8)
480 hdlc->crc = crc_ccitt_byte(hdlc->crc,
475be4d8 481 hdlc->shift_reg);
6bd4bcd3 482 if (hdlc->shift_reg & 0x01) {
1da177e4
LT
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++;
6bd4bcd3 496 if (hdlc->hdlc_bits1 == 5) {
1da177e4
LT
497 hdlc->hdlc_bits1 = 0;
498 break;
499 }
6bd4bcd3 500 if (hdlc->shift_reg & 0x01) {
1da177e4
LT
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 }
6bd4bcd3 510 if (hdlc->bit_shift == 0) {
1da177e4
LT
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++;
6bd4bcd3 519 if (hdlc->hdlc_bits1 == 5) {
1da177e4
LT
520 hdlc->hdlc_bits1 = 0;
521 break;
522 }
6bd4bcd3 523 if (hdlc->shift_reg & 0x01) {
1da177e4
LT
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 }
6bd4bcd3 533 if (hdlc->bit_shift == 0) {
1da177e4
LT
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++;
6bd4bcd3 542 if (hdlc->hdlc_bits1 == 5) {
1da177e4
LT
543 hdlc->hdlc_bits1 = 0;
544 break;
545 }
6bd4bcd3 546 if (hdlc->shift_reg & 0x01)
1da177e4 547 hdlc->cbin++;
1da177e4
LT
548 hdlc->shift_reg >>= 1;
549 hdlc->bit_shift--;
6bd4bcd3
KK
550 if (hdlc->bit_shift == 0) {
551 hdlc->ffvalue =
552 xfast_flag_value[hdlc->data_bits];
553 if (hdlc->dchannel) {
1da177e4
LT
554 hdlc->ffvalue = 0x7e;
555 hdlc->state = HDLC_SEND_IDLE1;
556 hdlc->bit_shift = 8-hdlc->data_bits;
6bd4bcd3
KK
557 if (hdlc->bit_shift == 0)
558 hdlc->state =
559 HDLC_SEND_FAST_IDLE;
1da177e4 560 } else {
6bd4bcd3
KK
561 if (!hdlc->do_adapt56) {
562 hdlc->state =
563 HDLC_SEND_FAST_FLAG;
1da177e4
LT
564 hdlc->data_received = 0;
565 } else {
566 hdlc->state = HDLC_SENDFLAG_B0;
567 hdlc->data_received = 0;
568 }
6bd4bcd3
KK
569 /* Finished this frame, send flags */
570 if (dsize > 1)
571 dsize = 1;
1da177e4
LT
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--;
6bd4bcd3 581 if (hdlc->bit_shift == 0) {
1da177e4
LT
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;
6bd4bcd3 590 if (hdlc->bit_shift == 8) {
1da177e4
LT
591 hdlc->cbin = 0x7e;
592 hdlc->state = HDLC_SEND_FIRST_FLAG;
593 } else {
c38fc3bc
KK
594 /* the code is for bitreverse streams */
595 if (hdlc->do_bitreverse == 0)
596 *dst++ = bitrev8(hdlc->cbin);
597 else
598 *dst++ = hdlc->cbin;
6bd4bcd3
KK
599 hdlc->bit_shift = 0;
600 hdlc->data_bits = 0;
1da177e4
LT
601 len++;
602 dsize = 0;
603 }
604 break;
605 default:
606 break;
607 }
6bd4bcd3
KK
608 if (hdlc->do_adapt56) {
609 if (hdlc->data_bits == 7) {
1da177e4
LT
610 hdlc->cbin <<= 1;
611 hdlc->cbin++;
612 hdlc->data_bits++;
613 }
614 }
6bd4bcd3 615 if (hdlc->data_bits == 8) {
c38fc3bc
KK
616 /* the code is for bitreverse streams */
617 if (hdlc->do_bitreverse == 0)
618 *dst++ = bitrev8(hdlc->cbin);
619 else
620 *dst++ = hdlc->cbin;
1da177e4
LT
621 hdlc->data_bits = 0;
622 len++;
623 dsize--;
624 }
625 }
626 *count -= slen;
627
628 return len;
629}
1da177e4 630EXPORT_SYMBOL(isdnhdlc_encode);