163 lines
3.5 KiB
C
163 lines
3.5 KiB
C
/* $Id: tpam_crcpc.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
|
|
*
|
|
* Turbo PAM ISDN driver for Linux. (Kernel Driver - CRC encoding)
|
|
*
|
|
* Copyright 1998-2000 AUVERTECH Télécom
|
|
* Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
|
|
*
|
|
* This software may be used and distributed according to the terms
|
|
* of the GNU General Public License, incorporated herein by reference.
|
|
*
|
|
* For all support questions please contact: <support@auvertech.fr>
|
|
*
|
|
*/
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Module Name:
|
|
|
|
crcpc.c
|
|
|
|
Abstract:
|
|
|
|
Modem HDLC coding
|
|
Software HDLC coding / decoding
|
|
|
|
Revision History:
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#include <linux/crc-ccitt.h>
|
|
#include "tpam.h"
|
|
|
|
#define HDLC_CTRL_CHAR_CMPL_MASK 0x20 /* HDLC control character complement mask */
|
|
#define HDLC_FLAG 0x7E /* HDLC flag */
|
|
#define HDLC_CTRL_ESC 0x7D /* HDLC control escapr character */
|
|
#define HDLC_LIKE_FCS_INIT_VAL 0xFFFF /* FCS initial value (0xFFFF for new equipment or 0) */
|
|
#define HDLC_FCS_OK 0xF0B8 /* This value is the only valid value of FCS */
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
static u8 ap_t_ctrl_char_complemented[256]; /* list of characters to complement */
|
|
|
|
static void ap_hdlc_like_ctrl_char_list (u32 ctrl_char) {
|
|
int i;
|
|
|
|
for (i = 0; i < 256; ++i)
|
|
ap_t_ctrl_char_complemented[i] = FALSE;
|
|
for (i = 0; i < 32; ++i)
|
|
if ((ctrl_char >> i) & 0x0001)
|
|
ap_t_ctrl_char_complemented [i] = TRUE;
|
|
ap_t_ctrl_char_complemented[HDLC_FLAG] = TRUE;
|
|
ap_t_ctrl_char_complemented[HDLC_CTRL_ESC] = TRUE;
|
|
|
|
}
|
|
|
|
void init_CRC(void) {
|
|
ap_hdlc_like_ctrl_char_list(0xffffffff);
|
|
}
|
|
|
|
void hdlc_encode_modem(u8 *buffer_in, u32 lng_in,
|
|
u8 *buffer_out, u32 *lng_out) {
|
|
u16 fcs;
|
|
register u8 data;
|
|
register u8 *p_data_out = buffer_out;
|
|
|
|
fcs = HDLC_LIKE_FCS_INIT_VAL;
|
|
|
|
/*
|
|
* Insert HDLC flag at the beginning of the frame
|
|
*/
|
|
*p_data_out++ = HDLC_FLAG;
|
|
|
|
#define ESCAPE_CHAR(data_out, data) \
|
|
if (ap_t_ctrl_char_complemented[data]) { \
|
|
*data_out++ = HDLC_CTRL_ESC; \
|
|
*data_out++ = data ^ 0x20; \
|
|
} \
|
|
else \
|
|
*data_out++ = data;
|
|
|
|
while (lng_in--) {
|
|
data = *buffer_in++;
|
|
|
|
/*
|
|
* FCS calculation
|
|
*/
|
|
fcs = crc_ccitt_byte(fcs, data);
|
|
|
|
ESCAPE_CHAR(p_data_out, data);
|
|
}
|
|
|
|
/*
|
|
* Add FCS and closing flag
|
|
*/
|
|
fcs ^= 0xFFFF; // Complement
|
|
|
|
data = (u8)(fcs & 0xff); /* LSB */
|
|
ESCAPE_CHAR(p_data_out, data);
|
|
|
|
data = (u8)((fcs >> 8)); /* MSB */
|
|
ESCAPE_CHAR(p_data_out, data);
|
|
#undef ESCAPE_CHAR
|
|
|
|
*p_data_out++ = HDLC_FLAG;
|
|
|
|
*lng_out = (u32)(p_data_out - buffer_out);
|
|
}
|
|
|
|
void hdlc_no_accm_encode(u8 *buffer_in, u32 lng_in,
|
|
u8 *buffer_out, u32 *lng_out) {
|
|
u16 fcs;
|
|
register u8 data;
|
|
register u8 *p_data_out = buffer_out;
|
|
|
|
/*
|
|
* Insert HDLC flag at the beginning of the frame
|
|
*/
|
|
fcs = HDLC_LIKE_FCS_INIT_VAL;
|
|
|
|
while (lng_in--) {
|
|
data = *buffer_in++;
|
|
/* calculate FCS */
|
|
fcs = crc_ccitt_byte(fcs, data);
|
|
*p_data_out++ = data;
|
|
}
|
|
|
|
/*
|
|
* Add FCS and closing flag
|
|
*/
|
|
fcs ^= 0xFFFF; // Complement
|
|
data = (u8)(fcs);
|
|
*p_data_out++ = data;
|
|
|
|
data =(u8)((fcs >> 8)); // revense MSB / LSB
|
|
*p_data_out++ = data;
|
|
|
|
*lng_out = (u32)(p_data_out - buffer_out);
|
|
}
|
|
|
|
u32 hdlc_no_accm_decode(u8 *buffer_in, u32 lng_in) {
|
|
u16 fcs;
|
|
u32 lng = lng_in;
|
|
register u8 data;
|
|
|
|
/*
|
|
* Insert HDLC flag at the beginning of the frame
|
|
*/
|
|
fcs = HDLC_LIKE_FCS_INIT_VAL;
|
|
|
|
while (lng_in--) {
|
|
data = *buffer_in++;
|
|
/* calculate FCS */
|
|
fcs = crc_ccitt_byte(fcs, data);
|
|
}
|
|
|
|
if (fcs == HDLC_FCS_OK)
|
|
return (lng-2);
|
|
else
|
|
return 0;
|
|
}
|
|
|