697 lines
28 KiB
C
697 lines
28 KiB
C
/* $Id$
|
|
******************************************************************************
|
|
|
|
Fax program for ISDN.
|
|
Encoder for HDLC-framing.
|
|
|
|
Copyright (C) 1999 Morten Rolland [Morten.Rolland@asker.mail.telia.com]
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
******************************************************************************
|
|
*/
|
|
|
|
/* Translate a block of binary data into a HDLC frame and output it
|
|
* as a stream of bits, usable for feeding the scrambler or V.21
|
|
* modulator.
|
|
*
|
|
* The block to be transmitted is presented to this module through the
|
|
* command interface. With no data to transmit, an idle-pattern is
|
|
* transmitted.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
#include <ifax/ifax.h>
|
|
#include <ifax/types.h>
|
|
#include <ifax/misc/malloc.h>
|
|
#include <ifax/bitreverse.h>
|
|
#include <ifax/modules/hdlc-framing.h>
|
|
|
|
#define MAXBUFFER 512
|
|
#define QUEUESIZE 128
|
|
|
|
#define FLAG_SEQUENCE 0x7e
|
|
|
|
typedef struct {
|
|
|
|
ifax_uint32 bitslide;
|
|
int bitslide_size;
|
|
|
|
enum { ADDRESS, PAYLOAD, FCS, IDLE } phase;
|
|
ifax_uint8 *src;
|
|
size_t remaining_bytes;
|
|
ifax_uint16 fcs;
|
|
ifax_uint8 fcs_tx[2];
|
|
|
|
int new_frame;
|
|
int current_frame;
|
|
int idle, idlebits;
|
|
|
|
struct {
|
|
size_t size;
|
|
ifax_uint8 *start;
|
|
ifax_uint8 address;
|
|
} framequeue[QUEUESIZE];
|
|
|
|
ifax_uint8 buffer[MAXBUFFER];
|
|
|
|
} encoder_hdlc_private;
|
|
|
|
|
|
/* The 'bitstufftbl' array is used to help determine when and where
|
|
* bit-stuffing should be applied. The HDLC protocol specifies that
|
|
* 6 bits in a row with value '1' is reserved for the FLAG sequence.
|
|
* A flag is used to start and stop a frame.
|
|
* When there are 5 bits in a row with value '1' in the body of
|
|
* a frame, they have to be bit-stuffed, so that there is a '0'
|
|
* inserted after the first 5 bits. The bit-stream is expanded as
|
|
* a result of this, but the advantage is that frame synchronisation
|
|
* is rapidly established.
|
|
*
|
|
* The 'bitstufftbl' is used to answer the following two questions:
|
|
*
|
|
* 1) How many consecutive '1' is there from LSB and up
|
|
* 2) Should a '0' be inserted in bit-positions 5-8 (0 means no stuffing)
|
|
*
|
|
* The index to the table is the 8 bit unsigned intger in question:
|
|
*
|
|
* x7 x6 x5 x4 x3 x2 x1 x0
|
|
* MSB LSB
|
|
*
|
|
* The lookup-value is a packed character, whith the following fields:
|
|
*
|
|
* v7 v6 v5 v4 | v3 v2 v1 v0
|
|
* --------------+------------
|
|
* Position | Number of
|
|
* of needed | '1' from
|
|
* stuffing | LSB and up
|
|
* 0 => none |
|
|
* 5-8 => x5-x8 |
|
|
*/
|
|
|
|
static ifax_uint8 bitstufftbl[256] = {
|
|
0x00, /* 00000000 => 0 bits */
|
|
0x01, /* 00000001 => 1 bits */
|
|
0x00, /* 00000010 => 0 bits */
|
|
0x02, /* 00000011 => 2 bits */
|
|
0x00, /* 00000100 => 0 bits */
|
|
0x01, /* 00000101 => 1 bits */
|
|
0x00, /* 00000110 => 0 bits */
|
|
0x03, /* 00000111 => 3 bits */
|
|
0x00, /* 00001000 => 0 bits */
|
|
0x01, /* 00001001 => 1 bits */
|
|
0x00, /* 00001010 => 0 bits */
|
|
0x02, /* 00001011 => 2 bits */
|
|
0x00, /* 00001100 => 0 bits */
|
|
0x01, /* 00001101 => 1 bits */
|
|
0x00, /* 00001110 => 0 bits */
|
|
0x04, /* 00001111 => 4 bits */
|
|
0x00, /* 00010000 => 0 bits */
|
|
0x01, /* 00010001 => 1 bits */
|
|
0x00, /* 00010010 => 0 bits */
|
|
0x02, /* 00010011 => 2 bits */
|
|
0x00, /* 00010100 => 0 bits */
|
|
0x01, /* 00010101 => 1 bits */
|
|
0x00, /* 00010110 => 0 bits */
|
|
0x03, /* 00010111 => 3 bits */
|
|
0x00, /* 00011000 => 0 bits */
|
|
0x01, /* 00011001 => 1 bits */
|
|
0x00, /* 00011010 => 0 bits */
|
|
0x02, /* 00011011 => 2 bits */
|
|
0x00, /* 00011100 => 0 bits */
|
|
0x01, /* 00011101 => 1 bits */
|
|
0x00, /* 00011110 => 0 bits */
|
|
0x55, /* 00011111 => 5 bits (Stuff at bit 5) */
|
|
0x00, /* 00100000 => 0 bits */
|
|
0x01, /* 00100001 => 1 bits */
|
|
0x00, /* 00100010 => 0 bits */
|
|
0x02, /* 00100011 => 2 bits */
|
|
0x00, /* 00100100 => 0 bits */
|
|
0x01, /* 00100101 => 1 bits */
|
|
0x00, /* 00100110 => 0 bits */
|
|
0x03, /* 00100111 => 3 bits */
|
|
0x00, /* 00101000 => 0 bits */
|
|
0x01, /* 00101001 => 1 bits */
|
|
0x00, /* 00101010 => 0 bits */
|
|
0x02, /* 00101011 => 2 bits */
|
|
0x00, /* 00101100 => 0 bits */
|
|
0x01, /* 00101101 => 1 bits */
|
|
0x00, /* 00101110 => 0 bits */
|
|
0x04, /* 00101111 => 4 bits */
|
|
0x00, /* 00110000 => 0 bits */
|
|
0x01, /* 00110001 => 1 bits */
|
|
0x00, /* 00110010 => 0 bits */
|
|
0x02, /* 00110011 => 2 bits */
|
|
0x00, /* 00110100 => 0 bits */
|
|
0x01, /* 00110101 => 1 bits */
|
|
0x00, /* 00110110 => 0 bits */
|
|
0x03, /* 00110111 => 3 bits */
|
|
0x00, /* 00111000 => 0 bits */
|
|
0x01, /* 00111001 => 1 bits */
|
|
0x00, /* 00111010 => 0 bits */
|
|
0x02, /* 00111011 => 2 bits */
|
|
0x00, /* 00111100 => 0 bits */
|
|
0x01, /* 00111101 => 1 bits */
|
|
0x60, /* 00111110 => 0 bits (Stuff at bit 6) */
|
|
0x56, /* 00111111 => 6 bits (Stuff at bit 5) */
|
|
0x00, /* 01000000 => 0 bits */
|
|
0x01, /* 01000001 => 1 bits */
|
|
0x00, /* 01000010 => 0 bits */
|
|
0x02, /* 01000011 => 2 bits */
|
|
0x00, /* 01000100 => 0 bits */
|
|
0x01, /* 01000101 => 1 bits */
|
|
0x00, /* 01000110 => 0 bits */
|
|
0x03, /* 01000111 => 3 bits */
|
|
0x00, /* 01001000 => 0 bits */
|
|
0x01, /* 01001001 => 1 bits */
|
|
0x00, /* 01001010 => 0 bits */
|
|
0x02, /* 01001011 => 2 bits */
|
|
0x00, /* 01001100 => 0 bits */
|
|
0x01, /* 01001101 => 1 bits */
|
|
0x00, /* 01001110 => 0 bits */
|
|
0x04, /* 01001111 => 4 bits */
|
|
0x00, /* 01010000 => 0 bits */
|
|
0x01, /* 01010001 => 1 bits */
|
|
0x00, /* 01010010 => 0 bits */
|
|
0x02, /* 01010011 => 2 bits */
|
|
0x00, /* 01010100 => 0 bits */
|
|
0x01, /* 01010101 => 1 bits */
|
|
0x00, /* 01010110 => 0 bits */
|
|
0x03, /* 01010111 => 3 bits */
|
|
0x00, /* 01011000 => 0 bits */
|
|
0x01, /* 01011001 => 1 bits */
|
|
0x00, /* 01011010 => 0 bits */
|
|
0x02, /* 01011011 => 2 bits */
|
|
0x00, /* 01011100 => 0 bits */
|
|
0x01, /* 01011101 => 1 bits */
|
|
0x00, /* 01011110 => 0 bits */
|
|
0x55, /* 01011111 => 5 bits (Stuff at bit 5) */
|
|
0x00, /* 01100000 => 0 bits */
|
|
0x01, /* 01100001 => 1 bits */
|
|
0x00, /* 01100010 => 0 bits */
|
|
0x02, /* 01100011 => 2 bits */
|
|
0x00, /* 01100100 => 0 bits */
|
|
0x01, /* 01100101 => 1 bits */
|
|
0x00, /* 01100110 => 0 bits */
|
|
0x03, /* 01100111 => 3 bits */
|
|
0x00, /* 01101000 => 0 bits */
|
|
0x01, /* 01101001 => 1 bits */
|
|
0x00, /* 01101010 => 0 bits */
|
|
0x02, /* 01101011 => 2 bits */
|
|
0x00, /* 01101100 => 0 bits */
|
|
0x01, /* 01101101 => 1 bits */
|
|
0x00, /* 01101110 => 0 bits */
|
|
0x04, /* 01101111 => 4 bits */
|
|
0x00, /* 01110000 => 0 bits */
|
|
0x01, /* 01110001 => 1 bits */
|
|
0x00, /* 01110010 => 0 bits */
|
|
0x02, /* 01110011 => 2 bits */
|
|
0x00, /* 01110100 => 0 bits */
|
|
0x01, /* 01110101 => 1 bits */
|
|
0x00, /* 01110110 => 0 bits */
|
|
0x03, /* 01110111 => 3 bits */
|
|
0x00, /* 01111000 => 0 bits */
|
|
0x01, /* 01111001 => 1 bits */
|
|
0x00, /* 01111010 => 0 bits */
|
|
0x02, /* 01111011 => 2 bits */
|
|
0x70, /* 01111100 => 0 bits (Stuff at bit 7) */
|
|
0x71, /* 01111101 => 1 bits (Stuff at bit 7) */
|
|
0x60, /* 01111110 => 0 bits (Stuff at bit 6) */
|
|
0x57, /* 01111111 => 7 bits (Stuff at bit 5) */
|
|
0x00, /* 10000000 => 0 bits */
|
|
0x01, /* 10000001 => 1 bits */
|
|
0x00, /* 10000010 => 0 bits */
|
|
0x02, /* 10000011 => 2 bits */
|
|
0x00, /* 10000100 => 0 bits */
|
|
0x01, /* 10000101 => 1 bits */
|
|
0x00, /* 10000110 => 0 bits */
|
|
0x03, /* 10000111 => 3 bits */
|
|
0x00, /* 10001000 => 0 bits */
|
|
0x01, /* 10001001 => 1 bits */
|
|
0x00, /* 10001010 => 0 bits */
|
|
0x02, /* 10001011 => 2 bits */
|
|
0x00, /* 10001100 => 0 bits */
|
|
0x01, /* 10001101 => 1 bits */
|
|
0x00, /* 10001110 => 0 bits */
|
|
0x04, /* 10001111 => 4 bits */
|
|
0x00, /* 10010000 => 0 bits */
|
|
0x01, /* 10010001 => 1 bits */
|
|
0x00, /* 10010010 => 0 bits */
|
|
0x02, /* 10010011 => 2 bits */
|
|
0x00, /* 10010100 => 0 bits */
|
|
0x01, /* 10010101 => 1 bits */
|
|
0x00, /* 10010110 => 0 bits */
|
|
0x03, /* 10010111 => 3 bits */
|
|
0x00, /* 10011000 => 0 bits */
|
|
0x01, /* 10011001 => 1 bits */
|
|
0x00, /* 10011010 => 0 bits */
|
|
0x02, /* 10011011 => 2 bits */
|
|
0x00, /* 10011100 => 0 bits */
|
|
0x01, /* 10011101 => 1 bits */
|
|
0x00, /* 10011110 => 0 bits */
|
|
0x55, /* 10011111 => 5 bits (Stuff at bit 5) */
|
|
0x00, /* 10100000 => 0 bits */
|
|
0x01, /* 10100001 => 1 bits */
|
|
0x00, /* 10100010 => 0 bits */
|
|
0x02, /* 10100011 => 2 bits */
|
|
0x00, /* 10100100 => 0 bits */
|
|
0x01, /* 10100101 => 1 bits */
|
|
0x00, /* 10100110 => 0 bits */
|
|
0x03, /* 10100111 => 3 bits */
|
|
0x00, /* 10101000 => 0 bits */
|
|
0x01, /* 10101001 => 1 bits */
|
|
0x00, /* 10101010 => 0 bits */
|
|
0x02, /* 10101011 => 2 bits */
|
|
0x00, /* 10101100 => 0 bits */
|
|
0x01, /* 10101101 => 1 bits */
|
|
0x00, /* 10101110 => 0 bits */
|
|
0x04, /* 10101111 => 4 bits */
|
|
0x00, /* 10110000 => 0 bits */
|
|
0x01, /* 10110001 => 1 bits */
|
|
0x00, /* 10110010 => 0 bits */
|
|
0x02, /* 10110011 => 2 bits */
|
|
0x00, /* 10110100 => 0 bits */
|
|
0x01, /* 10110101 => 1 bits */
|
|
0x00, /* 10110110 => 0 bits */
|
|
0x03, /* 10110111 => 3 bits */
|
|
0x00, /* 10111000 => 0 bits */
|
|
0x01, /* 10111001 => 1 bits */
|
|
0x00, /* 10111010 => 0 bits */
|
|
0x02, /* 10111011 => 2 bits */
|
|
0x00, /* 10111100 => 0 bits */
|
|
0x01, /* 10111101 => 1 bits */
|
|
0x60, /* 10111110 => 0 bits (Stuff at bit 6) */
|
|
0x56, /* 10111111 => 6 bits (Stuff at bit 5) */
|
|
0x00, /* 11000000 => 0 bits */
|
|
0x01, /* 11000001 => 1 bits */
|
|
0x00, /* 11000010 => 0 bits */
|
|
0x02, /* 11000011 => 2 bits */
|
|
0x00, /* 11000100 => 0 bits */
|
|
0x01, /* 11000101 => 1 bits */
|
|
0x00, /* 11000110 => 0 bits */
|
|
0x03, /* 11000111 => 3 bits */
|
|
0x00, /* 11001000 => 0 bits */
|
|
0x01, /* 11001001 => 1 bits */
|
|
0x00, /* 11001010 => 0 bits */
|
|
0x02, /* 11001011 => 2 bits */
|
|
0x00, /* 11001100 => 0 bits */
|
|
0x01, /* 11001101 => 1 bits */
|
|
0x00, /* 11001110 => 0 bits */
|
|
0x04, /* 11001111 => 4 bits */
|
|
0x00, /* 11010000 => 0 bits */
|
|
0x01, /* 11010001 => 1 bits */
|
|
0x00, /* 11010010 => 0 bits */
|
|
0x02, /* 11010011 => 2 bits */
|
|
0x00, /* 11010100 => 0 bits */
|
|
0x01, /* 11010101 => 1 bits */
|
|
0x00, /* 11010110 => 0 bits */
|
|
0x03, /* 11010111 => 3 bits */
|
|
0x00, /* 11011000 => 0 bits */
|
|
0x01, /* 11011001 => 1 bits */
|
|
0x00, /* 11011010 => 0 bits */
|
|
0x02, /* 11011011 => 2 bits */
|
|
0x00, /* 11011100 => 0 bits */
|
|
0x01, /* 11011101 => 1 bits */
|
|
0x00, /* 11011110 => 0 bits */
|
|
0x55, /* 11011111 => 5 bits (Stuff at bit 5) */
|
|
0x00, /* 11100000 => 0 bits */
|
|
0x01, /* 11100001 => 1 bits */
|
|
0x00, /* 11100010 => 0 bits */
|
|
0x02, /* 11100011 => 2 bits */
|
|
0x00, /* 11100100 => 0 bits */
|
|
0x01, /* 11100101 => 1 bits */
|
|
0x00, /* 11100110 => 0 bits */
|
|
0x03, /* 11100111 => 3 bits */
|
|
0x00, /* 11101000 => 0 bits */
|
|
0x01, /* 11101001 => 1 bits */
|
|
0x00, /* 11101010 => 0 bits */
|
|
0x02, /* 11101011 => 2 bits */
|
|
0x00, /* 11101100 => 0 bits */
|
|
0x01, /* 11101101 => 1 bits */
|
|
0x00, /* 11101110 => 0 bits */
|
|
0x04, /* 11101111 => 4 bits */
|
|
0x00, /* 11110000 => 0 bits */
|
|
0x01, /* 11110001 => 1 bits */
|
|
0x00, /* 11110010 => 0 bits */
|
|
0x02, /* 11110011 => 2 bits */
|
|
0x00, /* 11110100 => 0 bits */
|
|
0x01, /* 11110101 => 1 bits */
|
|
0x00, /* 11110110 => 0 bits */
|
|
0x03, /* 11110111 => 3 bits */
|
|
0x80, /* 11111000 => 0 bits (Stuff at bit 8) */
|
|
0x81, /* 11111001 => 1 bits (Stuff at bit 8) */
|
|
0x80, /* 11111010 => 0 bits (Stuff at bit 8) */
|
|
0x82, /* 11111011 => 2 bits (Stuff at bit 8) */
|
|
0x70, /* 11111100 => 0 bits (Stuff at bit 7) */
|
|
0x71, /* 11111101 => 1 bits (Stuff at bit 7) */
|
|
0x60, /* 11111110 => 0 bits (Stuff at bit 6) */
|
|
0x58, /* 11111111 => 8 bits (Stuff at bit 5) */
|
|
};
|
|
|
|
/* An important part of HDLC is frame cheacksum computation and checking.
|
|
* The checksum is computed using a shift register with XOR'ed feedback
|
|
* of (data xor bit 0) into bits 15, 10 and 3. The following small perl
|
|
* script illustrates how it works, and how the lookuptable below is
|
|
* generated.
|
|
*
|
|
* for ( $t=0; $t < 256; $t++ ) {
|
|
* $x = $t;
|
|
* for ( $b=0; $b < 8; $b++ ) {
|
|
* if ( $x & 1 ) {
|
|
* $x = ($x>>1) ^ 0x8408;
|
|
* } else {
|
|
* $x >>= 1;
|
|
* }
|
|
* }
|
|
* print sprintf("0x%04x,",$x);
|
|
* }
|
|
*/
|
|
|
|
static ifax_uint16 hdlc_fcs_lookup[256] = {
|
|
0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,0x8c48,0x9dc1,
|
|
0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,0x1081,0x0108,0x3393,0x221a,
|
|
0x56a5,0x472c,0x75b7,0x643e,0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,
|
|
0xf9ff,0xe876,0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,
|
|
0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,0x3183,0x200a,
|
|
0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c,0xbdcb,0xac42,0x9ed9,0x8f50,
|
|
0xfbef,0xea66,0xd8fd,0xc974,0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,
|
|
0x2732,0x36bb,0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,
|
|
0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a,0xdecd,0xcf44,
|
|
0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,0x6306,0x728f,0x4014,0x519d,
|
|
0x2522,0x34ab,0x0630,0x17b9,0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,
|
|
0x8a78,0x9bf1,0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738,
|
|
0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,0x8408,0x9581,
|
|
0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,0x0840,0x19c9,0x2b52,0x3adb,
|
|
0x4e64,0x5fed,0x6d76,0x7cff,0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,
|
|
0xf1bf,0xe036,0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,
|
|
0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,0x2942,0x38cb,
|
|
0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,0xb58b,0xa402,0x9699,0x8710,
|
|
0xf3af,0xe226,0xd0bd,0xc134,0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,
|
|
0x5cf5,0x4d7c,0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,
|
|
0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb,0xd68d,0xc704,
|
|
0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,0x5ac5,0x4b4c,0x79d7,0x685e,
|
|
0x1ce1,0x0d68,0x3ff3,0x2e7a,0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,
|
|
0x8238,0x93b1,0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9,
|
|
0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,0x7bc7,0x6a4e,
|
|
0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78
|
|
};
|
|
|
|
|
|
/* This function fills up the 'bitslide' variable in the encoder.
|
|
* Based on the internal state of the encoder, and the phase it is
|
|
* in, a proper bit-sequence is appended to the bitslide variable.
|
|
* This function is called whenever the bitslide is low on bits.
|
|
* FLAGs are generated if no frame is available for transmission.
|
|
* This function is rather large, but many of its large blocks
|
|
* only gets invoked once in a while (bitstuffing once in 32 calls
|
|
* for random binary data).
|
|
*
|
|
* A simple schetch to illustrate when bit-stuffing is
|
|
* performed (I got it wrong the first time...:-):
|
|
*
|
|
* Pos Stuffed Previous
|
|
* -----------------------
|
|
* 0 ???????+ 11111???
|
|
* 1 ??????+1 11110???
|
|
* 2 ?????+11 1110????
|
|
* 3 ????+111 110?????
|
|
* 4 ???+1111 10??????
|
|
* 5 ??+11111 0???????
|
|
* 6 ? ?+111110 ????????
|
|
* 7 ? +111110? ????????
|
|
* 8 + 111110?? ????????
|
|
* 9 +1 11110??? ????????
|
|
*
|
|
* Notice: ? Don't care
|
|
* + This is where bit-stuffing must be applied
|
|
*
|
|
* When bit-stuffing is applied, all the bits including the '+' and up
|
|
* is shifted one bit to the left, replacing the '+' with a zero.
|
|
* When bit-stuffing is applied in position 0-3, a second stuffing may
|
|
* have to be performed in position 6-9.
|
|
*/
|
|
|
|
void produce_bits(encoder_hdlc_private *priv)
|
|
{
|
|
ifax_uint16 next, LSB_mask, LSB_bits;
|
|
ifax_uint8 n, p, previous;
|
|
int next_size, stuffpos;
|
|
|
|
if ( priv->phase == IDLE ) {
|
|
/* Send idle-FLAGS, and possibly initiate a new transfer */
|
|
|
|
if ( !priv->idle ) {
|
|
/* We may go idle in a few bits time, prepare for this */
|
|
priv->idle = 1;
|
|
priv->idlebits = -8 - priv->bitslide_size;
|
|
}
|
|
|
|
if ( priv->current_frame != priv->new_frame ) {
|
|
/* There is a frame queued up, prepare for its transmission */
|
|
priv->phase = ADDRESS;
|
|
priv->fcs = 0xffff;
|
|
priv->src = &priv->framequeue[priv->current_frame].address;
|
|
priv->remaining_bytes = 1;
|
|
priv->idle = 0;
|
|
}
|
|
/* Transmit a FLAG-sequence, no bit-stuffing applied. This flag is
|
|
* either an idle-channel pattern, or the initial flag of a frame.
|
|
*/
|
|
priv->bitslide |= (FLAG_SEQUENCE<<priv->bitslide_size);
|
|
priv->bitslide_size += 8;
|
|
return;
|
|
}
|
|
|
|
/* Fetch the next byte to be transmitted, and compute FCS */
|
|
next = (*priv->src++ & 0x00ff);
|
|
next_size = 8;
|
|
priv->remaining_bytes--;
|
|
priv->fcs = (priv->fcs>>8) ^ hdlc_fcs_lookup[(priv->fcs&0xff)^next];
|
|
|
|
/* Advance to next phase if current phase exhausted */
|
|
if ( priv->remaining_bytes == 0 ) {
|
|
switch ( priv->phase ) {
|
|
|
|
case ADDRESS:
|
|
priv->phase = PAYLOAD;
|
|
priv->src = priv->framequeue[priv->current_frame].start;
|
|
priv->remaining_bytes = priv->framequeue[priv->current_frame].size;
|
|
break;
|
|
|
|
case PAYLOAD:
|
|
priv->phase = FCS;
|
|
priv->src = &priv->fcs_tx[0];
|
|
priv->remaining_bytes = 2;
|
|
priv->fcs_tx[0] = ~(priv->fcs & 0xff);
|
|
priv->fcs_tx[1] = ~((priv->fcs>>8) & 0xff);
|
|
break;
|
|
|
|
case FCS:
|
|
priv->phase = IDLE;
|
|
priv->current_frame++;
|
|
if ( priv->current_frame >= QUEUESIZE )
|
|
priv->current_frame = 0;
|
|
break;
|
|
|
|
case IDLE:
|
|
/* Should never get here, but these lines removes a compile warning */
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* insert 'next' into bitstream with bitstuffing active. First
|
|
* take a look at the previous completed byte, and see how many '1'
|
|
* there is in MSB (variable p, previous). Then look up the
|
|
* number of '1' from LSB of the byte to be inserted into the output-
|
|
* stream (and store in variable n, next).
|
|
* If p+n is 6 or larger, we have a string of 1s of length 6 or
|
|
* larger possibly spanning the previous byte and the one we prepare
|
|
* to output. If so, do bit stuffing.
|
|
*/
|
|
|
|
previous = priv->bitslide>>(priv->bitslide_size-8);
|
|
p = bitstufftbl[bitreverse[previous]&0xF] & 0xF;
|
|
n = bitstufftbl[next] & 0xF;
|
|
|
|
if ( p+n >= 5 ) {
|
|
/* Need bit-stuffing somewhere in position 1-5 */
|
|
stuffpos = 5 - p;
|
|
LSB_mask = (1<<stuffpos) - 1;
|
|
LSB_bits = next & LSB_mask;
|
|
next &= ~LSB_mask;
|
|
next <<= 1;
|
|
next_size++;
|
|
next |= LSB_bits;
|
|
}
|
|
|
|
/* The table-lookup will tell us if we have a string of '1' completely
|
|
* inside the 'next' word (which is 8 or 9 bits large at this point)
|
|
* which needs bit-stuffing. Since any string of 1s occupying
|
|
* bit-position 0 is taken care of in the previous test and stuffing,
|
|
* we can now consentrate on bits 1-8 (we assume bit 8 is used - it
|
|
* will be 0 and not cause bit-stuffing if it is not).
|
|
*/
|
|
|
|
stuffpos = bitstufftbl[next>>1]>>4;
|
|
|
|
if ( stuffpos ) {
|
|
LSB_mask = (2<<stuffpos) - 1;
|
|
LSB_bits = next & LSB_mask;
|
|
next &= ~LSB_mask;
|
|
next <<= 1;
|
|
next_size++;
|
|
next |= LSB_bits;
|
|
}
|
|
|
|
/* Finaly insert the (bit-stuffed) string of bits (8-10 bits) into
|
|
* the output-buffer
|
|
*/
|
|
priv->bitslide |= (next<<priv->bitslide_size);
|
|
priv->bitslide_size += next_size;
|
|
}
|
|
|
|
|
|
void encoder_hdlc_demand(ifax_modp self, size_t demand)
|
|
{
|
|
encoder_hdlc_private *priv;
|
|
ifax_uint8 *dst;
|
|
ifax_uint32 remaining_bits, bytes;
|
|
size_t chunk_bits, do_bits;
|
|
|
|
priv = self->private;
|
|
remaining_bits = demand;
|
|
|
|
while ( remaining_bits > 0 ) {
|
|
|
|
dst = priv->buffer;
|
|
chunk_bits = 0;
|
|
|
|
bytes = remaining_bits>>3;
|
|
if ( bytes > (MAXBUFFER-1) )
|
|
bytes = (MAXBUFFER-1);
|
|
|
|
if ( bytes ) {
|
|
/* Fill buffer with a whole number of bytes first */
|
|
chunk_bits = 8 * bytes;
|
|
remaining_bits -= chunk_bits;
|
|
while ( bytes-- ) {
|
|
if ( priv->bitslide_size < 17 )
|
|
produce_bits(priv);
|
|
*dst++ = priv->bitslide & 0xff;
|
|
priv->bitslide >>= 8;
|
|
priv->bitslide_size -= 8;
|
|
priv->idlebits += 8;
|
|
}
|
|
}
|
|
|
|
/* Finnish off with a possibly half-filled byte */
|
|
if ( remaining_bits > 0 ) {
|
|
if ( priv->bitslide_size < 17 )
|
|
produce_bits(priv);
|
|
do_bits = remaining_bits;
|
|
if ( do_bits > 8 )
|
|
do_bits = 8;
|
|
*dst++ = priv->bitslide & 0xff;
|
|
priv->bitslide >>= do_bits;
|
|
priv->bitslide_size -= do_bits;
|
|
priv->idlebits += do_bits;
|
|
chunk_bits += do_bits;
|
|
remaining_bits -= do_bits;
|
|
}
|
|
|
|
ifax_handle_input(self->sendto,priv->buffer,chunk_bits);
|
|
}
|
|
}
|
|
|
|
static int frame_queue_size(encoder_hdlc_private *priv)
|
|
{
|
|
if ( priv->new_frame < priv->current_frame )
|
|
return QUEUESIZE + priv->new_frame - priv->current_frame;
|
|
|
|
return priv->new_frame - priv->current_frame;
|
|
}
|
|
|
|
static void tx_frame(encoder_hdlc_private *priv, ifax_uint8 *start,
|
|
size_t size, ifax_uint8 address)
|
|
{
|
|
if ( frame_queue_size(priv) >= (QUEUESIZE-1) )
|
|
return;
|
|
priv->framequeue[priv->new_frame].size = size;
|
|
priv->framequeue[priv->new_frame].start = start;
|
|
priv->framequeue[priv->new_frame].address = address;
|
|
priv->new_frame++;
|
|
priv->idle = 0;
|
|
if ( priv->new_frame >= QUEUESIZE )
|
|
priv->new_frame = 0;
|
|
}
|
|
|
|
int encoder_hdlc_command(ifax_modp self, int cmd, va_list cmds)
|
|
{
|
|
encoder_hdlc_private *priv = self->private;
|
|
ifax_uint8 address, *frame_start;
|
|
size_t frame_size;
|
|
|
|
switch ( cmd ) {
|
|
|
|
case CMD_HDLC_FRAMING_TXFRAME:
|
|
frame_start = va_arg(cmds,ifax_uint8 *);
|
|
frame_size = va_arg(cmds,int);
|
|
address = va_arg(cmds,ifax_uint8);
|
|
tx_frame(priv,frame_start,frame_size,address);
|
|
break;
|
|
|
|
case CMD_HDLC_FRAMING_IDLE:
|
|
if ( priv->idle && priv->idlebits > 0 )
|
|
return priv->idlebits;
|
|
return 0;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void encoder_hdlc_destroy(ifax_modp self)
|
|
{
|
|
free(self->private);
|
|
}
|
|
|
|
int encoder_hdlc_construct(ifax_modp self,va_list args)
|
|
{
|
|
encoder_hdlc_private *priv;
|
|
|
|
priv = ifax_malloc(sizeof(encoder_hdlc_private),"HDLC encoder instance");
|
|
self->private = priv;
|
|
|
|
self->destroy = encoder_hdlc_destroy;
|
|
self->handle_input = 0;
|
|
self->handle_demand = encoder_hdlc_demand;
|
|
self->command = encoder_hdlc_command;
|
|
|
|
priv->bitslide = (FLAG_SEQUENCE<<8) | FLAG_SEQUENCE;
|
|
priv->bitslide_size = 16;
|
|
priv->phase = IDLE;
|
|
priv->new_frame = 0;
|
|
priv->current_frame = 0;
|
|
priv->idle = 1;
|
|
priv->idlebits = 1;
|
|
|
|
return 0;
|
|
}
|