Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * isdnhdlc.c -- General purpose ISDN HDLC decoder. | |
3 | * | |
96de0e25 | 4 | *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de> |
1da177e4 LT |
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 | ||
96de0e25 | 30 | MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, " |
1da177e4 LT |
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 | ||
1da177e4 LT |
38 | enum { |
39 | HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7, | |
40 | HDLC_GET_DATA,HDLC_FAST_FLAG | |
41 | }; | |
42 | ||
43 | enum { | |
44 | HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG, | |
45 | HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG, | |
46 | HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0, | |
47 | HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED | |
48 | }; | |
49 | ||
50 | void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56) | |
51 | { | |
52 | hdlc->bit_shift = 0; | |
53 | hdlc->hdlc_bits1 = 0; | |
54 | hdlc->data_bits = 0; | |
55 | hdlc->ffbit_shift = 0; | |
56 | hdlc->data_received = 0; | |
57 | hdlc->state = HDLC_GET_DATA; | |
58 | hdlc->do_adapt56 = do_adapt56; | |
59 | hdlc->dchannel = 0; | |
60 | hdlc->crc = 0; | |
61 | hdlc->cbin = 0; | |
62 | hdlc->shift_reg = 0; | |
63 | hdlc->ffvalue = 0; | |
64 | hdlc->dstpos = 0; | |
65 | } | |
66 | ||
67 | void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56) | |
68 | { | |
69 | hdlc->bit_shift = 0; | |
70 | hdlc->hdlc_bits1 = 0; | |
71 | hdlc->data_bits = 0; | |
72 | hdlc->ffbit_shift = 0; | |
73 | hdlc->data_received = 0; | |
74 | hdlc->do_closing = 0; | |
75 | hdlc->ffvalue = 0; | |
76 | if (is_d_channel) { | |
77 | hdlc->dchannel = 1; | |
78 | hdlc->state = HDLC_SEND_FIRST_FLAG; | |
79 | } else { | |
80 | hdlc->dchannel = 0; | |
81 | hdlc->state = HDLC_SEND_FAST_FLAG; | |
82 | hdlc->ffvalue = 0x7e; | |
83 | } | |
84 | hdlc->cbin = 0x7e; | |
85 | hdlc->bit_shift = 0; | |
86 | if(do_adapt56){ | |
87 | hdlc->do_adapt56 = 1; | |
88 | hdlc->data_bits = 0; | |
89 | hdlc->state = HDLC_SENDFLAG_B0; | |
90 | } else { | |
91 | hdlc->do_adapt56 = 0; | |
92 | hdlc->data_bits = 8; | |
93 | } | |
94 | hdlc->shift_reg = 0; | |
95 | } | |
96 | ||
97 | /* | |
98 | isdnhdlc_decode - decodes HDLC frames from a transparent bit stream. | |
99 | ||
100 | The source buffer is scanned for valid HDLC frames looking for | |
101 | flags (01111110) to indicate the start of a frame. If the start of | |
102 | the frame is found, the bit stuffing is removed (0 after 5 1's). | |
103 | When a new flag is found, the complete frame has been received | |
104 | and the CRC is checked. | |
105 | If a valid frame is found, the function returns the frame length | |
106 | excluding the CRC with the bit HDLC_END_OF_FRAME set. | |
107 | If the beginning of a valid frame is found, the function returns | |
108 | the length. | |
109 | If a framing error is found (too many 1s and not a flag) the function | |
110 | returns the length with the bit HDLC_FRAMING_ERROR set. | |
111 | If a CRC error is found the function returns the length with the | |
112 | bit HDLC_CRC_ERROR set. | |
113 | If the frame length exceeds the destination buffer size, the function | |
114 | returns the length with the bit HDLC_LENGTH_ERROR set. | |
115 | ||
116 | src - source buffer | |
117 | slen - source buffer length | |
118 | count - number of bytes removed (decoded) from the source buffer | |
119 | dst _ destination buffer | |
120 | dsize - destination buffer size | |
121 | returns - number of decoded bytes in the destination buffer and status | |
122 | flag. | |
123 | */ | |
124 | int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, | |
125 | int slen, int *count, unsigned char *dst, int dsize) | |
126 | { | |
127 | int status=0; | |
128 | ||
129 | static const unsigned char fast_flag[]={ | |
130 | 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f | |
131 | }; | |
132 | ||
133 | static const unsigned char fast_flag_value[]={ | |
134 | 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f | |
135 | }; | |
136 | ||
137 | static const unsigned char fast_abort[]={ | |
138 | 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff | |
139 | }; | |
140 | ||
141 | *count = slen; | |
142 | ||
143 | while(slen > 0){ | |
144 | if(hdlc->bit_shift==0){ | |
145 | hdlc->cbin = *src++; | |
146 | slen--; | |
147 | hdlc->bit_shift = 8; | |
148 | if(hdlc->do_adapt56){ | |
149 | hdlc->bit_shift --; | |
150 | } | |
151 | } | |
152 | ||
153 | switch(hdlc->state){ | |
154 | case STOPPED: | |
155 | return 0; | |
156 | case HDLC_FAST_IDLE: | |
157 | if(hdlc->cbin == 0xff){ | |
158 | hdlc->bit_shift = 0; | |
159 | break; | |
160 | } | |
161 | hdlc->state = HDLC_GET_FLAG_B0; | |
162 | hdlc->hdlc_bits1 = 0; | |
163 | hdlc->bit_shift = 8; | |
164 | break; | |
165 | case HDLC_GET_FLAG_B0: | |
166 | if(!(hdlc->cbin & 0x80)) { | |
167 | hdlc->state = HDLC_GETFLAG_B1A6; | |
168 | hdlc->hdlc_bits1 = 0; | |
169 | } else { | |
170 | if(!hdlc->do_adapt56){ | |
171 | if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1) | |
172 | hdlc->state = HDLC_FAST_IDLE; | |
173 | } | |
174 | } | |
175 | hdlc->cbin<<=1; | |
176 | hdlc->bit_shift --; | |
177 | break; | |
178 | case HDLC_GETFLAG_B1A6: | |
179 | if(hdlc->cbin & 0x80){ | |
180 | hdlc->hdlc_bits1++; | |
181 | if(hdlc->hdlc_bits1==6){ | |
182 | hdlc->state = HDLC_GETFLAG_B7; | |
183 | } | |
184 | } else { | |
185 | hdlc->hdlc_bits1 = 0; | |
186 | } | |
187 | hdlc->cbin<<=1; | |
188 | hdlc->bit_shift --; | |
189 | break; | |
190 | case HDLC_GETFLAG_B7: | |
191 | if(hdlc->cbin & 0x80) { | |
192 | hdlc->state = HDLC_GET_FLAG_B0; | |
193 | } else { | |
194 | hdlc->state = HDLC_GET_DATA; | |
195 | hdlc->crc = 0xffff; | |
196 | hdlc->shift_reg = 0; | |
197 | hdlc->hdlc_bits1 = 0; | |
198 | hdlc->data_bits = 0; | |
199 | hdlc->data_received = 0; | |
200 | } | |
201 | hdlc->cbin<<=1; | |
202 | hdlc->bit_shift --; | |
203 | break; | |
204 | case HDLC_GET_DATA: | |
205 | if(hdlc->cbin & 0x80){ | |
206 | hdlc->hdlc_bits1++; | |
207 | switch(hdlc->hdlc_bits1){ | |
208 | case 6: | |
209 | break; | |
210 | case 7: | |
211 | if(hdlc->data_received) { | |
212 | // bad frame | |
213 | status = -HDLC_FRAMING_ERROR; | |
214 | } | |
215 | if(!hdlc->do_adapt56){ | |
216 | if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){ | |
217 | hdlc->state = HDLC_FAST_IDLE; | |
218 | hdlc->bit_shift=1; | |
219 | break; | |
220 | } | |
221 | } else { | |
222 | hdlc->state = HDLC_GET_FLAG_B0; | |
223 | } | |
224 | break; | |
225 | default: | |
226 | hdlc->shift_reg>>=1; | |
227 | hdlc->shift_reg |= 0x80; | |
228 | hdlc->data_bits++; | |
229 | break; | |
230 | } | |
231 | } else { | |
232 | switch(hdlc->hdlc_bits1){ | |
233 | case 5: | |
234 | break; | |
235 | case 6: | |
236 | if(hdlc->data_received){ | |
237 | if (hdlc->dstpos < 2) { | |
238 | status = -HDLC_FRAMING_ERROR; | |
239 | } else if (hdlc->crc != 0xf0b8){ | |
240 | // crc error | |
241 | status = -HDLC_CRC_ERROR; | |
242 | } else { | |
243 | // remove CRC | |
244 | hdlc->dstpos -= 2; | |
245 | // good frame | |
246 | status = hdlc->dstpos; | |
247 | } | |
248 | } | |
249 | hdlc->crc = 0xffff; | |
250 | hdlc->shift_reg = 0; | |
251 | hdlc->data_bits = 0; | |
252 | if(!hdlc->do_adapt56){ | |
253 | if(hdlc->cbin==fast_flag[hdlc->bit_shift]){ | |
254 | hdlc->ffvalue = fast_flag_value[hdlc->bit_shift]; | |
255 | hdlc->state = HDLC_FAST_FLAG; | |
256 | hdlc->ffbit_shift = hdlc->bit_shift; | |
257 | hdlc->bit_shift = 1; | |
258 | } else { | |
259 | hdlc->state = HDLC_GET_DATA; | |
260 | hdlc->data_received = 0; | |
261 | } | |
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, hdlc->shift_reg); | |
285 | ||
286 | // good byte received | |
287 | if (hdlc->dstpos < dsize) { | |
288 | dst[hdlc->dstpos++] = hdlc->shift_reg; | |
289 | } else { | |
290 | // frame too long | |
291 | status = -HDLC_LENGTH_ERROR; | |
292 | hdlc->dstpos = 0; | |
293 | } | |
294 | } | |
295 | hdlc->cbin <<= 1; | |
296 | hdlc->bit_shift--; | |
297 | break; | |
298 | case HDLC_FAST_FLAG: | |
299 | if(hdlc->cbin==hdlc->ffvalue){ | |
300 | hdlc->bit_shift = 0; | |
301 | break; | |
302 | } else { | |
303 | if(hdlc->cbin == 0xff){ | |
304 | hdlc->state = HDLC_FAST_IDLE; | |
305 | hdlc->bit_shift=0; | |
306 | } else if(hdlc->ffbit_shift==8){ | |
307 | hdlc->state = HDLC_GETFLAG_B7; | |
308 | break; | |
309 | } else { | |
310 | hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1]; | |
311 | hdlc->hdlc_bits1 = hdlc->ffbit_shift-2; | |
312 | if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0; | |
313 | hdlc->data_bits = hdlc->ffbit_shift-1; | |
314 | hdlc->state = HDLC_GET_DATA; | |
315 | hdlc->data_received = 0; | |
316 | } | |
317 | } | |
318 | break; | |
319 | default: | |
320 | break; | |
321 | } | |
322 | } | |
323 | *count -= slen; | |
324 | return 0; | |
325 | } | |
326 | ||
327 | /* | |
328 | isdnhdlc_encode - encodes HDLC frames to a transparent bit stream. | |
329 | ||
330 | The bit stream starts with a beginning flag (01111110). After | |
331 | that each byte is added to the bit stream with bit stuffing added | |
332 | (0 after 5 1's). | |
333 | When the last byte has been removed from the source buffer, the | |
334 | CRC (2 bytes is added) and the frame terminates with the ending flag. | |
335 | For the dchannel, the idle character (all 1's) is also added at the end. | |
336 | If this function is called with empty source buffer (slen=0), flags or | |
337 | idle character will be generated. | |
338 | ||
339 | src - source buffer | |
340 | slen - source buffer length | |
341 | count - number of bytes removed (encoded) from source buffer | |
342 | dst _ destination buffer | |
343 | dsize - destination buffer size | |
344 | returns - number of encoded bytes in the destination buffer | |
345 | */ | |
346 | int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, | |
347 | unsigned short slen, int *count, | |
348 | unsigned char *dst, int dsize) | |
349 | { | |
350 | static const unsigned char xfast_flag_value[] = { | |
351 | 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e | |
352 | }; | |
353 | ||
354 | int len = 0; | |
355 | ||
356 | *count = slen; | |
357 | ||
358 | while (dsize > 0) { | |
359 | if(hdlc->bit_shift==0){ | |
360 | if(slen && !hdlc->do_closing){ | |
361 | hdlc->shift_reg = *src++; | |
362 | slen--; | |
363 | if (slen == 0) | |
364 | hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */ | |
365 | hdlc->bit_shift = 8; | |
366 | } else { | |
367 | if(hdlc->state == HDLC_SEND_DATA){ | |
368 | if(hdlc->data_received){ | |
369 | hdlc->state = HDLC_SEND_CRC1; | |
370 | hdlc->crc ^= 0xffff; | |
371 | hdlc->bit_shift = 8; | |
372 | hdlc->shift_reg = hdlc->crc & 0xff; | |
373 | } else if(!hdlc->do_adapt56){ | |
374 | hdlc->state = HDLC_SEND_FAST_FLAG; | |
375 | } else { | |
376 | hdlc->state = HDLC_SENDFLAG_B0; | |
377 | } | |
378 | } | |
379 | ||
380 | } | |
381 | } | |
382 | ||
383 | switch(hdlc->state){ | |
384 | case STOPPED: | |
385 | while (dsize--) | |
386 | *dst++ = 0xff; | |
387 | ||
388 | return dsize; | |
389 | case HDLC_SEND_FAST_FLAG: | |
390 | hdlc->do_closing = 0; | |
391 | if(slen == 0){ | |
392 | *dst++ = hdlc->ffvalue; | |
393 | len++; | |
394 | dsize--; | |
395 | break; | |
396 | } | |
397 | if(hdlc->bit_shift==8){ | |
398 | hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits); | |
399 | hdlc->state = HDLC_SEND_DATA; | |
400 | hdlc->crc = 0xffff; | |
401 | hdlc->hdlc_bits1 = 0; | |
402 | hdlc->data_received = 1; | |
403 | } | |
404 | break; | |
405 | case HDLC_SENDFLAG_B0: | |
406 | hdlc->do_closing = 0; | |
407 | hdlc->cbin <<= 1; | |
408 | hdlc->data_bits++; | |
409 | hdlc->hdlc_bits1 = 0; | |
410 | hdlc->state = HDLC_SENDFLAG_B1A6; | |
411 | break; | |
412 | case HDLC_SENDFLAG_B1A6: | |
413 | hdlc->cbin <<= 1; | |
414 | hdlc->data_bits++; | |
415 | hdlc->cbin++; | |
416 | if(++hdlc->hdlc_bits1 == 6) | |
417 | hdlc->state = HDLC_SENDFLAG_B7; | |
418 | break; | |
419 | case HDLC_SENDFLAG_B7: | |
420 | hdlc->cbin <<= 1; | |
421 | hdlc->data_bits++; | |
422 | if(slen == 0){ | |
423 | hdlc->state = HDLC_SENDFLAG_B0; | |
424 | break; | |
425 | } | |
426 | if(hdlc->bit_shift==8){ | |
427 | hdlc->state = HDLC_SEND_DATA; | |
428 | hdlc->crc = 0xffff; | |
429 | hdlc->hdlc_bits1 = 0; | |
430 | hdlc->data_received = 1; | |
431 | } | |
432 | break; | |
433 | case HDLC_SEND_FIRST_FLAG: | |
434 | hdlc->data_received = 1; | |
435 | if(hdlc->data_bits==8){ | |
436 | hdlc->state = HDLC_SEND_DATA; | |
437 | hdlc->crc = 0xffff; | |
438 | hdlc->hdlc_bits1 = 0; | |
439 | break; | |
440 | } | |
441 | hdlc->cbin <<= 1; | |
442 | hdlc->data_bits++; | |
443 | if(hdlc->shift_reg & 0x01) | |
444 | hdlc->cbin++; | |
445 | hdlc->shift_reg >>= 1; | |
446 | hdlc->bit_shift--; | |
447 | if(hdlc->bit_shift==0){ | |
448 | hdlc->state = HDLC_SEND_DATA; | |
449 | hdlc->crc = 0xffff; | |
450 | hdlc->hdlc_bits1 = 0; | |
451 | } | |
452 | break; | |
453 | case HDLC_SEND_DATA: | |
454 | hdlc->cbin <<= 1; | |
455 | hdlc->data_bits++; | |
456 | if(hdlc->hdlc_bits1 == 5){ | |
457 | hdlc->hdlc_bits1 = 0; | |
458 | break; | |
459 | } | |
460 | if(hdlc->bit_shift==8){ | |
461 | hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); | |
462 | } | |
463 | if(hdlc->shift_reg & 0x01){ | |
464 | hdlc->hdlc_bits1++; | |
465 | hdlc->cbin++; | |
466 | hdlc->shift_reg >>= 1; | |
467 | hdlc->bit_shift--; | |
468 | } else { | |
469 | hdlc->hdlc_bits1 = 0; | |
470 | hdlc->shift_reg >>= 1; | |
471 | hdlc->bit_shift--; | |
472 | } | |
473 | break; | |
474 | case HDLC_SEND_CRC1: | |
475 | hdlc->cbin <<= 1; | |
476 | hdlc->data_bits++; | |
477 | if(hdlc->hdlc_bits1 == 5){ | |
478 | hdlc->hdlc_bits1 = 0; | |
479 | break; | |
480 | } | |
481 | if(hdlc->shift_reg & 0x01){ | |
482 | hdlc->hdlc_bits1++; | |
483 | hdlc->cbin++; | |
484 | hdlc->shift_reg >>= 1; | |
485 | hdlc->bit_shift--; | |
486 | } else { | |
487 | hdlc->hdlc_bits1 = 0; | |
488 | hdlc->shift_reg >>= 1; | |
489 | hdlc->bit_shift--; | |
490 | } | |
491 | if(hdlc->bit_shift==0){ | |
492 | hdlc->shift_reg = (hdlc->crc >> 8); | |
493 | hdlc->state = HDLC_SEND_CRC2; | |
494 | hdlc->bit_shift = 8; | |
495 | } | |
496 | break; | |
497 | case HDLC_SEND_CRC2: | |
498 | hdlc->cbin <<= 1; | |
499 | hdlc->data_bits++; | |
500 | if(hdlc->hdlc_bits1 == 5){ | |
501 | hdlc->hdlc_bits1 = 0; | |
502 | break; | |
503 | } | |
504 | if(hdlc->shift_reg & 0x01){ | |
505 | hdlc->hdlc_bits1++; | |
506 | hdlc->cbin++; | |
507 | hdlc->shift_reg >>= 1; | |
508 | hdlc->bit_shift--; | |
509 | } else { | |
510 | hdlc->hdlc_bits1 = 0; | |
511 | hdlc->shift_reg >>= 1; | |
512 | hdlc->bit_shift--; | |
513 | } | |
514 | if(hdlc->bit_shift==0){ | |
515 | hdlc->shift_reg = 0x7e; | |
516 | hdlc->state = HDLC_SEND_CLOSING_FLAG; | |
517 | hdlc->bit_shift = 8; | |
518 | } | |
519 | break; | |
520 | case HDLC_SEND_CLOSING_FLAG: | |
521 | hdlc->cbin <<= 1; | |
522 | hdlc->data_bits++; | |
523 | if(hdlc->hdlc_bits1 == 5){ | |
524 | hdlc->hdlc_bits1 = 0; | |
525 | break; | |
526 | } | |
527 | if(hdlc->shift_reg & 0x01){ | |
528 | hdlc->cbin++; | |
529 | } | |
530 | hdlc->shift_reg >>= 1; | |
531 | hdlc->bit_shift--; | |
532 | if(hdlc->bit_shift==0){ | |
533 | hdlc->ffvalue = xfast_flag_value[hdlc->data_bits]; | |
534 | if(hdlc->dchannel){ | |
535 | hdlc->ffvalue = 0x7e; | |
536 | hdlc->state = HDLC_SEND_IDLE1; | |
537 | hdlc->bit_shift = 8-hdlc->data_bits; | |
538 | if(hdlc->bit_shift==0) | |
539 | hdlc->state = HDLC_SEND_FAST_IDLE; | |
540 | } else { | |
541 | if(!hdlc->do_adapt56){ | |
542 | hdlc->state = HDLC_SEND_FAST_FLAG; | |
543 | hdlc->data_received = 0; | |
544 | } else { | |
545 | hdlc->state = HDLC_SENDFLAG_B0; | |
546 | hdlc->data_received = 0; | |
547 | } | |
548 | // Finished with this frame, send flags | |
549 | if (dsize > 1) dsize = 1; | |
550 | } | |
551 | } | |
552 | break; | |
553 | case HDLC_SEND_IDLE1: | |
554 | hdlc->do_closing = 0; | |
555 | hdlc->cbin <<= 1; | |
556 | hdlc->cbin++; | |
557 | hdlc->data_bits++; | |
558 | hdlc->bit_shift--; | |
559 | if(hdlc->bit_shift==0){ | |
560 | hdlc->state = HDLC_SEND_FAST_IDLE; | |
561 | hdlc->bit_shift = 0; | |
562 | } | |
563 | break; | |
564 | case HDLC_SEND_FAST_IDLE: | |
565 | hdlc->do_closing = 0; | |
566 | hdlc->cbin = 0xff; | |
567 | hdlc->data_bits = 8; | |
568 | if(hdlc->bit_shift == 8){ | |
569 | hdlc->cbin = 0x7e; | |
570 | hdlc->state = HDLC_SEND_FIRST_FLAG; | |
571 | } else { | |
572 | *dst++ = hdlc->cbin; | |
573 | hdlc->bit_shift = hdlc->data_bits = 0; | |
574 | len++; | |
575 | dsize = 0; | |
576 | } | |
577 | break; | |
578 | default: | |
579 | break; | |
580 | } | |
581 | if(hdlc->do_adapt56){ | |
582 | if(hdlc->data_bits==7){ | |
583 | hdlc->cbin <<= 1; | |
584 | hdlc->cbin++; | |
585 | hdlc->data_bits++; | |
586 | } | |
587 | } | |
588 | if(hdlc->data_bits==8){ | |
589 | *dst++ = hdlc->cbin; | |
590 | hdlc->data_bits = 0; | |
591 | len++; | |
592 | dsize--; | |
593 | } | |
594 | } | |
595 | *count -= slen; | |
596 | ||
597 | return len; | |
598 | } | |
599 | ||
1da177e4 LT |
600 | EXPORT_SYMBOL(isdnhdlc_rcv_init); |
601 | EXPORT_SYMBOL(isdnhdlc_decode); | |
602 | EXPORT_SYMBOL(isdnhdlc_out_init); | |
603 | EXPORT_SYMBOL(isdnhdlc_encode); |