소스 검색

ISDN: Add support for none reverse bitstreams to isdnhdc

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>
Karsten Keil 16 년 전
부모
커밋
c38fc3bc2e
5개의 변경된 파일56개의 추가작업 그리고 44개의 파일을 삭제
  1. 4 1
      drivers/isdn/hisax/st5481_b.c
  2. 1 1
      drivers/isdn/hisax/st5481_d.c
  3. 7 4
      drivers/isdn/hisax/st5481_usb.c
  4. 35 35
      drivers/isdn/i4l/isdnhdlc.c
  5. 9 3
      include/linux/isdn/hdlc.h

+ 4 - 1
drivers/isdn/hisax/st5481_b.c

@@ -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);
 	

+ 1 - 1
drivers/isdn/hisax/st5481_d.c

@@ -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);

+ 7 - 4
drivers/isdn/hisax/st5481_usb.c

@@ -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,

+ 35 - 35
drivers/isdn/i4l/isdnhdlc.c

@@ -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--;

+ 9 - 3
include/linux/isdn/hdlc.h

@@ -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);