blob: 4ced5afd5df73acd34a02e31194b7c4831006d44 [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
Harald Welte4ce820a2022-11-30 23:00:18 +0100100 excluding the CRC.
Harald Welte85b9fba2018-05-11 17:36:13 +0200101 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 Welte4ce820a2022-11-30 23:00:18 +0100104 returns -OSMO_HDLC_FRAMING_ERROR.
105 If a CRC error is found the function returns -OSMO_HDLC_CRC_ERROR.
Harald Welte85b9fba2018-05-11 17:36:13 +0200106 If the frame length exceeds the destination buffer size, the function
Harald Welte9da77ab2018-05-11 17:39:21 +0200107 returns the length with the bit OSMO_HDLC_LENGTH_ERROR set.
Harald Welte85b9fba2018-05-11 17:36:13 +0200108
Harald Welte9da77ab2018-05-11 17:39:21 +0200109 \param[in] src source buffer
110 \param[in] slen source buffer length
111 \param[out] count number of bytes removed (decoded) from the source buffer
112 \param[out] dst destination buffer
113 \param[in] dsize destination buffer size
114 \returns number of decoded bytes in the destination buffer and status flag.
Harald Welte85b9fba2018-05-11 17:36:13 +0200115*/
Harald Welte9da77ab2018-05-11 17:39:21 +0200116int osmo_isdnhdlc_decode(struct osmo_isdnhdlc_vars *hdlc, const uint8_t *src, int slen,
117 int *count, uint8_t *dst, int dsize)
Harald Welte85b9fba2018-05-11 17:36:13 +0200118{
119 int status = 0;
120
121 static const unsigned char fast_flag[] = {
122 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f
123 };
124
125 static const unsigned char fast_flag_value[] = {
126 0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f
127 };
128
129 static const unsigned char fast_abort[] = {
130 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
131 };
132
133#define handle_fast_flag(h) \
134 do { \
135 if (h->cbin == fast_flag[h->bit_shift]) { \
136 h->ffvalue = fast_flag_value[h->bit_shift]; \
137 h->state = HDLC_FAST_FLAG; \
138 h->ffbit_shift = h->bit_shift; \
139 h->bit_shift = 1; \
140 } else { \
141 h->state = HDLC_GET_DATA; \
142 h->data_received = 0; \
143 } \
144 } while (0)
145
146#define handle_abort(h) \
147 do { \
148 h->shift_reg = fast_abort[h->ffbit_shift - 1]; \
149 h->hdlc_bits1 = h->ffbit_shift - 2; \
150 if (h->hdlc_bits1 < 0) \
151 h->hdlc_bits1 = 0; \
152 h->data_bits = h->ffbit_shift - 1; \
153 h->state = HDLC_GET_DATA; \
154 h->data_received = 0; \
155 } while (0)
156
157 *count = slen;
158
159 while (slen > 0) {
160 if (hdlc->bit_shift == 0) {
161 /* the code is for bitreverse streams */
162 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200163 hdlc->cbin = osmo_revbytebits_8(*src++);
Harald Welte85b9fba2018-05-11 17:36:13 +0200164 else
165 hdlc->cbin = *src++;
166 slen--;
167 hdlc->bit_shift = 8;
168 if (hdlc->do_adapt56)
169 hdlc->bit_shift--;
170 }
171
172 switch (hdlc->state) {
173 case STOPPED:
174 return 0;
175 case HDLC_FAST_IDLE:
176 if (hdlc->cbin == 0xff) {
177 hdlc->bit_shift = 0;
178 break;
179 }
180 hdlc->state = HDLC_GET_FLAG_B0;
181 hdlc->hdlc_bits1 = 0;
182 hdlc->bit_shift = 8;
183 break;
184 case HDLC_GET_FLAG_B0:
185 if (!(hdlc->cbin & 0x80)) {
186 hdlc->state = HDLC_GETFLAG_B1A6;
187 hdlc->hdlc_bits1 = 0;
188 } else {
189 if ((!hdlc->do_adapt56) &&
190 (++hdlc->hdlc_bits1 >= 8) &&
191 (hdlc->bit_shift == 1))
192 hdlc->state = HDLC_FAST_IDLE;
193 }
194 hdlc->cbin <<= 1;
195 hdlc->bit_shift--;
196 break;
197 case HDLC_GETFLAG_B1A6:
198 if (hdlc->cbin & 0x80) {
199 hdlc->hdlc_bits1++;
200 if (hdlc->hdlc_bits1 == 6)
201 hdlc->state = HDLC_GETFLAG_B7;
202 } else
203 hdlc->hdlc_bits1 = 0;
204 hdlc->cbin <<= 1;
205 hdlc->bit_shift--;
206 break;
207 case HDLC_GETFLAG_B7:
208 if (hdlc->cbin & 0x80) {
209 hdlc->state = HDLC_GET_FLAG_B0;
210 } else {
211 hdlc->state = HDLC_GET_DATA;
212 hdlc->crc = 0xffff;
213 hdlc->shift_reg = 0;
214 hdlc->hdlc_bits1 = 0;
215 hdlc->data_bits = 0;
216 hdlc->data_received = 0;
217 }
218 hdlc->cbin <<= 1;
219 hdlc->bit_shift--;
220 break;
221 case HDLC_GET_DATA:
222 if (hdlc->cbin & 0x80) {
223 hdlc->hdlc_bits1++;
224 switch (hdlc->hdlc_bits1) {
225 case 6:
226 break;
227 case 7:
228 if (hdlc->data_received)
229 /* bad frame */
Harald Welte9da77ab2018-05-11 17:39:21 +0200230 status = -OSMO_HDLC_FRAMING_ERROR;
Harald Welte85b9fba2018-05-11 17:36:13 +0200231 if (!hdlc->do_adapt56) {
232 if (hdlc->cbin == fast_abort
233 [hdlc->bit_shift + 1]) {
234 hdlc->state =
235 HDLC_FAST_IDLE;
236 hdlc->bit_shift = 1;
237 break;
238 }
239 } else
240 hdlc->state = HDLC_GET_FLAG_B0;
241 break;
242 default:
243 hdlc->shift_reg >>= 1;
244 hdlc->shift_reg |= 0x80;
245 hdlc->data_bits++;
246 break;
247 }
248 } else {
249 switch (hdlc->hdlc_bits1) {
250 case 5:
251 break;
252 case 6:
253 if (hdlc->data_received)
254 status = check_frame(hdlc);
255 hdlc->crc = 0xffff;
256 hdlc->shift_reg = 0;
257 hdlc->data_bits = 0;
258 if (!hdlc->do_adapt56)
259 handle_fast_flag(hdlc);
260 else {
261 hdlc->state = HDLC_GET_DATA;
262 hdlc->data_received = 0;
263 }
264 break;
265 default:
266 hdlc->shift_reg >>= 1;
267 hdlc->data_bits++;
268 break;
269 }
270 hdlc->hdlc_bits1 = 0;
271 }
272 if (status) {
273 hdlc->dstpos = 0;
274 *count -= slen;
275 hdlc->cbin <<= 1;
276 hdlc->bit_shift--;
277 return status;
278 }
279 if (hdlc->data_bits == 8) {
280 hdlc->data_bits = 0;
281 hdlc->data_received = 1;
282 hdlc->crc = crc_ccitt_byte(hdlc->crc,
283 hdlc->shift_reg);
284
285 /* good byte received */
286 if (hdlc->dstpos < dsize)
287 dst[hdlc->dstpos++] = hdlc->shift_reg;
288 else {
289 /* frame too long */
Harald Welte9da77ab2018-05-11 17:39:21 +0200290 status = -OSMO_HDLC_LENGTH_ERROR;
Harald Welte85b9fba2018-05-11 17:36:13 +0200291 hdlc->dstpos = 0;
292 }
293 }
294 hdlc->cbin <<= 1;
295 hdlc->bit_shift--;
296 break;
297 case HDLC_FAST_FLAG:
298 if (hdlc->cbin == hdlc->ffvalue) {
299 hdlc->bit_shift = 0;
300 break;
301 } else {
302 if (hdlc->cbin == 0xff) {
303 hdlc->state = HDLC_FAST_IDLE;
304 hdlc->bit_shift = 0;
305 } else if (hdlc->ffbit_shift == 8) {
306 hdlc->state = HDLC_GETFLAG_B7;
307 break;
308 } else
309 handle_abort(hdlc);
310 }
311 break;
312 default:
313 break;
314 }
315 }
316 *count -= slen;
317 return 0;
318}
Harald Welte9da77ab2018-05-11 17:39:21 +0200319/*! encodes HDLC frames to a transparent bit stream.
Harald Welte85b9fba2018-05-11 17:36:13 +0200320
321 The bit stream starts with a beginning flag (01111110). After
322 that each byte is added to the bit stream with bit stuffing added
323 (0 after 5 1's).
324 When the last byte has been removed from the source buffer, the
325 CRC (2 bytes is added) and the frame terminates with the ending flag.
326 For the dchannel, the idle character (all 1's) is also added at the end.
327 If this function is called with empty source buffer (slen=0), flags or
328 idle character will be generated.
329
Harald Welte9da77ab2018-05-11 17:39:21 +0200330 \param[in] src source buffer
331 \param[in] slen source buffer length
332 \param[out] count number of bytes removed (encoded) from source buffer
333 \param[out] dst destination buffer
334 \param[in] dsize destination buffer size
335 \returns - number of encoded bytes in the destination buffer
Harald Welte85b9fba2018-05-11 17:36:13 +0200336*/
Harald Welte9da77ab2018-05-11 17:39:21 +0200337int osmo_isdnhdlc_encode(struct osmo_isdnhdlc_vars *hdlc, const uint8_t *src, uint16_t slen,
338 int *count, uint8_t *dst, int dsize)
Harald Welte85b9fba2018-05-11 17:36:13 +0200339{
340 static const unsigned char xfast_flag_value[] = {
341 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e
342 };
343
344 int len = 0;
345
346 *count = slen;
347
348 /* special handling for one byte frames */
349 if ((slen == 1) && (hdlc->state == HDLC_SEND_FAST_FLAG))
350 hdlc->state = HDLC_SENDFLAG_ONE;
351 while (dsize > 0) {
352 if (hdlc->bit_shift == 0) {
353 if (slen && !hdlc->do_closing) {
354 hdlc->shift_reg = *src++;
355 slen--;
356 if (slen == 0)
357 /* closing sequence, CRC + flag(s) */
358 hdlc->do_closing = 1;
359 hdlc->bit_shift = 8;
360 } else {
361 if (hdlc->state == HDLC_SEND_DATA) {
362 if (hdlc->data_received) {
363 hdlc->state = HDLC_SEND_CRC1;
364 hdlc->crc ^= 0xffff;
365 hdlc->bit_shift = 8;
366 hdlc->shift_reg =
367 hdlc->crc & 0xff;
368 } else if (!hdlc->do_adapt56)
369 hdlc->state =
370 HDLC_SEND_FAST_FLAG;
371 else
372 hdlc->state =
373 HDLC_SENDFLAG_B0;
374 }
375
376 }
377 }
378
379 switch (hdlc->state) {
380 case STOPPED:
381 while (dsize--)
382 *dst++ = 0xff;
383 return dsize;
384 case HDLC_SEND_FAST_FLAG:
385 hdlc->do_closing = 0;
386 if (slen == 0) {
387 /* the code is for bitreverse streams */
388 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200389 *dst++ = osmo_revbytebits_8(hdlc->ffvalue);
Harald Welte85b9fba2018-05-11 17:36:13 +0200390 else
391 *dst++ = hdlc->ffvalue;
392 len++;
393 dsize--;
394 break;
395 }
396 /* fall through */
397 case HDLC_SENDFLAG_ONE:
398 if (hdlc->bit_shift == 8) {
399 hdlc->cbin = hdlc->ffvalue >>
400 (8 - hdlc->data_bits);
401 hdlc->state = HDLC_SEND_DATA;
402 hdlc->crc = 0xffff;
403 hdlc->hdlc_bits1 = 0;
404 hdlc->data_received = 1;
405 }
406 break;
407 case HDLC_SENDFLAG_B0:
408 hdlc->do_closing = 0;
409 hdlc->cbin <<= 1;
410 hdlc->data_bits++;
411 hdlc->hdlc_bits1 = 0;
412 hdlc->state = HDLC_SENDFLAG_B1A6;
413 break;
414 case HDLC_SENDFLAG_B1A6:
415 hdlc->cbin <<= 1;
416 hdlc->data_bits++;
417 hdlc->cbin++;
418 if (++hdlc->hdlc_bits1 == 6)
419 hdlc->state = HDLC_SENDFLAG_B7;
420 break;
421 case HDLC_SENDFLAG_B7:
422 hdlc->cbin <<= 1;
423 hdlc->data_bits++;
424 if (slen == 0) {
425 hdlc->state = HDLC_SENDFLAG_B0;
426 break;
427 }
428 if (hdlc->bit_shift == 8) {
429 hdlc->state = HDLC_SEND_DATA;
430 hdlc->crc = 0xffff;
431 hdlc->hdlc_bits1 = 0;
432 hdlc->data_received = 1;
433 }
434 break;
435 case HDLC_SEND_FIRST_FLAG:
436 hdlc->data_received = 1;
437 if (hdlc->data_bits == 8) {
438 hdlc->state = HDLC_SEND_DATA;
439 hdlc->crc = 0xffff;
440 hdlc->hdlc_bits1 = 0;
441 break;
442 }
443 hdlc->cbin <<= 1;
444 hdlc->data_bits++;
445 if (hdlc->shift_reg & 0x01)
446 hdlc->cbin++;
447 hdlc->shift_reg >>= 1;
448 hdlc->bit_shift--;
449 if (hdlc->bit_shift == 0) {
450 hdlc->state = HDLC_SEND_DATA;
451 hdlc->crc = 0xffff;
452 hdlc->hdlc_bits1 = 0;
453 }
454 break;
455 case HDLC_SEND_DATA:
456 hdlc->cbin <<= 1;
457 hdlc->data_bits++;
458 if (hdlc->hdlc_bits1 == 5) {
459 hdlc->hdlc_bits1 = 0;
460 break;
461 }
462 if (hdlc->bit_shift == 8)
463 hdlc->crc = crc_ccitt_byte(hdlc->crc,
464 hdlc->shift_reg);
465 if (hdlc->shift_reg & 0x01) {
466 hdlc->hdlc_bits1++;
467 hdlc->cbin++;
468 hdlc->shift_reg >>= 1;
469 hdlc->bit_shift--;
470 } else {
471 hdlc->hdlc_bits1 = 0;
472 hdlc->shift_reg >>= 1;
473 hdlc->bit_shift--;
474 }
475 break;
476 case HDLC_SEND_CRC1:
477 hdlc->cbin <<= 1;
478 hdlc->data_bits++;
479 if (hdlc->hdlc_bits1 == 5) {
480 hdlc->hdlc_bits1 = 0;
481 break;
482 }
483 if (hdlc->shift_reg & 0x01) {
484 hdlc->hdlc_bits1++;
485 hdlc->cbin++;
486 hdlc->shift_reg >>= 1;
487 hdlc->bit_shift--;
488 } else {
489 hdlc->hdlc_bits1 = 0;
490 hdlc->shift_reg >>= 1;
491 hdlc->bit_shift--;
492 }
493 if (hdlc->bit_shift == 0) {
494 hdlc->shift_reg = (hdlc->crc >> 8);
495 hdlc->state = HDLC_SEND_CRC2;
496 hdlc->bit_shift = 8;
497 }
498 break;
499 case HDLC_SEND_CRC2:
500 hdlc->cbin <<= 1;
501 hdlc->data_bits++;
502 if (hdlc->hdlc_bits1 == 5) {
503 hdlc->hdlc_bits1 = 0;
504 break;
505 }
506 if (hdlc->shift_reg & 0x01) {
507 hdlc->hdlc_bits1++;
508 hdlc->cbin++;
509 hdlc->shift_reg >>= 1;
510 hdlc->bit_shift--;
511 } else {
512 hdlc->hdlc_bits1 = 0;
513 hdlc->shift_reg >>= 1;
514 hdlc->bit_shift--;
515 }
516 if (hdlc->bit_shift == 0) {
517 hdlc->shift_reg = 0x7e;
518 hdlc->state = HDLC_SEND_CLOSING_FLAG;
519 hdlc->bit_shift = 8;
520 }
521 break;
522 case HDLC_SEND_CLOSING_FLAG:
523 hdlc->cbin <<= 1;
524 hdlc->data_bits++;
525 if (hdlc->hdlc_bits1 == 5) {
526 hdlc->hdlc_bits1 = 0;
527 break;
528 }
529 if (hdlc->shift_reg & 0x01)
530 hdlc->cbin++;
531 hdlc->shift_reg >>= 1;
532 hdlc->bit_shift--;
533 if (hdlc->bit_shift == 0) {
534 hdlc->ffvalue =
535 xfast_flag_value[hdlc->data_bits];
536 if (hdlc->dchannel) {
537 hdlc->ffvalue = 0x7e;
538 hdlc->state = HDLC_SEND_IDLE1;
539 hdlc->bit_shift = 8-hdlc->data_bits;
540 if (hdlc->bit_shift == 0)
541 hdlc->state =
542 HDLC_SEND_FAST_IDLE;
543 } else {
544 if (!hdlc->do_adapt56) {
545 hdlc->state =
546 HDLC_SEND_FAST_FLAG;
547 hdlc->data_received = 0;
548 } else {
549 hdlc->state = HDLC_SENDFLAG_B0;
550 hdlc->data_received = 0;
551 }
552 /* Finished this frame, send flags */
553 if (dsize > 1)
554 dsize = 1;
555 }
556 }
557 break;
558 case HDLC_SEND_IDLE1:
559 hdlc->do_closing = 0;
560 hdlc->cbin <<= 1;
561 hdlc->cbin++;
562 hdlc->data_bits++;
563 hdlc->bit_shift--;
564 if (hdlc->bit_shift == 0) {
565 hdlc->state = HDLC_SEND_FAST_IDLE;
566 hdlc->bit_shift = 0;
567 }
568 break;
569 case HDLC_SEND_FAST_IDLE:
570 hdlc->do_closing = 0;
571 hdlc->cbin = 0xff;
572 hdlc->data_bits = 8;
573 if (hdlc->bit_shift == 8) {
574 hdlc->cbin = 0x7e;
575 hdlc->state = HDLC_SEND_FIRST_FLAG;
576 } else {
577 /* the code is for bitreverse streams */
578 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200579 *dst++ = osmo_revbytebits_8(hdlc->cbin);
Harald Welte85b9fba2018-05-11 17:36:13 +0200580 else
581 *dst++ = hdlc->cbin;
582 hdlc->bit_shift = 0;
583 hdlc->data_bits = 0;
584 len++;
585 dsize = 0;
586 }
587 break;
588 default:
589 break;
590 }
591 if (hdlc->do_adapt56) {
592 if (hdlc->data_bits == 7) {
593 hdlc->cbin <<= 1;
594 hdlc->cbin++;
595 hdlc->data_bits++;
596 }
597 }
598 if (hdlc->data_bits == 8) {
599 /* the code is for bitreverse streams */
600 if (hdlc->do_bitreverse == 0)
Harald Welte9da77ab2018-05-11 17:39:21 +0200601 *dst++ = osmo_revbytebits_8(hdlc->cbin);
Harald Welte85b9fba2018-05-11 17:36:13 +0200602 else
603 *dst++ = hdlc->cbin;
604 hdlc->data_bits = 0;
605 len++;
606 dsize--;
607 }
608 }
609 *count -= slen;
610
611 return len;
612}