blob: 58b4a661568cb99e3583927f8622062d5fdb1589 [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.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
Harald Welte9da77ab2018-05-11 17:39:21 +020027#include <string.h>
Harald Welte85b9fba2018-05-11 17:36:13 +020028
Harald Welte9da77ab2018-05-11 17:39:21 +020029#include <osmocom/core/crc16.h>
30#include <osmocom/core/bits.h>
31#include <osmocom/core/isdnhdlc.h>
Harald Welte85b9fba2018-05-11 17:36:13 +020032
33enum {
34 HDLC_FAST_IDLE, HDLC_GET_FLAG_B0, HDLC_GETFLAG_B1A6, HDLC_GETFLAG_B7,
35 HDLC_GET_DATA, HDLC_FAST_FLAG
36};
37
38enum {
39 HDLC_SEND_DATA, HDLC_SEND_CRC1, HDLC_SEND_FAST_FLAG,
40 HDLC_SEND_FIRST_FLAG, HDLC_SEND_CRC2, HDLC_SEND_CLOSING_FLAG,
41 HDLC_SEND_IDLE1, HDLC_SEND_FAST_IDLE, HDLC_SENDFLAG_B0,
42 HDLC_SENDFLAG_B1A6, HDLC_SENDFLAG_B7, STOPPED, HDLC_SENDFLAG_ONE
43};
44
Harald Welte9da77ab2018-05-11 17:39:21 +020045#define crc_ccitt_byte osmo_crc16_ccitt_byte
46
47void osmo_isdnhdlc_rcv_init(struct osmo_isdnhdlc_vars *hdlc, uint32_t features)
Harald Welte85b9fba2018-05-11 17:36:13 +020048{
Harald Welte9da77ab2018-05-11 17:39:21 +020049 memset(hdlc, 0, sizeof(*hdlc));
Harald Welte85b9fba2018-05-11 17:36:13 +020050 hdlc->state = HDLC_GET_DATA;
Harald Welte9da77ab2018-05-11 17:39:21 +020051 if (features & OSMO_HDLC_F_56KBIT)
Harald Welte85b9fba2018-05-11 17:36:13 +020052 hdlc->do_adapt56 = 1;
Harald Welte9da77ab2018-05-11 17:39:21 +020053 if (features & OSMO_HDLC_F_BITREVERSE)
Harald Welte85b9fba2018-05-11 17:36:13 +020054 hdlc->do_bitreverse = 1;
55}
Harald Welte85b9fba2018-05-11 17:36:13 +020056
Harald Welte9da77ab2018-05-11 17:39:21 +020057void osmo_isdnhdlc_out_init(struct osmo_isdnhdlc_vars *hdlc, uint32_t features)
Harald Welte85b9fba2018-05-11 17:36:13 +020058{
Harald Welte9da77ab2018-05-11 17:39:21 +020059 memset(hdlc, 0, sizeof(*hdlc));
60 if (features & OSMO_HDLC_F_DCHANNEL) {
Harald Welte85b9fba2018-05-11 17:36:13 +020061 hdlc->dchannel = 1;
62 hdlc->state = HDLC_SEND_FIRST_FLAG;
63 } else {
64 hdlc->dchannel = 0;
65 hdlc->state = HDLC_SEND_FAST_FLAG;
66 hdlc->ffvalue = 0x7e;
67 }
68 hdlc->cbin = 0x7e;
Harald Welte9da77ab2018-05-11 17:39:21 +020069 if (features & OSMO_HDLC_F_56KBIT) {
Harald Welte85b9fba2018-05-11 17:36:13 +020070 hdlc->do_adapt56 = 1;
71 hdlc->state = HDLC_SENDFLAG_B0;
72 } else
73 hdlc->data_bits = 8;
Harald Welte9da77ab2018-05-11 17:39:21 +020074 if (features & OSMO_HDLC_F_BITREVERSE)
Harald Welte85b9fba2018-05-11 17:36:13 +020075 hdlc->do_bitreverse = 1;
76}
Harald Welte85b9fba2018-05-11 17:36:13 +020077
78static int
Harald Welte9da77ab2018-05-11 17:39:21 +020079check_frame(struct osmo_isdnhdlc_vars *hdlc)
Harald Welte85b9fba2018-05-11 17:36:13 +020080{
81 int status;
82
83 if (hdlc->dstpos < 2) /* too small - framing error */
Harald Welte9da77ab2018-05-11 17:39:21 +020084 status = -OSMO_HDLC_FRAMING_ERROR;
Harald Welte85b9fba2018-05-11 17:36:13 +020085 else if (hdlc->crc != 0xf0b8) /* crc error */
Harald Welte9da77ab2018-05-11 17:39:21 +020086 status = -OSMO_HDLC_CRC_ERROR;
Harald Welte85b9fba2018-05-11 17:36:13 +020087 else {
88 /* remove CRC */
89 hdlc->dstpos -= 2;
90 /* good frame */
91 status = hdlc->dstpos;
92 }
93 return status;
94}
95
Harald Welte9da77ab2018-05-11 17:39:21 +020096/*! decodes HDLC frames from a transparent bit stream.
Harald Welte85b9fba2018-05-11 17:36:13 +020097
98 The source buffer is scanned for valid HDLC frames looking for
99 flags (01111110) to indicate the start of a frame. If the start of
100 the frame is found, the bit stuffing is removed (0 after 5 1's).
101 When a new flag is found, the complete frame has been received
102 and the CRC is checked.
103 If a valid frame is found, the function returns the frame length
104 excluding the CRC with the bit HDLC_END_OF_FRAME set.
105 If the beginning of a valid frame is found, the function returns
106 the length.
107 If a framing error is found (too many 1s and not a flag) the function
Harald Welte9da77ab2018-05-11 17:39:21 +0200108 returns the length with the bit OSMO_HDLC_FRAMING_ERROR set.
Harald Welte85b9fba2018-05-11 17:36:13 +0200109 If a CRC error is found the function returns the length with the
Harald Welte9da77ab2018-05-11 17:39:21 +0200110 bit OSMO_HDLC_CRC_ERROR set.
Harald Welte85b9fba2018-05-11 17:36:13 +0200111 If the frame length exceeds the destination buffer size, the function
Harald Welte9da77ab2018-05-11 17:39:21 +0200112 returns the length with the bit OSMO_HDLC_LENGTH_ERROR set.
Harald Welte85b9fba2018-05-11 17:36:13 +0200113
Harald Welte9da77ab2018-05-11 17:39:21 +0200114 \param[in] src source buffer
115 \param[in] slen source buffer length
116 \param[out] count number of bytes removed (decoded) from the source buffer
117 \param[out] dst destination buffer
118 \param[in] dsize destination buffer size
119 \returns number of decoded bytes in the destination buffer and status flag.
Harald Welte85b9fba2018-05-11 17:36:13 +0200120*/
Harald Welte9da77ab2018-05-11 17:39:21 +0200121int osmo_isdnhdlc_decode(struct osmo_isdnhdlc_vars *hdlc, const uint8_t *src, int slen,
122 int *count, uint8_t *dst, int dsize)
Harald Welte85b9fba2018-05-11 17:36:13 +0200123{
124 int status = 0;
125
126 static const unsigned char fast_flag[] = {
127 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f
128 };
129
130 static const unsigned char fast_flag_value[] = {
131 0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f
132 };
133
134 static const unsigned char fast_abort[] = {
135 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
136 };
137
138#define handle_fast_flag(h) \
139 do { \
140 if (h->cbin == fast_flag[h->bit_shift]) { \
141 h->ffvalue = fast_flag_value[h->bit_shift]; \
142 h->state = HDLC_FAST_FLAG; \
143 h->ffbit_shift = h->bit_shift; \
144 h->bit_shift = 1; \
145 } else { \
146 h->state = HDLC_GET_DATA; \
147 h->data_received = 0; \
148 } \
149 } while (0)
150
151#define handle_abort(h) \
152 do { \
153 h->shift_reg = fast_abort[h->ffbit_shift - 1]; \
154 h->hdlc_bits1 = h->ffbit_shift - 2; \
155 if (h->hdlc_bits1 < 0) \
156 h->hdlc_bits1 = 0; \
157 h->data_bits = h->ffbit_shift - 1; \
158 h->state = HDLC_GET_DATA; \
159 h->data_received = 0; \
160 } while (0)
161
162 *count = slen;
163
164 while (slen > 0) {
165 if (hdlc->bit_shift == 0) {
166 /* the code is for bitreverse streams */
167 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200168 hdlc->cbin = osmo_revbytebits_8(*src++);
Harald Welte85b9fba2018-05-11 17:36:13 +0200169 else
170 hdlc->cbin = *src++;
171 slen--;
172 hdlc->bit_shift = 8;
173 if (hdlc->do_adapt56)
174 hdlc->bit_shift--;
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 (++hdlc->hdlc_bits1 >= 8) &&
196 (hdlc->bit_shift == 1))
197 hdlc->state = HDLC_FAST_IDLE;
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 } else
208 hdlc->hdlc_bits1 = 0;
209 hdlc->cbin <<= 1;
210 hdlc->bit_shift--;
211 break;
212 case HDLC_GETFLAG_B7:
213 if (hdlc->cbin & 0x80) {
214 hdlc->state = HDLC_GET_FLAG_B0;
215 } else {
216 hdlc->state = HDLC_GET_DATA;
217 hdlc->crc = 0xffff;
218 hdlc->shift_reg = 0;
219 hdlc->hdlc_bits1 = 0;
220 hdlc->data_bits = 0;
221 hdlc->data_received = 0;
222 }
223 hdlc->cbin <<= 1;
224 hdlc->bit_shift--;
225 break;
226 case HDLC_GET_DATA:
227 if (hdlc->cbin & 0x80) {
228 hdlc->hdlc_bits1++;
229 switch (hdlc->hdlc_bits1) {
230 case 6:
231 break;
232 case 7:
233 if (hdlc->data_received)
234 /* bad frame */
Harald Welte9da77ab2018-05-11 17:39:21 +0200235 status = -OSMO_HDLC_FRAMING_ERROR;
Harald Welte85b9fba2018-05-11 17:36:13 +0200236 if (!hdlc->do_adapt56) {
237 if (hdlc->cbin == fast_abort
238 [hdlc->bit_shift + 1]) {
239 hdlc->state =
240 HDLC_FAST_IDLE;
241 hdlc->bit_shift = 1;
242 break;
243 }
244 } else
245 hdlc->state = HDLC_GET_FLAG_B0;
246 break;
247 default:
248 hdlc->shift_reg >>= 1;
249 hdlc->shift_reg |= 0x80;
250 hdlc->data_bits++;
251 break;
252 }
253 } else {
254 switch (hdlc->hdlc_bits1) {
255 case 5:
256 break;
257 case 6:
258 if (hdlc->data_received)
259 status = check_frame(hdlc);
260 hdlc->crc = 0xffff;
261 hdlc->shift_reg = 0;
262 hdlc->data_bits = 0;
263 if (!hdlc->do_adapt56)
264 handle_fast_flag(hdlc);
265 else {
266 hdlc->state = HDLC_GET_DATA;
267 hdlc->data_received = 0;
268 }
269 break;
270 default:
271 hdlc->shift_reg >>= 1;
272 hdlc->data_bits++;
273 break;
274 }
275 hdlc->hdlc_bits1 = 0;
276 }
277 if (status) {
278 hdlc->dstpos = 0;
279 *count -= slen;
280 hdlc->cbin <<= 1;
281 hdlc->bit_shift--;
282 return status;
283 }
284 if (hdlc->data_bits == 8) {
285 hdlc->data_bits = 0;
286 hdlc->data_received = 1;
287 hdlc->crc = crc_ccitt_byte(hdlc->crc,
288 hdlc->shift_reg);
289
290 /* good byte received */
291 if (hdlc->dstpos < dsize)
292 dst[hdlc->dstpos++] = hdlc->shift_reg;
293 else {
294 /* frame too long */
Harald Welte9da77ab2018-05-11 17:39:21 +0200295 status = -OSMO_HDLC_LENGTH_ERROR;
Harald Welte85b9fba2018-05-11 17:36:13 +0200296 hdlc->dstpos = 0;
297 }
298 }
299 hdlc->cbin <<= 1;
300 hdlc->bit_shift--;
301 break;
302 case HDLC_FAST_FLAG:
303 if (hdlc->cbin == hdlc->ffvalue) {
304 hdlc->bit_shift = 0;
305 break;
306 } else {
307 if (hdlc->cbin == 0xff) {
308 hdlc->state = HDLC_FAST_IDLE;
309 hdlc->bit_shift = 0;
310 } else if (hdlc->ffbit_shift == 8) {
311 hdlc->state = HDLC_GETFLAG_B7;
312 break;
313 } else
314 handle_abort(hdlc);
315 }
316 break;
317 default:
318 break;
319 }
320 }
321 *count -= slen;
322 return 0;
323}
Harald Welte9da77ab2018-05-11 17:39:21 +0200324/*! encodes HDLC frames to a transparent bit stream.
Harald Welte85b9fba2018-05-11 17:36:13 +0200325
326 The bit stream starts with a beginning flag (01111110). After
327 that each byte is added to the bit stream with bit stuffing added
328 (0 after 5 1's).
329 When the last byte has been removed from the source buffer, the
330 CRC (2 bytes is added) and the frame terminates with the ending flag.
331 For the dchannel, the idle character (all 1's) is also added at the end.
332 If this function is called with empty source buffer (slen=0), flags or
333 idle character will be generated.
334
Harald Welte9da77ab2018-05-11 17:39:21 +0200335 \param[in] src source buffer
336 \param[in] slen source buffer length
337 \param[out] count number of bytes removed (encoded) from source buffer
338 \param[out] dst destination buffer
339 \param[in] dsize destination buffer size
340 \returns - number of encoded bytes in the destination buffer
Harald Welte85b9fba2018-05-11 17:36:13 +0200341*/
Harald Welte9da77ab2018-05-11 17:39:21 +0200342int osmo_isdnhdlc_encode(struct osmo_isdnhdlc_vars *hdlc, const uint8_t *src, uint16_t slen,
343 int *count, uint8_t *dst, int dsize)
Harald Welte85b9fba2018-05-11 17:36:13 +0200344{
345 static const unsigned char xfast_flag_value[] = {
346 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e
347 };
348
349 int len = 0;
350
351 *count = slen;
352
353 /* special handling for one byte frames */
354 if ((slen == 1) && (hdlc->state == HDLC_SEND_FAST_FLAG))
355 hdlc->state = HDLC_SENDFLAG_ONE;
356 while (dsize > 0) {
357 if (hdlc->bit_shift == 0) {
358 if (slen && !hdlc->do_closing) {
359 hdlc->shift_reg = *src++;
360 slen--;
361 if (slen == 0)
362 /* closing sequence, CRC + flag(s) */
363 hdlc->do_closing = 1;
364 hdlc->bit_shift = 8;
365 } else {
366 if (hdlc->state == HDLC_SEND_DATA) {
367 if (hdlc->data_received) {
368 hdlc->state = HDLC_SEND_CRC1;
369 hdlc->crc ^= 0xffff;
370 hdlc->bit_shift = 8;
371 hdlc->shift_reg =
372 hdlc->crc & 0xff;
373 } else if (!hdlc->do_adapt56)
374 hdlc->state =
375 HDLC_SEND_FAST_FLAG;
376 else
377 hdlc->state =
378 HDLC_SENDFLAG_B0;
379 }
380
381 }
382 }
383
384 switch (hdlc->state) {
385 case STOPPED:
386 while (dsize--)
387 *dst++ = 0xff;
388 return dsize;
389 case HDLC_SEND_FAST_FLAG:
390 hdlc->do_closing = 0;
391 if (slen == 0) {
392 /* the code is for bitreverse streams */
393 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200394 *dst++ = osmo_revbytebits_8(hdlc->ffvalue);
Harald Welte85b9fba2018-05-11 17:36:13 +0200395 else
396 *dst++ = hdlc->ffvalue;
397 len++;
398 dsize--;
399 break;
400 }
401 /* fall through */
402 case HDLC_SENDFLAG_ONE:
403 if (hdlc->bit_shift == 8) {
404 hdlc->cbin = hdlc->ffvalue >>
405 (8 - hdlc->data_bits);
406 hdlc->state = HDLC_SEND_DATA;
407 hdlc->crc = 0xffff;
408 hdlc->hdlc_bits1 = 0;
409 hdlc->data_received = 1;
410 }
411 break;
412 case HDLC_SENDFLAG_B0:
413 hdlc->do_closing = 0;
414 hdlc->cbin <<= 1;
415 hdlc->data_bits++;
416 hdlc->hdlc_bits1 = 0;
417 hdlc->state = HDLC_SENDFLAG_B1A6;
418 break;
419 case HDLC_SENDFLAG_B1A6:
420 hdlc->cbin <<= 1;
421 hdlc->data_bits++;
422 hdlc->cbin++;
423 if (++hdlc->hdlc_bits1 == 6)
424 hdlc->state = HDLC_SENDFLAG_B7;
425 break;
426 case HDLC_SENDFLAG_B7:
427 hdlc->cbin <<= 1;
428 hdlc->data_bits++;
429 if (slen == 0) {
430 hdlc->state = HDLC_SENDFLAG_B0;
431 break;
432 }
433 if (hdlc->bit_shift == 8) {
434 hdlc->state = HDLC_SEND_DATA;
435 hdlc->crc = 0xffff;
436 hdlc->hdlc_bits1 = 0;
437 hdlc->data_received = 1;
438 }
439 break;
440 case HDLC_SEND_FIRST_FLAG:
441 hdlc->data_received = 1;
442 if (hdlc->data_bits == 8) {
443 hdlc->state = HDLC_SEND_DATA;
444 hdlc->crc = 0xffff;
445 hdlc->hdlc_bits1 = 0;
446 break;
447 }
448 hdlc->cbin <<= 1;
449 hdlc->data_bits++;
450 if (hdlc->shift_reg & 0x01)
451 hdlc->cbin++;
452 hdlc->shift_reg >>= 1;
453 hdlc->bit_shift--;
454 if (hdlc->bit_shift == 0) {
455 hdlc->state = HDLC_SEND_DATA;
456 hdlc->crc = 0xffff;
457 hdlc->hdlc_bits1 = 0;
458 }
459 break;
460 case HDLC_SEND_DATA:
461 hdlc->cbin <<= 1;
462 hdlc->data_bits++;
463 if (hdlc->hdlc_bits1 == 5) {
464 hdlc->hdlc_bits1 = 0;
465 break;
466 }
467 if (hdlc->bit_shift == 8)
468 hdlc->crc = crc_ccitt_byte(hdlc->crc,
469 hdlc->shift_reg);
470 if (hdlc->shift_reg & 0x01) {
471 hdlc->hdlc_bits1++;
472 hdlc->cbin++;
473 hdlc->shift_reg >>= 1;
474 hdlc->bit_shift--;
475 } else {
476 hdlc->hdlc_bits1 = 0;
477 hdlc->shift_reg >>= 1;
478 hdlc->bit_shift--;
479 }
480 break;
481 case HDLC_SEND_CRC1:
482 hdlc->cbin <<= 1;
483 hdlc->data_bits++;
484 if (hdlc->hdlc_bits1 == 5) {
485 hdlc->hdlc_bits1 = 0;
486 break;
487 }
488 if (hdlc->shift_reg & 0x01) {
489 hdlc->hdlc_bits1++;
490 hdlc->cbin++;
491 hdlc->shift_reg >>= 1;
492 hdlc->bit_shift--;
493 } else {
494 hdlc->hdlc_bits1 = 0;
495 hdlc->shift_reg >>= 1;
496 hdlc->bit_shift--;
497 }
498 if (hdlc->bit_shift == 0) {
499 hdlc->shift_reg = (hdlc->crc >> 8);
500 hdlc->state = HDLC_SEND_CRC2;
501 hdlc->bit_shift = 8;
502 }
503 break;
504 case HDLC_SEND_CRC2:
505 hdlc->cbin <<= 1;
506 hdlc->data_bits++;
507 if (hdlc->hdlc_bits1 == 5) {
508 hdlc->hdlc_bits1 = 0;
509 break;
510 }
511 if (hdlc->shift_reg & 0x01) {
512 hdlc->hdlc_bits1++;
513 hdlc->cbin++;
514 hdlc->shift_reg >>= 1;
515 hdlc->bit_shift--;
516 } else {
517 hdlc->hdlc_bits1 = 0;
518 hdlc->shift_reg >>= 1;
519 hdlc->bit_shift--;
520 }
521 if (hdlc->bit_shift == 0) {
522 hdlc->shift_reg = 0x7e;
523 hdlc->state = HDLC_SEND_CLOSING_FLAG;
524 hdlc->bit_shift = 8;
525 }
526 break;
527 case HDLC_SEND_CLOSING_FLAG:
528 hdlc->cbin <<= 1;
529 hdlc->data_bits++;
530 if (hdlc->hdlc_bits1 == 5) {
531 hdlc->hdlc_bits1 = 0;
532 break;
533 }
534 if (hdlc->shift_reg & 0x01)
535 hdlc->cbin++;
536 hdlc->shift_reg >>= 1;
537 hdlc->bit_shift--;
538 if (hdlc->bit_shift == 0) {
539 hdlc->ffvalue =
540 xfast_flag_value[hdlc->data_bits];
541 if (hdlc->dchannel) {
542 hdlc->ffvalue = 0x7e;
543 hdlc->state = HDLC_SEND_IDLE1;
544 hdlc->bit_shift = 8-hdlc->data_bits;
545 if (hdlc->bit_shift == 0)
546 hdlc->state =
547 HDLC_SEND_FAST_IDLE;
548 } else {
549 if (!hdlc->do_adapt56) {
550 hdlc->state =
551 HDLC_SEND_FAST_FLAG;
552 hdlc->data_received = 0;
553 } else {
554 hdlc->state = HDLC_SENDFLAG_B0;
555 hdlc->data_received = 0;
556 }
557 /* Finished this frame, send flags */
558 if (dsize > 1)
559 dsize = 1;
560 }
561 }
562 break;
563 case HDLC_SEND_IDLE1:
564 hdlc->do_closing = 0;
565 hdlc->cbin <<= 1;
566 hdlc->cbin++;
567 hdlc->data_bits++;
568 hdlc->bit_shift--;
569 if (hdlc->bit_shift == 0) {
570 hdlc->state = HDLC_SEND_FAST_IDLE;
571 hdlc->bit_shift = 0;
572 }
573 break;
574 case HDLC_SEND_FAST_IDLE:
575 hdlc->do_closing = 0;
576 hdlc->cbin = 0xff;
577 hdlc->data_bits = 8;
578 if (hdlc->bit_shift == 8) {
579 hdlc->cbin = 0x7e;
580 hdlc->state = HDLC_SEND_FIRST_FLAG;
581 } else {
582 /* the code is for bitreverse streams */
583 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200584 *dst++ = osmo_revbytebits_8(hdlc->cbin);
Harald Welte85b9fba2018-05-11 17:36:13 +0200585 else
586 *dst++ = hdlc->cbin;
587 hdlc->bit_shift = 0;
588 hdlc->data_bits = 0;
589 len++;
590 dsize = 0;
591 }
592 break;
593 default:
594 break;
595 }
596 if (hdlc->do_adapt56) {
597 if (hdlc->data_bits == 7) {
598 hdlc->cbin <<= 1;
599 hdlc->cbin++;
600 hdlc->data_bits++;
601 }
602 }
603 if (hdlc->data_bits == 8) {
604 /* the code is for bitreverse streams */
605 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200606 *dst++ = osmo_revbytebits_8(hdlc->cbin);
Harald Welte85b9fba2018-05-11 17:36:13 +0200607 else
608 *dst++ = hdlc->cbin;
609 hdlc->data_bits = 0;
610 len++;
611 dsize--;
612 }
613 }
614 *count -= slen;
615
616 return len;
617}