ISDN: Add support for none reverse bitstreams to isdnhdc
authorKarsten Keil <keil@b1-systems.de>
Wed, 8 Jul 2009 18:31:42 +0000 (20:31 +0200)
committerKarsten Keil <keil@b1-systems.de>
Sat, 25 Jul 2009 18:16:01 +0000 (20:16 +0200)
The original isdnhdlc code was developed for devices which had
reversed bitorder in the byte stream. Adding code to handle normal
bitstreams as well.

Signed-off-by: Karsten Keil <keil@b1-systems.de>
drivers/isdn/hisax/st5481_b.c
drivers/isdn/hisax/st5481_d.c
drivers/isdn/hisax/st5481_usb.c
drivers/isdn/i4l/isdnhdlc.c
include/linux/isdn/hdlc.h

index 0074b600a0efa2d98b86c8ef16f97b0ebfdd4404..95b1cdd979584999707bbf3c84b80fed1129d66f 100644 (file)
@@ -218,7 +218,10 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode)
        if (bcs->mode != L1_MODE_NULL) {
                // Open the B channel
                if (bcs->mode != L1_MODE_TRANS) {
-                       isdnhdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K);
+                       u32 features = HDLC_BITREVERSE;
+                       if (bcs->mode == L1_MODE_HDLC_56K)
+                               features |= HDLC_56KBIT;
+                       isdnhdlc_out_init(&b_out->hdlc_state, features);
                }
                st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2, NULL, NULL);
        
index 077991c1cd050d9f93c0228155877d8377b95b88..39e8e49cfd2de8ee0ae293eda4409a5b707f006e 100644 (file)
@@ -417,7 +417,7 @@ static void dout_start_xmit(struct FsmInst *fsm, int event, void *arg)
 
        DBG(2,"len=%d",skb->len);
 
