Mercurial > hg > audiostuff
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 ------------------------------------------------------------*/ |
