comparison spandsp-0.0.6pre17/src/hdlc.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * hdlc.c
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2003 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: hdlc.c,v 1.72 2009/06/02 16:03:56 steveu Exp $
26 */
27
28 /*! \file */
29
30 #if defined(HAVE_CONFIG_H)
31 #include "config.h"
32 #endif
33
34 #include <stdlib.h>
35 #include <inttypes.h>
36 #include <string.h>
37 #include <stdio.h>
38
39 #include "spandsp/telephony.h"
40 #include "spandsp/async.h"
41 #include "spandsp/crc.h"
42 #include "spandsp/bit_operations.h"
43 #include "spandsp/hdlc.h"
44 #include "spandsp/private/hdlc.h"
45
46 static void report_status_change(hdlc_rx_state_t *s, int status)
47 {
48 if (s->status_handler)
49 s->status_handler(s->status_user_data, status);
50 else if (s->frame_handler)
51 s->frame_handler(s->frame_user_data, NULL, status, TRUE);
52 }
53 /*- End of function --------------------------------------------------------*/
54
55 static void rx_special_condition(hdlc_rx_state_t *s, int status)
56 {
57 /* Special conditions */
58 switch (status)
59 {
60 case SIG_STATUS_CARRIER_UP:
61 case SIG_STATUS_TRAINING_SUCCEEDED:
62 /* Reset the HDLC receiver. */
63 s->raw_bit_stream = 0;
64 s->len = 0;
65 s->num_bits = 0;
66 s->flags_seen = 0;
67 s->framing_ok_announced = FALSE;
68 /* Fall through */
69 case SIG_STATUS_TRAINING_IN_PROGRESS:
70 case SIG_STATUS_TRAINING_FAILED:
71 case SIG_STATUS_CARRIER_DOWN:
72 case SIG_STATUS_END_OF_DATA:
73 report_status_change(s, status);
74 break;
75 default:
76 //printf("Eh!\n");
77 break;
78 }
79 }
80 /*- End of function --------------------------------------------------------*/
81
82 static __inline__ void octet_set_and_count(hdlc_rx_state_t *s)
83 {
84 if (s->octet_count_report_interval == 0)
85 return;
86
87 /* If we are not in octet counting mode, we start it.
88 If we are in octet counting mode, we update it. */
89 if (s->octet_counting_mode)
90 {
91 if (--s->octet_count <= 0)
92 {
93 s->octet_count = s->octet_count_report_interval;
94 report_status_change(s, SIG_STATUS_OCTET_REPORT);
95 }
96 }
97 else
98 {
99 s->octet_counting_mode = TRUE;
100 s->octet_count = s->octet_count_report_interval;
101 }
102 }
103 /*- End of function --------------------------------------------------------*/
104
105 static __inline__ void octet_count(hdlc_rx_state_t *s)
106 {
107 if (s->octet_count_report_interval == 0)
108 return;
109
110 /* If we are not in octet counting mode, we start it.
111 If we are in octet counting mode, we update it. */
112 if (s->octet_counting_mode)
113 {
114 if (--s->octet_count <= 0)
115 {
116 s->octet_count = s->octet_count_report_interval;
117 report_status_change(s, SIG_STATUS_OCTET_REPORT);
118 }
119 }
120 }
121 /*- End of function --------------------------------------------------------*/
122
123 static void rx_flag_or_abort(hdlc_rx_state_t *s)
124 {
125 if ((s->raw_bit_stream & 0x8000))
126 {
127 /* Hit HDLC abort */
128 s->rx_aborts++;
129 report_status_change(s, SIG_STATUS_ABORT);
130 /* If we have not yet seen enough flags, restart the count. If we
131 are beyond that point, just back off one step, so we need to see
132 another flag before proceeding to collect frame octets. */
133 if (s->flags_seen < s->framing_ok_threshold - 1)
134 s->flags_seen = 0;
135 else
136 s->flags_seen = s->framing_ok_threshold - 1;
137 /* An abort starts octet counting */
138 octet_set_and_count(s);
139 }
140 else
141 {
142 /* Hit HDLC flag */
143 /* A flag clears octet counting */
144 s->octet_counting_mode = FALSE;
145 if (s->flags_seen >= s->framing_ok_threshold)
146 {
147 /* We may have a frame, or we may have back to back flags */
148 if (s->len)
149 {
150 if (s->num_bits == 7 && s->len >= (size_t) s->crc_bytes && s->len <= s->max_frame_len)
151 {
152 if ((s->crc_bytes == 2 && crc_itu16_check(s->buffer, s->len))
153 ||
154 (s->crc_bytes != 2 && crc_itu32_check(s->buffer, s->len)))
155 {
156 s->rx_frames++;
157 s->rx_bytes += s->len - s->crc_bytes;
158 s->len -= s->crc_bytes;
159 s->frame_handler(s->frame_user_data, s->buffer, s->len, TRUE);
160 }
161 else
162 {
163 s->rx_crc_errors++;
164 if (s->report_bad_frames)
165 {
166 s->len -= s->crc_bytes;
167 s->frame_handler(s->frame_user_data, s->buffer, s->len, FALSE);
168 }
169 }
170 }
171 else
172 {
173 /* Frame too short or too long, or the flag is misaligned with its octets. */
174 if (s->report_bad_frames)
175 {
176 /* Don't let the length go below zero, or it will be confused
177 with one of the special conditions. */
178 if (s->len >= (size_t) s->crc_bytes)
179 s->len -= s->crc_bytes;
180 else
181 s->len = 0;
182 s->frame_handler(s->frame_user_data, s->buffer, s->len, FALSE);
183 }
184 s->rx_length_errors++;
185 }
186 }
187 }
188 else
189 {
190 /* Check the flags are back-to-back when testing for valid preamble. This
191 greatly reduces the chances of false preamble detection, and anything
192 which doesn't send them back-to-back is badly broken. */
193 if (s->num_bits != 7)
194 {
195 /* Don't set the flags seen indicator back to zero too aggressively.
196 We want to pick up with the minimum of discarded data when there
197 is a bit error in the stream, and a bit error could emulate a
198 misaligned flag. */
199 if (s->flags_seen < s->framing_ok_threshold - 1)
200 s->flags_seen = 0;
201 else
202 s->flags_seen = s->framing_ok_threshold - 1;
203 }
204 if (++s->flags_seen >= s->framing_ok_threshold && !s->framing_ok_announced)
205 {
206 report_status_change(s, SIG_STATUS_FRAMING_OK);
207 s->framing_ok_announced = TRUE;
208 }
209 }
210 }
211 s->len = 0;
212 s->num_bits = 0;
213 }
214 /*- End of function --------------------------------------------------------*/
215
216 static __inline__ void hdlc_rx_put_bit_core(hdlc_rx_state_t *s)
217 {
218 if ((s->raw_bit_stream & 0x3F00) == 0x3E00)
219 {
220 /* Its time to either skip a bit, for stuffing, or process a
221 flag or abort */
222 if ((s->raw_bit_stream & 0x4000))
223 rx_flag_or_abort(s);
224 return;
225 }
226 s->num_bits++;
227 if (s->flags_seen < s->framing_ok_threshold)
228 {
229 if ((s->num_bits & 0x7) == 0)
230 octet_count(s);
231 return;
232 }
233 s->byte_in_progress = (s->byte_in_progress | (s->raw_bit_stream & 0x100)) >> 1;
234 if (s->num_bits == 8)
235 {
236 /* Ensure we do not accept an overlength frame, and especially that
237 we do not overflow our buffer */
238 if (s->len < s->max_frame_len)
239 {
240 s->buffer[s->len++] = (uint8_t) s->byte_in_progress;
241 }
242 else
243 {
244 /* This is too long. Abandon the frame, and wait for the next
245 flag octet. */
246 s->len = sizeof(s->buffer) + 1;
247 s->flags_seen = s->framing_ok_threshold - 1;
248 octet_set_and_count(s);
249 }
250 s->num_bits = 0;
251 }
252 }
253 /*- End of function --------------------------------------------------------*/
254
255 SPAN_DECLARE_NONSTD(void) hdlc_rx_put_bit(hdlc_rx_state_t *s, int new_bit)
256 {
257 if (new_bit < 0)
258 {
259 rx_special_condition(s, new_bit);
260 return;
261 }
262 s->raw_bit_stream = (s->raw_bit_stream << 1) | ((new_bit << 8) & 0x100);
263 hdlc_rx_put_bit_core(s);
264 }
265 /*- End of function --------------------------------------------------------*/
266
267 SPAN_DECLARE_NONSTD(void) hdlc_rx_put_byte(hdlc_rx_state_t *s, int new_byte)
268 {
269 int i;
270
271 if (new_byte < 0)
272 {
273 rx_special_condition(s, new_byte);
274 return;
275 }
276 s->raw_bit_stream |= new_byte;
277 for (i = 0; i < 8; i++)
278 {
279 s->raw_bit_stream <<= 1;
280 hdlc_rx_put_bit_core(s);
281 }
282 }
283 /*- End of function --------------------------------------------------------*/
284
285 SPAN_DECLARE_NONSTD(void) hdlc_rx_put(hdlc_rx_state_t *s, const uint8_t buf[], int len)
286 {
287 int i;
288
289 for (i = 0; i < len; i++)
290 hdlc_rx_put_byte(s, buf[i]);
291 }
292 /*- End of function --------------------------------------------------------*/
293
294 SPAN_DECLARE(void) hdlc_rx_set_max_frame_len(hdlc_rx_state_t *s, size_t max_len)
295 {
296 max_len += s->crc_bytes;
297 s->max_frame_len = (max_len <= sizeof(s->buffer)) ? max_len : sizeof(s->buffer);
298 }
299 /*- End of function --------------------------------------------------------*/
300
301 SPAN_DECLARE(void) hdlc_rx_set_octet_counting_report_interval(hdlc_rx_state_t *s, int interval)
302 {
303 s->octet_count_report_interval = interval;
304 }
305 /*- End of function --------------------------------------------------------*/
306
307 SPAN_DECLARE(hdlc_rx_state_t *) hdlc_rx_init(hdlc_rx_state_t *s,
308 int crc32,
309 int report_bad_frames,
310 int framing_ok_threshold,
311 hdlc_frame_handler_t handler,
312 void *user_data)
313 {
314 if (s == NULL)
315 {
316 if ((s = (hdlc_rx_state_t *) malloc(sizeof(*s))) == NULL)
317 return NULL;
318 }
319 memset(s, 0, sizeof(*s));
320 s->frame_handler = handler;
321 s->frame_user_data = user_data;
322 s->crc_bytes = (crc32) ? 4 : 2;
323 s->report_bad_frames = report_bad_frames;
324 s->framing_ok_threshold = (framing_ok_threshold < 1) ? 1 : framing_ok_threshold;
325 s->max_frame_len = sizeof(s->buffer);
326 return s;
327 }
328 /*- End of function --------------------------------------------------------*/
329
330 SPAN_DECLARE(void) hdlc_rx_set_frame_handler(hdlc_rx_state_t *s, hdlc_frame_handler_t handler, void *user_data)
331 {
332 s->frame_handler = handler;
333 s->frame_user_data = user_data;
334 }
335 /*- End of function --------------------------------------------------------*/
336
337 SPAN_DECLARE(void) hdlc_rx_set_status_handler(hdlc_rx_state_t *s, modem_rx_status_func_t handler, void *user_data)
338 {
339 s->status_handler = handler;
340 s->status_user_data = user_data;
341 }
342 /*- End of function --------------------------------------------------------*/
343
344 SPAN_DECLARE(int) hdlc_rx_release(hdlc_rx_state_t *s)
345 {
346 return 0;
347 }
348 /*- End of function --------------------------------------------------------*/
349
350 SPAN_DECLARE(int) hdlc_rx_free(hdlc_rx_state_t *s)
351 {
352 free(s);
353 return 0;
354 }
355 /*- End of function --------------------------------------------------------*/
356
357 SPAN_DECLARE(int) hdlc_rx_get_stats(hdlc_rx_state_t *s,
358 hdlc_rx_stats_t *t)
359 {
360 t->bytes = s->rx_bytes;
361 t->good_frames = s->rx_frames;
362 t->crc_errors = s->rx_crc_errors;
363 t->length_errors = s->rx_length_errors;
364 t->aborts = s->rx_aborts;
365 return 0;
366 }
367 /*- End of function --------------------------------------------------------*/
368
369 SPAN_DECLARE(int) hdlc_tx_frame(hdlc_tx_state_t *s, const uint8_t *frame, size_t len)
370 {
371 if (len <= 0)
372 {
373 s->tx_end = TRUE;
374 return 0;
375 }
376 if (s->len + len > s->max_frame_len)
377 return -1;
378 if (s->progressive)
379 {
380 /* Only lock out if we are in the CRC section. */
381 if (s->pos >= HDLC_MAXFRAME_LEN)
382 return -1;
383 }
384 else
385 {
386 /* Lock out if there is anything in the buffer. */
387 if (s->len)
388 return -1;
389 }
390 memcpy(s->buffer + s->len, frame, len);
391 if (s->crc_bytes == 2)
392 s->crc = crc_itu16_calc(frame, len, (uint16_t) s->crc);
393 else
394 s->crc = crc_itu32_calc(frame, len, s->crc);
395 if (s->progressive)
396 s->len += len;
397 else
398 s->len = len;
399 s->tx_end = FALSE;
400 return 0;
401 }
402 /*- End of function --------------------------------------------------------*/
403
404 SPAN_DECLARE(int) hdlc_tx_flags(hdlc_tx_state_t *s, int len)
405 {
406 /* Some HDLC applications require the ability to force a period of HDLC
407 flag words. */
408 if (s->pos)
409 return -1;
410 if (len < 0)
411 s->flag_octets += -len;
412 else
413 s->flag_octets = len;
414 s->report_flag_underflow = TRUE;
415 s->tx_end = FALSE;
416 return 0;
417 }
418 /*- End of function --------------------------------------------------------*/
419
420 SPAN_DECLARE(int) hdlc_tx_abort(hdlc_tx_state_t *s)
421 {
422 /* TODO: This is a really crude way of just fudging an abort out for simple
423 test purposes. */
424 s->flag_octets++;
425 s->abort_octets++;
426 return -1;
427 }
428 /*- End of function --------------------------------------------------------*/
429
430 SPAN_DECLARE(int) hdlc_tx_corrupt_frame(hdlc_tx_state_t *s)
431 {
432 if (s->len <= 0)
433 return -1;
434 s->crc ^= 0xFFFF;
435 s->buffer[HDLC_MAXFRAME_LEN] ^= 0xFF;
436 s->buffer[HDLC_MAXFRAME_LEN + 1] ^= 0xFF;
437 s->buffer[HDLC_MAXFRAME_LEN + 2] ^= 0xFF;
438 s->buffer[HDLC_MAXFRAME_LEN + 3] ^= 0xFF;
439 return 0;
440 }
441 /*- End of function --------------------------------------------------------*/
442
443 SPAN_DECLARE_NONSTD(int) hdlc_tx_get_byte(hdlc_tx_state_t *s)
444 {
445 int i;
446 int byte_in_progress;
447 int txbyte;
448
449 if (s->flag_octets > 0)
450 {
451 /* We are in a timed flag section (preamble, inter frame gap, etc.) */
452 if (--s->flag_octets <= 0 && s->report_flag_underflow)
453 {
454 s->report_flag_underflow = FALSE;
455 if (s->len == 0)
456 {
457 /* The timed flags have finished, there is nothing else queued to go,
458 and we have been told to report this underflow. */
459 if (s->underflow_handler)
460 s->underflow_handler(s->user_data);
461 }
462 }
463 if (s->abort_octets)
464 {
465 s->abort_octets = 0;
466 return 0x7F;
467 }
468 return s->idle_octet;
469 }
470 if (s->len)
471 {
472 if (s->num_bits >= 8)
473 {
474 s->num_bits -= 8;
475 return (s->octets_in_progress >> s->num_bits) & 0xFF;
476 }
477 if (s->pos >= s->len)
478 {
479 if (s->pos == s->len)
480 {
481 s->crc ^= 0xFFFFFFFF;
482 s->buffer[HDLC_MAXFRAME_LEN] = (uint8_t) s->crc;
483 s->buffer[HDLC_MAXFRAME_LEN + 1] = (uint8_t) (s->crc >> 8);
484 if (s->crc_bytes == 4)
485 {
486 s->buffer[HDLC_MAXFRAME_LEN + 2] = (uint8_t) (s->crc >> 16);
487 s->buffer[HDLC_MAXFRAME_LEN + 3] = (uint8_t) (s->crc >> 24);
488 }
489 s->pos = HDLC_MAXFRAME_LEN;
490 }
491 else if (s->pos == (size_t) (HDLC_MAXFRAME_LEN + s->crc_bytes))
492 {
493 /* Finish off the current byte with some flag bits. If we are at the
494 start of a byte we need a at least one whole byte of flag to ensure
495 we cannot end up with back to back frames, and no flag octet at all */
496 txbyte = (uint8_t) ((s->octets_in_progress << (8 - s->num_bits)) | (0x7E >> s->num_bits));
497 /* Create a rotated octet of flag for idling... */
498 s->idle_octet = (0x7E7E >> s->num_bits) & 0xFF;
499 /* ...and the partial flag octet needed to start off the next message. */
500 s->octets_in_progress = s->idle_octet >> (8 - s->num_bits);
501 s->flag_octets = s->inter_frame_flags - 1;
502 s->len = 0;
503 s->pos = 0;
504 if (s->crc_bytes == 2)
505 s->crc = 0xFFFF;
506 else
507 s->crc = 0xFFFFFFFF;
508 /* Report the underflow now. If there are timed flags still in progress, loading the
509 next frame right now will be harmless. */
510 s->report_flag_underflow = FALSE;
511 if (s->underflow_handler)
512 s->underflow_handler(s->user_data);
513 /* Make sure we finish off with at least one flag octet, if the underflow report did not result
514 in a new frame being sent. */
515 if (s->len == 0 && s->flag_octets < 2)
516 s->flag_octets = 2;
517 return txbyte;
518 }
519 }
520 byte_in_progress = s->buffer[s->pos++];
521 i = bottom_bit(byte_in_progress | 0x100);
522 s->octets_in_progress <<= i;
523 byte_in_progress >>= i;
524 for ( ; i < 8; i++)
525 {
526 s->octets_in_progress = (s->octets_in_progress << 1) | (byte_in_progress & 0x01);
527 byte_in_progress >>= 1;
528 if ((s->octets_in_progress & 0x1F) == 0x1F)
529 {
530 /* There are 5 ones - stuff */
531 s->octets_in_progress <<= 1;
532 s->num_bits++;
533 }
534 }
535 /* An input byte will generate between 8 and 10 output bits */
536 return (s->octets_in_progress >> s->num_bits) & 0xFF;
537 }
538 /* Untimed idling on flags */
539 if (s->tx_end)
540 {
541 s->tx_end = FALSE;
542 return SIG_STATUS_END_OF_DATA;
543 }
544 return s->idle_octet;
545 }
546 /*- End of function --------------------------------------------------------*/
547
548 SPAN_DECLARE_NONSTD(int) hdlc_tx_get_bit(hdlc_tx_state_t *s)
549 {
550 int txbit;
551
552 if (s->bits == 0)
553 {
554 if ((s->byte = hdlc_tx_get_byte(s)) < 0)
555 return s->byte;
556 s->bits = 8;
557 }
558 s->bits--;
559 txbit = (s->byte >> s->bits) & 0x01;
560 return txbit;
561 }
562 /*- End of function --------------------------------------------------------*/
563
564 SPAN_DECLARE_NONSTD(int) hdlc_tx_get(hdlc_tx_state_t *s, uint8_t buf[], size_t max_len)
565 {
566 size_t i;
567 int x;
568
569 for (i = 0; i < max_len; i++)
570 {
571 if ((x = hdlc_tx_get_byte(s)) == SIG_STATUS_END_OF_DATA)
572 return i;
573 buf[i] = (uint8_t) x;
574 }
575 return (int) i;
576 }
577 /*- End of function --------------------------------------------------------*/
578
579 SPAN_DECLARE(void) hdlc_tx_set_max_frame_len(hdlc_tx_state_t *s, size_t max_len)
580 {
581 s->max_frame_len = (max_len <= HDLC_MAXFRAME_LEN) ? max_len : HDLC_MAXFRAME_LEN;
582 }
583 /*- End of function --------------------------------------------------------*/
584
585 SPAN_DECLARE(hdlc_tx_state_t *) hdlc_tx_init(hdlc_tx_state_t *s,
586 int crc32,
587 int inter_frame_flags,
588 int progressive,
589 hdlc_underflow_handler_t handler,
590 void *user_data)
591 {
592 if (s == NULL)
593 {
594 if ((s = (hdlc_tx_state_t *) malloc(sizeof(*s))) == NULL)
595 return NULL;
596 }
597 memset(s, 0, sizeof(*s));
598 s->idle_octet = 0x7E;
599 s->underflow_handler = handler;
600 s->user_data = user_data;
601 s->inter_frame_flags = (inter_frame_flags < 1) ? 1 : inter_frame_flags;
602 if (crc32)
603 {
604 s->crc_bytes = 4;
605 s->crc = 0xFFFFFFFF;
606 }
607 else
608 {
609 s->crc_bytes = 2;
610 s->crc = 0xFFFF;
611 }
612 s->progressive = progressive;
613 s->max_frame_len = HDLC_MAXFRAME_LEN;
614 return s;
615 }
616 /*- End of function --------------------------------------------------------*/
617
618 SPAN_DECLARE(int) hdlc_tx_release(hdlc_tx_state_t *s)
619 {
620 return 0;
621 }
622 /*- End of function --------------------------------------------------------*/
623
624 SPAN_DECLARE(int) hdlc_tx_free(hdlc_tx_state_t *s)
625 {
626 free(s);
627 return 0;
628 }
629 /*- End of function --------------------------------------------------------*/
630 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.