-       isdnhdlc_out_init(&d_out->hdlc_state, 1, 0);
+       isdnhdlc_out_init(&d_out->hdlc_state, HDLC_DCHANNEL | HDLC_BITREVERSE);
 
        if (test_and_set_bit(buf_nr, &d_out->busy)) {
                WARNING("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
index 2b3a055059ea6c2588f083fbfda5a24e43d7c807..10d41c5d73ed7c9a848b0f2de4096959dd514834 100644 (file)
@@ -637,10 +637,13 @@ void st5481_in_mode(struct st5481_in *in, int mode)
        usb_unlink_urb(in->urb[1]);
 
        if (in->mode != L1_MODE_NULL) {
-               if (in->mode != L1_MODE_TRANS)
-                       isdnhdlc_rcv_init(&in->hdlc_state,
-                               in->mode == L1_MODE_HDLC_56K);
-               
+               if (in->mode != L1_MODE_TRANS) {
+                       u32 features = HDLC_BITREVERSE;
+
+                       if (in->mode == L1_MODE_HDLC_56K)
+                               features |= HDLC_56KBIT;
+                       isdnhdlc_rcv_init(&in->hdlc_state, features);
+               }
                st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL);
                st5481_usb_device_ctrl_msg(in->adapter, in->counter,
                                           in->packet_size,
index b80e55ab89141387ee6ee54922000639aabbee7c..df345ce73f48db80a24ec0f4002b88190187f4c0 100644 (file)
@@ -2,6 +2,7 @@
  * isdnhdlc.c  --  General purpose ISDN HDLC decoder.
  *
  * Copyright (C)
+ *     2009    Karsten Keil            <keil@b1-systems.de>
  *     2002    Wolfgang Mües          <wolfgang@iksw-muees.de>
  *     2001    Frode Isaksen           <fisaksen@bewan.com>
  *      2001   Kai Germaschewski       <kai.germaschewski@gmx.de>
@@ -25,6 +26,7 @@
 #include <linux/init.h>
 #include <linux/crc-ccitt.h>
 #include <linux/isdn/hdlc.h>
+#include <linux/bitrev.h>
 
 /*-------------------------------------------------------------------*/
 
@@ -48,35 +50,21 @@ enum {
        HDLC_SENDFLAG_B1A6, HDLC_SENDFLAG_B7, STOPPED
 };
 
-void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, int do_adapt56)
+void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, u32 features)
 {
-       hdlc->bit_shift = 0;
-       hdlc->hdlc_bits1 = 0;
-       hdlc->data_bits = 0;
-       hdlc->ffbit_shift = 0;
-       hdlc->data_received = 0;
+       memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
        hdlc->state = HDLC_GET_DATA;
-       hdlc->do_adapt56 = do_adapt56;
-       hdlc->dchannel = 0;
-       hdlc->crc = 0;
-       hdlc->cbin = 0;
-       hdlc->shift_reg = 0;
-       hdlc->ffvalue = 0;
-       hdlc->dstpos = 0;
+       if (features & HDLC_56KBIT)
+               hdlc->do_adapt56 = 1;
+       if (features & HDLC_BITREVERSE)
+               hdlc->do_bitreverse = 1;
 }
 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, u32 features)
 {
-       hdlc->bit_shift = 0;
-       hdlc->hdlc_bits1 = 0;
-       hdlc->data_bits = 0;
-       hdlc->ffbit_shift = 0;
-       hdlc->data_received = 0;
-       hdlc->do_closing = 0;
-       hdlc->ffvalue = 0;
-       if (is_d_channel) {
+       memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
+       if (features & HDLC_DCHANNEL) {
                hdlc->dchannel = 1;
                hdlc->state = HDLC_SEND_FIRST_FLAG;
        } else {
@@ -85,16 +73,13 @@ void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, int is_d_channel,
                hdlc->ffvalue = 0x7e;
        }
        hdlc->cbin = 0x7e;
-       hdlc->bit_shift = 0;
-       if (do_adapt56) {
+       if (features & HDLC_56KBIT) {
                hdlc->do_adapt56 = 1;
-               hdlc->data_bits = 0;
                hdlc->state = HDLC_SENDFLAG_B0;
-       } else {
-               hdlc->do_adapt56 = 0;
+       } else
                hdlc->data_bits = 8;
-       }
-       hdlc->shift_reg = 0;
+       if (features & HDLC_BITREVERSE)
+               hdlc->do_bitreverse = 1;
 }
 EXPORT_SYMBOL(isdnhdlc_rcv_init);
 
@@ -188,7 +173,11 @@ int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen,
 
        while (slen > 0) {
                if (hdlc->bit_shift == 0) {
-                       hdlc->cbin = *src++;
+                       /* 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)
@@ -405,12 +394,15 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen,
                case STOPPED:
                        while (dsize--)
                                *dst++ = 0xff;
-
                        return dsize;
                case HDLC_SEND_FAST_FLAG:
                        hdlc->do_closing = 0;
                        if (slen == 0) {
-                               *dst++ = hdlc->ffvalue;
+                               /* the code is for bitreverse streams */
+                               if (hdlc->do_bitreverse == 0)
+                                       *dst++ = bitrev8(hdlc->ffvalue);
+                               else
+                                       *dst++ = hdlc->ffvalue;
                                len++;
                                dsize--;
                                break;
@@ -594,7 +586,11 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen,
                                hdlc->cbin = 0x7e;
                                hdlc->state = HDLC_SEND_FIRST_FLAG;
                        } else {
-                               *dst++ = hdlc->cbin;
+                               /* the code is for bitreverse streams */
+                               if (hdlc->do_bitreverse == 0)
+                                       *dst++ = bitrev8(hdlc->cbin);
+                               else
+                                       *dst++ = hdlc->cbin;
                                hdlc->bit_shift = 0;
                                hdlc->data_bits = 0;
                                len++;
@@ -612,7 +608,11 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen,
                        }
                }
                if (hdlc->data_bits == 8) {
-                       *dst++ = hdlc->cbin;
+                       /* the code is for bitreverse streams */
+                       if (hdlc->do_bitreverse == 0)
+                               *dst++ = bitrev8(hdlc->cbin);
+                       else
+                               *dst++ = hdlc->cbin;
                        hdlc->data_bits = 0;
                        len++;
                        dsize--;
index 8f3540c7f6923ff37e0661a196119b0db79304b7..4b3ecc40889a450c36b49d9eea167f0ae9a9cef3 100644 (file)
@@ -6,6 +6,7 @@
  * controllers.
  *
  * Copyright (C)
+ *     2009    Karsten Keil            <keil@b1-systems.de>
  *     2002    Wolfgang Mües          <wolfgang@iksw-muees.de>
  *     2001    Frode Isaksen           <fisaksen@bewan.com>
  *     2001    Kai Germaschewski       <kai.germaschewski@gmx.de>
@@ -50,8 +51,14 @@ struct isdnhdlc_vars {
        u32 do_adapt56:1;
        /* set if in closing phase (need to send CRC + flag) */
        u32 do_closing:1;
+       /* set if data is bitreverse */
+       u32 do_bitreverse:1;
 };
 
+/* Feature Flags */
+#define HDLC_56KBIT    0x01
+#define HDLC_DCHANNEL  0x02
+#define HDLC_BITREVERSE        0x04
 
 /*
   The return value from isdnhdlc_decode is
@@ -62,13 +69,12 @@ struct isdnhdlc_vars {
 #define HDLC_CRC_ERROR         2
 #define HDLC_LENGTH_ERROR      3
 
-extern void    isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, int do_adapt56);
+extern void    isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, u32 features);
 
 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, u32 features);
 
 extern int     isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src,
                        u16 slen, int *count, u8 *dst, int dsize);