blob: 8ec1c956cdd4326ada3a35b90ca2af9f64812ba1 [file] [log] [blame]
Harald Welte85b9fba2018-05-11 17:36:13 +02001/*
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 *
Harald Welte9da77ab2018-05-11 17:39:21 +020010 * slightly adapted for use in userspace / osmocom envrionment by Harald Welte
11 *
Harald Welte85b9fba2018-05-11 17:36:13 +020012 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
Harald Welte85b9fba2018-05-11 17:36:13 +020021 */
22
Harald Welte9da77ab2018-05-11 17:39:21 +020023#include <string.h>
Harald Welte85b9fba2018-05-11 17:36:13 +020024
Harald Welte9da77ab2018-05-11 17:39:21 +020025#include <osmocom/core/crc16.h>
26#include <osmocom/core/bits.h>
27#include <osmocom/core/isdnhdlc.h>
Harald Welte85b9fba2018-05-11 17:36:13 +020028
29enum {
30 HDLC_FAST_IDLE, HDLC_GET_FLAG_B0, HDLC_GETFLAG_B1A6, HDLC_GETFLAG_B7,
31 HDLC_GET_DATA, HDLC_FAST_FLAG
32};
33
34enum {
35 HDLC_SEND_DATA, HDLC_SEND_CRC1, HDLC_SEND_FAST_FLAG,
36 HDLC_SEND_FIRST_FLAG, HDLC_SEND_CRC2, HDLC_SEND_CLOSING_FLAG,
37 HDLC_SEND_IDLE1, HDLC_SEND_FAST_IDLE, HDLC_SENDFLAG_B0,
38 HDLC_SENDFLAG_B1A6, HDLC_SENDFLAG_B7, STOPPED, HDLC_SENDFLAG_ONE
39};
40
Harald Welte9da77ab2018-05-11 17:39:21 +020041#define crc_ccitt_byte osmo_crc16_ccitt_byte
42
43void osmo_isdnhdlc_rcv_init(struct osmo_isdnhdlc_vars *hdlc, uint32_t features)
Harald Welte85b9fba2018-05-11 17:36:13 +020044{
Harald Welte9da77ab2018-05-11 17:39:21 +020045 memset(hdlc, 0, sizeof(*hdlc));
Harald Welte85b9fba2018-05-11 17:36:13 +020046 hdlc->state = HDLC_GET_DATA;
Harald Welte9da77ab2018-05-11 17:39:21 +020047 if (features & OSMO_HDLC_F_56KBIT)
Harald Welte85b9fba2018-05-11 17:36:13 +020048 hdlc->do_adapt56 = 1;
Harald Welte9da77ab2018-05-11 17:39:21 +020049 if (features & OSMO_HDLC_F_BITREVERSE)
Harald Welte85b9fba2018-05-11 17:36:13 +020050 hdlc->do_bitreverse = 1;
51}
Harald Welte85b9fba2018-05-11 17:36:13 +020052
Harald Welte9da77ab2018-05-11 17:39:21 +020053void osmo_isdnhdlc_out_init(struct osmo_isdnhdlc_vars *hdlc, uint32_t features)
Harald Welte85b9fba2018-05-11 17:36:13 +020054{
Harald Welte9da77ab2018-05-11 17:39:21 +020055 memset(hdlc, 0, sizeof(*hdlc));
56 if (features & OSMO_HDLC_F_DCHANNEL) {
Harald Welte85b9fba2018-05-11 17:36:13 +020057 hdlc->dchannel = 1;
58 hdlc->state = HDLC_SEND_FIRST_FLAG;
59 } else {
60 hdlc->dchannel = 0;
61 hdlc->state = HDLC_SEND_FAST_FLAG;
62 hdlc->ffvalue = 0x7e;
63 }
64 hdlc->cbin = 0x7e;
Harald Welte9da77ab2018-05-11 17:39:21 +020065 if (features & OSMO_HDLC_F_56KBIT) {
Harald Welte85b9fba2018-05-11 17:36:13 +020066 hdlc->do_adapt56 = 1;
67 hdlc->state = HDLC_SENDFLAG_B0;
68 } else
69 hdlc->data_bits = 8;
Harald Welte9da77ab2018-05-11 17:39:21 +020070 if (features & OSMO_HDLC_F_BITREVERSE)
Harald Welte85b9fba2018-05-11 17:36:13 +020071 hdlc->do_bitreverse = 1;
72}
Harald Welte85b9fba2018-05-11 17:36:13 +020073
74static int
Harald Welte9da77ab2018-05-11 17:39:21 +020075check_frame(struct osmo_isdnhdlc_vars *hdlc)
Harald Welte85b9fba2018-05-11 17:36:13 +020076{
77 int status;
78
79 if (hdlc->dstpos < 2) /* too small - framing error */
Harald Welte9da77ab2018-05-11 17:39:21 +020080 status = -OSMO_HDLC_FRAMING_ERROR;
Harald Welte85b9fba2018-05-11 17:36:13 +020081 else if (hdlc->crc != 0xf0b8) /* crc error */
Harald Welte9da77ab2018-05-11 17:39:21 +020082 status = -OSMO_HDLC_CRC_ERROR;
Harald Welte85b9fba2018-05-11 17:36:13 +020083 else {
84 /* remove CRC */
85 hdlc->dstpos -= 2;
86 /* good frame */
87 status = hdlc->dstpos;
88 }
89 return status;
90}
91
Harald Welte9da77ab2018-05-11 17:39:21 +020092/*! decodes HDLC frames from a transparent bit stream.
Harald Welte85b9fba2018-05-11 17:36:13 +020093
94 The source buffer is scanned for valid HDLC frames looking for
95 flags (01111110) to indicate the start of a frame. If the start of
96 the frame is found, the bit stuffing is removed (0 after 5 1's).
97 When a new flag is found, the complete frame has been received
98 and the CRC is checked.
99 If a valid frame is found, the function returns the frame length
100 excluding the CRC with the bit HDLC_END_OF_FRAME set.
101 If the beginning of a valid frame is found, the function returns
102 the length.
103 If a framing error is found (too many 1s and not a flag) the function
Harald Welte9da77ab2018-05-11 17:39:21 +0200104 returns the length with the bit OSMO_HDLC_FRAMING_ERROR set.
Harald Welte85b9fba2018-05-11 17:36:13 +0200105 If a CRC error is found the function returns the length with the
Harald Welte9da77ab2018-05-11 17:39:21 +0200106 bit OSMO_HDLC_CRC_ERROR set.
Harald Welte85b9fba2018-05-11 17:36:13 +0200107 If the frame length exceeds the destination buffer size, the function
Harald Welte9da77ab2018-05-11 17:39:21 +0200108 returns the length with the bit OSMO_HDLC_LENGTH_ERROR set.
Harald Welte85b9fba2018-05-11 17:36:13 +0200109
Harald Welte9da77ab2018-05-11 17:39:21 +0200110 \param[in] src source buffer
111 \param[in] slen source buffer length
112 \param[out] count number of bytes removed (decoded) from the source buffer
113 \param[out] dst destination buffer
114 \param[in] dsize destination buffer size
115 \returns number of decoded bytes in the destination buffer and status flag.
Harald Welte85b9fba2018-05-11 17:36:13 +0200116*/
Harald Welte9da77ab2018-05-11 17:39:21 +0200117int osmo_isdnhdlc_decode(struct osmo_isdnhdlc_vars *hdlc, const uint8_t *src, int slen,
118 int *count, uint8_t *dst, int dsize)
Harald Welte85b9fba2018-05-11 17:36:13 +0200119{
120 int status = 0;
121
122 static const unsigned char fast_flag[] = {
123 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f
124 };
125
126 static const unsigned char fast_flag_value[] = {
127 0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f
128 };
129
130 static const unsigned char fast_abort[] = {
131 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
132 };
133
134#define handle_fast_flag(h) \
135 do { \
136 if (h->cbin == fast_flag[h->bit_shift]) { \
137 h->ffvalue = fast_flag_value[h->bit_shift]; \
138 h->state = HDLC_FAST_FLAG; \
139 h->ffbit_shift = h->bit_shift; \
140 h->bit_shift = 1; \
141 } else { \
142 h->state = HDLC_GET_DATA; \
143 h->data_received = 0; \
144 } \
145 } while (0)
146
147#define handle_abort(h) \
148 do { \
149 h->shift_reg = fast_abort[h->ffbit_shift - 1]; \
150 h->hdlc_bits1 = h->ffbit_shift - 2; \
151 if (h->hdlc_bits1 < 0) \
152 h->hdlc_bits1 = 0; \
153 h->data_bits = h->ffbit_shift - 1; \
154 h->state = HDLC_GET_DATA; \
155 h->data_received = 0; \
156 } while (0)
157
158 *count = slen;
159
160 while (slen > 0) {
161 if (hdlc->bit_shift == 0) {
162 /* the code is for bitreverse streams */
163 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200164 hdlc->cbin = osmo_revbytebits_8(*src++);
Harald Welte85b9fba2018-05-11 17:36:13 +0200165 else
166 hdlc->cbin = *src++;
167 slen--;
168 hdlc->bit_shift = 8;
169 if (hdlc->do_adapt56)
170 hdlc->bit_shift--;
171 }
172
173 switch (hdlc->state) {
174 case STOPPED:
175 return 0;
176 case HDLC_FAST_IDLE:
177 if (hdlc->cbin == 0xff) {
178 hdlc->bit_shift = 0;
179 break;
180 }
181 hdlc->state = HDLC_GET_FLAG_B0;
182 hdlc->hdlc_bits1 = 0;
183 hdlc->bit_shift = 8;
184 break;
185 case HDLC_GET_FLAG_B0:
186 if (!(hdlc->cbin & 0x80)) {
187 hdlc->state = HDLC_GETFLAG_B1A6;
188 hdlc->hdlc_bits1 = 0;
189 } else {
190 if ((!hdlc->do_adapt56) &&
191 (++hdlc->hdlc_bits1 >= 8) &&
192 (hdlc->bit_shift == 1))
193 hdlc->state = HDLC_FAST_IDLE;
194 }
195 hdlc->cbin <<= 1;
196 hdlc->bit_shift--;
197 break;
198 case HDLC_GETFLAG_B1A6:
199 if (hdlc->cbin & 0x80) {
200 hdlc->hdlc_bits1++;
201 if (hdlc->hdlc_bits1 == 6)
202 hdlc->state = HDLC_GETFLAG_B7;
203 } else
204 hdlc->hdlc_bits1 = 0;
205 hdlc->cbin <<= 1;
206 hdlc->bit_shift--;
207 break;
208 case HDLC_GETFLAG_B7:
209 if (hdlc->cbin & 0x80) {
210 hdlc->state = HDLC_GET_FLAG_B0;
211 } else {
212 hdlc->state = HDLC_GET_DATA;
213 hdlc->crc = 0xffff;
214 hdlc->shift_reg = 0;
215 hdlc->hdlc_bits1 = 0;
216 hdlc->data_bits = 0;
217 hdlc->data_received = 0;
218 }
219 hdlc->cbin <<= 1;
220 hdlc->bit_shift--;
221 break;
222 case HDLC_GET_DATA:
223 if (hdlc->cbin & 0x80) {
224 hdlc->hdlc_bits1++;
225 switch (hdlc->hdlc_bits1) {
226 case 6:
227 break;
228 case 7:
229 if (hdlc->data_received)
230 /* bad frame */
Harald Welte9da77ab2018-05-11 17:39:21 +0200231 status = -OSMO_HDLC_FRAMING_ERROR;
Harald Welte85b9fba2018-05-11 17:36:13 +0200232 if (!hdlc->do_adapt56) {
233 if (hdlc->cbin == fast_abort
234 [hdlc->bit_shift + 1]) {
235 hdlc->state =
236 HDLC_FAST_IDLE;
237 hdlc->bit_shift = 1;
238 break;
239 }
240 } else
241 hdlc->state = HDLC_GET_FLAG_B0;
242 break;
243 default:
244 hdlc->shift_reg >>= 1;
245 hdlc->shift_reg |= 0x80;
246 hdlc->data_bits++;
247 break;
248 }
249 } else {
250 switch (hdlc->hdlc_bits1) {
251 case 5:
252 break;
253 case 6:
254 if (hdlc->data_received)
255 status = check_frame(hdlc);
256 hdlc->crc = 0xffff;
257 hdlc->shift_reg = 0;
258 hdlc->data_bits = 0;
259 if (!hdlc->do_adapt56)
260 handle_fast_flag(hdlc);
261 else {
262 hdlc->state = HDLC_GET_DATA;
263 hdlc->data_received = 0;
264 }
265 break;
266 default:
267 hdlc->shift_reg >>= 1;
268 hdlc->data_bits++;
269 break;
270 }
271 hdlc->hdlc_bits1 = 0;
272 }
273 if (status) {
274 hdlc->dstpos = 0;
275 *count -= slen;
276 hdlc->cbin <<= 1;
277 hdlc->bit_shift--;
278 return status;
279 }
280 if (hdlc->data_bits == 8) {
281 hdlc->data_bits = 0;
282 hdlc->data_received = 1;
283 hdlc->crc = crc_ccitt_byte(hdlc->crc,
284 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 */
Harald Welte9da77ab2018-05-11 17:39:21 +0200291 status = -OSMO_HDLC_LENGTH_ERROR;
Harald Welte85b9fba2018-05-11 17:36:13 +0200292 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 handle_abort(hdlc);
311 }
312 break;
313 default:
314 break;
315 }
316 }
317 *count -= slen;
318 return 0;
319}
Harald Welte9da77ab2018-05-11 17:39:21 +0200320/*! encodes HDLC frames to a transparent bit stream.
Harald Welte85b9fba2018-05-11 17:36:13 +0200321
322 The bit stream starts with a beginning flag (01111110). After
323 that each byte is added to the bit stream with bit stuffing added
324 (0 after 5 1's).
325 When the last byte has been removed from the source buffer, the
326 CRC (2 bytes is added) and the frame terminates with the ending flag.
327 For the dchannel, the idle character (all 1's) is also added at the end.
328 If this function is called with empty source buffer (slen=0), flags or
329 idle character will be generated.
330
Harald Welte9da77ab2018-05-11 17:39:21 +0200331 \param[in] src source buffer
332 \param[in] slen source buffer length
333 \param[out] count number of bytes removed (encoded) from source buffer
334 \param[out] dst destination buffer
335 \param[in] dsize destination buffer size
336 \returns - number of encoded bytes in the destination buffer
Harald Welte85b9fba2018-05-11 17:36:13 +0200337*/
Harald Welte9da77ab2018-05-11 17:39:21 +0200338int osmo_isdnhdlc_encode(struct osmo_isdnhdlc_vars *hdlc, const uint8_t *src, uint16_t slen,
339 int *count, uint8_t *dst, int dsize)
Harald Welte85b9fba2018-05-11 17:36:13 +0200340{
341 static const unsigned char xfast_flag_value[] = {
342 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e
343 };
344
345 int len = 0;
346
347 *count = slen;
348
349 /* special handling for one byte frames */
350 if ((slen == 1) && (hdlc->state == HDLC_SEND_FAST_FLAG))
351 hdlc->state = HDLC_SENDFLAG_ONE;
352 while (dsize > 0) {
353 if (hdlc->bit_shift == 0) {
354 if (slen && !hdlc->do_closing) {
355 hdlc->shift_reg = *src++;
356 slen--;
357 if (slen == 0)
358 /* closing sequence, CRC + flag(s) */
359 hdlc->do_closing = 1;
360 hdlc->bit_shift = 8;
361 } else {
362 if (hdlc->state == HDLC_SEND_DATA) {
363 if (hdlc->data_received) {
364 hdlc->state = HDLC_SEND_CRC1;
365 hdlc->crc ^= 0xffff;
366 hdlc->bit_shift = 8;
367 hdlc->shift_reg =
368 hdlc->crc & 0xff;
369 } else if (!hdlc->do_adapt56)
370 hdlc->state =
371 HDLC_SEND_FAST_FLAG;
372 else
373 hdlc->state =
374 HDLC_SENDFLAG_B0;
375 }
376
377 }
378 }
379
380 switch (hdlc->state) {
381 case STOPPED:
382 while (dsize--)
383 *dst++ = 0xff;
384 return dsize;
385 case HDLC_SEND_FAST_FLAG:
386 hdlc->do_closing = 0;
387 if (slen == 0) {
388 /* the code is for bitreverse streams */
389 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200390 *dst++ = osmo_revbytebits_8(hdlc->ffvalue);
Harald Welte85b9fba2018-05-11 17:36:13 +0200391 else
392 *dst++ = hdlc->ffvalue;
393 len++;
394 dsize--;
395 break;
396 }
397 /* fall through */
398 case HDLC_SENDFLAG_ONE:
399 if (hdlc->bit_shift == 8) {
400 hdlc->cbin = hdlc->ffvalue >>
401 (8 - hdlc->data_bits);
402 hdlc->state = HDLC_SEND_DATA;
403 hdlc->crc = 0xffff;
404 hdlc->hdlc_bits1 = 0;
405 hdlc->data_received = 1;
406 }
407 break;
408 case HDLC_SENDFLAG_B0:
409 hdlc->do_closing = 0;
410 hdlc->cbin <<= 1;
411 hdlc->data_bits++;
412 hdlc->hdlc_bits1 = 0;
413 hdlc->state = HDLC_SENDFLAG_B1A6;
414 break;
415 case HDLC_SENDFLAG_B1A6:
416 hdlc->cbin <<= 1;
417 hdlc->data_bits++;
418 hdlc->cbin++;
419 if (++hdlc->hdlc_bits1 == 6)
420 hdlc->state = HDLC_SENDFLAG_B7;
421 break;
422 case HDLC_SENDFLAG_B7:
423 hdlc->cbin <<= 1;
424 hdlc->data_bits++;
425 if (slen == 0) {
426 hdlc->state = HDLC_SENDFLAG_B0;
427 break;
428 }
429 if (hdlc->bit_shift == 8) {
430 hdlc->state = HDLC_SEND_DATA;
431 hdlc->crc = 0xffff;
432 hdlc->hdlc_bits1 = 0;
433 hdlc->data_received = 1;
434 }
435 break;
436 case HDLC_SEND_FIRST_FLAG:
437 hdlc->data_received = 1;
438 if (hdlc->data_bits == 8) {
439 hdlc->state = HDLC_SEND_DATA;
440 hdlc->crc = 0xffff;
441 hdlc->hdlc_bits1 = 0;
442 break;
443 }
444 hdlc->cbin <<= 1;
445 hdlc->data_bits++;
446 if (hdlc->shift_reg & 0x01)
447 hdlc->cbin++;
448 hdlc->shift_reg >>= 1;
449 hdlc->bit_shift--;
450 if (hdlc->bit_shift == 0) {
451 hdlc->state = HDLC_SEND_DATA;
452 hdlc->crc = 0xffff;
453 hdlc->hdlc_bits1 = 0;
454 }
455 break;
456 case HDLC_SEND_DATA:
457 hdlc->cbin <<= 1;
458 hdlc->data_bits++;
459 if (hdlc->hdlc_bits1 == 5) {
460 hdlc->hdlc_bits1 = 0;
461 break;
462 }
463 if (hdlc->bit_shift == 8)
464 hdlc->crc = crc_ccitt_byte(hdlc->crc,
465 hdlc->shift_reg);
466 if (hdlc->shift_reg & 0x01) {
467 hdlc->hdlc_bits1++;
468 hdlc->cbin++;
469 hdlc->shift_reg >>= 1;
470 hdlc->bit_shift--;
471 } else {
472 hdlc->hdlc_bits1 = 0;
473 hdlc->shift_reg >>= 1;
474 hdlc->bit_shift--;
475 }
476 break;
477 case HDLC_SEND_CRC1:
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->shift_reg & 0x01) {
485 hdlc->hdlc_bits1++;
486 hdlc->cbin++;
487 hdlc->shift_reg >>= 1;
488 hdlc->bit_shift--;
489 } else {
490 hdlc->hdlc_bits1 = 0;
491 hdlc->shift_reg >>= 1;
492 hdlc->bit_shift--;
493 }
494 if (hdlc->bit_shift == 0) {
495 hdlc->shift_reg = (hdlc->crc >> 8);
496 hdlc->state = HDLC_SEND_CRC2;
497 hdlc->bit_shift = 8;
498 }
499 break;
500 case HDLC_SEND_CRC2:
501 hdlc->cbin <<= 1;
502 hdlc->data_bits++;
503 if (hdlc->hdlc_bits1 == 5) {
504 hdlc->hdlc_bits1 = 0;
505 break;
506 }
507 if (hdlc->shift_reg & 0x01) {
508 hdlc->hdlc_bits1++;
509 hdlc->cbin++;
510 hdlc->shift_reg >>= 1;
511 hdlc->bit_shift--;
512 } else {
513 hdlc->hdlc_bits1 = 0;
514 hdlc->shift_reg >>= 1;
515 hdlc->bit_shift--;
516 }
517 if (hdlc->bit_shift == 0) {
518 hdlc->shift_reg = 0x7e;
519 hdlc->state = HDLC_SEND_CLOSING_FLAG;
520 hdlc->bit_shift = 8;
521 }
522 break;
523 case HDLC_SEND_CLOSING_FLAG:
524 hdlc->cbin <<= 1;
525 hdlc->data_bits++;
526 if (hdlc->hdlc_bits1 == 5) {
527 hdlc->hdlc_bits1 = 0;
528 break;
529 }
530 if (hdlc->shift_reg & 0x01)
531 hdlc->cbin++;
532 hdlc->shift_reg >>= 1;
533 hdlc->bit_shift--;
534 if (hdlc->bit_shift == 0) {
535 hdlc->ffvalue =
536 xfast_flag_value[hdlc->data_bits];
537 if (hdlc->dchannel) {
538 hdlc->ffvalue = 0x7e;
539 hdlc->state = HDLC_SEND_IDLE1;
540 hdlc->bit_shift = 8-hdlc->data_bits;
541 if (hdlc->bit_shift == 0)
542 hdlc->state =
543 HDLC_SEND_FAST_IDLE;
544 } else {
545 if (!hdlc->do_adapt56) {
546 hdlc->state =
547 HDLC_SEND_FAST_FLAG;
548 hdlc->data_received = 0;
549 } else {
550 hdlc->state = HDLC_SENDFLAG_B0;
551 hdlc->data_received = 0;
552 }
553 /* Finished this frame, send flags */
554 if (dsize > 1)
555 dsize = 1;
556 }
557 }
558 break;
559 case HDLC_SEND_IDLE1:
560 hdlc->do_closing = 0;
561 hdlc->cbin <<= 1;
562 hdlc->cbin++;
563 hdlc->data_bits++;
564 hdlc->bit_shift--;
565 if (hdlc->bit_shift == 0) {
566 hdlc->state = HDLC_SEND_FAST_IDLE;
567 hdlc->bit_shift = 0;
568 }
569 break;
570 case HDLC_SEND_FAST_IDLE:
571 hdlc->do_closing = 0;
572 hdlc->cbin = 0xff;
573 hdlc->data_bits = 8;
574 if (hdlc->bit_shift == 8) {
575 hdlc->cbin = 0x7e;
576 hdlc->state = HDLC_SEND_FIRST_FLAG;
577 } else {
578 /* the code is for bitreverse streams */
579 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200580 *dst++ = osmo_revbytebits_8(hdlc->cbin);
Harald Welte85b9fba2018-05-11 17:36:13 +0200581 else
582 *dst++ = hdlc->cbin;
583 hdlc->bit_shift = 0;
584 hdlc->data_bits = 0;
585 len++;
586 dsize = 0;
587 }
588 break;
589 default:
590 break;
591 }
592 if (hdlc->do_adapt56) {
593 if (hdlc->data_bits == 7) {
594 hdlc->cbin <<= 1;
595 hdlc->cbin++;
596 hdlc->data_bits++;
597 }
598 }
599 if (hdlc->data_bits == 8) {
600 /* the code is for bitreverse streams */
601 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200602 *dst++ = osmo_revbytebits_8(hdlc->cbin);
Harald Welte85b9fba2018-05-11 17:36:13 +0200603 else
604 *dst++ = hdlc->cbin;
605 hdlc->data_bits = 0;
606 len++;
607 dsize--;
608 }
609 }
610 *count -= slen;
611
612 return len;
613}