From 602f55372c56cc0995d76eb0843247508723497d Mon Sep 17 00:00:00 2001
From: Christian Vogel <vogelchr@vogel.cx>
Date: Sun, 23 Jan 2011 13:19:07 +0100
Subject: [PATCH 1/2] Table based msb-first crc16 functions.

---
 include/osmocore/Makefile.am  |    3 +-
 include/osmocore/osmo_crc16.h |   50 ++++++++++++++++++++++++++++++
 src/Makefile.am               |    2 +-
 src/osmo_crc16.c              |   67 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 120 insertions(+), 2 deletions(-)
 create mode 100644 include/osmocore/osmo_crc16.h
 create mode 100644 src/osmo_crc16.c

diff --git a/include/osmocore/Makefile.am b/include/osmocore/Makefile.am
index a3b12ef..ca69748 100644
--- a/include/osmocore/Makefile.am
+++ b/include/osmocore/Makefile.am
@@ -2,7 +2,8 @@ osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h bits.h \
 		   tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \
 		   gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \
 		   gsm48_ie.h logging.h gsm0808.h rate_ctr.h gsmtap_util.h \
-		   plugin.h crc16.h panic.h process.h gsm0480.h msgfile.h
+		   plugin.h crc16.h panic.h process.h gsm0480.h msgfile.h \
+		   osmo_crc16.h
 
 if ENABLE_TALLOC
 osmocore_HEADERS += talloc.h
diff --git a/include/osmocore/osmo_crc16.h b/include/osmocore/osmo_crc16.h
new file mode 100644
index 0000000..9b6aa79
--- /dev/null
+++ b/include/osmocore/osmo_crc16.h
@@ -0,0 +1,50 @@
+#ifndef OSMOCORE_OSMO_CRC16_H
+#define OSMOCORE_OSMO_CRC16_H
+
+#include <stdint.h>
+#include <osmocore/bits.h>
+
+/* Routines for calculating bit-wise CRC16 checksums with a given
+   polynomial operating on pbit_t and ubit_t arrays.
+   CRCs are calculated MSB first, unlike the more traditional
+   <osmocore/crc16.h> (lsb-first) */
+
+/* initialize the array used for fast calculation of 16-bit CRCs for a given
+   polynomial */
+extern void
+osmo_crc16_table_init(uint16_t *table,uint16_t poly);
+
+/* calculate/append crc with bits from given pbit_t array */
+extern uint16_t
+osmo_crc16(uint16_t *table,uint16_t crc,const pbit_t *pbits,unsigned int nbits);
+
+/* calculate/append crc with bits from given ubit_t array */
+extern uint16_t
+osmo_crc16_ubits(uint16_t *table,uint16_t crc, const ubit_t *ubits,
+		 unsigned int nbits);
+
+/* inline version for one ubit_t bit at a time */
+static inline uint16_t
+osmo_crc16_ubit(uint16_t poly,uint16_t crc,ubit_t ubit){
+	if(ubit)
+		crc ^= 0x8000;
+	if(crc & 0x8000){
+		crc = (crc << 1) ^ poly;
+	} else {
+		crc <<= 1;
+	}
+	return crc;
+}
+
+/* update crc with (1..8) bits from a single pbit_t */
+static inline uint16_t
+osmo_crc16_pbit(uint16_t *table,uint16_t crc,pbit_t pbit,unsigned int nbits){
+	uint8_t index;
+	/* yields the nbits top bits ^ pbit as lsb */
+	index = ((crc >> 8)^pbit) >> (8-nbits);
+	return (crc << nbits)^table[index];
+}
+
+#endif
+
+  
diff --git a/src/Makefile.am b/src/Makefile.am
index d4c6e12..43217d4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,7 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c bits.c \
 			 tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \
 			 write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \
 			 logging.c gsm0808.c rate_ctr.c gsmtap_util.c \
-			 gprs_cipher_core.c crc16.c panic.c process.c gsm0480.c
+			 gprs_cipher_core.c crc16.c panic.c process.c gsm0480.c osmo_crc16.c
 
 if ENABLE_PLUGIN
 libosmocore_la_SOURCES += plugin.c
diff --git a/src/osmo_crc16.c b/src/osmo_crc16.c
new file mode 100644
index 0000000..1be8dad
--- /dev/null
+++ b/src/osmo_crc16.c
@@ -0,0 +1,67 @@
+/* table based crc functions in msb-first order, operating on
+   ubits and pbits */
+/* (C) 2008-2010 by Christian Vogel <vogelchr@vogel.cx>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <osmocore/osmo_crc16.h>
+
+void
+osmo_crc16_table_init(uint16_t *table,uint16_t poly){
+	uint8_t val=0;
+	uint8_t mask;
+	uint16_t crc;
+	do {
+		crc=0;
+		for(mask=0x80;mask;mask>>=1){
+			if(val & mask)
+				crc ^= 0x8000;
+			if(crc & 0x8000){
+				crc <<= 1;
+				crc ^= poly;
+			} else {
+				crc <<= 1;
+			}
+		}
+		table[val]=crc;
+		val++;
+	} while(val != 0xff);
+}
+
+uint16_t
+osmo_crc16(uint16_t *table,uint16_t crc,const pbit_t *pbits,
+	   unsigned int nbits){
+	while(nbits >= 8){
+		crc = osmo_crc16_pbit(table,crc,*pbits,8);
+		nbits -= 8;
+		pbits++;
+	}
+	if(nbits == 0)
+		return crc;
+	return osmo_crc16_pbit(table,crc,*pbits,nbits);
+}
+
+uint16_t
+osmo_crc16_ubits(uint16_t *table,uint16_t crc,const ubit_t *ubits,
+		 unsigned int nbits){
+	unsigned int i;
+
+	for(i=0;i<nbits;i++)
+		crc = osmo_crc16_ubit(table[1],crc,ubits[i]);
+	return crc;
+}
-- 
1.6.3.3

