2  * isdnhdlc.c  --  General purpose ISDN HDLC decoder.
 
   4  *Copyright (C) 2002    Wolfgang Mües      <wolfgang@iksw-muees.de>
 
   5  *              2001    Frode Isaksen      <fisaksen@bewan.com>
 
   6  *              2001    Kai Germaschewski  <kai.germaschewski@gmx.de>
 
   8  *      This program is free software; you can redistribute it and/or modify
 
   9  *      it under the terms of the GNU General Public License as published by
 
  10  *      the Free Software Foundation; either version 2 of the License, or
 
  11  *      (at your option) any later version.
 
  13  *      This program is distributed in the hope that it will be useful,
 
  14  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  15  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  16  *      GNU General Public License for more details.
 
  18  *      You should have received a copy of the GNU General Public License
 
  19  *      along with this program; if not, write to the Free Software
 
  20  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
  23 #include <linux/module.h>
 
  24 #include <linux/init.h>
 
  25 #include <linux/crc-ccitt.h>
 
  28 /*-------------------------------------------------------------------*/
 
  30 MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, "
 
  31               "Frode Isaksen <fisaksen@bewan.com>, "
 
  32               "Kai Germaschewski <kai.germaschewski@gmx.de>");
 
  33 MODULE_DESCRIPTION("General purpose ISDN HDLC decoder");
 
  34 MODULE_LICENSE("GPL");
 
  36 /*-------------------------------------------------------------------*/
 
  39         HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7,
 
  40         HDLC_GET_DATA,HDLC_FAST_FLAG
 
  44         HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG,
 
  45         HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG,
 
  46         HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0,
 
  47         HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED
 
  50 void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56)
 
  55         hdlc->ffbit_shift = 0;
 
  56         hdlc->data_received = 0;
 
  57         hdlc->state = HDLC_GET_DATA;
 
  58         hdlc->do_adapt56 = do_adapt56;
 
  67 void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56)
 
  72         hdlc->ffbit_shift = 0;
 
  73         hdlc->data_received = 0;
 
  78                 hdlc->state = HDLC_SEND_FIRST_FLAG;
 
  81                 hdlc->state = HDLC_SEND_FAST_FLAG;
 
  89                 hdlc->state = HDLC_SENDFLAG_B0;
 
  98   isdnhdlc_decode - decodes HDLC frames from a transparent bit stream.
 
 100   The source buffer is scanned for valid HDLC frames looking for
 
 101   flags (01111110) to indicate the start of a frame. If the start of
 
 102   the frame is found, the bit stuffing is removed (0 after 5 1's).
 
 103   When a new flag is found, the complete frame has been received
 
 104   and the CRC is checked.
 
 105   If a valid frame is found, the function returns the frame length
 
 106   excluding the CRC with the bit HDLC_END_OF_FRAME set.
 
 107   If the beginning of a valid frame is found, the function returns
 
 109   If a framing error is found (too many 1s and not a flag) the function
 
 110   returns the length with the bit HDLC_FRAMING_ERROR set.
 
 111   If a CRC error is found the function returns the length with the
 
 112   bit HDLC_CRC_ERROR set.
 
 113   If the frame length exceeds the destination buffer size, the function
 
 114   returns the length with the bit HDLC_LENGTH_ERROR set.
 
 117   slen - source buffer length
 
 118   count - number of bytes removed (decoded) from the source buffer
 
 119   dst _ destination buffer
 
 120   dsize - destination buffer size
 
 121   returns - number of decoded bytes in the destination buffer and status
 
 124 int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
 
 125                      int slen, int *count, unsigned char *dst, int dsize)
 
 129         static const unsigned char fast_flag[]={
 
 130                 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f
 
 133         static const unsigned char fast_flag_value[]={
 
 134                 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f
 
 137         static const unsigned char fast_abort[]={
 
 138                 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff
 
 144                 if(hdlc->bit_shift==0){
 
 148                         if(hdlc->do_adapt56){
 
 157                         if(hdlc->cbin == 0xff){
 
 161                         hdlc->state = HDLC_GET_FLAG_B0;
 
 162                         hdlc->hdlc_bits1 = 0;
 
 165                 case HDLC_GET_FLAG_B0:
 
 166                         if(!(hdlc->cbin & 0x80)) {
 
 167                                 hdlc->state = HDLC_GETFLAG_B1A6;
 
 168                                 hdlc->hdlc_bits1 = 0;
 
 170                                 if(!hdlc->do_adapt56){
 
 171                                         if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1)
 
 172                                                 hdlc->state = HDLC_FAST_IDLE;
 
 178                 case HDLC_GETFLAG_B1A6:
 
 179                         if(hdlc->cbin & 0x80){
 
 181                                 if(hdlc->hdlc_bits1==6){
 
 182                                         hdlc->state = HDLC_GETFLAG_B7;
 
 185                                 hdlc->hdlc_bits1 = 0;
 
 190                 case HDLC_GETFLAG_B7:
 
 191                         if(hdlc->cbin & 0x80) {
 
 192                                 hdlc->state = HDLC_GET_FLAG_B0;
 
 194                                 hdlc->state = HDLC_GET_DATA;
 
 197                                 hdlc->hdlc_bits1 = 0;
 
 199                                 hdlc->data_received = 0;
 
 205                         if(hdlc->cbin & 0x80){
 
 207                                 switch(hdlc->hdlc_bits1){
 
 211                                         if(hdlc->data_received) {
 
 213                                                 status = -HDLC_FRAMING_ERROR;
 
 215                                         if(!hdlc->do_adapt56){
 
 216                                                 if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){
 
 217                                                         hdlc->state = HDLC_FAST_IDLE;
 
 222                                                 hdlc->state = HDLC_GET_FLAG_B0;
 
 227                                         hdlc->shift_reg |= 0x80;
 
 232                                 switch(hdlc->hdlc_bits1){
 
 236                                         if(hdlc->data_received){
 
 237                                                 if (hdlc->dstpos < 2) {
 
 238                                                         status = -HDLC_FRAMING_ERROR;
 
 239                                                 } else if (hdlc->crc != 0xf0b8){
 
 241                                                         status = -HDLC_CRC_ERROR;
 
 246                                                         status = hdlc->dstpos;
 
 252                                         if(!hdlc->do_adapt56){
 
 253                                                 if(hdlc->cbin==fast_flag[hdlc->bit_shift]){
 
 254                                                         hdlc->ffvalue = fast_flag_value[hdlc->bit_shift];
 
 255                                                         hdlc->state = HDLC_FAST_FLAG;
 
 256                                                         hdlc->ffbit_shift = hdlc->bit_shift;
 
 259                                                         hdlc->state = HDLC_GET_DATA;
 
 260                                                         hdlc->data_received = 0;
 
 263                                                 hdlc->state = HDLC_GET_DATA;
 
 264                                                 hdlc->data_received = 0;
 
 272                                 hdlc->hdlc_bits1 = 0;
 
 281                         if(hdlc->data_bits==8){
 
 283                                 hdlc->data_received = 1;
 
 284                                 hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
 
 286                                 // good byte received
 
 287                                 if (hdlc->dstpos < dsize) {
 
 288                                         dst[hdlc->dstpos++] = hdlc->shift_reg;
 
 291                                         status = -HDLC_LENGTH_ERROR;
 
 299                         if(hdlc->cbin==hdlc->ffvalue){
 
 303                                 if(hdlc->cbin == 0xff){
 
 304                                         hdlc->state = HDLC_FAST_IDLE;
 
 306                                 } else if(hdlc->ffbit_shift==8){
 
 307                                         hdlc->state = HDLC_GETFLAG_B7;
 
 310                                         hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1];
 
 311                                         hdlc->hdlc_bits1 = hdlc->ffbit_shift-2;
 
 312                                         if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0;
 
 313                                         hdlc->data_bits = hdlc->ffbit_shift-1;
 
 314                                         hdlc->state = HDLC_GET_DATA;
 
 315                                         hdlc->data_received = 0;
 
 328   isdnhdlc_encode - encodes HDLC frames to a transparent bit stream.
 
 330   The bit stream starts with a beginning flag (01111110). After
 
 331   that each byte is added to the bit stream with bit stuffing added
 
 333   When the last byte has been removed from the source buffer, the
 
 334   CRC (2 bytes is added) and the frame terminates with the ending flag.
 
 335   For the dchannel, the idle character (all 1's) is also added at the end.
 
 336   If this function is called with empty source buffer (slen=0), flags or
 
 337   idle character will be generated.
 
 340   slen - source buffer length
 
 341   count - number of bytes removed (encoded) from source buffer
 
 342   dst _ destination buffer
 
 343   dsize - destination buffer size
 
 344   returns - number of encoded bytes in the destination buffer
 
 346 int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
 
 347                 unsigned short slen, int *count,
 
 348                 unsigned char *dst, int dsize)
 
 350         static const unsigned char xfast_flag_value[] = {
 
 351                 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e
 
 359                 if(hdlc->bit_shift==0){
 
 360                         if(slen && !hdlc->do_closing){
 
 361                                 hdlc->shift_reg = *src++;
 
 364                                         hdlc->do_closing = 1;  /* closing sequence, CRC + flag(s) */
 
 367                                 if(hdlc->state == HDLC_SEND_DATA){
 
 368                                         if(hdlc->data_received){
 
 369                                                 hdlc->state = HDLC_SEND_CRC1;
 
 372                                                 hdlc->shift_reg = hdlc->crc & 0xff;
 
 373                                         } else if(!hdlc->do_adapt56){
 
 374                                                 hdlc->state = HDLC_SEND_FAST_FLAG;
 
 376                                                 hdlc->state = HDLC_SENDFLAG_B0;
 
 389                 case HDLC_SEND_FAST_FLAG:
 
 390                         hdlc->do_closing = 0;
 
 392                                 *dst++ = hdlc->ffvalue;
 
 397                         if(hdlc->bit_shift==8){
 
 398                                 hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits);
 
 399                                 hdlc->state = HDLC_SEND_DATA;
 
 401                                 hdlc->hdlc_bits1 = 0;
 
 402                                 hdlc->data_received = 1;
 
 405                 case HDLC_SENDFLAG_B0:
 
 406                         hdlc->do_closing = 0;
 
 409                         hdlc->hdlc_bits1 = 0;
 
 410                         hdlc->state = HDLC_SENDFLAG_B1A6;
 
 412                 case HDLC_SENDFLAG_B1A6:
 
 416                         if(++hdlc->hdlc_bits1 == 6)
 
 417                                 hdlc->state = HDLC_SENDFLAG_B7;
 
 419                 case HDLC_SENDFLAG_B7:
 
 423                                 hdlc->state = HDLC_SENDFLAG_B0;
 
 426                         if(hdlc->bit_shift==8){
 
 427                                 hdlc->state = HDLC_SEND_DATA;
 
 429                                 hdlc->hdlc_bits1 = 0;
 
 430                                 hdlc->data_received = 1;
 
 433                 case HDLC_SEND_FIRST_FLAG:
 
 434                         hdlc->data_received = 1;
 
 435                         if(hdlc->data_bits==8){
 
 436                                 hdlc->state = HDLC_SEND_DATA;
 
 438                                 hdlc->hdlc_bits1 = 0;
 
 443                         if(hdlc->shift_reg & 0x01)
 
 445                         hdlc->shift_reg >>= 1;
 
 447                         if(hdlc->bit_shift==0){
 
 448                                 hdlc->state = HDLC_SEND_DATA;
 
 450                                 hdlc->hdlc_bits1 = 0;
 
 456                         if(hdlc->hdlc_bits1 == 5){
 
 457                                 hdlc->hdlc_bits1 = 0;
 
 460                         if(hdlc->bit_shift==8){
 
 461                                 hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
 
 463                         if(hdlc->shift_reg & 0x01){
 
 466                                 hdlc->shift_reg >>= 1;
 
 469                                 hdlc->hdlc_bits1 = 0;
 
 470                                 hdlc->shift_reg >>= 1;
 
 477                         if(hdlc->hdlc_bits1 == 5){
 
 478                                 hdlc->hdlc_bits1 = 0;
 
 481                         if(hdlc->shift_reg & 0x01){
 
 484                                 hdlc->shift_reg >>= 1;
 
 487                                 hdlc->hdlc_bits1 = 0;
 
 488                                 hdlc->shift_reg >>= 1;
 
 491                         if(hdlc->bit_shift==0){
 
 492                                 hdlc->shift_reg = (hdlc->crc >> 8);
 
 493                                 hdlc->state = HDLC_SEND_CRC2;
 
 500                         if(hdlc->hdlc_bits1 == 5){
 
 501                                 hdlc->hdlc_bits1 = 0;
 
 504                         if(hdlc->shift_reg & 0x01){
 
 507                                 hdlc->shift_reg >>= 1;
 
 510                                 hdlc->hdlc_bits1 = 0;
 
 511                                 hdlc->shift_reg >>= 1;
 
 514                         if(hdlc->bit_shift==0){
 
 515                                 hdlc->shift_reg = 0x7e;
 
 516                                 hdlc->state = HDLC_SEND_CLOSING_FLAG;
 
 520                 case HDLC_SEND_CLOSING_FLAG:
 
 523                         if(hdlc->hdlc_bits1 == 5){
 
 524                                 hdlc->hdlc_bits1 = 0;
 
 527                         if(hdlc->shift_reg & 0x01){
 
 530                         hdlc->shift_reg >>= 1;
 
 532                         if(hdlc->bit_shift==0){
 
 533                                 hdlc->ffvalue = xfast_flag_value[hdlc->data_bits];
 
 535                                         hdlc->ffvalue = 0x7e;
 
 536                                         hdlc->state = HDLC_SEND_IDLE1;
 
 537                                         hdlc->bit_shift = 8-hdlc->data_bits;
 
 538                                         if(hdlc->bit_shift==0)
 
 539                                                 hdlc->state = HDLC_SEND_FAST_IDLE;
 
 541                                         if(!hdlc->do_adapt56){
 
 542                                                 hdlc->state = HDLC_SEND_FAST_FLAG;
 
 543                                                 hdlc->data_received = 0;
 
 545                                                 hdlc->state = HDLC_SENDFLAG_B0;
 
 546                                                 hdlc->data_received = 0;
 
 548                                         // Finished with this frame, send flags
 
 549                                         if (dsize > 1) dsize = 1;
 
 553                 case HDLC_SEND_IDLE1:
 
 554                         hdlc->do_closing = 0;
 
 559                         if(hdlc->bit_shift==0){
 
 560                                 hdlc->state = HDLC_SEND_FAST_IDLE;
 
 564                 case HDLC_SEND_FAST_IDLE:
 
 565                         hdlc->do_closing = 0;
 
 568                         if(hdlc->bit_shift == 8){
 
 570                                 hdlc->state = HDLC_SEND_FIRST_FLAG;
 
 573                                 hdlc->bit_shift = hdlc->data_bits = 0;
 
 581                 if(hdlc->do_adapt56){
 
 582                         if(hdlc->data_bits==7){
 
 588                 if(hdlc->data_bits==8){
 
 600 EXPORT_SYMBOL(isdnhdlc_rcv_init);
 
 601 EXPORT_SYMBOL(isdnhdlc_decode);
 
 602 EXPORT_SYMBOL(isdnhdlc_out_init);
 
 603 EXPORT_SYMBOL(isdnhdlc_encode);