Loading drivers/isdn/i4l/isdnhdlc.c +194 −172 Original line number Diff line number Diff line /* * isdnhdlc.c -- General purpose ISDN HDLC decoder. * *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de> * Copyright (C) * 2002 Wolfgang Mües <wolfgang@iksw-muees.de> * 2001 Frode Isaksen <fisaksen@bewan.com> * 2001 Kai Germaschewski <kai.germaschewski@gmx.de> * Loading Loading @@ -63,8 +64,10 @@ void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56) hdlc->ffvalue = 0; hdlc->dstpos = 0; } EXPORT_SYMBOL(isdnhdlc_out_init); void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56) void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56) { hdlc->bit_shift = 0; hdlc->hdlc_bits1 = 0; Loading Loading @@ -93,6 +96,25 @@ void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_ada } hdlc->shift_reg = 0; } EXPORT_SYMBOL(isdnhdlc_rcv_init); static int check_frame(struct isdnhdlc_vars *hdlc) { int status; if (hdlc->dstpos < 2) /* too small - framing error */ status = -HDLC_FRAMING_ERROR; else if (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. Loading Loading @@ -121,8 +143,8 @@ void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_ada returns - number of decoded bytes in the destination buffer and status flag. */ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen, int *count, unsigned char *dst, int dsize) int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, int *count, u8 *dst, int dsize) { int status = 0; Loading @@ -138,6 +160,30 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; #define handle_fast_flag(h) \ do {\ if (h->cbin == fast_flag[h->bit_shift]) {\ h->ffvalue = fast_flag_value[h->bit_shift];\ h->state = HDLC_FAST_FLAG;\ h->ffbit_shift = h->bit_shift;\ h->bit_shift = 1;\ } else {\ h->state = HDLC_GET_DATA;\ h->data_received = 0;\ } \ } while (0) #define handle_abort(h) \ do {\ h->shift_reg = fast_abort[h->ffbit_shift - 1];\ h->hdlc_bits1 = h->ffbit_shift - 2;\ if (h->hdlc_bits1 < 0)\ h->hdlc_bits1 = 0;\ h->data_bits = h->ffbit_shift - 1;\ h->state = HDLC_GET_DATA;\ h->data_received = 0;\ } while (0) *count = slen; while (slen > 0) { Loading @@ -145,10 +191,9 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->cbin = *src++; slen--; hdlc->bit_shift = 8; if(hdlc->do_adapt56){ if (hdlc->do_adapt56) hdlc->bit_shift--; } } switch (hdlc->state) { case STOPPED: Loading @@ -167,23 +212,21 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->state = HDLC_GETFLAG_B1A6; hdlc->hdlc_bits1 = 0; } else { if(!hdlc->do_adapt56){ if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1) 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){ if (hdlc->hdlc_bits1 == 6) hdlc->state = HDLC_GETFLAG_B7; } } else { } else hdlc->hdlc_bits1 = 0; } hdlc->cbin <<= 1; hdlc->bit_shift--; break; Loading @@ -208,19 +251,19 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, case 6: break; case 7: if(hdlc->data_received) { // bad frame 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; if (hdlc->cbin == fast_abort [hdlc->bit_shift + 1]) { hdlc->state = HDLC_FAST_IDLE; hdlc->bit_shift = 1; break; } } else { } else hdlc->state = HDLC_GET_FLAG_B0; } break; default: hdlc->shift_reg >>= 1; Loading @@ -233,33 +276,14 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, case 5: break; case 6: if(hdlc->data_received){ if (hdlc->dstpos < 2) { status = -HDLC_FRAMING_ERROR; } else if (hdlc->crc != 0xf0b8){ // crc error status = -HDLC_CRC_ERROR; } else { // remove CRC hdlc->dstpos -= 2; // good frame status = hdlc->dstpos; } } if (hdlc->data_received) status = check_frame(hdlc); hdlc->crc = 0xffff; hdlc->shift_reg = 0; hdlc->data_bits = 0; if(!hdlc->do_adapt56){ if(hdlc->cbin==fast_flag[hdlc->bit_shift]){ hdlc->ffvalue = fast_flag_value[hdlc->bit_shift]; hdlc->state = HDLC_FAST_FLAG; hdlc->ffbit_shift = hdlc->bit_shift; hdlc->bit_shift = 1; } else { hdlc->state = HDLC_GET_DATA; hdlc->data_received = 0; } } else { if (!hdlc->do_adapt56) handle_fast_flag(hdlc); else { hdlc->state = HDLC_GET_DATA; hdlc->data_received = 0; } Loading @@ -281,13 +305,14 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, if (hdlc->data_bits == 8) { hdlc->data_bits = 0; hdlc->data_received = 1; hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); // good byte received if (hdlc->dstpos < dsize) { /* good byte received */ if (hdlc->dstpos < dsize) dst[hdlc->dstpos++] = hdlc->shift_reg; } else { // frame too long else { /* frame too long */ status = -HDLC_LENGTH_ERROR; hdlc->dstpos = 0; } Loading @@ -306,14 +331,8 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, } else if (hdlc->ffbit_shift == 8) { hdlc->state = HDLC_GETFLAG_B7; break; } else { hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1]; hdlc->hdlc_bits1 = hdlc->ffbit_shift-2; if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0; hdlc->data_bits = hdlc->ffbit_shift-1; hdlc->state = HDLC_GET_DATA; hdlc->data_received = 0; } } else handle_abort(hdlc); } break; default: Loading @@ -323,7 +342,7 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, *count -= slen; return 0; } EXPORT_SYMBOL(isdnhdlc_decode); /* isdnhdlc_encode - encodes HDLC frames to a transparent bit stream. Loading @@ -343,9 +362,8 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, dsize - destination buffer size returns - number of encoded bytes in the destination buffer */ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, unsigned short slen, int *count, unsigned char *dst, int dsize) int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, int *count, u8 *dst, int dsize) { static const unsigned char xfast_flag_value[] = { 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e Loading @@ -361,7 +379,8 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->shift_reg = *src++; slen--; if (slen == 0) hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */ /* closing sequence, CRC + flag(s) */ hdlc->do_closing = 1; hdlc->bit_shift = 8; } else { if (hdlc->state == HDLC_SEND_DATA) { Loading @@ -369,12 +388,14 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->state = HDLC_SEND_CRC1; hdlc->crc ^= 0xffff; hdlc->bit_shift = 8; hdlc->shift_reg = hdlc->crc & 0xff; } else if(!hdlc->do_adapt56){ hdlc->state = HDLC_SEND_FAST_FLAG; } else { hdlc->state = HDLC_SENDFLAG_B0; } hdlc->shift_reg = hdlc->crc & 0xff; } else if (!hdlc->do_adapt56) hdlc->state = HDLC_SEND_FAST_FLAG; else hdlc->state = HDLC_SENDFLAG_B0; } } Loading @@ -395,7 +416,8 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, break; } if (hdlc->bit_shift == 8) { hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits); hdlc->cbin = hdlc->ffvalue >> (8 - hdlc->data_bits); hdlc->state = HDLC_SEND_DATA; hdlc->crc = 0xffff; hdlc->hdlc_bits1 = 0; Loading Loading @@ -457,9 +479,9 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->hdlc_bits1 = 0; break; } if(hdlc->bit_shift==8){ hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); } if (hdlc->bit_shift == 8) hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); if (hdlc->shift_reg & 0x01) { hdlc->hdlc_bits1++; hdlc->cbin++; Loading Loading @@ -524,29 +546,32 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->hdlc_bits1 = 0; break; } if(hdlc->shift_reg & 0x01){ if (hdlc->shift_reg & 0x01) hdlc->cbin++; } hdlc->shift_reg >>= 1; hdlc->bit_shift--; if (hdlc->bit_shift == 0) { hdlc->ffvalue = xfast_flag_value[hdlc->data_bits]; hdlc->ffvalue = xfast_flag_value[hdlc->data_bits]; if (hdlc->dchannel) { hdlc->ffvalue = 0x7e; hdlc->state = HDLC_SEND_IDLE1; hdlc->bit_shift = 8-hdlc->data_bits; if (hdlc->bit_shift == 0) hdlc->state = HDLC_SEND_FAST_IDLE; hdlc->state = HDLC_SEND_FAST_IDLE; } else { if (!hdlc->do_adapt56) { hdlc->state = HDLC_SEND_FAST_FLAG; hdlc->state = HDLC_SEND_FAST_FLAG; hdlc->data_received = 0; } else { hdlc->state = HDLC_SENDFLAG_B0; hdlc->data_received = 0; } // Finished with this frame, send flags if (dsize > 1) dsize = 1; /* Finished this frame, send flags */ if (dsize > 1) dsize = 1; } } break; Loading @@ -570,7 +595,8 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->state = HDLC_SEND_FIRST_FLAG; } else { *dst++ = hdlc->cbin; hdlc->bit_shift = hdlc->data_bits = 0; hdlc->bit_shift = 0; hdlc->data_bits = 0; len++; dsize = 0; } Loading @@ -596,8 +622,4 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, return len; } EXPORT_SYMBOL(isdnhdlc_rcv_init); EXPORT_SYMBOL(isdnhdlc_decode); EXPORT_SYMBOL(isdnhdlc_out_init); EXPORT_SYMBOL(isdnhdlc_encode); include/linux/isdn/hdlc.h +37 −31 Original line number Diff line number Diff line /* * isdnhdlc.h -- General purpose ISDN HDLC decoder. * hdlc.h -- General purpose ISDN HDLC decoder. * * Implementation of a HDLC decoder/encoder in software. * Neccessary because some ISDN devices don't have HDLC * controllers. Also included: a bit reversal table. * controllers. * *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de> * Copyright (C) * 2002 Wolfgang Mües <wolfgang@iksw-muees.de> * 2001 Frode Isaksen <fisaksen@bewan.com> * 2001 Kai Germaschewski <kai.germaschewski@gmx.de> * Loading @@ -31,20 +32,24 @@ struct isdnhdlc_vars { int bit_shift; int hdlc_bits1; int data_bits; int ffbit_shift; // encoding only int ffbit_shift; /* encoding only */ int state; int dstpos; unsigned short crc; u16 crc; unsigned char cbin; unsigned char shift_reg; unsigned char ffvalue; u8 cbin; u8 shift_reg; u8 ffvalue; unsigned int data_received:1; // set if transferring data unsigned int dchannel:1; // set if D channel (send idle instead of flags) unsigned int do_adapt56:1; // set if 56K adaptation unsigned int do_closing:1; // set if in closing phase (need to send CRC + flag /* set if transferring data */ u32 data_received:1; /* set if D channel (send idle instead of flags) */ u32 dchannel:1; /* set if 56K adaptation */ u32 do_adapt56:1; /* set if in closing phase (need to send CRC + flag) */ u32 do_closing:1; }; Loading @@ -59,12 +64,13 @@ struct isdnhdlc_vars { extern void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, int do_adapt56); extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count, unsigned char *dst, int dsize); extern int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, int *count, u8 *dst, int dsize); extern void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc,int is_d_channel,int do_adapt56); extern void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56); extern int isdnhdlc_encode (struct isdnhdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count, unsigned char *dst,int dsize); extern int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, int *count, u8 *dst, int dsize); #endif /* __ISDNHDLC_H__ */ Loading
drivers/isdn/i4l/isdnhdlc.c +194 −172 Original line number Diff line number Diff line /* * isdnhdlc.c -- General purpose ISDN HDLC decoder. * *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de> * Copyright (C) * 2002 Wolfgang Mües <wolfgang@iksw-muees.de> * 2001 Frode Isaksen <fisaksen@bewan.com> * 2001 Kai Germaschewski <kai.germaschewski@gmx.de> * Loading Loading @@ -63,8 +64,10 @@ void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56) hdlc->ffvalue = 0; hdlc->dstpos = 0; } EXPORT_SYMBOL(isdnhdlc_out_init); void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56) void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56) { hdlc->bit_shift = 0; hdlc->hdlc_bits1 = 0; Loading Loading @@ -93,6 +96,25 @@ void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_ada } hdlc->shift_reg = 0; } EXPORT_SYMBOL(isdnhdlc_rcv_init); static int check_frame(struct isdnhdlc_vars *hdlc) { int status; if (hdlc->dstpos < 2) /* too small - framing error */ status = -HDLC_FRAMING_ERROR; else if (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. Loading Loading @@ -121,8 +143,8 @@ void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_ada returns - number of decoded bytes in the destination buffer and status flag. */ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen, int *count, unsigned char *dst, int dsize) int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, int *count, u8 *dst, int dsize) { int status = 0; Loading @@ -138,6 +160,30 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; #define handle_fast_flag(h) \ do {\ if (h->cbin == fast_flag[h->bit_shift]) {\ h->ffvalue = fast_flag_value[h->bit_shift];\ h->state = HDLC_FAST_FLAG;\ h->ffbit_shift = h->bit_shift;\ h->bit_shift = 1;\ } else {\ h->state = HDLC_GET_DATA;\ h->data_received = 0;\ } \ } while (0) #define handle_abort(h) \ do {\ h->shift_reg = fast_abort[h->ffbit_shift - 1];\ h->hdlc_bits1 = h->ffbit_shift - 2;\ if (h->hdlc_bits1 < 0)\ h->hdlc_bits1 = 0;\ h->data_bits = h->ffbit_shift - 1;\ h->state = HDLC_GET_DATA;\ h->data_received = 0;\ } while (0) *count = slen; while (slen > 0) { Loading @@ -145,10 +191,9 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->cbin = *src++; slen--; hdlc->bit_shift = 8; if(hdlc->do_adapt56){ if (hdlc->do_adapt56) hdlc->bit_shift--; } } switch (hdlc->state) { case STOPPED: Loading @@ -167,23 +212,21 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->state = HDLC_GETFLAG_B1A6; hdlc->hdlc_bits1 = 0; } else { if(!hdlc->do_adapt56){ if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1) 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){ if (hdlc->hdlc_bits1 == 6) hdlc->state = HDLC_GETFLAG_B7; } } else { } else hdlc->hdlc_bits1 = 0; } hdlc->cbin <<= 1; hdlc->bit_shift--; break; Loading @@ -208,19 +251,19 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, case 6: break; case 7: if(hdlc->data_received) { // bad frame 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; if (hdlc->cbin == fast_abort [hdlc->bit_shift + 1]) { hdlc->state = HDLC_FAST_IDLE; hdlc->bit_shift = 1; break; } } else { } else hdlc->state = HDLC_GET_FLAG_B0; } break; default: hdlc->shift_reg >>= 1; Loading @@ -233,33 +276,14 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, case 5: break; case 6: if(hdlc->data_received){ if (hdlc->dstpos < 2) { status = -HDLC_FRAMING_ERROR; } else if (hdlc->crc != 0xf0b8){ // crc error status = -HDLC_CRC_ERROR; } else { // remove CRC hdlc->dstpos -= 2; // good frame status = hdlc->dstpos; } } if (hdlc->data_received) status = check_frame(hdlc); hdlc->crc = 0xffff; hdlc->shift_reg = 0; hdlc->data_bits = 0; if(!hdlc->do_adapt56){ if(hdlc->cbin==fast_flag[hdlc->bit_shift]){ hdlc->ffvalue = fast_flag_value[hdlc->bit_shift]; hdlc->state = HDLC_FAST_FLAG; hdlc->ffbit_shift = hdlc->bit_shift; hdlc->bit_shift = 1; } else { hdlc->state = HDLC_GET_DATA; hdlc->data_received = 0; } } else { if (!hdlc->do_adapt56) handle_fast_flag(hdlc); else { hdlc->state = HDLC_GET_DATA; hdlc->data_received = 0; } Loading @@ -281,13 +305,14 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, if (hdlc->data_bits == 8) { hdlc->data_bits = 0; hdlc->data_received = 1; hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); // good byte received if (hdlc->dstpos < dsize) { /* good byte received */ if (hdlc->dstpos < dsize) dst[hdlc->dstpos++] = hdlc->shift_reg; } else { // frame too long else { /* frame too long */ status = -HDLC_LENGTH_ERROR; hdlc->dstpos = 0; } Loading @@ -306,14 +331,8 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, } else if (hdlc->ffbit_shift == 8) { hdlc->state = HDLC_GETFLAG_B7; break; } else { hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1]; hdlc->hdlc_bits1 = hdlc->ffbit_shift-2; if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0; hdlc->data_bits = hdlc->ffbit_shift-1; hdlc->state = HDLC_GET_DATA; hdlc->data_received = 0; } } else handle_abort(hdlc); } break; default: Loading @@ -323,7 +342,7 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, *count -= slen; return 0; } EXPORT_SYMBOL(isdnhdlc_decode); /* isdnhdlc_encode - encodes HDLC frames to a transparent bit stream. Loading @@ -343,9 +362,8 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, dsize - destination buffer size returns - number of encoded bytes in the destination buffer */ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, unsigned short slen, int *count, unsigned char *dst, int dsize) int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, int *count, u8 *dst, int dsize) { static const unsigned char xfast_flag_value[] = { 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e Loading @@ -361,7 +379,8 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->shift_reg = *src++; slen--; if (slen == 0) hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */ /* closing sequence, CRC + flag(s) */ hdlc->do_closing = 1; hdlc->bit_shift = 8; } else { if (hdlc->state == HDLC_SEND_DATA) { Loading @@ -369,12 +388,14 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->state = HDLC_SEND_CRC1; hdlc->crc ^= 0xffff; hdlc->bit_shift = 8; hdlc->shift_reg = hdlc->crc & 0xff; } else if(!hdlc->do_adapt56){ hdlc->state = HDLC_SEND_FAST_FLAG; } else { hdlc->state = HDLC_SENDFLAG_B0; } hdlc->shift_reg = hdlc->crc & 0xff; } else if (!hdlc->do_adapt56) hdlc->state = HDLC_SEND_FAST_FLAG; else hdlc->state = HDLC_SENDFLAG_B0; } } Loading @@ -395,7 +416,8 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, break; } if (hdlc->bit_shift == 8) { hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits); hdlc->cbin = hdlc->ffvalue >> (8 - hdlc->data_bits); hdlc->state = HDLC_SEND_DATA; hdlc->crc = 0xffff; hdlc->hdlc_bits1 = 0; Loading Loading @@ -457,9 +479,9 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->hdlc_bits1 = 0; break; } if(hdlc->bit_shift==8){ hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); } if (hdlc->bit_shift == 8) hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); if (hdlc->shift_reg & 0x01) { hdlc->hdlc_bits1++; hdlc->cbin++; Loading Loading @@ -524,29 +546,32 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->hdlc_bits1 = 0; break; } if(hdlc->shift_reg & 0x01){ if (hdlc->shift_reg & 0x01) hdlc->cbin++; } hdlc->shift_reg >>= 1; hdlc->bit_shift--; if (hdlc->bit_shift == 0) { hdlc->ffvalue = xfast_flag_value[hdlc->data_bits]; hdlc->ffvalue = xfast_flag_value[hdlc->data_bits]; if (hdlc->dchannel) { hdlc->ffvalue = 0x7e; hdlc->state = HDLC_SEND_IDLE1; hdlc->bit_shift = 8-hdlc->data_bits; if (hdlc->bit_shift == 0) hdlc->state = HDLC_SEND_FAST_IDLE; hdlc->state = HDLC_SEND_FAST_IDLE; } else { if (!hdlc->do_adapt56) { hdlc->state = HDLC_SEND_FAST_FLAG; hdlc->state = HDLC_SEND_FAST_FLAG; hdlc->data_received = 0; } else { hdlc->state = HDLC_SENDFLAG_B0; hdlc->data_received = 0; } // Finished with this frame, send flags if (dsize > 1) dsize = 1; /* Finished this frame, send flags */ if (dsize > 1) dsize = 1; } } break; Loading @@ -570,7 +595,8 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, hdlc->state = HDLC_SEND_FIRST_FLAG; } else { *dst++ = hdlc->cbin; hdlc->bit_shift = hdlc->data_bits = 0; hdlc->bit_shift = 0; hdlc->data_bits = 0; len++; dsize = 0; } Loading @@ -596,8 +622,4 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, return len; } EXPORT_SYMBOL(isdnhdlc_rcv_init); EXPORT_SYMBOL(isdnhdlc_decode); EXPORT_SYMBOL(isdnhdlc_out_init); EXPORT_SYMBOL(isdnhdlc_encode);
include/linux/isdn/hdlc.h +37 −31 Original line number Diff line number Diff line /* * isdnhdlc.h -- General purpose ISDN HDLC decoder. * hdlc.h -- General purpose ISDN HDLC decoder. * * Implementation of a HDLC decoder/encoder in software. * Neccessary because some ISDN devices don't have HDLC * controllers. Also included: a bit reversal table. * controllers. * *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de> * Copyright (C) * 2002 Wolfgang Mües <wolfgang@iksw-muees.de> * 2001 Frode Isaksen <fisaksen@bewan.com> * 2001 Kai Germaschewski <kai.germaschewski@gmx.de> * Loading @@ -31,20 +32,24 @@ struct isdnhdlc_vars { int bit_shift; int hdlc_bits1; int data_bits; int ffbit_shift; // encoding only int ffbit_shift; /* encoding only */ int state; int dstpos; unsigned short crc; u16 crc; unsigned char cbin; unsigned char shift_reg; unsigned char ffvalue; u8 cbin; u8 shift_reg; u8 ffvalue; unsigned int data_received:1; // set if transferring data unsigned int dchannel:1; // set if D channel (send idle instead of flags) unsigned int do_adapt56:1; // set if 56K adaptation unsigned int do_closing:1; // set if in closing phase (need to send CRC + flag /* set if transferring data */ u32 data_received:1; /* set if D channel (send idle instead of flags) */ u32 dchannel:1; /* set if 56K adaptation */ u32 do_adapt56:1; /* set if in closing phase (need to send CRC + flag) */ u32 do_closing:1; }; Loading @@ -59,12 +64,13 @@ struct isdnhdlc_vars { extern void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, int do_adapt56); extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count, unsigned char *dst, int dsize); extern int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, int *count, u8 *dst, int dsize); extern void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc,int is_d_channel,int do_adapt56); extern void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56); extern int isdnhdlc_encode (struct isdnhdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count, unsigned char *dst,int dsize); extern int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, int *count, u8 *dst, int dsize); #endif /* __ISDNHDLC_H__ */