staticint
check_frame(struct isdnhdlc_vars *hdlc)
{ int status;
if (hdlc->dstpos < 2) /* too small - framing error */
status = -HDLC_FRAMING_ERROR; elseif (hdlc->crc != 0xf0b8) /* crc error */
status = -HDLC_CRC_ERROR; else { /* remove CRC */
hdlc->dstpos -= 2; /* good frame */
status = hdlc->dstpos;
} return status;
}
/* isdnhdlc_decode - decodes HDLC frames from a transparent bit stream.
The source buffer is scanned for valid HDLC frames looking for flags (01111110) to indicate the start of a frame. If the start of the frame is found, the bit stuffing is removed (0 after 5 1's). When a new flag is found, the complete frame has been received and the CRC is checked. If a valid frame is found, the function returns the frame length excluding the CRC with the bit HDLC_END_OF_FRAME set. If the beginning of a valid frame is found, the function returns the length. If a framing error is found (too many 1s and not a flag) the function returns the length with the bit HDLC_FRAMING_ERROR set. If a CRC error is found the function returns the length with the bit HDLC_CRC_ERROR set. If the frame length exceeds the destination buffer size, the function returns the length with the bit HDLC_LENGTH_ERROR set.
src - source buffer slen - source buffer length count - number of bytes removed (decoded) from the source buffer dst _ destination buffer dsize - destination buffer size returns - number of decoded bytes in the destination buffer and status flag.
*/ int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, int *count, u8 *dst, int dsize)
{ int status = 0;
while (slen > 0) { if (hdlc->bit_shift == 0) { /* the code is for bitreverse streams */ if (hdlc->do_bitreverse == 0)
hdlc->cbin = bitrev8(*src++); else
hdlc->cbin = *src++;
slen--;
hdlc->bit_shift = 8; if (hdlc->do_adapt56)
hdlc->bit_shift--;
}
switch (hdlc->state) { case STOPPED: return 0; case HDLC_FAST_IDLE: if (hdlc->cbin == 0xff) {
hdlc->bit_shift = 0; break;
}
hdlc->state = HDLC_GET_FLAG_B0;
hdlc->hdlc_bits1 = 0;
hdlc->bit_shift = 8; break; case HDLC_GET_FLAG_B0: if (!(hdlc->cbin & 0x80)) {
hdlc->state = HDLC_GETFLAG_B1A6;
hdlc->hdlc_bits1 = 0;
} else { if ((!hdlc->do_adapt56) &&
(++hdlc->hdlc_bits1 >= 8) &&
(hdlc->bit_shift == 1))
hdlc->state = HDLC_FAST_IDLE;
}
hdlc->cbin <<= 1;
hdlc->bit_shift--; break; case HDLC_GETFLAG_B1A6: if (hdlc->cbin & 0x80) {
hdlc->hdlc_bits1++; if (hdlc->hdlc_bits1 == 6)
hdlc->state = HDLC_GETFLAG_B7;
} else
hdlc->hdlc_bits1 = 0;
hdlc->cbin <<= 1;
hdlc->bit_shift--; break; case HDLC_GETFLAG_B7: if (hdlc->cbin & 0x80) {
hdlc->state = HDLC_GET_FLAG_B0;
} else {
hdlc->state = HDLC_GET_DATA;
hdlc->crc = 0xffff;
hdlc->shift_reg = 0;
hdlc->hdlc_bits1 = 0;
hdlc->data_bits = 0;
hdlc->data_received = 0;
}
hdlc->cbin <<= 1;
hdlc->bit_shift--; break; case HDLC_GET_DATA: if (hdlc->cbin & 0x80) {
hdlc->hdlc_bits1++; switch (hdlc->hdlc_bits1) { case 6: break; case 7: if (hdlc->data_received) /* bad frame */
status = -HDLC_FRAMING_ERROR; if (!hdlc->do_adapt56) { if (hdlc->cbin == fast_abort
[hdlc->bit_shift + 1]) {
hdlc->state =
HDLC_FAST_IDLE;
hdlc->bit_shift = 1; break;
}
} else
hdlc->state = HDLC_GET_FLAG_B0; break; default:
hdlc->shift_reg >>= 1;
hdlc->shift_reg |= 0x80;
hdlc->data_bits++; break;
}
} else { switch (hdlc->hdlc_bits1) { case 5: break; case 6: if (hdlc->data_received)
status = check_frame(hdlc);
hdlc->crc = 0xffff;
hdlc->shift_reg = 0;
hdlc->data_bits = 0; if (!hdlc->do_adapt56)
handle_fast_flag(hdlc); else {
hdlc->state = HDLC_GET_DATA;
hdlc->data_received = 0;
} break; default:
hdlc->shift_reg >>= 1;
hdlc->data_bits++; break;
}
hdlc->hdlc_bits1 = 0;
} if (status) {
hdlc->dstpos = 0;
*count -= slen;
hdlc->cbin <<= 1;
hdlc->bit_shift--; return status;
} if (hdlc->data_bits == 8) {
hdlc->data_bits = 0;
hdlc->data_received = 1;
hdlc->crc = crc_ccitt_byte(hdlc->crc,
hdlc->shift_reg);
/* good byte received */ if (hdlc->dstpos < dsize)
dst[hdlc->dstpos++] = hdlc->shift_reg; else { /* frame too long */
status = -HDLC_LENGTH_ERROR;
hdlc->dstpos = 0;
}
}
hdlc->cbin <<= 1;
hdlc->bit_shift--; break; case HDLC_FAST_FLAG: if (hdlc->cbin == hdlc->ffvalue) {
hdlc->bit_shift = 0; break;
} else { if (hdlc->cbin == 0xff) {
hdlc->state = HDLC_FAST_IDLE;
hdlc->bit_shift = 0;
} elseif (hdlc->ffbit_shift == 8) {
hdlc->state = HDLC_GETFLAG_B7; break;
} else
handle_abort(hdlc);
} break; default: break;
}
}
*count -= slen; return 0;
}
EXPORT_SYMBOL(isdnhdlc_decode); /* isdnhdlc_encode - encodes HDLC frames to a transparent bit stream.
The bit stream starts with a beginning flag (01111110). After that each byte is added to the bit stream with bit stuffing added (0 after 5 1's). When the last byte has been removed from the source buffer, the CRC (2 bytes is added) and the frame terminates with the ending flag. For the dchannel, the idle character (all 1's) is also added at the end. If this function is called with empty source buffer (slen=0), flags or idle character will be generated.
src - source buffer slen - source buffer length count - number of bytes removed (encoded) from source buffer dst _ destination buffer dsize - destination buffer size returns - number of encoded bytes in the destination buffer
*/ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, int *count, u8 *dst, int dsize)
{ staticconstunsignedchar xfast_flag_value[] = {
0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e
};
int len = 0;
*count = slen;
/* special handling for one byte frames */ if ((slen == 1) && (hdlc->state == HDLC_SEND_FAST_FLAG))
hdlc->state = HDLC_SENDFLAG_ONE; while (dsize > 0) { if (hdlc->bit_shift == 0) { if (slen && !hdlc->do_closing) {
hdlc->shift_reg = *src++;
slen--; if (slen == 0) /* closing sequence, CRC + flag(s) */
hdlc->do_closing = 1;
hdlc->bit_shift = 8;
} else { if (hdlc->state == HDLC_SEND_DATA) { if (hdlc->data_received) {
hdlc->state = HDLC_SEND_CRC1;
hdlc->crc ^= 0xffff;
hdlc->bit_shift = 8;
hdlc->shift_reg =
hdlc->crc & 0xff;
} elseif (!hdlc->do_adapt56)
hdlc->state =
HDLC_SEND_FAST_FLAG; else
hdlc->state =
HDLC_SENDFLAG_B0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.