summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gssm/AUTHORS4
-rw-r--r--gssm/ChangeLog0
-rw-r--r--gssm/LICENSE34
-rw-r--r--gssm/Makefile.am3
-rw-r--r--gssm/Makefile.common2
-rw-r--r--gssm/NEWS0
-rw-r--r--gssm/README247
-rw-r--r--gssm/TODO1
-rwxr-xr-xgssm/bootstrap7
-rw-r--r--gssm/config/Makefile.am61
-rw-r--r--gssm/config/acx_pthread.m4190
-rw-r--r--gssm/config/bnv_have_qt.m4404
-rw-r--r--gssm/config/cppunit.m480
-rw-r--r--gssm/config/gr_as.m434
-rw-r--r--gssm/config/gr_boost.m470
-rw-r--r--gssm/config/gr_check_mc4020.m437
-rw-r--r--gssm/config/gr_check_shm_open.m429
-rw-r--r--gssm/config/gr_check_usrp.m432
-rw-r--r--gssm/config/gr_doxygen.m456
-rw-r--r--gssm/config/gr_gprof.m472
-rw-r--r--gssm/config/gr_omnithread.m451
-rw-r--r--gssm/config/gr_pwin32.m4146
-rw-r--r--gssm/config/gr_python.m4104
-rw-r--r--gssm/config/gr_scripting.m430
-rw-r--r--gssm/config/gr_set_md_cpu.m441
-rw-r--r--gssm/config/gr_swig.m485
-rw-r--r--gssm/config/gr_sysv_shm.m436
-rw-r--r--gssm/config/lf_cc.m442
-rw-r--r--gssm/config/lf_cxx.m4121
-rw-r--r--gssm/config/lf_warnings.m4128
-rw-r--r--gssm/config/lf_x11.m439
-rw-r--r--gssm/config/mkstemp.m489
-rw-r--r--gssm/config/onceonly.m463
-rw-r--r--gssm/config/pkg.m468
-rw-r--r--gssm/config/usrp_fusb_tech.m454
-rw-r--r--gssm/config/usrp_libusb.m438
-rw-r--r--gssm/config/usrp_sdcc.m467
-rw-r--r--gssm/configure.ac101
-rw-r--r--gssm/patch/wireshark-0.99.5-gssm.patch2669
-rw-r--r--gssm/src/Makefile.am4
-rw-r--r--gssm/src/lib/Makefile.am44
-rw-r--r--gssm/src/lib/buffer.h4
-rw-r--r--gssm/src/lib/burst_types.h217
-rw-r--r--gssm/src/lib/bursts.cc153
-rw-r--r--gssm/src/lib/bursts.h10
-rw-r--r--gssm/src/lib/cch.cc460
-rw-r--r--gssm/src/lib/cch.h42
-rw-r--r--gssm/src/lib/display.cc46
-rw-r--r--gssm/src/lib/display.h4
-rw-r--r--gssm/src/lib/gsm_constants.h76
-rw-r--r--gssm/src/lib/gssm.i28
-rw-r--r--gssm/src/lib/gssm_sink.cc764
-rw-r--r--gssm/src/lib/gssm_sink.h125
-rw-r--r--gssm/src/lib/gssm_state.h9
-rw-r--r--gssm/src/lib/rr_decode.cc236
-rw-r--r--gssm/src/lib/rr_decode.h4
-rw-r--r--gssm/src/lib/rrm.h22
-rw-r--r--gssm/src/lib/sch.cc320
-rw-r--r--gssm/src/lib/sch.h3
-rw-r--r--gssm/src/lib/tun.cc125
-rw-r--r--gssm/src/lib/tun.h4
-rw-r--r--gssm/src/mktun/Makefile.am7
-rw-r--r--gssm/src/mktun/mktun.c125
-rwxr-xr-xgssm/src/python/file_gssm.py45
-rwxr-xr-xgssm/src/python/file_stats.py46
-rwxr-xr-xgssm/src/python/gssm_stats.py85
-rwxr-xr-xgssm/src/python/gssm_usrp.py63
67 files changed, 8406 insertions, 0 deletions
diff --git a/gssm/AUTHORS b/gssm/AUTHORS
new file mode 100644
index 0000000..5d2553d
--- /dev/null
+++ b/gssm/AUTHORS
@@ -0,0 +1,4 @@
+Josh Lackey <jl@thre.at>
+
+The functions mm_demod() and quad_demod() are dervied from the corresponding
+functions in the GNU Radio project.
diff --git a/gssm/ChangeLog b/gssm/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gssm/ChangeLog
diff --git a/gssm/LICENSE b/gssm/LICENSE
new file mode 100644
index 0000000..db9d807
--- /dev/null
+++ b/gssm/LICENSE
@@ -0,0 +1,34 @@
+Copyright (c) 2007, Joshua Lackey (jl@thre.at)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of Threat Security nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+--
+
+The functions mm_demod() and quad_demod() in gssm_sink.cc are derived from the
+corresponding functions in the GNU Radio project.
+
diff --git a/gssm/Makefile.am b/gssm/Makefile.am
new file mode 100644
index 0000000..90b432f
--- /dev/null
+++ b/gssm/Makefile.am
@@ -0,0 +1,3 @@
+include $(top_srcdir)/Makefile.common
+
+SUBDIRS = src
diff --git a/gssm/Makefile.common b/gssm/Makefile.common
new file mode 100644
index 0000000..ec4ab08
--- /dev/null
+++ b/gssm/Makefile.common
@@ -0,0 +1,2 @@
+grincludedir = $(includedir)/gnuradio
+swigincludedir = $(grincludedir)/swig
diff --git a/gssm/NEWS b/gssm/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gssm/NEWS
diff --git a/gssm/README b/gssm/README
new file mode 100644
index 0000000..370a0a1
--- /dev/null
+++ b/gssm/README
@@ -0,0 +1,247 @@
+gssm -- Groupe Special (Software) Mobile
+
+ or
+
+gssm -- The Global Software System for Mobile communications
+
+---
+
+SUMMARY
+
+This package monitors GSM base station control channels. It uses the USRP
+and various daughterboards to capture live data, GNU Radio and custom
+modules to demodulate and decode the GSM packets, and Wireshark to display
+the data.
+
+Get it here: http://thre.at/gsm.
+
+Talk about it here: gsm-subscribe@lists.segfault.net.
+
+More here: http://wiki.thc.org/gsm.
+
+---
+
+WHAT
+
+This package monitors GSM base station control channels. It uses the USRP
+and various daughterboards to capture live data, GNU Radio and custom
+modules to demodulate and decode the GSM packets, and Wireshark to display
+the data.
+
+This version of gssm decodes most of the control channels. The control
+channels contain the information necessary for a mobile to communicate with
+a base station. The control channels which gssm currently decodes are:
+
+ FCCH The frequency correction channel.
+ SCH The synchronization channel.
+ BCCH The broadcast control channel.
+ PCH The paging channel. Downlink only, used to page mobiles.
+ AGCH The access grant channel. Downlink only, used to allocate
+ an SDCCH or directly a TCH.
+ SACCH Slow associated control channel.
+ SDCCH Stand-alone dedicated control channel.
+
+gssm displays the decoded data using Wireshark. Not only does this give us a
+very nice graphical front end to examine the dissected packets, but Wireshark
+already has quite a bit of code to dissect GSM data. Unfortunately, the
+current implementation of Wireshark does not dissect packets unique to the
+wireless interface. Up to now, there was no reason to include code to dissect
+these packets. I include a patch for wireshark-0.99.5 which adds (partial) Um
+packet dissection capability and a new custom ethertype to interface with the
+USRP.
+
+While gssm has basic functionality now, it really is alpha-quality software
+and there are a number of enhancements which must be made before it becomes
+truly useful.
+
+ 1. The Mueller and Muller clock recovery method doesn't always
+ handle the quarter-bits present in a GSM burst. A more reliable
+ method must be implemented. Until then, this software will suffer
+ from a large number of receive errors even with a high
+ signal-to-noise ratio.
+
+ 2. Wireshark dissects most GSM packets except those specific to
+ the Um interface, the wireless interface between the mobile and
+ the BTS, the Base Transciever Station.
+
+ a. I've only implemented a small portion of the Um
+ interface. Much more work must be done to complete this.
+
+ b. Only the Bbis frame type is implemented. When packets
+ arrive in Wireshark which are "malformed" or with strange
+ protocol descriptors, it is because they were sent using
+ some other frame type.
+
+ c. The interface between gssm and Wireshark is extremely
+ hacky, to say the least. It would be nice to eventually
+ standardize a GNU Radio interface for Wireshark. I also want
+ to clean up my Um interface and submit that there as well.
+
+ 3. You need to find your local GSM tower by hand. Once you've
+ found it, you need to edit the python script and enter the
+ information by hand. It would be very nice if this information was
+ automatically generated.
+
+ 4. The code is designed to support all frequency bands but I
+ haven't implemented anything but U.S. support.
+
+ 5. This code is receive-only and currently can only monitor tower
+ to mobile transmissions.
+
+ 6. Lots more.
+
+---
+
+WHERE
+
+This code is being adopted by the GSM Scanner Project and will be used as
+the base for further improvements. Questions and suggestions can certainly
+be sent to me, but they also should be directed to the mailing list --
+gsm-subscribe@lists.segfault.net. Also, check out the wiki at
+http://wiki.thc.org/gsm.
+
+The current version of the code can be found here: http://thre.at/gsm.
+Updates and bug-fixes will be found at the GSM Scanner Project,
+http://wiki.thc.org/gsm.
+
+---
+
+HOW
+
+First, you must install the gssm package.
+
+1. First install GNU Radio. Any relatively recent GNU Radio build
+ should work. I've been testing on revision 5220.
+
+2. Now build gssm. It should be as simple to install as:
+
+ jl@hackphoo ~ $ cd ~/src/gssm
+ jl@hackphoo ~/src/gssm $ ./bootstrap && ./configure && make && sudo make install
+ [...]
+ jl@hackphoo ~/src/gssm $
+
+3. Get the latest version of Wireshark and apply the patch in the
+ patch directory and then build Wireshark as usual. Note that the
+ current version of this patch is for wireshark-0.99.5 and may not
+ apply cleanly to newer versions.
+
+ jl@hackphoo ~ $ cd ~/src/wireshark-0.99.5
+ jl@hackphoo ~/src/wireshark-0.99.5 $ patch -p1 < ~/src/gssm/patch/wireshark-0.99.5-gssm.patch
+ patching file epan/dissectors/packet-gsm_a.c
+ jl@hackphoo ~/src/wireshark-0.99.5 $ ./configure && make && sudo make install
+ [...]
+ jl@hackphoo ~/src/wireshark-0.99.5 $
+
+4. gssm uses a TUN interface to send packets to Wireshark. You must
+ have the tun.ko kernel module loaded.
+
+ jl@hackphoo:~$ lsmod | grep tun
+ tun 12032 0
+ jl@hackphoo:~$
+
+ If the tun.ko kernel module is not loaded, you can try and load it
+ by hand.
+
+ jl@hackphoo:~$ lsmod | grep tun
+ jl@hackphoo:~$ sudo modprobe tun
+ jl@hackphoo:~$ lsmod | grep tun
+ tun 12032 0
+ jl@hackphoo:~$
+
+ If that doesn't work and you get a "FATAL: Module tun not found",
+ you are most likely going to have to rebuild your kernel and make
+ sure that you enable support for the TUN device.
+
+ It appears that Ubuntu 7.04 supports the TUN device by default.
+
+5. It is possible to configure the TUN device so that any user, or
+ users in a certain group, can create and delete interfaces.
+ Unfortunately, it appears that no matter who creates the
+ interfaces only root can mark these interfaces up.
+
+ Rather than require gssm to run as root, we instead use another
+ simpler program to create the interface and mark it up. This
+ program, mktun, was installed with gssm.
+
+ jl@hackphoo:~$ /usr/local/bin/mktun --help
+ note: you must be root (except perhaps to delete the interface)
+ usage: mktun [--help | -h] | [--delete | -d] <interface_name>
+ jl@hackphoo:~$ sudo /usr/local/bin/mktun gsm
+ jl@hackphoo:~$ ifconfig
+ [...]
+
+ gsm Link encap:Ethernet HWaddr 22:07:3F:7F:6A:EC
+ inet6 addr: fe80::2007:3fff:fe7f:6aec/64 Scope:Link
+ UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
+ RX packets:33324 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:0 errors:0 dropped:6 overruns:0 carrier:0
+ collisions:0 txqueuelen:500
+ RX bytes:1199664 (1.1 MiB) TX bytes:0 (0.0 b)
+
+ [...]
+ jl@hackphoo:~$
+
+ You can always delete the interface when you want to get rid of it.
+
+ jl@hackphoo:~$ sudo /usr/local/bin/mktun -d gsm
+ jl@hackphoo:~$ ifconfig | grep gsm
+ jl@hackphoo:~$
+
+Now, demod some traffic.
+
+1. Since this program doesn't scan the GSM frequency ranges for you, you
+ must locate your closest tower by hand. There are instructions on how
+ to do this at http://wiki.thc.org/gsm.
+
+ Essentially, use usrp_fft.py in the GSM frequency ranges
+ (http://en.wikipedia.org/wiki/GSM_frequency_ranges) and look for a peak
+ roughly 300kHz wide. The main channel on a base station, channel 0,
+ does not use frequency hopping so the peak of the signal you are
+ looking for should be constant.
+
+ The M&M clock recovery occasionally fails to synchronize with bursts
+ and so you need a fairly strong signal to get good results with the
+ current code. Look for signals that are at least 20dB above the noise
+ floor. (!)
+
+2. The USRP daughterboards have a frequency offset error which differs
+ from board to board. Normally this error ranges from 4kHz to 32kHz.
+ The current code will demodulate data with offsets up to 32kHz but will
+ perform much better if you compensate for the offset.
+
+ The GSM Scanner Project has a matlab script which will locate your
+ offset. This doesn't help if you don't own matlab. Currently, the
+ easiest alternative method is as follows.
+
+ a. Use usrp_fft.py and set the decimation rate to 112. When
+ the frequency correction burst is transmitted it forms a peak
+ in the signal 62.5kHz above the center of the channel.
+
+ b. Locate the 62.5kHz peak and eyeball the offset. You should
+ be able to estimate the offset within 10kHz or so.
+
+3. Enter in the frequency and the offset above into the script
+ gssm-v0.1/src/python/gssm_usrp.py.
+
+4. Start Wireshark and monitor the gsm interface.
+
+5. Start the gssm_usrp.py script.
+
+ You should see a bunch of errors start flying by. This is expected
+ even when we aren't receiving bad data because of the fairly brain-dead
+ way the code determines if channels have data. Any data displayed in
+ Wireshark has been successfully Viterbi decoded and has survived a FIRE
+ parity check and is therefore, with extremely high-probability, valid.
+ So, don't worry about all the errors. There aren't really that many
+ and it doesn't affect the valid data anyway.
+
+ If it is displayed incorrectly in Wireshark it is because I haven't
+ implemented frame types besides Bbis.
+
+ You can expand most of the packets you see and you can use the
+ Wireshark filter functionality on quite a few of the GSM information
+ elements.
+
+6. Notice obvious errors. Write code to fix the errors. Send us patches.
+
+
diff --git a/gssm/TODO b/gssm/TODO
new file mode 100644
index 0000000..c3ca5b4
--- /dev/null
+++ b/gssm/TODO
@@ -0,0 +1 @@
+Lots.
diff --git a/gssm/bootstrap b/gssm/bootstrap
new file mode 100755
index 0000000..a725425
--- /dev/null
+++ b/gssm/bootstrap
@@ -0,0 +1,7 @@
+rm -rf config.cache autom4te*.cache
+
+aclocal -I config
+autoconf
+autoheader
+libtoolize --automake
+automake --add-missing
diff --git a/gssm/config/Makefile.am b/gssm/config/Makefile.am
new file mode 100644
index 0000000..ad85978
--- /dev/null
+++ b/gssm/config/Makefile.am
@@ -0,0 +1,61 @@
+#
+# Copyright 2001 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+include $(top_srcdir)/Makefile.common
+
+# Install m4 macros in this directory
+m4datadir = $(datadir)/aclocal
+
+# List your m4 macros here
+m4macros = \
+ acx_pthread.m4 \
+ bnv_have_qt.m4 \
+ cppunit.m4 \
+ gr_as.m4 \
+ gr_boost.m4 \
+ gr_check_usrp.m4 \
+ gr_check_mc4020.m4 \
+ gr_check_shm_open.m4 \
+ gr_doxygen.m4 \
+ gr_gprof.m4 \
+ gr_omnithread.m4 \
+ gr_pwin32.m4 \
+ gr_python.m4 \
+ gr_scripting.m4 \
+ gr_set_md_cpu.m4 \
+ gr_swig.m4 \
+ gr_sysv_shm.m4 \
+ lf_cc.m4 \
+ lf_cxx.m4 \
+ lf_warnings.m4 \
+ lf_x11.m4 \
+ mkstemp.m4 \
+ onceonly.m4 \
+ pkg.m4 \
+ usrp_fusb_tech.m4 \
+ usrp_libusb.m4 \
+ usrp_sdcc.m4
+
+
+# Don't install m4 macros anymore
+# m4data_DATA = $(m4macros)
+
+EXTRA_DIST = $(m4macros)
diff --git a/gssm/config/acx_pthread.m4 b/gssm/config/acx_pthread.m4
new file mode 100644
index 0000000..d318ab0
--- /dev/null
+++ b/gssm/config/acx_pthread.m4
@@ -0,0 +1,190 @@
+dnl Available from the GNU Autoconf Macro Archive at:
+dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html
+dnl
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test x"$acx_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+
+case "${host_cpu}-${host_os}" in
+ *solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthread or
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+ ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_TRY_LINK([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+ [acx_pthread_ok=yes])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test "x$acx_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: threads are created detached by default
+ # and the JOINABLE attribute has a nonstandard name (UNDETACHED).
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ AC_TRY_LINK([#include <pthread.h>],
+ [int attr=PTHREAD_CREATE_JOINABLE;],
+ ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
+ if test x"$ok" = xunknown; then
+ AC_TRY_LINK([#include <pthread.h>],
+ [int attr=PTHREAD_CREATE_UNDETACHED;],
+ ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
+ fi
+ if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
+ [Define to the necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+ AC_MSG_RESULT(${ok})
+ if test x"$ok" = xunknown; then
+ AC_MSG_WARN([we do not know how to create joinable pthreads])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";;
+ *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with cc_r
+ AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ acx_pthread_ok=no
+ $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
diff --git a/gssm/config/bnv_have_qt.m4 b/gssm/config/bnv_have_qt.m4
new file mode 100644
index 0000000..1469bfb
--- /dev/null
+++ b/gssm/config/bnv_have_qt.m4
@@ -0,0 +1,404 @@
+dnl Available from the GNU Autoconf Macro Archive at:
+dnl http://www.gnu.org/software/ac-archive/htmldoc/bnv_have_qt.html
+dnl
+AC_DEFUN([BNV_HAVE_QT],
+[
+ dnl THANKS! This code includes bug fixes by:
+ dnl Tim McClarren.
+
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([AC_PATH_X])
+ AC_REQUIRE([AC_PATH_XTRA])
+
+ AC_MSG_CHECKING(for Qt)
+
+ AC_ARG_WITH([Qt-dir],
+ [ --with-Qt-dir=DIR DIR is equal to \$QTDIR if you have followed the
+ installation instructions of Trolltech. Header
+ files are in DIR/include, binary utilities are
+ in DIR/bin and the library is in DIR/lib])
+ AC_ARG_WITH([Qt-include-dir],
+ [ --with-Qt-include-dir=DIR
+ Qt header files are in DIR])
+ AC_ARG_WITH([Qt-bin-dir],
+ [ --with-Qt-bin-dir=DIR Qt utilities such as moc and uic are in DIR])
+ AC_ARG_WITH([Qt-lib-dir],
+ [ --with-Qt-lib-dir=DIR The Qt library is in DIR])
+ AC_ARG_WITH([Qt-lib],
+ [ --with-Qt-lib=LIB Use -lLIB to link with the Qt library])
+ if test x"$with_Qt_dir" = x"no" ||
+ test x"$with_Qt_include-dir" = x"no" ||
+ test x"$with_Qt_bin_dir" = x"no" ||
+ test x"$with_Qt_lib_dir" = x"no" ||
+ test x"$with_Qt_lib" = x"no"; then
+ # user disabled Qt. Leave cache alone.
+ have_qt="User disabled Qt."
+ else
+ # "yes" is a bogus option
+ if test x"$with_Qt_dir" = xyes; then
+ with_Qt_dir=
+ fi
+ if test x"$with_Qt_include_dir" = xyes; then
+ with_Qt_include_dir=
+ fi
+ if test x"$with_Qt_bin_dir" = xyes; then
+ with_Qt_bin_dir=
+ fi
+ if test x"$with_Qt_lib_dir" = xyes; then
+ with_Qt_lib_dir=
+ fi
+ if test x"$with_Qt_lib" = xyes; then
+ with_Qt_lib=
+ fi
+ # No Qt unless we discover otherwise
+ have_qt=no
+ # Check whether we are requested to link with a specific version
+ if test x"$with_Qt_lib" != x; then
+ bnv_qt_lib="$with_Qt_lib"
+ fi
+ # Check whether we were supplied with an answer already
+ if test x"$with_Qt_dir" != x; then
+ have_qt=yes
+ bnv_qt_dir="$with_Qt_dir"
+ bnv_qt_include_dir="$with_Qt_dir/include"
+ bnv_qt_bin_dir="$with_Qt_dir/bin"
+ bnv_qt_lib_dir="$with_Qt_dir/lib"
+ # Only search for the lib if the user did not define one already
+ if test x"$bnv_qt_lib" = x; then
+ bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p |
+ sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`"
+ fi
+ bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ else
+ # Use cached value or do search, starting with suggestions from
+ # the command line
+ AC_CACHE_VAL(bnv_cv_have_qt,
+ [
+ # We are not given a solution and there is no cached value.
+ bnv_qt_dir=NO
+ bnv_qt_include_dir=NO
+ bnv_qt_lib_dir=NO
+ if test x"$bnv_qt_lib" = x; then
+ bnv_qt_lib=NO
+ fi
+ BNV_PATH_QT_DIRECT
+ if test "$bnv_qt_dir" = NO ||
+ test "$bnv_qt_include_dir" = NO ||
+ test "$bnv_qt_lib_dir" = NO ||
+ test "$bnv_qt_lib" = NO; then
+ # Problem with finding complete Qt. Cache the known absence of Qt.
+ bnv_cv_have_qt="have_qt=no"
+ else
+ # Record where we found Qt for the cache.
+ bnv_cv_have_qt="have_qt=yes \
+ bnv_qt_dir=$bnv_qt_dir \
+ bnv_qt_include_dir=$bnv_qt_include_dir \
+ bnv_qt_bin_dir=$bnv_qt_bin_dir \
+ bnv_qt_LIBS=\"$bnv_qt_LIBS\""
+ fi
+ ])dnl
+ eval "$bnv_cv_have_qt"
+ fi # all $bnv_qt_* are set
+ fi # $have_qt reflects the system status
+ if test x"$have_qt" = xyes; then
+ QT_CXXFLAGS="-I$bnv_qt_include_dir"
+ QT_DIR="$bnv_qt_dir"
+ QT_LIBS="$bnv_qt_LIBS"
+ # If bnv_qt_dir is defined, utilities are expected to be in the
+ # bin subdirectory
+ if test x"$bnv_qt_dir" != x; then
+ if test -x "$bnv_qt_dir/bin/uic"; then
+ QT_UIC="$bnv_qt_dir/bin/uic"
+ else
+ # Old versions of Qt don't have uic
+ QT_UIC=
+ fi
+ QT_MOC="$bnv_qt_dir/bin/moc"
+ else
+ # Or maybe we are told where to look for the utilities
+ if test x"$bnv_qt_bin_dir" != x; then
+ if test -x "$bnv_qt_bin_dir/uic"; then
+ QT_UIC="$bnv_qt_bin_dir/uic"
+ else
+ # Old versions of Qt don't have uic
+ QT_UIC=
+ fi
+ QT_MOC="$bnv_qt_bin_dir/moc"
+ else
+ # Last possibility is that they are in $PATH
+ QT_UIC="`which uic`"
+ QT_MOC="`which moc`"
+ fi
+ fi
+ # All variables are defined, report the result
+ AC_MSG_RESULT([$have_qt:
+ QT_CXXFLAGS=$QT_CXXFLAGS
+ QT_DIR=$QT_DIR
+ QT_LIBS=$QT_LIBS
+ QT_UIC=$QT_UIC
+ QT_MOC=$QT_MOC])
+ else
+ # Qt was not found
+ QT_CXXFLAGS=
+ QT_DIR=
+ QT_LIBS=
+ QT_UIC=
+ QT_MOC=
+ AC_MSG_RESULT($have_qt)
+ fi
+ AC_SUBST(QT_CXXFLAGS)
+ AC_SUBST(QT_DIR)
+ AC_SUBST(QT_LIBS)
+ AC_SUBST(QT_UIC)
+ AC_SUBST(QT_MOC)
+
+ #### Being paranoid:
+ if test x"$have_qt" = xyes; then
+ AC_MSG_CHECKING(correct functioning of Qt installation)
+ AC_CACHE_VAL(bnv_cv_qt_test_result,
+ [
+ cat > bnv_qt_test.h << EOF
+#include <qobject.h>
+class Test : public QObject
+{
+Q_OBJECT
+public:
+ Test() {}
+ ~Test() {}
+public slots:
+ void receive() {}
+signals:
+ void send();
+};
+EOF
+
+ cat > bnv_qt_main.$ac_ext << EOF
+#include "bnv_qt_test.h"
+#include <qapplication.h>
+int main( int argc, char **argv )
+{
+ QApplication app( argc, argv );
+ Test t;
+ QObject::connect( &t, SIGNAL(send()), &t, SLOT(receive()) );
+}
+EOF
+
+ bnv_cv_qt_test_result="failure"
+ bnv_try_1="$QT_MOC bnv_qt_test.h -o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_1.out"
+ AC_TRY_EVAL(bnv_try_1)
+ bnv_err_1=`grep -v '^ *+' bnv_qt_test_1.out | grep -v "^bnv_qt_test.h\$"`
+ if test x"$bnv_err_1" != x; then
+ echo "$bnv_err_1" >&AC_FD_CC
+ echo "configure: could not run $QT_MOC on:" >&AC_FD_CC
+ cat bnv_qt_test.h >&AC_FD_CC
+ else
+ bnv_try_2="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o moc_bnv_qt_test.o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_2.out"
+ AC_TRY_EVAL(bnv_try_2)
+ bnv_err_2=`grep -v '^ *+' bnv_qt_test_2.out | grep -v "^bnv_qt_test.{$ac_ext}\$"`
+ if test x"$bnv_err_2" != x; then
+ echo "$bnv_err_2" >&AC_FD_CC
+ echo "configure: could not compile:" >&AC_FD_CC
+ cat bnv_qt_test.$ac_ext >&AC_FD_CC
+ else
+ bnv_try_3="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o bnv_qt_main.o bnv_qt_main.$ac_ext >/dev/null 2>bnv_qt_test_3.out"
+ AC_TRY_EVAL(bnv_try_3)
+ bnv_err_3=`grep -v '^ *+' bnv_qt_test_3.out | grep -v "^bnv_qt_main.{$ac_ext}\$"`
+ if test x"$bnv_err_3" != x; then
+ echo "$bnv_err_3" >&AC_FD_CC
+ echo "configure: could not compile:" >&AC_FD_CC
+ cat bnv_qt_main.$ac_ext >&AC_FD_CC
+ else
+ bnv_try_4="$CXX $QT_LIBS $LIBS -o bnv_qt_main bnv_qt_main.o moc_bnv_qt_test.o >/dev/null 2>bnv_qt_test_4.out"
+ AC_TRY_EVAL(bnv_try_4)
+ bnv_err_4=`grep -v '^ *+' bnv_qt_test_4.out`
+ if test x"$bnv_err_4" != x; then
+ echo "$bnv_err_4" >&AC_FD_CC
+ else
+ bnv_cv_qt_test_result="success"
+ fi
+ fi
+ fi
+ fi
+ ])dnl AC_CACHE_VAL bnv_cv_qt_test_result
+ AC_MSG_RESULT([$bnv_cv_qt_test_result]);
+ if test x"$bnv_cv_qt_test_result" = "xfailure"; then
+ # working Qt was not found
+ QT_CXXFLAGS=
+ QT_DIR=
+ QT_LIBS=
+ QT_UIC=
+ QT_MOC=
+ have_qt=no
+ AC_MSG_WARN([Failed to find matching components of a complete
+ Qt installation. Try using more options,
+ see ./configure --help.])
+ fi
+
+ rm -f bnv_qt_test.h moc_bnv_qt_test.$ac_ext moc_bnv_qt_test.o \
+ bnv_qt_main.$ac_ext bnv_qt_main.o bnv_qt_main \
+ bnv_qt_test_1.out bnv_qt_test_2.out bnv_qt_test_3.out bnv_qt_test_4.out
+ fi
+])
+
+dnl Internal subroutine of BNV_HAVE_QT
+dnl Set bnv_qt_dir bnv_qt_include_dir bnv_qt_bin_dir bnv_qt_lib_dir bnv_qt_lib
+dnl Copyright 2001 Bastiaan N. Veelo <Bastiaan.N.Veelo@immtek.ntnu.no>
+AC_DEFUN([BNV_PATH_QT_DIRECT],
+[
+ ## Binary utilities ##
+ if test x"$with_Qt_bin_dir" != x; then
+ bnv_qt_bin_dir=$with_Qt_bin_dir
+ fi
+ ## Look for header files ##
+ if test x"$with_Qt_include_dir" != x; then
+ bnv_qt_include_dir="$with_Qt_include_dir"
+ else
+ # The following header file is expected to define QT_VERSION.
+ qt_direct_test_header=qglobal.h
+ # Look for the header file in a standard set of common directories.
+ bnv_include_path_list="
+ /usr/include
+ `ls -dr /usr/include/qt* 2>/dev/null`
+ `ls -dr /usr/lib/qt*/include 2>/dev/null`
+ `ls -dr /usr/local/qt*/include 2>/dev/null`
+ `ls -dr /opt/qt*/include 2>/dev/null`
+ "
+ for bnv_dir in $bnv_include_path_list; do
+ if test -r "$bnv_dir/$qt_direct_test_header"; then
+ bnv_dirs="$bnv_dirs $bnv_dir"
+ fi
+ done
+ # Now look for the newest in this list
+ bnv_prev_ver=0
+ for bnv_dir in $bnv_dirs; do
+ bnv_this_ver=`egrep -w '#define QT_VERSION' $bnv_dir/$qt_direct_test_header | sed s/'#define QT_VERSION'//`
+ if expr $bnv_this_ver '>' $bnv_prev_ver > /dev/null; then
+ bnv_qt_include_dir=$bnv_dir
+ bnv_prev_ver=$bnv_this_ver
+ fi
+ done
+ fi dnl Found header files.
+
+ # Are these headers located in a traditional Trolltech installation?
+ # That would be $bnv_qt_include_dir stripped from its last element:
+ bnv_possible_qt_dir=`dirname $bnv_qt_include_dir`
+ if test -x $bnv_possible_qt_dir/bin/moc &&
+ ls $bnv_possible_qt_dir/lib/libqt* > /dev/null; then
+ # Then the rest is a piece of cake
+ bnv_qt_dir=$bnv_possible_qt_dir
+ bnv_qt_bin_dir="$bnv_qt_dir/bin"
+ bnv_qt_lib_dir="$bnv_qt_dir/lib"
+ # Only look for lib if the user did not supply it already
+ if test x"$bnv_qt_lib" = xNO; then
+ bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p |
+ sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`"
+ fi
+ bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ else
+ # There is no valid definition for $QTDIR as Trolltech likes to see it
+ bnv_qt_dir=
+ ## Look for Qt library ##
+ if test x"$with_Qt_lib_dir" != x; then
+ bnv_qt_lib_dir="$with_Qt_lib_dir"
+ # Only look for lib if the user did not supply it already
+ if test x"$bnv_qt_lib" = xNO; then
+ bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p |
+ sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`"
+ fi
+ bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ else
+ # Normally, when there is no traditional Trolltech installation,
+ # the library is installed in a place where the linker finds it
+ # automatically.
+ # If the user did not define the library name, try with qt
+ if test x"$bnv_qt_lib" = xNO; then
+ bnv_qt_lib=qt
+ fi
+ qt_direct_test_header=qapplication.h
+ qt_direct_test_main="
+ int argc;
+ char ** argv;
+ QApplication app(argc,argv);
+ "
+ # See if we find the library without any special options.
+ # Don't add top $LIBS permanently yet
+ bnv_save_LIBS="$LIBS"
+ LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ bnv_qt_LIBS="$LIBS"
+ bnv_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="-I$bnv_qt_include_dir"
+ AC_TRY_LINK([#include <$qt_direct_test_header>],
+ $qt_direct_test_main,
+ [
+ # Success.
+ # We can link with no special library directory.
+ bnv_qt_lib_dir=
+ ], [
+ # That did not work. Try the multi-threaded version
+ echo "Non-critical error, please neglect the above." >&AC_FD_CC
+ bnv_qt_lib=qt-mt
+ LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ AC_TRY_LINK([#include <$qt_direct_test_header>],
+ $qt_direct_test_main,
+ [
+ # Success.
+ # We can link with no special library directory.
+ bnv_qt_lib_dir=
+ ], [
+ # That did not work. Try the OpenGL version
+ echo "Non-critical error, please neglect the above." >&AC_FD_CC
+ bnv_qt_lib=qt-gl
+ LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ AC_TRY_LINK([#include <$qt_direct_test_header>],
+ $qt_direct_test_main,
+ [
+ # Succes.
+ # We can link with no special library directory.
+ bnv_qt_lib_dir=
+ ], [
+ # That did not work. Maybe a library version I don't know about?
+ echo "Non-critical error, please neglect the above." >&AC_FD_CC
+ # Look for some Qt lib in a standard set of common directories.
+ bnv_dir_list="
+ `echo $bnv_qt_includes | sed ss/includess`
+ /lib
+ /usr/lib
+ /usr/local/lib
+ /opt/lib
+ `ls -dr /usr/lib/qt* 2>/dev/null`
+ `ls -dr /usr/local/qt* 2>/dev/null`
+ `ls -dr /opt/qt* 2>/dev/null`
+ "
+ for bnv_dir in $bnv_dir_list; do
+ if ls $bnv_dir/libqt*; then
+ # Gamble that it's the first one...
+ bnv_qt_lib="`ls $bnv_dir/libqt* | sed -n 1p |
+ sed s@$bnv_dir/lib@@ | sed s/[.].*//`"
+ bnv_qt_lib_dir="$bnv_dir"
+ break
+ fi
+ done
+ # Try with that one
+ LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ AC_TRY_LINK([#include <$qt_direct_test_header>],
+ $qt_direct_test_main,
+ [
+ # Succes.
+ # We can link with no special library directory.
+ bnv_qt_lib_dir=
+ ], [
+ # Leave bnv_qt_lib_dir defined
+ ])
+ ])
+ ])
+ ])
+ if test x"$bnv_qt_lib_dir" != x; then
+ bnv_qt_LIBS="-l$bnv_qt_lib_dir $LIBS"
+ else
+ bnv_qt_LIBS="$LIBS"
+ fi
+ LIBS="$bnv_save_LIBS"
+ CXXFLAGS="$bnv_save_CXXFLAGS"
+ fi dnl $with_Qt_lib_dir was not given
+ fi dnl Done setting up for non-traditional Trolltech installation
+])
diff --git a/gssm/config/cppunit.m4 b/gssm/config/cppunit.m4
new file mode 100644
index 0000000..0991d51
--- /dev/null
+++ b/gssm/config/cppunit.m4
@@ -0,0 +1,80 @@
+dnl
+dnl AM_PATH_CPPUNIT(MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl
+AC_DEFUN([AM_PATH_CPPUNIT],
+[
+
+AC_ARG_WITH(cppunit-prefix,[ --with-cppunit-prefix=PFX Prefix where CppUnit is installed (optional)],
+ cppunit_config_prefix="$withval", cppunit_config_prefix="")
+AC_ARG_WITH(cppunit-exec-prefix,[ --with-cppunit-exec-prefix=PFX Exec prefix where CppUnit is installed (optional)],
+ cppunit_config_exec_prefix="$withval", cppunit_config_exec_prefix="")
+
+ if test x$cppunit_config_exec_prefix != x ; then
+ cppunit_config_args="$cppunit_config_args --exec-prefix=$cppunit_config_exec_prefix"
+ if test x${CPPUNIT_CONFIG+set} != xset ; then
+ CPPUNIT_CONFIG=$cppunit_config_exec_prefix/bin/cppunit-config
+ fi
+ fi
+ if test x$cppunit_config_prefix != x ; then
+ cppunit_config_args="$cppunit_config_args --prefix=$cppunit_config_prefix"
+ if test x${CPPUNIT_CONFIG+set} != xset ; then
+ CPPUNIT_CONFIG=$cppunit_config_prefix/bin/cppunit-config
+ fi
+ fi
+
+ AC_PATH_PROG(CPPUNIT_CONFIG, cppunit-config, no)
+ cppunit_version_min=$1
+
+ AC_MSG_CHECKING(for Cppunit - version >= $cppunit_version_min)
+ no_cppunit=""
+ if test "$CPPUNIT_CONFIG" = "no" ; then
+ no_cppunit=yes
+ else
+ CPPUNIT_CFLAGS=`$CPPUNIT_CONFIG --cflags`
+ CPPUNIT_LIBS=`$CPPUNIT_CONFIG --libs`
+ cppunit_version=`$CPPUNIT_CONFIG --version`
+
+ cppunit_major_version=`echo $cppunit_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ cppunit_minor_version=`echo $cppunit_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ cppunit_micro_version=`echo $cppunit_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+ cppunit_major_min=`echo $cppunit_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ cppunit_minor_min=`echo $cppunit_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ cppunit_micro_min=`echo $cppunit_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+ cppunit_version_proper=`expr \
+ $cppunit_major_version \> $cppunit_major_min \| \
+ $cppunit_major_version \= $cppunit_major_min \& \
+ $cppunit_minor_version \> $cppunit_minor_min \| \
+ $cppunit_major_version \= $cppunit_major_min \& \
+ $cppunit_minor_version \= $cppunit_minor_min \& \
+ $cppunit_micro_version \>= $cppunit_micro_min `
+
+ if test "$cppunit_version_proper" = "1" ; then
+ AC_MSG_RESULT([$cppunit_major_version.$cppunit_minor_version.$cppunit_micro_version])
+ else
+ AC_MSG_RESULT(no)
+ no_cppunit=yes
+ fi
+ fi
+
+ if test "x$no_cppunit" = x ; then
+ ifelse([$2], , :, [$2])
+ else
+ CPPUNIT_CFLAGS=""
+ CPPUNIT_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+
+ AC_SUBST(CPPUNIT_CFLAGS)
+ AC_SUBST(CPPUNIT_LIBS)
+])
+
+
+
diff --git a/gssm/config/gr_as.m4 b/gssm/config/gr_as.m4
new file mode 100644
index 0000000..a069547
--- /dev/null
+++ b/gssm/config/gr_as.m4
@@ -0,0 +1,34 @@
+# Figure out how to run the assembler. -*- Autoconf -*-
+
+# serial 2
+
+# Copyright 2001 Free Software Foundation, Inc.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# I just copy and renamed this from automake-1.6.3 so we should work
+# under both 1.4-p6 and later. -eb
+
+# GR_PROG_AS
+# ----------
+AC_DEFUN([GR_PROG_AS],
+[# By default we simply use the C compiler to build assembly code.
+AC_REQUIRE([AC_PROG_CC])
+: ${CCAS='$(CC)'}
+# Set ASFLAGS if not already set.
+: ${CCASFLAGS='$(CFLAGS)'}
+AC_SUBST(CCAS)
+AC_SUBST(CCASFLAGS)])
diff --git a/gssm/config/gr_boost.m4 b/gssm/config/gr_boost.m4
new file mode 100644
index 0000000..dc44219
--- /dev/null
+++ b/gssm/config/gr_boost.m4
@@ -0,0 +1,70 @@
+dnl
+dnl Copyright 2004 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+AC_DEFUN([GR_REQUIRE_BOOST_INCLUDES],
+[
+ AC_LANG_PUSH(C++)
+ gr_boost_include_dir=
+ AC_ARG_WITH([boost-include-dir],
+ AC_HELP_STRING([--with-boost-include-dir=<path>],
+ [path to boost c++ include files]),
+ [
+ # "yes" and "no" are bogus answers
+ if test x"$with_boost_include_dir" == xyes ||
+ test x"$with_boost_include_dir" == xno; then
+ gr_boost_include_dir=
+ else
+ gr_boost_include_dir=$with_boost_include_dir
+ fi
+ ])
+ echo "gr_boost_include_dir = $gr_boost_include_dir"
+ if test x$gr_boost_include_dir != x; then
+ # if user specified a directory, then we use it
+ OLD_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS -I$gr_boost_include_dir"
+ AC_CHECK_HEADER([boost/shared_ptr.hpp],
+ [BOOST_CFLAGS="-I$gr_boost_include_dir"],
+ [AC_MSG_ERROR(
+ [Failed to locate boost/shared_ptr.hpp.
+Try using --with-boost-include-dir=<path>])])
+ CPPFLAGS=$OLD_CPPFLAGS
+ else
+ # is the header in the default place?
+ AC_CHECK_HEADER([boost/shared_ptr.hpp],
+ [BOOST_CFLAGS=""],
+ [ # nope, look one more place
+ # wipe out cached value. KLUDGE: AC should have API for this
+ unset AS_TR_SH([ac_cv_header_boost/shared_ptr.hpp])
+ p=/usr/local/include/boost-1_31
+ OLD_CPPFLAGS=$CPP_FLAGS
+ CPPFLAGS="$CPPFLAGS -I$p"
+ AC_CHECK_HEADER([boost/shared_ptr.hpp],
+ [BOOST_CFLAGS="-I$p"],
+ [AC_MSG_ERROR(
+ [Failed to locate boost/shared_ptr.hpp.
+Try using --with-boost-include-dir=<path>])])
+ CPPFLAGS=$OLD_CPPFLAGS
+ ])
+
+ fi
+ AC_LANG_POP
+ AC_SUBST(BOOST_CFLAGS)
+])
diff --git a/gssm/config/gr_check_mc4020.m4 b/gssm/config/gr_check_mc4020.m4
new file mode 100644
index 0000000..0c4318e
--- /dev/null
+++ b/gssm/config/gr_check_mc4020.m4
@@ -0,0 +1,37 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+AC_DEFUN([GR_CHECK_MC4020],[
+ AC_MSG_CHECKING([for mc4020 A/D driver include file])
+ AC_COMPILE_IFELSE([
+#include <mc4020.h>
+int main (int argc, char **argv)
+{
+ return 0;
+}
+],[HAVE_MC4020=yes
+ AC_DEFINE(HAVE_MC4020,[1],[Define if you have a Measurement Computing PCI-DAS4020/12 A/D])],
+ [HAVE_MC4020=no])
+
+ AC_MSG_RESULT($HAVE_MC4020)
+ AM_CONDITIONAL(HAVE_MC4020, test x$HAVE_MC4020 = xyes)
+])
+
diff --git a/gssm/config/gr_check_shm_open.m4 b/gssm/config/gr_check_shm_open.m4
new file mode 100644
index 0000000..27c9ee6
--- /dev/null
+++ b/gssm/config/gr_check_shm_open.m4
@@ -0,0 +1,29 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+
+AC_DEFUN([GR_CHECK_SHM_OPEN],
+[
+ SHM_OPEN_LIBS=""
+ save_LIBS="$LIBS"
+ AC_SEARCH_LIBS([shm_open], [rt], [SHM_OPEN_LIBS="$LIBS"])
+ AC_CHECK_FUNCS([shm_open])
+ LIBS="$save_LIBS"
+ AC_SUBST(SHM_OPEN_LIBS)
+])
diff --git a/gssm/config/gr_check_usrp.m4 b/gssm/config/gr_check_usrp.m4
new file mode 100644
index 0000000..b818a69
--- /dev/null
+++ b/gssm/config/gr_check_usrp.m4
@@ -0,0 +1,32 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+dnl Check for Universal Software Radio Peripheral
+
+AC_DEFUN([GR_CHECK_USRP],[
+ PKG_CHECK_MODULES(USRP, usrp >= 0.2,
+ [HAVE_USRP=yes
+ AC_DEFINE(HAVE_USRP,[1],[Define if you have a USRP])],
+ [HAVE_USRP=no])
+
+ AM_CONDITIONAL(HAVE_USRP, test x$HAVE_USRP = xyes)
+])
+
diff --git a/gssm/config/gr_doxygen.m4 b/gssm/config/gr_doxygen.m4
new file mode 100644
index 0000000..b40b1ea
--- /dev/null
+++ b/gssm/config/gr_doxygen.m4
@@ -0,0 +1,56 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+AC_DEFUN([GR_CHECK_DOXYGEN],[
+ AC_ARG_ENABLE(doxygen, [ --enable-doxygen enable documentation generation with doxygen (auto)])
+ AC_ARG_ENABLE(dot, [ --enable-dot use 'dot' to generate graphs in doxygen (auto)])
+ AC_ARG_ENABLE(html-docs, [ --enable-html-docs enable HTML generation with doxygen (yes)], [], [ enable_html_docs=yes])
+ AC_ARG_ENABLE(latex-docs, [ --enable-latex-docs enable LaTeX doc generation with doxygen (no)], [], [ enable_latex_docs=no])
+
+ if test "x$enable_doxygen" = xno; then
+ enable_doc=no
+ else
+ AC_PATH_PROG(DOXYGEN, doxygen, , $PATH)
+ if test x$DOXYGEN = x; then
+ if test "x$enable_doxygen" = xyes; then
+ AC_MSG_ERROR([could not find doxygen])
+ fi
+ enable_doc=no
+ else
+ enable_doc=yes
+ AC_PATH_PROG(DOT, dot, , $PATH)
+ fi
+ fi
+
+ AM_CONDITIONAL(DOC, test x$enable_doc = xyes)
+
+ if test x$DOT = x; then
+ if test "x$enable_dot" = xyes; then
+ AC_MSG_ERROR([could not find dot])
+ fi
+ enable_dot=no
+ else
+ enable_dot=yes
+ fi
+ AC_SUBST(enable_dot)
+ AC_SUBST(enable_html_docs)
+ AC_SUBST(enable_latex_docs)
+])
diff --git a/gssm/config/gr_gprof.m4 b/gssm/config/gr_gprof.m4
new file mode 100644
index 0000000..cc50508
--- /dev/null
+++ b/gssm/config/gr_gprof.m4
@@ -0,0 +1,72 @@
+dnl
+dnl Copyright 2002 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+dnl FIXME probably need to add linker flag too...
+
+AC_DEFUN([GR_SET_GPROF],[
+ dnl Check for --with-gprof
+ AC_MSG_CHECKING([whether user wants gprof])
+ AC_ARG_WITH(gprof,
+ [ --with-gprof Turn on gprof profiling],
+ [], [ with_gprof=no ])
+ AC_MSG_RESULT($with_gprof)
+
+ dnl gprof profiling flags for the two main compilers
+ cc_profiling_flags="-pg"
+ cxx_profiling_flags="-pg"
+ ld_profiling_flags="-pg"
+ if test $with_gprof = yes
+ then
+ if test -n "${CC}"
+ then
+ LF_CHECK_CC_FLAG($cc_profiling_flags)
+ fi
+ if test -n "${CXX}"
+ then
+ LF_CHECK_CXX_FLAG($cxx_profiling_flags)
+ fi
+ fi
+])
+
+AC_DEFUN([GR_SET_PROF],[
+ dnl Check for --with-prof
+ AC_MSG_CHECKING([whether user wants prof])
+ AC_ARG_WITH(prof,
+ [ --with-prof Turn on prof profiling],
+ [], [ with_prof=no ])
+ AC_MSG_RESULT($with_prof)
+
+ dnl prof profiling flags for the two main compilers
+ cc_profiling_flags="-p"
+ cxx_profiling_flags="-p"
+ ld_profiling_flags="-p"
+ if test $with_prof = yes
+ then
+ if test -n "${CC}"
+ then
+ LF_CHECK_CC_FLAG($cc_profiling_flags)
+ fi
+ if test -n "${CXX}"
+ then
+ LF_CHECK_CXX_FLAG($cxx_profiling_flags)
+ fi
+ fi
+])
diff --git a/gssm/config/gr_omnithread.m4 b/gssm/config/gr_omnithread.m4
new file mode 100644
index 0000000..7c3150b
--- /dev/null
+++ b/gssm/config/gr_omnithread.m4
@@ -0,0 +1,51 @@
+# Check for Omnithread (pthread/NT) thread support. -*- Autoconf -*-
+
+# Copyright 2003 Free Software Foundation, Inc.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+AC_DEFUN([GR_OMNITHREAD],
+[
+ # Check first for POSIX
+ ACX_PTHREAD(
+ [ ot_posix="yes"
+ AC_DEFINE(OMNITHREAD_POSIX,[1],[Define to 1 to enable pthread])
+ ],[
+ # If no POSIX support found, then check for NT threads
+ AC_MSG_CHECKING([for NT threads])
+
+ AC_LINK_IFELSE([
+ #include <windows.h>
+ #include <winbase.h>
+ int main() { InitializeCriticalSection(NULL); return 0; }
+ ],
+ [
+ ot_nt="yes"
+ AC_DEFINE(OMNITHREAD_NT,[1],[Define to 1 to enable NT thread])
+ ],
+ [AC_MSG_FAILURE([GNU Radio requires POSIX threads. pthreads not found.])]
+ )
+ AC_MSG_RESULT(yes)
+ ])
+ AM_CONDITIONAL(OMNITHREAD_POSIX, test "x$ot_posix" = xyes)
+ AM_CONDITIONAL(OMNITHREAD_NT, test "x$ot_nt" = xyes)
+
+ save_LIBS="$LIBS"
+ AC_SEARCH_LIBS([clock_gettime], [rt], [PTHREAD_LIBS="$PTHREAD_LIBS $LIBS"])
+ AC_CHECK_FUNCS([clock_gettime gettimeofday nanosleep])
+ LIBS="$save_LIBS"
+])
+
diff --git a/gssm/config/gr_pwin32.m4 b/gssm/config/gr_pwin32.m4
new file mode 100644
index 0000000..5f748af
--- /dev/null
+++ b/gssm/config/gr_pwin32.m4
@@ -0,0 +1,146 @@
+# Check for (mingw)win32 POSIX replacements. -*- Autoconf -*-
+
+# Copyright 2003,2004,2005 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+
+AC_DEFUN([GR_PWIN32],
+[
+AC_REQUIRE([AC_HEADER_TIME])
+AC_CHECK_HEADERS([sys/types.h fcntl.h io.h])
+AC_CHECK_HEADERS([windows.h])
+AC_CHECK_HEADERS([winioctl.h winbase.h], [], [], [
+ #if HAVE_WINDOWS_H
+ #include <windows.h>
+ #endif
+])
+
+AC_CHECK_FUNCS([getopt usleep gettimeofday nanosleep rand srand random srandom sleep sigaction])
+AC_CHECK_TYPES([struct timezone, struct timespec, ssize_t],[],[],[
+ #if HAVE_SYS_TYPES_H
+ # include <sys/types.h>
+ #endif
+ #if TIME_WITH_SYS_TIME
+ # include <sys/time.h>
+ # include <time.h>
+ #else
+ # if HAVE_SYS_TIME_H
+ # include <sys/time.h>
+ # else
+ # include <time.h>
+ # endif
+ #endif
+])
+
+dnl Checks for replacements
+AC_REPLACE_FUNCS([getopt usleep gettimeofday])
+
+
+AC_MSG_CHECKING(for Sleep)
+AC_TRY_LINK([ #include <windows.h>
+ #include <winbase.h>
+ ], [ Sleep(0); ],
+ [AC_DEFINE(HAVE_SSLEEP,1,[Define to 1 if you have win32 Sleep])
+ AC_MSG_RESULT(yes)],
+ AC_MSG_RESULT(no)
+ )
+
+dnl Under Win32, mkdir prototype in io.h has only one arg
+AC_MSG_CHECKING(whether mkdir accepts only one arg)
+AC_TRY_COMPILE([#include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>], [
+ mkdir("")
+ ], [ AC_MSG_RESULT(yes)
+ AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ],
+ [ AC_MSG_RESULT(no)
+ ])
+
+AH_BOTTOM(
+[
+/* Define missing prototypes, implemented in replacement lib */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef HAVE_GETOPT
+int getopt (int argc, char * const argv[], const char * optstring);
+extern char * optarg;
+extern int optind, opterr, optopt;
+#endif
+
+#ifndef HAVE_USLEEP
+int usleep(unsigned long usec); /* SUSv2 */
+#endif
+
+#ifndef HAVE_NANOSLEEP
+#ifndef HAVE_STRUCT_TIMESPEC
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h> /* need time_t */
+#endif
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#endif
+static inline int nanosleep(const struct timespec *req, struct timespec *rem) { return usleep(req->tv_sec*1000000+req->tv_nsec/1000); }
+#endif
+
+#if defined(HAVE_SSLEEP) && !defined(HAVE_SLEEP)
+#ifdef HAVE_WINBASE_H
+#include <windows.h>
+#include <winbase.h>
+#endif
+/* TODO: what about SleepEx? */
+static inline unsigned int sleep (unsigned int nb_sec) { Sleep(nb_sec*1000); return 0; }
+#endif
+
+#ifndef HAVE_GETTIMEOFDAY
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifndef HAVE_STRUCT_TIMEZONE
+struct timezone {
+ int tz_minuteswest;
+ int tz_dsttime;
+};
+#endif
+int gettimeofday(struct timeval *tv, struct timezone *tz);
+#endif
+
+#if !defined(HAVE_RANDOM) && defined(HAVE_RAND)
+#include <stdlib.h>
+static inline long int random (void) { return rand(); }
+#endif
+
+#if !defined(HAVE_SRANDOM) && defined(HAVE_SRAND)
+static inline void srandom (unsigned int seed) { srand(seed); }
+#endif
+
+#ifndef HAVE_SSIZE_T
+typedef size_t ssize_t;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+])
+
+
+])
diff --git a/gssm/config/gr_python.m4 b/gssm/config/gr_python.m4
new file mode 100644
index 0000000..957d557
--- /dev/null
+++ b/gssm/config/gr_python.m4
@@ -0,0 +1,104 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+# PYTHON_DEVEL()
+#
+# Checks for Python and tries to get the include path to 'Python.h'.
+# It provides the $(PYTHON_CPPFLAGS) output variable.
+AC_DEFUN([PYTHON_DEVEL],[
+ AC_REQUIRE([AM_PATH_PYTHON])
+
+ # Check for Python include path
+ AC_MSG_CHECKING([for Python include path])
+ if test -z "$PYTHON" ; then
+ AC_MSG_ERROR([cannot find Python path])
+ fi
+
+ python_path=${PYTHON%/bin*}
+ for i in "$python_path/include/python$PYTHON_VERSION/" "$python_path/include/python/" "$python_path/" ; do
+ python_path=`find $i -type f -name Python.h -print`
+ if test -n "$python_path" ; then
+ break
+ fi
+ done
+ for i in $python_path ; do
+ python_path=${python_path%/Python.h}
+ break
+ done
+ AC_MSG_RESULT([$python_path])
+ if test -z "$python_path" ; then
+ AC_MSG_ERROR([cannot find Python include path])
+ fi
+
+ AC_SUBST(PYTHON_CPPFLAGS,[-I$python_path])
+
+ # Check for Python headers usability
+ python_save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
+ AC_CHECK_HEADERS([Python.h], [],
+ [AC_MSG_ERROR([cannot find usable Python headers])])
+ CPPFLAGS="$python_save_CPPFLAGS"
+
+ # Check for Python library path
+ AC_MSG_CHECKING([for Python library path])
+ python_path=`echo $PYTHON | sed "s,/bin.*$,,"`
+ for i in "$python_path/lib/python$PYTHON_VERSION/config/" "$python_path/lib/python$PYTHON_VERSION/" "$python_path/lib/python/config/" "$python_path/lib/python/" "$python_path/" "$python_path/libs" ; do
+ python_path=`find $i -type f -name libpython$PYTHON_VERSION.* -print | sed "1q"`
+ if test -n "$python_path" ; then
+ break
+ fi
+ done
+ python_path=`echo $python_path | sed "s,/libpython.*$,,"`
+ if test -z "$python_path" ; then
+ AC_MSG_WARN(cannot find Python library path)
+ fi
+ AC_MSG_RESULT([$python_path])
+
+ AC_SUBST([PYTHON_LDFLAGS],["-L$python_path -lpython$PYTHON_VERSION"])
+ #
+ python_site=`echo $python_path | sed "s/config/site-packages/"`
+ AC_SUBST([PYTHON_SITE_PKG],[$python_site])
+ #
+ # libraries which must be linked in when embedding
+ #
+ AC_MSG_CHECKING(python extra libraries)
+ PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
+ conf = distutils.sysconfig.get_config_var; \
+ print conf('LOCALMODLIBS')+' '+conf('LIBS')"
+ AC_MSG_RESULT($PYTHON_EXTRA_LIBS)`
+ AC_SUBST(PYTHON_EXTRA_LIBS)
+
+
+ # Check for Python library usability
+ python_save_LIBS=$LIBS
+ python_save_CPPFLAGS=$CPPFLAGS
+ LIBS="$LIBS $PYTHON_LDFLAGS $PYTHON_EXTRA_LIBS"
+ CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
+
+ AC_MSG_CHECKING(Python headers and library usability)
+ AC_TRY_LINK([ #include <Python.h> ], [ PyArg_Parse(NULL, NULL); ],
+ [AC_MSG_RESULT(yes)],
+ [AC_MSG_WARN(no dev lib, crossing fingers)
+ AC_SUBST([PYTHON_LDFLAGS],[""])])
+
+ CPPFLAGS="$python_save_CPPFLAGS"
+ LIBS="$python_save_LIBS"
+])
diff --git a/gssm/config/gr_scripting.m4 b/gssm/config/gr_scripting.m4
new file mode 100644
index 0000000..7f3abde
--- /dev/null
+++ b/gssm/config/gr_scripting.m4
@@ -0,0 +1,30 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+AC_DEFUN([GR_SCRIPTING],[
+ AC_REQUIRE([AC_PROG_LN_S])
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([AC_PROG_LIBTOOL])
+
+ SWIG_PROG(1.3.23)
+ SWIG_ENABLE_CXX
+ SWIG_PYTHON
+])
diff --git a/gssm/config/gr_set_md_cpu.m4 b/gssm/config/gr_set_md_cpu.m4
new file mode 100644
index 0000000..e53eeaf
--- /dev/null
+++ b/gssm/config/gr_set_md_cpu.m4
@@ -0,0 +1,41 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+AC_DEFUN([GR_SET_MD_CPU],[
+ AC_REQUIRE([AC_CANONICAL_TARGET])
+ AC_ARG_WITH(md-cpu,
+ [ --with-md-cpu=ARCH set machine dependent speedups (auto)],
+ [cf_with_md_cpu="$withval"],
+ [cf_with_md_cpu="$target_cpu"])
+
+ AC_MSG_CHECKING([for machine dependent speedups])
+ case "$cf_with_md_cpu" in
+ x86 | i[[3-7]]86) MD_CPU=x86 ;;
+# sparc) MD_CPU=sparc ;;
+ *) MD_CPU=generic ;;
+ esac
+ AC_MSG_RESULT($MD_CPU)
+ AC_SUBST(MD_CPU)
+
+ AM_CONDITIONAL(MD_CPU_x86, test $MD_CPU = x86)
+ AM_CONDITIONAL(MD_CPU_generic, test $MD_CPU = generic)
+])
+
diff --git a/gssm/config/gr_swig.m4 b/gssm/config/gr_swig.m4
new file mode 100644
index 0000000..a587c6d
--- /dev/null
+++ b/gssm/config/gr_swig.m4
@@ -0,0 +1,85 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+# SWIG_PROG([required-version])
+#
+# Checks for the SWIG program. If found you can (and should) call SWIG via $(SWIG).
+# You can use the optional first argument to check if the version of the available SWIG
+# is greater or equal to the value of the argument. It should have the format:
+# N[.N[.N]] (N is a number between 0 and 999. Only the first N is mandatory.)
+AC_DEFUN([SWIG_PROG],[
+ AC_REQUIRE([AC_PROG_MAKE_SET])
+ AC_CHECK_PROG(SWIG,swig,[`which swig`])
+ if test -z "$SWIG" ; then
+ AC_MSG_ERROR([Cannot find 'swig' program. SWIG version >= $1 required])
+ SWIG=false
+ elif test -n "$1" ; then
+ AC_MSG_CHECKING([for SWIG version])
+ swig_version=`$SWIG -version 2>&1 | \
+ awk '/^SWIG Version [[0-9]+\.[0-9]+\.[0-9]]+.*$/ { split($[3],a,"[[^.0-9]]"); print a[[1]] }'`
+ AC_MSG_RESULT([$swig_version])
+ if test -n "$swig_version" ; then
+ swig_version=`echo $swig_version | \
+ awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null`
+ swig_required_version=`echo $1 | \
+ awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null`
+ if test $swig_required_version -gt $swig_version ; then
+ AC_MSG_ERROR([SWIG version >= $1 required])
+ fi
+ else
+ AC_MSG_ERROR([cannot determine SWIG version])
+ fi
+ fi
+])
+
+# SWIG_ENABLE_CXX()
+#
+# Enable swig C++ support. This effects all invocations of $(SWIG).
+AC_DEFUN([SWIG_ENABLE_CXX],[
+ AC_REQUIRE([SWIG_PROG])
+ AC_REQUIRE([AC_PROG_CXX])
+ if test "$SWIG" != "false" ; then
+ SWIG="$SWIG -c++"
+ fi
+])
+
+# SWIG_PYTHON([use-shadow-classes])
+#
+# Checks for Python and provides the $(SWIG_PYTHON_CPPFLAGS),
+# $(SWIG_PYTHON_LIB) and $(SWIG_PYTHON_OPT) output variables.
+# $(SWIG_PYTHON_OPT) contains all necessary swig options to generate
+# code for Python. If you need multi module support use
+# $(SWIG_PYTHON_LIB) (provided by the SWIG_MULTI_MODULE_SUPPORT()
+# macro) to link against the appropriate library. It contains the
+# SWIG Python runtime library that is needed by the type check system
+# for example.
+
+AC_DEFUN([SWIG_PYTHON],[
+ AC_REQUIRE([SWIG_PROG])
+ AC_REQUIRE([PYTHON_DEVEL])
+ if test "$SWIG" != "false" ; then
+ AC_SUBST(SWIG_PYTHON_LIB,[-lswigpy])
+dnl test ! "x$1" = "xno" && swig_shadow=" -shadow" || swig_shadow=""
+dnl AC_SUBST(SWIG_PYTHON_OPT,[-python$swig_shadow])
+ AC_SUBST(SWIG_PYTHON_OPT,[-python])
+ fi
+ AC_SUBST(SWIG_PYTHON_CPPFLAGS,[$PYTHON_CPPFLAGS])
+])
diff --git a/gssm/config/gr_sysv_shm.m4 b/gssm/config/gr_sysv_shm.m4
new file mode 100644
index 0000000..5e11e49
--- /dev/null
+++ b/gssm/config/gr_sysv_shm.m4
@@ -0,0 +1,36 @@
+# Check for IPC System V shm support. -*- Autoconf -*-
+
+# Copyright 2003 Free Software Foundation, Inc.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+AC_DEFUN([GR_SYSV_SHM],
+[
+ AC_LANG_SAVE
+ AC_LANG_C
+
+ AC_CHECK_HEADERS([sys/ipc.h sys/shm.h])
+
+ save_LIBS="$LIBS"
+ AC_SEARCH_LIBS(shmat, [cygipc ipc],
+ [ IPC_LIBS="$LIBS" ],
+ [ AC_MSG_WARN([SystemV IPC support not found. ]) ]
+ )
+ LIBS="$save_LIBS"
+
+ AC_LANG_RESTORE
+ AC_SUBST(IPC_LIBS)
+])
diff --git a/gssm/config/lf_cc.m4 b/gssm/config/lf_cc.m4
new file mode 100644
index 0000000..f9bd715
--- /dev/null
+++ b/gssm/config/lf_cc.m4
@@ -0,0 +1,42 @@
+dnl Autoconf support for C++
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+# -------------------------------------------------------------------------
+# Use this macro to configure your C compiler
+# When called the macro does the following things:
+# 1. It finds an appropriate C compiler.
+# If you passed the flag --with-cc=foo then it uses that
+# particular compiler
+# 2. Check whether the compiler works.
+# 3. Checks whether the compiler accepts the -g
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CONFIGURE_CC],[
+ dnl Sing the song
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_PROG_CPP])dnl
+ AC_REQUIRE([AC_AIX])dnl
+ AC_REQUIRE([AC_ISC_POSIX])dnl
+ AC_REQUIRE([AC_MINIX])dnl
+ AC_REQUIRE([AC_HEADER_STDC])dnl
+])
+
diff --git a/gssm/config/lf_cxx.m4 b/gssm/config/lf_cxx.m4
new file mode 100644
index 0000000..8ade1fb
--- /dev/null
+++ b/gssm/config/lf_cxx.m4
@@ -0,0 +1,121 @@
+dnl Autoconf support for C++
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+# -----------------------------------------------------------------
+# This macro should be called to configure your C++ compiler.
+# When called, the macro does the following things:
+# 1. It finds an appropriate C++ compiler
+# If you passed the flag --with-cxx=foo, then it uses that
+# particular compiler
+# 2. Checks whether the compiler accepts the -g
+# ------------------------------------------------------------------
+
+AC_DEFUN([LF_CONFIGURE_CXX],[
+ AC_REQUIRE([AC_PROG_CXX])dnl
+ AC_REQUIRE([AC_PROG_CXXCPP])dnl
+ LF_CXX_PORTABILITY
+])
+
+# -----------------------------------------------------------------------
+# This macro tests the C++ compiler for various portability problem.
+# 1. Defines CXX_HAS_NO_BOOL if the compiler does not support the bool
+# data type
+# 2. Defines CXX_HAS_BUGGY_FOR_LOOPS if the compiler has buggy
+# scoping for the for-loop
+# 3. Defines USE_ASSERT if the user wants to use assertions
+# -----------------------------------------------------------------------
+
+
+AC_DEFUN([LF_CXX_PORTABILITY],[
+
+ dnl
+ dnl Check for common C++ portability problems
+ dnl
+
+ dnl AC_LANG_PUSH
+ dnl AC_LANG_CPLUSPLUS
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+
+ dnl Check whether we have bool
+ AC_MSG_CHECKING(whether C++ has bool)
+ AC_TRY_RUN([main() { bool b1=true; bool b2=false; }],
+ [ AC_MSG_RESULT(yes) ],
+ [ AC_MSG_RESULT(no)
+ AC_DEFINE(CXX_HAS_NO_BOOL,[],[Define if C++ is missing bool type]) ],
+ [ AC_MSG_WARN(Don't cross-compile)]
+ )
+
+ dnl Test whether C++ has buggy for-loops
+ AC_MSG_CHECKING(whether C++ has buggy scoping in for-loops)
+ AC_TRY_COMPILE([#include <iostream.h>], [
+ for (int i=0;i<10;i++) { }
+ for (int i=0;i<10;i++) { }
+], [ AC_MSG_RESULT(no) ],
+ [ AC_MSG_RESULT(yes)
+ AC_DEFINE(CXX_HAS_BUGGY_FOR_LOOPS,[],[Define if for loop scoping is broken]) ])
+
+ dnl Test whether the user wants to enable assertions
+ AC_MSG_CHECKING(whether user wants assertions)
+ AC_ARG_ENABLE(assert,
+ [ --disable-assert don't use cpp.h assert],
+ [ AC_DEFINE(NDEBUG,[],[Define to disable asserts (don't doit!)])
+ AC_MSG_RESULT(no) ],
+ [ AC_MSG_RESULT(yes) ],
+ )
+
+ dnl Test whether C++ has std::isnan
+ AC_MSG_CHECKING(whether C++ has std::isnan)
+ AC_TRY_COMPILE([#include <math.h>], [
+ std::isnan(0);
+], [ AC_MSG_RESULT(yes)
+ AC_DEFINE(CXX_HAS_STD_ISNAN,[],[Define if has std::isnan]) ],
+ [ AC_MSG_RESULT(no) ])
+
+ dnl Done with the portability checks
+ dnl AC_LANG_POP([C++])
+ AC_LANG_RESTORE
+])
+
+AH_BOTTOM([// Workaround for compilers with buggy for-loop scoping
+// That's quite a few compilers actually including recent versions of
+// Dec Alpha cxx, HP-UX CC and SGI CC.
+// The trivial "if" statement provides the correct scoping to the
+// for loop
+
+#ifdef CXX_HAS_BUGGY_FOR_LOOPS
+#undef for
+#define for if(1) for
+#endif
+])
+
+AH_BOTTOM([// If the C++ compiler we use doesn't have bool, then
+// the following is a near-perfect work-around.
+// You must make sure your code does not depend on "int" and "bool"
+// being two different types, in overloading for instance.
+
+#ifdef CXX_HAS_NO_BOOL
+#define bool int
+#define true 1
+#define false 0
+#endif
+])
diff --git a/gssm/config/lf_warnings.m4 b/gssm/config/lf_warnings.m4
new file mode 100644
index 0000000..0ebb97e
--- /dev/null
+++ b/gssm/config/lf_warnings.m4
@@ -0,0 +1,128 @@
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+# --------------------------------------------------------------------------
+# Check whether the C++ compiler accepts a certain flag
+# If it does it adds the flag to CXXFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# LF_CHECK_CXX_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CHECK_CXX_FLAG],[
+ echo 'void f(){}' > conftest.cc
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $CXX accepts $i])
+ if test -z "`${CXX} $i -c conftest.cc 2>&1`"
+ then
+ CXXFLAGS="${CXXFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.cc conftest.o
+])
+
+# --------------------------------------------------------------------------
+# Check whether the C compiler accepts a certain flag
+# If it does it adds the flag to CFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# LF_CHECK_CC_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CHECK_CC_FLAG],[
+ echo 'void f(){}' > conftest.c
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $CC accepts $i])
+ if test -z "`${CC} $i -c conftest.c 2>&1`"
+ then
+ CFLAGS="${CFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.c conftest.o
+])
+
+# --------------------------------------------------------------------------
+# Check whether the Fortran compiler accepts a certain flag
+# If it does it adds the flag to FFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# LF_CHECK_F77_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CHECK_F77_FLAG],[
+ cat << EOF > conftest.f
+c....:++++++++++++++++++++++++
+ PROGRAM MAIN
+ PRINT*,'Hello World!'
+ END
+EOF
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $F77 accepts $i])
+ if test -z "`${F77} $i -c conftest.f 2>&1`"
+ then
+ FFLAGS="${FFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.f conftest.o
+])
+
+# ----------------------------------------------------------------------
+# Provide the configure script with an --with-warnings option that
+# turns on warnings. Call this command AFTER you have configured ALL your
+# compilers.
+# ----------------------------------------------------------------------
+
+AC_DEFUN([LF_SET_WARNINGS],[
+ dnl Check for --with-warnings
+ AC_MSG_CHECKING([whether user wants warnings])
+ AC_ARG_WITH(warnings,
+ [ --with-warnings Turn on warnings],
+ [ lf_warnings=yes ], [ lf_warnings=no ])
+ lf_warnings=yes # hard code for now -eb
+ AC_MSG_RESULT($lf_warnings)
+
+ dnl Warnings for the two main compilers
+ cc_warning_flags="-Wall"
+ cxx_warning_flags="-Wall -Woverloaded-virtual"
+ if test $lf_warnings = yes
+ then
+ if test -n "${CC}"
+ then
+ LF_CHECK_CC_FLAG($cc_warning_flags)
+ fi
+ if test -n "${CXX}"
+ then
+ LF_CHECK_CXX_FLAG($cxx_warning_flags)
+ fi
+ fi
+])
diff --git a/gssm/config/lf_x11.m4 b/gssm/config/lf_x11.m4
new file mode 100644
index 0000000..3bd19f2
--- /dev/null
+++ b/gssm/config/lf_x11.m4
@@ -0,0 +1,39 @@
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+
+#-----------------------------------------------------------------------
+# This macro searches for Xlib and when it finds it it adds the
+# appropriate flags to CXXFLAGS and export the link sequence to
+# the variable XLIB.
+# In your configure.in file add:
+# LF_PATH_XLIB
+# In your Makefile.am add
+# program_LDADD = .... $(XLIB)
+#------------------------------------------------------------------------
+
+AC_DEFUN([LF_PATH_XLIB],[
+ AC_PATH_XTRA
+ CXXFLAGS="$CXXFLAGS $X_CFLAGS"
+ XLIB="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
+ AC_SUBST(XLIB)
+])
+
diff --git a/gssm/config/mkstemp.m4 b/gssm/config/mkstemp.m4
new file mode 100644
index 0000000..4af0f0a
--- /dev/null
+++ b/gssm/config/mkstemp.m4
@@ -0,0 +1,89 @@
+#serial 4
+
+# On some hosts (e.g., HP-UX 10.20, SunOS 4.1.4, Solaris 2.5.1), mkstemp has a
+# silly limit that it can create no more than 26 files from a given template.
+# Other systems lack mkstemp altogether.
+# On OSF1/Tru64 V4.0F, the system-provided mkstemp function can create
+# only 32 files per process.
+# On systems like the above, arrange to use the replacement function.
+AC_DEFUN([UTILS_FUNC_MKSTEMP],
+[dnl
+ AC_REPLACE_FUNCS(mkstemp)
+ if test $ac_cv_func_mkstemp = no; then
+ utils_cv_func_mkstemp_limitations=yes
+ else
+ AC_CACHE_CHECK([for mkstemp limitations],
+ utils_cv_func_mkstemp_limitations,
+ [
+ AC_TRY_RUN([
+# include <stdlib.h>
+ int main ()
+ {
+ int i;
+ for (i = 0; i < 70; i++)
+ {
+ char template[] = "conftestXXXXXX";
+ int fd = mkstemp (template);
+ if (fd == -1)
+ exit (1);
+ close (fd);
+ }
+ exit (0);
+ }
+ ],
+ utils_cv_func_mkstemp_limitations=no,
+ utils_cv_func_mkstemp_limitations=yes,
+ utils_cv_func_mkstemp_limitations=yes
+ )
+ ]
+ )
+ fi
+
+ if test $utils_cv_func_mkstemp_limitations = yes; then
+ AC_LIBOBJ(mkstemp)
+ AC_LIBOBJ(tempname)
+ AC_DEFINE(mkstemp, rpl_mkstemp,
+ [Define to rpl_mkstemp if the replacement function should be used.])
+ gl_PREREQ_MKSTEMP
+ jm_PREREQ_TEMPNAME
+ fi
+])
+
+# Prerequisites of lib/mkstemp.c.
+AC_DEFUN([gl_PREREQ_MKSTEMP],
+[
+ AH_BOTTOM(
+ [
+ #ifndef HAVE_MKSTEMP
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ int rpl_mkstemp (char *templ);
+ #ifdef __cplusplus
+ }
+ #endif
+ #endif
+ ])
+])
+
+# Prerequisites of lib/tempname.c.
+AC_DEFUN([jm_PREREQ_TEMPNAME],
+[
+ AC_REQUIRE([AC_HEADER_STAT])
+ AC_CHECK_HEADERS_ONCE(fcntl.h sys/time.h unistd.h)
+ AC_CHECK_HEADERS(stdint.h)
+ AC_CHECK_FUNCS(__secure_getenv gettimeofday lstat)
+ AC_CHECK_DECLS_ONCE(getenv)
+ # AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])
+
+ dnl Under Win32, mkdir prototype in io.h has only one arg
+ AC_MSG_CHECKING(whether mkdir accepts only one arg)
+ AC_TRY_COMPILE([#include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>], [
+ mkdir("")
+ ], [ AC_MSG_RESULT(yes)
+ AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ],
+ [ AC_MSG_RESULT(no)
+ ])
+])
diff --git a/gssm/config/onceonly.m4 b/gssm/config/onceonly.m4
new file mode 100644
index 0000000..f6fec37
--- /dev/null
+++ b/gssm/config/onceonly.m4
@@ -0,0 +1,63 @@
+# onceonly.m4 serial 3
+dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl This file defines some "once only" variants of standard autoconf macros.
+dnl AC_CHECK_HEADERS_ONCE like AC_CHECK_HEADERS
+dnl AC_CHECK_FUNCS_ONCE like AC_CHECK_FUNCS
+dnl AC_CHECK_DECLS_ONCE like AC_CHECK_DECLS
+dnl AC_REQUIRE([AC_HEADER_STDC]) like AC_HEADER_STDC
+dnl The advantage is that the check for each of the headers/functions/decls
+dnl will be put only once into the 'configure' file. It keeps the size of
+dnl the 'configure' file down, and avoids redundant output when 'configure'
+dnl is run.
+dnl The drawback is that the checks cannot be conditionalized. If you write
+dnl if some_condition; then gl_CHECK_HEADERS(stdlib.h); fi
+dnl inside an AC_DEFUNed function, the gl_CHECK_HEADERS macro call expands to
+dnl empty, and the check will be inserted before the body of the AC_DEFUNed
+dnl function.
+
+dnl Autoconf version 2.57 or newer is recommended.
+AC_PREREQ(2.54)
+
+# AC_CHECK_HEADERS_ONCE(HEADER1 HEADER2 ...) is a once-only variant of
+# AC_CHECK_HEADERS(HEADER1 HEADER2 ...).
+AC_DEFUN([AC_CHECK_HEADERS_ONCE], [
+ :
+ AC_FOREACH([gl_HEADER_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(defn([gl_HEADER_NAME]),
+ [-./], [___])), [
+ AC_CHECK_HEADERS(gl_HEADER_NAME)
+ ])
+ AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME,
+ [-./], [___])))
+ ])
+])
+
+# AC_CHECK_FUNCS_ONCE(FUNC1 FUNC2 ...) is a once-only variant of
+# AC_CHECK_FUNCS(FUNC1 FUNC2 ...).
+AC_DEFUN([AC_CHECK_FUNCS_ONCE], [
+ :
+ AC_FOREACH([gl_FUNC_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_FUNC_]defn([gl_FUNC_NAME]), [
+ AC_CHECK_FUNCS(defn([gl_FUNC_NAME]))
+ ])
+ AC_REQUIRE([gl_CHECK_FUNC_]defn([gl_FUNC_NAME]))
+ ])
+])
+
+# AC_CHECK_DECLS_ONCE(DECL1 DECL2 ...) is a once-only variant of
+# AC_CHECK_DECLS(DECL1, DECL2, ...).
+AC_DEFUN([AC_CHECK_DECLS_ONCE], [
+ :
+ AC_FOREACH([gl_DECL_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_DECL_]defn([gl_DECL_NAME]), [
+ AC_CHECK_DECLS(defn([gl_DECL_NAME]))
+ ])
+ AC_REQUIRE([gl_CHECK_DECL_]defn([gl_DECL_NAME]))
+ ])
+])
diff --git a/gssm/config/pkg.m4 b/gssm/config/pkg.m4
new file mode 100644
index 0000000..770f062
--- /dev/null
+++ b/gssm/config/pkg.m4
@@ -0,0 +1,68 @@
+dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
+dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
+dnl also defines GSTUFF_PKG_ERRORS on error
+AC_DEFUN([PKG_CHECK_MODULES], [
+ succeeded=no
+
+ if test -z "$PKG_CONFIG"; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ fi
+
+ if test "$PKG_CONFIG" = "no" ; then
+ echo "*** The pkg-config script could not be found. Make sure it is"
+ echo "*** in your path, or set the PKG_CONFIG environment variable"
+ echo "*** to the full path to pkg-config."
+ echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
+ else
+ dnl If PKG_CONFIG_PATH is not already set, add /usr/local/lib/pkgconfig.
+ dnl If it's set, assume the user knows what they're doing.
+ dnl This should help avoid failures while looking for fftw3f
+ if test -z "$PKG_CONFIG_PATH"; then
+ export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig"
+ fi
+
+ PKG_CONFIG_MIN_VERSION=0.9.0
+ if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
+ AC_MSG_CHECKING(for $2)
+
+ if $PKG_CONFIG --exists "$2" ; then
+ AC_MSG_RESULT(yes)
+ succeeded=yes
+
+ AC_MSG_CHECKING($1_CFLAGS)
+ $1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
+ AC_MSG_RESULT($$1_CFLAGS)
+
+ AC_MSG_CHECKING($1_LIBS)
+ $1_LIBS=`$PKG_CONFIG --libs "$2"`
+ AC_MSG_RESULT($$1_LIBS)
+
+ AC_MSG_CHECKING($1_INCLUDEDIR)
+ $1_INCLUDEDIR=`$PKG_CONFIG --variable=includedir "$2"`
+ AC_MSG_RESULT($$1_INCLUDEDIR)
+ else
+ $1_CFLAGS=""
+ $1_LIBS=""
+ ## If we have a custom action on failure, don't print errors, but
+ ## do set a variable so people can do so.
+ $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ ifelse([$4], ,echo $$1_PKG_ERRORS,)
+ fi
+
+ AC_SUBST($1_CFLAGS)
+ AC_SUBST($1_LIBS)
+ AC_SUBST($1_INCLUDEDIR)
+ else
+ echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
+ echo "*** See http://www.freedesktop.org/software/pkgconfig"
+ fi
+ fi
+
+ if test $succeeded = yes; then
+ ifelse([$3], , :, [$3])
+ else
+ ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
+ fi
+])
+
+
diff --git a/gssm/config/usrp_fusb_tech.m4 b/gssm/config/usrp_fusb_tech.m4
new file mode 100644
index 0000000..573c175
--- /dev/null
+++ b/gssm/config/usrp_fusb_tech.m4
@@ -0,0 +1,54 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+AC_DEFUN([USRP_SET_FUSB_TECHNIQUE],[
+ AC_REQUIRE([AC_CANONICAL_TARGET])
+ AC_ARG_WITH(fusb-tech,
+ [ --with-fusb-tech=OS set fast usb technique (auto)],
+ [cf_with_fusb_tech="$withval"],
+ [cf_with_fusb_tech="$target_os"])
+
+
+ AC_CHECK_HEADER([linux/usbdevice_fs.h],
+ [x_have_usbdevice_fs_h=yes],
+ [x_have_usbdevice_fs_h=no])
+
+ AC_MSG_CHECKING([for fast usb technique to use])
+ case "$cf_with_fusb_tech" in
+ linux*) if test x${x_have_usbdevice_fs_h} = xyes;
+ then
+ FUSB_TECH=linux
+ else
+ FUSB_TECH=generic
+ fi ;;
+
+ darwin*) FUSB_TECH=darwin ;;
+ *) FUSB_TECH=generic ;;
+ esac
+
+ AC_MSG_RESULT($FUSB_TECH)
+ AC_SUBST(FUSB_TECH)
+
+ AM_CONDITIONAL(FUSB_TECH_darwin, test $FUSB_TECH = darwin)
+ AM_CONDITIONAL(FUSB_TECH_generic, test $FUSB_TECH = generic)
+ AM_CONDITIONAL(FUSB_TECH_linux, test $FUSB_TECH = linux)
+])
+
diff --git a/gssm/config/usrp_libusb.m4 b/gssm/config/usrp_libusb.m4
new file mode 100644
index 0000000..27f8c2a
--- /dev/null
+++ b/gssm/config/usrp_libusb.m4
@@ -0,0 +1,38 @@
+# Check for libusb support. -*- Autoconf -*-
+
+# Copyright 2003 Free Software Foundation, Inc.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+AC_DEFUN([USRP_LIBUSB],
+[
+ AC_LANG_PUSH(C)
+
+ AC_CHECK_HEADERS([usb.h],
+ [],
+ [ AC_MSG_ERROR([USRP requires libusb. usb.h not found, stop. See http://libusb.sf.net]) ]
+ )
+
+ save_LIBS="$LIBS"
+ AC_SEARCH_LIBS(usb_bulk_write, [usb],
+ [ USB_LIBS="$LIBS" ],
+ [ AC_MSG_ERROR([USRP requires libusb. usb_bulk_write not found, stop. See http://libusb.sf.net]) ]
+ )
+ LIBS="$save_LIBS"
+
+ AC_LANG_POP
+ AC_SUBST(USB_LIBS)
+])
diff --git a/gssm/config/usrp_sdcc.m4 b/gssm/config/usrp_sdcc.m4
new file mode 100644
index 0000000..81c255a
--- /dev/null
+++ b/gssm/config/usrp_sdcc.m4
@@ -0,0 +1,67 @@
+# Check for sdcc support. -*- Autoconf -*-
+
+# Copyright 2004 Free Software Foundation, Inc.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+AC_DEFUN([USRP_SDCC],
+[
+ AC_CHECK_PROG(XCC, sdcc, sdcc -mmcs51 --no-xinit-opt,no)
+ AC_CHECK_PROG(XAS, asx8051, asx8051 -plosgff,no)
+
+ if test "$XCC" = "no" -o "$XAS" = "no" ; then
+ AC_MSG_ERROR([USRP requires sdcc. sdcc not found, stop. See http://sdcc.sf.net])
+ fi
+
+ sdcc_version_min=$1
+
+ sdcc_version=`sdcc --version 2>&1 | \
+ sed 's/\(SDCC.* \)\([[0-9]]*\.[[0-9]]*\.[[0-9]]*\)\( .*$\)/\2/'`
+
+ AC_MSG_CHECKING([sdcc_version "$sdcc_version"])
+
+ sdcc_major_version=`echo $sdcc_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ sdcc_minor_version=`echo $sdcc_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ sdcc_micro_version=`echo $sdcc_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+ sdcc_major_min=`echo $sdcc_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ sdcc_minor_min=`echo $sdcc_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ sdcc_micro_min=`echo $sdcc_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+ sdcc_version_proper=`expr \
+ "$sdcc_major_version" \> "$sdcc_major_min" \| \
+ "$sdcc_major_version" \= "$sdcc_major_min" \& \
+ "$sdcc_minor_version" \> "$sdcc_minor_min" \| \
+ "$sdcc_major_version" \= "$sdcc_major_min" \& \
+ "$sdcc_minor_version" \= "$sdcc_minor_min" \& \
+ "$sdcc_micro_version" \>= "$sdcc_micro_min" `
+
+ if test "$sdcc_version_proper" = "1" ; then
+ AC_MSG_RESULT([$sdcc_major_version.$sdcc_minor_version.$sdcc_micro_version])
+ else
+ AC_MSG_ERROR([USRP requires sdcc >= $sdcc_version_min. sdcc not found, stop. See http://sdcc.sf.net])
+ fi
+
+ AC_SUBST(XCC)
+ AC_SUBST(XAS)
+
+])
diff --git a/gssm/configure.ac b/gssm/configure.ac
new file mode 100644
index 0000000..7ce1181
--- /dev/null
+++ b/gssm/configure.ac
@@ -0,0 +1,101 @@
+dnl
+dnl Copyright 2004 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+dnl Boston, MA 02111-1307, USA.
+dnl
+
+AC_INIT
+AC_PREREQ(2.57)
+AC_CONFIG_SRCDIR([src/lib/gssm.i])
+AM_CONFIG_HEADER(config.h)
+AC_CANONICAL_TARGET([])
+AM_INIT_AUTOMAKE(gssm, 0.0)
+
+dnl disable maintainer rules: e.g., rebuilding configure, makefile.in's unless
+dnl user explicitly specifies --enable-maintainer-mode
+dnl AM_MAINTAINER_MODE
+
+dnl LF_CONFIGURE_CC
+LF_CONFIGURE_CXX
+LF_SET_WARNINGS
+GR_SET_GPROF
+GR_SET_PROF
+GR_PROG_AS
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_INSTALL
+
+AC_LIBTOOL_WIN32_DLL
+AC_ENABLE_SHARED dnl do build shared libraries
+AC_DISABLE_STATIC dnl don't build static libraries
+AC_PROG_LIBTOOL
+
+dnl locate python, swig,
+GR_SCRIPTING
+
+dnl check for threads (mandatory)
+GR_OMNITHREAD
+
+dnl CFLAGS="${CFLAGS} $PTHREAD_CFLAGS"
+dnl CXXFLAGS="${CXXFLAGS} $PTHREAD_CFLAGS"
+CFLAGS="-O3 $PTHREAD_CFLAGS"
+CXXFLAGS="-O3 $PTHREAD_CFLAGS"
+
+if test "x$CXX_FOR_BUILD" = x
+then
+ CXX_FOR_BUILD=${CXX}
+fi
+AC_SUBST(CXX_FOR_BUILD)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(fcntl.h limits.h strings.h sys/ioctl.h sys/time.h unistd.h)
+AC_CHECK_HEADERS(sys/mman.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS([])
+
+dnl check for mingw
+GR_PWIN32
+
+PKG_CHECK_MODULES(GNURADIO_CORE, gnuradio-core >= 2)
+LIBS="$LIBS $GNURADIO_CORE_LIBS"
+
+dnl Define where to find boost includes
+dnl defines BOOST_CFLAGS
+GR_REQUIRE_BOOST_INCLUDES
+
+STD_DEFINES_AND_INCLUDES="$GNURADIO_CORE_CFLAGS $BOOST_CFLAGS"
+AC_SUBST(STD_DEFINES_AND_INCLUDES)
+
+AC_CONFIG_FILES([\
+ Makefile \
+ config/Makefile \
+ src/Makefile \
+ src/lib/Makefile \
+ src/mktun/Makefile \
+ ])
+
+AC_OUTPUT
diff --git a/gssm/patch/wireshark-0.99.5-gssm.patch b/gssm/patch/wireshark-0.99.5-gssm.patch
new file mode 100644
index 0000000..655b909
--- /dev/null
+++ b/gssm/patch/wireshark-0.99.5-gssm.patch
@@ -0,0 +1,2669 @@
+*** wireshark-0.99.5/epan/dissectors/packet-gsm_a.c 2007-02-01 15:00:39.000000000 -0800
+--- wireshark-0.99.5-gssm/epan/dissectors/packet-gsm_a.c 2007-05-31 00:24:56.000000000 -0700
+***************
+*** 567,575 ****
+ /* [3] 10.5.2.8b Channel Request Description 2 */
+ /* Pos 20 */
+ { 0x00, "Cipher Mode Setting" }, /* [3] 10.5.2.9 */
+! /* [3] 10.5.2.10 Cipher Response
+! * [3] 10.5.2.11 Control Channel Description
+! * [3] 10.5.2.11a DTM Information Details */
+ { 0x00, "Dynamic ARFCN Mapping" }, /* [3] 10.5.2.11b */
+ { 0x00, "Frequency Channel Sequence" }, /* [3] 10.5.2.12 */
+ { 0x00, "Frequency List" }, /* 10.5.2.13 */
+--- 567,576 ----
+ /* [3] 10.5.2.8b Channel Request Description 2 */
+ /* Pos 20 */
+ { 0x00, "Cipher Mode Setting" }, /* [3] 10.5.2.9 */
+! /* [3] 10.5.2.10 Cipher Response */
+! {0x00, "Control Channel Description"}, /* [3] 10.5.2.11 Control Channel Description */ // jl
+! /* [3] 10.5.2.11 Control Channel Description */
+! /* [3] 10.5.2.11a DTM Information Details */
+ { 0x00, "Dynamic ARFCN Mapping" }, /* [3] 10.5.2.11b */
+ { 0x00, "Frequency Channel Sequence" }, /* [3] 10.5.2.12 */
+ { 0x00, "Frequency List" }, /* 10.5.2.13 */
+***************
+*** 594,633 ****
+ { 0x00, "MultiRate configuration" }, /* [3] 10.5.2.21aa */
+ /* Pos 30 */
+ { 0x00, "Multislot Allocation" }, /* [3] 10.5.2.21b */
+! /*
+ * [3] 10.5.2.21c NC mode
+! * [3] 10.5.2.22 Neighbour Cell Description
+ * [3] 10.5.2.22a Neighbour Cell Description 2
+ * [3] 10.5.2.22b (void)
+ * [3] 10.5.2.22c NT/N Rest Octets
+! * [3] 10.5.2.23 P1 Rest Octets
+ * [3] 10.5.2.24 P2 Rest Octets
+ * [3] 10.5.2.25 P3 Rest Octets
+! * [3] 10.5.2.25a Packet Channel Description
+! * [3] 10.5.2.25b Dedicated mode or TBF
+ * [3] 10.5.2.25c RR Packet Uplink Assignment
+ * [3] 10.5.2.25d RR Packet Downlink Assignment
+! * [3] 10.5.2.26 Page Mode
+ * [3] 10.5.2.26a (void)
+ * [3] 10.5.2.26b (void)
+ * [3] 10.5.2.26c (void)
+ * [3] 10.5.2.26d (void)
+- * [3] 10.5.2.27 NCC Permitted
+ */
+ { 0x00, "Power Command" }, /* 10.5.2.28 */
+ { 0x00, "Power Command and access type" }, /* 10.5.2.28a */
+! /*
+! * [3] 10.5.2.29 RACH Control Parameters
+! * [3] 10.5.2.30 Request Reference
+! */
+! { 0x00, "RR Cause" }, /* 10.5.2.31 */
+ { 0x00, "Synchronization Indication" }, /* 10.5.2.39 */
+! /* [3] 10.5.2.32 SI 1 Rest Octets
+ * [3] 10.5.2.33 SI 2bis Rest Octets
+ * [3] 10.5.2.33a SI 2ter Rest Octets
+ * [3] 10.5.2.33b SI 2quater Rest Octets
+! * [3] 10.5.2.34 SI 3 Rest Octets
+! * [3] 10.5.2.35 SI 4 Rest Octets
+ * [3] 10.5.2.35a SI 6 Rest Octets
+ * [3] 10.5.2.36 SI 7 Rest Octets
+ * [3] 10.5.2.37 SI 8 Rest Octets
+--- 595,643 ----
+ { 0x00, "MultiRate configuration" }, /* [3] 10.5.2.21aa */
+ /* Pos 30 */
+ { 0x00, "Multislot Allocation" }, /* [3] 10.5.2.21b */
+! /*
+ * [3] 10.5.2.21c NC mode
+! */
+! {0x00, "Neighbor Cell Description"}, /* [3] 10.5.2.22 Neighbour Cell Description */ // jl
+! /*
+ * [3] 10.5.2.22a Neighbour Cell Description 2
+ * [3] 10.5.2.22b (void)
+ * [3] 10.5.2.22c NT/N Rest Octets
+! */
+! {0x00, "P1 Rest Octets"}, /* [3] 10.5.2.23 P1 Rest Octets */ // jl
+! /*
+ * [3] 10.5.2.24 P2 Rest Octets
+ * [3] 10.5.2.25 P3 Rest Octets
+! */
+! {0x00, "Packet Channel Description"}, /* [3] 10.5.2.25a Packet Channel Description */ // jl
+! {0x00, "Dedicated Mode or TBF" }, /* [3] 10.5.2.25b Dedicated mode or TBF */ // jl
+! /*
+ * [3] 10.5.2.25c RR Packet Uplink Assignment
+ * [3] 10.5.2.25d RR Packet Downlink Assignment
+! */
+! {0x00, "Page Mode"}, /* [3] 10.5.2.26 Page Mode */ // jl
+! /*
+ * [3] 10.5.2.26a (void)
+ * [3] 10.5.2.26b (void)
+ * [3] 10.5.2.26c (void)
+ * [3] 10.5.2.26d (void)
+ */
++ {0x00, "NCC Permitted"}, /* [3] 10.5.2.27 NCC Permitted */ // jl
+ { 0x00, "Power Command" }, /* 10.5.2.28 */
+ { 0x00, "Power Command and access type" }, /* 10.5.2.28a */
+! {0x00, "RACH Control Parameters"}, /* [3] 10.5.2.29 RACH Control Parameters */ // jl
+! {0x00, "Request Reference"}, /* [3] 10.5.2.30 Request Reference */ // jl
+! { 0x00, "RR Cause" }, /* 10.5.2.31 */
+ { 0x00, "Synchronization Indication" }, /* 10.5.2.39 */
+! {0x00, "SI 1 Rest Octets"}, /* [3] 10.5.2.32 SI 1 Rest Octets */ // jl
+! /*
+ * [3] 10.5.2.33 SI 2bis Rest Octets
+ * [3] 10.5.2.33a SI 2ter Rest Octets
+ * [3] 10.5.2.33b SI 2quater Rest Octets
+! */
+! {0x00, "SI 3 Rest Octets"}, /* [3] 10.5.2.34 SI 3 Rest Octets */ // jl
+! {0x00, "SI 4 Rest Octets"}, /* [3] 10.5.2.35 SI 4 Rest Octets */ // jl
+! /*
+ * [3] 10.5.2.35a SI 6 Rest Octets
+ * [3] 10.5.2.36 SI 7 Rest Octets
+ * [3] 10.5.2.37 SI 8 Rest Octets
+***************
+*** 1057,1062 ****
+--- 1067,1093 ----
+ #define DTAP_SS_IEI_MASK 0x3f
+
+ /* Initialize the protocol and registered fields */
++ static int hf_gsm_a_rr_rach_cp_max_retrans = -1; // jl
++ static int hf_gsm_a_rr_rach_cp_tx_integer = -1; // jl
++ static int hf_gsm_a_rr_rach_cp_cell_bar_access = -1; // jl
++ static int hf_gsm_a_rr_rach_cp_re = -1; // jl
++ static int hf_gsm_a_rr_rach_cp_ec = -1; // jl
++ static int hf_gsm_a_rr_si_1_rest_octets = -1; // jl
++
++ static int hf_gsm_a_rr_neigh_cell_dsc_ext = -1; // jl
++ static int hf_gsm_a_rr_neigh_cell_dsc_ba = -1; // jl
++
++ static int hf_gsm_a_rr_cc_dsc_mscr = -1; // jl
++ static int hf_gsm_a_rr_cc_dsc_att = -1; // jl
++ static int hf_gsm_a_rr_cc_dsc_cbq3 = -1; // jl
++ static int hf_gsm_a_rr_cc_dsc_ccch = -1; // jl
++
++ static int hf_gsm_a_rr_co_bcch_dn_ind = -1; // jl
++ static int hf_gsm_a_rr_co_bcch_pwrc = -1; // jl
++ static int hf_gsm_a_rr_co_bcch_dtx = -1; // jl
++
++ static int hf_gsm_a_rr_dm_or_tbf = -1; // jl
++
+ static int proto_a_bssmap = -1;
+ static int proto_a_dtap = -1;
+ static int proto_a_rp = -1;
+***************
+*** 3211,3220 ****
+ * [3] 10.5.2.1e Cell selection indicator after release of all TCH and SDCCH IE
+ */
+ DE_RR_CELL_DSC, /* 10.5.2.2 RR Cell Description */
+ /*
+- * [3] 10.5.2.3 Cell Options (BCCH)
+ * [3] 10.5.2.3a Cell Options (SACCH)
+! * [3] 10.5.2.4 Cell Selection Parameters
+ * [3] 10.5.2.4a (void)
+ */
+ DE_RR_CH_DSC, /* [3] 10.5.2.5 Channel Description */
+--- 3242,3254 ----
+ * [3] 10.5.2.1e Cell selection indicator after release of all TCH and SDCCH IE
+ */
+ DE_RR_CELL_DSC, /* 10.5.2.2 RR Cell Description */
++ DE_RR_CO_BCCH, /* [3] 10.5.2.3 Cell Options (BCCH) */ // jl
++
+ /*
+ * [3] 10.5.2.3a Cell Options (SACCH)
+! */
+! DE_RR_CELL_SEL_PARAM, /* [3] 10.5.2.4 Cell Selection Parameters */ // jl
+! /*
+ * [3] 10.5.2.4a (void)
+ */
+ DE_RR_CH_DSC, /* [3] 10.5.2.5 Channel Description */
+***************
+*** 3230,3237 ****
+ * [3] 10.5.2.8b Channel Request Description 2 */
+ /* Pos 20 */
+ DE_RR_CIP_MODE_SET, /* [3] 10.5.2.9 Cipher Mode Setting */
+! /* [3] 10.5.2.10 Cipher Response
+! * [3] 10.5.2.11 Control Channel Description
+ * [3] 10.5.2.11a DTM Information Details */
+ DE_RR_DYN_ARFCN_MAP, /* [3] 10.5.2.11b Dynamic ARFCN Mapping */
+ DE_RR_FREQ_CH_SEQ, /* [3] 10.5.2.12 Frequency Channel Sequence */
+--- 3264,3275 ----
+ * [3] 10.5.2.8b Channel Request Description 2 */
+ /* Pos 20 */
+ DE_RR_CIP_MODE_SET, /* [3] 10.5.2.9 Cipher Mode Setting */
+! /*
+! * [3] 10.5.2.10 Cipher Response
+! */
+! DE_RR_CC_DSC, /* [3] 10.5.2.11 Control Channel Description */ // jl
+!
+! /*
+ * [3] 10.5.2.11a DTM Information Details */
+ DE_RR_DYN_ARFCN_MAP, /* [3] 10.5.2.11b Dynamic ARFCN Mapping */
+ DE_RR_FREQ_CH_SEQ, /* [3] 10.5.2.12 Frequency Channel Sequence */
+***************
+*** 3245,3252 ****
+ */
+
+ DE_RR_HO_REF, /* 10.5.2.15 Handover Reference */
+ /*
+- * [3] 10.5.2.16 IA Rest Octets
+ * [3] 10.5.2.17 IAR Rest Octets
+ * [3] 10.5.2.18 IAX Rest Octets
+ * [3] 10.5.2.19 L2 Pseudo Length
+--- 3283,3290 ----
+ */
+
+ DE_RR_HO_REF, /* 10.5.2.15 Handover Reference */
++ DE_RR_IA_REST_OCTETS, /* [3] 10.5.2.16 IA Rest Octets */ // jl
+ /*
+ * [3] 10.5.2.17 IAR Rest Octets
+ * [3] 10.5.2.18 IAX Rest Octets
+ * [3] 10.5.2.19 L2 Pseudo Length
+***************
+*** 3261,3298 ****
+
+ /*
+ * [3] 10.5.2.21c NC mode
+! * [3] 10.5.2.22 Neighbour Cell Description
+ * [3] 10.5.2.22a Neighbour Cell Description 2
+ * [3] 10.5.2.22b (void)
+ * [3] 10.5.2.22c NT/N Rest Octets
+ * [3] 10.5.2.23 P1 Rest Octets
+ * [3] 10.5.2.24 P2 Rest Octets
+ * [3] 10.5.2.25 P3 Rest Octets
+! * [3] 10.5.2.25a Packet Channel Description
+! * [3] 10.5.2.25b Dedicated mode or TBF
+ * [3] 10.5.2.25c RR Packet Uplink Assignment
+ * [3] 10.5.2.25d RR Packet Downlink Assignment
+! * [3] 10.5.2.26 Page Mode
+ * [3] 10.5.2.26a (void)
+ * [3] 10.5.2.26b (void)
+ * [3] 10.5.2.26c (void)
+ * [3] 10.5.2.26d (void)
+- * [3] 10.5.2.27 NCC Permitted
+ */
+ DE_RR_POW_CMD, /* 10.5.2.28 Power Command */
+ DE_RR_POW_CMD_AND_ACC_TYPE, /* 10.5.2.28a Power Command and access type */
+! /*
+! * [3] 10.5.2.29 RACH Control Parameters
+! * [3] 10.5.2.30 Request Reference
+! */
+! DE_RR_CAUSE, /* 10.5.2.31 RR Cause */
+ DE_RR_SYNC_IND, /* 10.5.2.39 Synchronization Indication */
+! /* [3] 10.5.2.32 SI 1 Rest Octets
+ * [3] 10.5.2.33 SI 2bis Rest Octets
+ * [3] 10.5.2.33a SI 2ter Rest Octets
+ * [3] 10.5.2.33b SI 2quater Rest Octets
+! * [3] 10.5.2.34 SI 3 Rest Octets
+! * [3] 10.5.2.35 SI 4 Rest Octets
+ * [3] 10.5.2.35a SI 6 Rest Octets
+ * [3] 10.5.2.36 SI 7 Rest Octets
+ * [3] 10.5.2.37 SI 8 Rest Octets
+--- 3299,3346 ----
+
+ /*
+ * [3] 10.5.2.21c NC mode
+! */
+! DE_RR_NEIGH_CELL_DSC, /* [3] 10.5.2.22 Neighbour Cell Description */ // jl
+! /*
+ * [3] 10.5.2.22a Neighbour Cell Description 2
+ * [3] 10.5.2.22b (void)
+ * [3] 10.5.2.22c NT/N Rest Octets
++ */
++ DE_RR_P1_REST_OCTETS, /* [3] 10.5.2.23 P1 Rest Octets */ // jl
++ /*
+ * [3] 10.5.2.23 P1 Rest Octets
+ * [3] 10.5.2.24 P2 Rest Octets
+ * [3] 10.5.2.25 P3 Rest Octets
+! */
+! DE_RR_PCD, /* [3] 10.5.2.25a Packet Channel Description */ // jl
+! DE_RR_DM_OR_TBF, /* [3] 10.5.2.25b Dedicated mode or TBF */ // jl
+! /*
+ * [3] 10.5.2.25c RR Packet Uplink Assignment
+ * [3] 10.5.2.25d RR Packet Downlink Assignment
+! */
+! DE_RR_PAGE_MODE, /* [3] 10.5.2.26 Page Mode */ // jl
+! /*
+ * [3] 10.5.2.26a (void)
+ * [3] 10.5.2.26b (void)
+ * [3] 10.5.2.26c (void)
+ * [3] 10.5.2.26d (void)
+ */
++ DE_RR_NCC_PERMITTED, /* [3] 10.5.2.27 NCC Permitted */ // jl
+ DE_RR_POW_CMD, /* 10.5.2.28 Power Command */
+ DE_RR_POW_CMD_AND_ACC_TYPE, /* 10.5.2.28a Power Command and access type */
+! DE_RR_RACH_CP, /* [3] 10.5.2.29 RACH Control Parameters */ // jl
+! DE_RR_REQ_REF, /* [3] 10.5.2.30 Request Reference */ // jl
+! DE_RR_CAUSE, /* 10.5.2.31 RR Cause */
+ DE_RR_SYNC_IND, /* 10.5.2.39 Synchronization Indication */
+! DE_RR_SI_1_REST_OCTETS, /* [3] 10.5.2.32 SI 1 Rest Octets */ // jl
+! /*
+ * [3] 10.5.2.33 SI 2bis Rest Octets
+ * [3] 10.5.2.33a SI 2ter Rest Octets
+ * [3] 10.5.2.33b SI 2quater Rest Octets
+! */
+! DE_RR_SI_3_REST_OCTETS, /* [3] 10.5.2.34 SI 3 Rest Octets */ // jl
+! DE_RR_SI_4_REST_OCTETS, /* [3] 10.5.2.35 SI 4 Rest Octets */ // jl
+! /*
+ * [3] 10.5.2.35a SI 6 Rest Octets
+ * [3] 10.5.2.36 SI 7 Rest Octets
+ * [3] 10.5.2.37 SI 8 Rest Octets
+***************
+*** 3463,3480 ****
+ de_cell_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string, int string_len)
+ {
+ guint32 curr_offset;
+
+! curr_offset = offset;
+
+- curr_offset +=
+ /* 0x02 CI */
+! be_cell_id_aux(tvb, tree, offset, len, add_string, string_len, 0x02);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+ }
+
+ /*
+ * [3] 10.5.1.3
+ */
+--- 3511,3631 ----
+ de_cell_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string, int string_len)
+ {
+ guint32 curr_offset;
++ proto_item *item;
++ proto_tree *subtree;
+
+! curr_offset = offset;
+!
+! item = proto_tree_add_text(tree, tvb, curr_offset, 2, gsm_dtap_elem_strings[DE_CELL_ID].strptr);
+! subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CELL_ID]);
+
+ /* 0x02 CI */
+! curr_offset += be_cell_id_aux(tvb, subtree, offset, len, add_string, string_len, 0x02);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+ }
+
++
++ // jl -- got this list somewhere off the net...
++ typedef struct mcc_mnc_name_s {
++ char *mcc;
++ char *mnc;
++ char *name;
++ } mcc_mnc_name_t;
++
++ static mcc_mnc_name_t mcc_mnc_names[] = {
++ {"310", "110", "Wireless 2000 PCS"},
++ {"310", "020", "Union Telephone"},
++ {"310", "260", "T-Mobile"},
++ {"310", "030", "Centennial"},
++ {"310", "310", "T-Mobile"},
++ {"310", "040", "Concho Wireless"},
++ {"310", "460", "Simmetry"},
++ {"310", "070", "Highland Cellular"},
++ {"310", "080", "Corr Wireless"},
++ {"310", "090", "Edge Wireless"},
++ {"310", "100", "Plateau Wireless"},
++ {"310", "170", "T-Mobile (formerly Cingular Wireless CA/NV)"},
++ {"310", "180", "West Central"},
++ {"310", "190", "Alaska Wireless"},
++ {"310", "320", "Cellular One"},
++ {"310", "340", "WestLink"},
++ {"310", "390", "Yorkville"},
++ {"310", "410", "Cingular Wireless"},
++ {"310", "420", "Cincinnati Bell"},
++ {"310", "430", "Alaska DigiTel"},
++ {"310", "440", "Cellular One"},
++ {"310", "450", "Viaero Wireless"},
++ {"310", "460", "Simmetry (formerly OneLink PCS)"},
++ {"310", "490", "SunCom"},
++ {"310", "500", "Alltel (formerly PSC Wireless - GA/AL region only)"},
++ {"310", "530", "West VA Wireless"},
++ {"310", "540", "Oklahoma Western"},
++ {"310", "560", "Cellular One DCS"},
++ {"310", "590", "Western Wireless (now parto of Alltel)"},
++ {"310", "610", "Epic Touch"},
++ {"310", "620", "Coleman Telecomm"},
++ {"310", "630", "AmeriLink PCS"},
++ {"310", "640", "Einstein PCS"},
++ {"310", "680", "Cellular One DCS (Dobson. Formerly NPI Wireless)"},
++ {"310", "690", "Immix Wireless"},
++ {"310", "740", "Telemetrix"},
++ {"310", "760", "Panhandle Telecomm"},
++ {"310", "770", "Iowa Wireless"},
++ {"310", "790", "PinPoint Wireless"},
++ {"310", "830", "Caprock Cellular"},
++ {"310", "870", "Kaplan"},
++ {"310", "880", "Advantage Cellular"},
++ {"310", "890", "RCC/Unicell"},
++ {"310", "900", "Texas Cellular"},
++ {"310", "910", "First Cellular"},
++ {"310", "940", "Digital Cellular"},
++ {"310", "950", "XIT Wireless"},
++ {"310", "980", "Cingular Wireless (not in commercial use)"},
++ {"310", "990", "Cingular Wireless (not in commercial use)"},
++ {"311", "000", "Mid-Tex Cellular"},
++ {"311", "030", "Indigo Wireless"},
++ {"311", "040", "Commnet Wireless"},
++ {"311", "050", "Wilkes Cellular"},
++ {"311", "070", "Easterbrooke"},
++ {"311", "080", "Pine Cellular"},
++ {"311", "090", "Siouxland PCS"},
++ {"311", "110", "High Plains Wireless"},
++ {"311", "130", "Cell One Amarillo"},
++ {"311", "140", "Sprocket (aka MBO Wireless)"},
++ {"311", "150", "Wilkes Cellular"},
++ {"311", "160", "Cellular One DCS (Dobson. Formerly EMW)"},
++ {"311", "170", "PetroCom"},
++ {"311", "180", "Cingular Wireless (not in commercial use)"},
++ {"311", "190", "Cellular Properties Inc (aka CellOne East Central IL)"},
++ {"311", "210", "Farmers Cellular"},
++ {"311", "250", "USA i CAN"},
++ {"310", "110", "Wireless 2000 PCS (no longer in business)"},
++ {"310", "150", "Cingular Wireless (SE GA/SC/NC/E TN. Consolidated with 310-410)"},
++ {"310", "160", "T-Mobile (consolidated with 310-260. Formerly Omnipoint)"},
++ {"310", "200", "T-Mobile (consolidated with 310-260)"},
++ {"310", "210", "T-Mobile (consolidated with 310-260)"},
++ {"310", "220", "T-Mobile (consolidated with 310-260)"},
++ {"310", "230", "T-Mobile (consolidated with 310-260)"},
++ {"310", "240", "T-Mobile (consolidated with 310-260)"},
++ {"310", "250", "T-Mobile (consolidated with 310-260)"},
++ {"310", "260", "T-Mobile (consolidated with 310-260)"},
++ {"310", "270", "T-Mobile (consolidated with 310-260. Former Powertel)"},
++ {"310", "310", "T-Mobile (consolidated with 310-260. Former Aerial)"},
++ {"310", "350", "Carolina Phone (No longer in business)"},
++ {"310", "380", "Cingular Wireless (formerly AT&T Wireless)"},
++ {"310", "400", "Minnesota Southern (never actually used)"},
++ {"310", "580", "T-Mobile (consolidated with 310-260. Former PCS One)"},
++ {"310", "660", "T-Mobile (consolidated with 310-260. Former DigiPH)"},
++ {"310", "670", "Wireless 2000 PCS (No longer in business)"},
++ {"310", "780", "AirLink PCS (No longer in business)"},
++ {"310", "800", "T-Mobile (consolidated with 310-260)"},
++ {0, 0, 0}
++ };
++
++
+ /*
+ * [3] 10.5.1.3
+ */
+***************
+*** 3485,3493 ****
+ guint16 value;
+ guint32 curr_offset;
+ proto_tree *subtree;
+! proto_item *item;
+ gchar mcc[4];
+ gchar mnc[4];
+
+ len = len;
+ curr_offset = offset;
+--- 3636,3646 ----
+ guint16 value;
+ guint32 curr_offset;
+ proto_tree *subtree;
+! proto_item *item, *item_name;
+ gchar mcc[4];
+ gchar mnc[4];
++ mcc_mnc_name_t *mmn = &mcc_mnc_names[0];
++
+
+ len = len;
+ curr_offset = offset;
+***************
+*** 3506,3516 ****
+ mcc_mnc_aux(octs, mcc, mnc);
+
+
+! proto_tree_add_text(subtree,
+ tvb, curr_offset, 3,
+ "Mobile Country Code (MCC): %s, Mobile Network Code (MNC): %s",
+ mcc,
+ mnc);
+
+ curr_offset += 3;
+
+--- 3659,3676 ----
+ mcc_mnc_aux(octs, mcc, mnc);
+
+
+! item_name = proto_tree_add_text(subtree,
+ tvb, curr_offset, 3,
+ "Mobile Country Code (MCC): %s, Mobile Network Code (MNC): %s",
+ mcc,
+ mnc);
++ while(mmn->name) {
++ if((!strncmp(mcc, mmn->mcc, 3)) && (!strncmp(mnc, mmn->mnc, 3))) {
++ proto_item_append_text(item_name, " -- %s", mmn->name);
++ break;
++ }
++ mmn++;
++ }
+
+ curr_offset += 3;
+
+***************
+*** 4051,4071 ****
+ guint8 oct,bit,byte;
+ guint16 arfcn;
+ proto_item *item;
+!
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ /* FORMAT-ID, Format Identifier (part of octet 3)*/
+! proto_tree_add_item(tree, hf_gsm_a_rr_format_id, tvb, curr_offset, 1, FALSE);
+ /* Cell Channel Description */
+
+ if ((oct & 0xc0) == 0x00)
+ {
+ /* bit map 0 */
+! item = proto_tree_add_text(tree,tvb, curr_offset, 16,"list of ARFCN for hopping = ");
+ bit = 4;
+ arfcn = 125;
+ for (byte = 0;byte <= 15;byte++)
+--- 4211,4237 ----
+ guint8 oct,bit,byte;
+ guint16 arfcn;
+ proto_item *item;
+! proto_tree *subtree;
+
+ len = len;
+ curr_offset = offset;
+
++ item = proto_tree_add_text(tree, tvb, curr_offset, 16, gsm_dtap_elem_strings[DE_RR_CELL_CH_DSC].strptr);
++ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_CELL_CH_DSC]);
++
+ oct = tvb_get_guint8(tvb, curr_offset);
+
++ // mask out "spare" bits which can be used for other channel lists -- jl
++ oct = oct & 0xcf;
++
+ /* FORMAT-ID, Format Identifier (part of octet 3)*/
+! proto_tree_add_item(subtree, hf_gsm_a_rr_format_id, tvb, curr_offset, 1, FALSE);
+ /* Cell Channel Description */
+
+ if ((oct & 0xc0) == 0x00)
+ {
+ /* bit map 0 */
+! item = proto_tree_add_text(subtree,tvb, curr_offset, 16,"list of ARFCN for hopping = ");
+ bit = 4;
+ arfcn = 125;
+ for (byte = 0;byte <= 15;byte++)
+***************
+*** 4086,4117 ****
+ else if ((oct & 0xf8) == 0x80)
+ {
+ /* 1024 range */
+! proto_tree_add_text(tree,tvb, curr_offset, 16,"Cell Channel Description (1024 range) (Not decoded)");
+ curr_offset = curr_offset + 16;
+ }
+ else if ((oct & 0xfe) == 0x88)
+ {
+ /* 512 range */
+! proto_tree_add_text(tree,tvb, curr_offset, 16,"Cell Channel Description (512 range) (Not decoded)");
+ curr_offset = curr_offset + 16;
+ }
+ else if ((oct & 0xfe) == 0x8a)
+ {
+ /* 256 range */
+! proto_tree_add_text(tree,tvb, curr_offset, 16,"Cell Channel Description (256 range) (Not decoded)");
+ curr_offset = curr_offset + 16;
+ }
+ else if ((oct & 0xfe) == 0x8c)
+ {
+ /* 128 range */
+! proto_tree_add_text(tree,tvb, curr_offset, 16,"Cell Channel Description (128 range) (Not decoded)");
+ curr_offset = curr_offset + 16;
+ }
+ else if ((oct & 0xfe) == 0x8e)
+ {
+ /* variable bit map */
+ arfcn = ((oct & 0x01) << 9) | (tvb_get_guint8(tvb, curr_offset+1) << 1) | ((tvb_get_guint8(tvb, curr_offset + 2) & 0x80) >> 7);
+! item = proto_tree_add_text(tree,tvb, curr_offset, 16,"list of ARFCN for hopping = %d",arfcn);
+ curr_offset = curr_offset + 2;
+ bit = 7;
+ for (byte = 0;byte <= 13;byte++)
+--- 4252,4283 ----
+ else if ((oct & 0xf8) == 0x80)
+ {
+ /* 1024 range */
+! proto_tree_add_text(subtree,tvb, curr_offset, 16,"Cell Channel Description (1024 range) (Not decoded)");
+ curr_offset = curr_offset + 16;
+ }
+ else if ((oct & 0xfe) == 0x88)
+ {
+ /* 512 range */
+! proto_tree_add_text(subtree,tvb, curr_offset, 16,"Cell Channel Description (512 range) (Not decoded)");
+ curr_offset = curr_offset + 16;
+ }
+ else if ((oct & 0xfe) == 0x8a)
+ {
+ /* 256 range */
+! proto_tree_add_text(subtree,tvb, curr_offset, 16,"Cell Channel Description (256 range) (Not decoded)");
+ curr_offset = curr_offset + 16;
+ }
+ else if ((oct & 0xfe) == 0x8c)
+ {
+ /* 128 range */
+! proto_tree_add_text(subtree,tvb, curr_offset, 16,"Cell Channel Description (128 range) (Not decoded)");
+ curr_offset = curr_offset + 16;
+ }
+ else if ((oct & 0xfe) == 0x8e)
+ {
+ /* variable bit map */
+ arfcn = ((oct & 0x01) << 9) | (tvb_get_guint8(tvb, curr_offset+1) << 1) | ((tvb_get_guint8(tvb, curr_offset + 2) & 0x80) >> 7);
+! item = proto_tree_add_text(subtree,tvb, curr_offset, 16,"list of ARFCN for hopping = %d",arfcn);
+ curr_offset = curr_offset + 2;
+ bit = 7;
+ for (byte = 0;byte <= 13;byte++)
+***************
+*** 4172,4181 ****
+
+ return(curr_offset - offset);
+ }
+! /*
+ * [3] 10.5.2.3 Cell Options (BCCH)
+ * [3] 10.5.2.3a Cell Options (SACCH)
+ * [3] 10.5.2.4 Cell Selection Parameters
+ * [3] 10.5.2.4a MAC Mode and Channel Coding Requested
+ * [3] 10.5.2.5 Channel Description
+ */
+--- 4338,4545 ----
+
+ return(curr_offset - offset);
+ }
+!
+!
+! /* // jl
+ * [3] 10.5.2.3 Cell Options (BCCH)
++ *
++ * DN-IND, Dynamic ARFCN mapping indicator (octet 2) Note 4
++ * 87654321
++ * 0....... Dynamic ARFCN mapping is not used by the PLMN
++ * 1....... Dynamic ARFCN mapping is used by the PLMN
++ *
++ * PWRC Power control indicator (octet 2) Note 1
++ * 87654321
++ * .0...... PWRC is not set
++ * .1...... PWRC is set
++ *
++ * DTX, DTX indicator (octet 2) Note 3
++ * 65
++ * ..00.... The MSs may use uplink discontinuous transmission
++ * ..01.... The MSs shall use uplink discontinuous transmission
++ * ..10.... The MS shall not use uplink discontinuous transmission
++ *
++ * RADIO-LINK_TIMEOUT (octet 2) Note 2
++ * 4321
++ * ....0000 4
++ * ....0001 8
++ * ....0010 12
++ *
++ * ....1110 60
++ * ....1111 64
++ *
++ * NOTE 1: The precise meaning of the PWRC parameter can be found in 3GPP TS 45.008.
++ * NOTE 2: The precise meaning of RADIO-LINK-TIMEOUT parameter can be found in 3GPP TS 45.008.
++ * NOTE 3: The DTX indicator field is not related to the use of downlink discontinuous transmission.
++ * NOTE 4: Dynamic ARFCN mapping is specified in 3GPP TS 45.005.
++ */
++ static const value_string gsm_a_rr_co_bcch_dn_ind_vals[] = {
++ {0, "Dynamic ARFCN mapping is not used by the PLMN"},
++ {1, "Dynamic ARFCN mapping is used by the PLMN"},
++ {0, 0}
++ };
++
++ static const value_string gsm_a_rr_co_bcch_pwrc_vals[] = {
++ {0, "PWRC is not set"},
++ {1, "PWRC is set"},
++ {0, 0}
++ };
++
++ static const value_string gsm_a_rr_co_bcch_dtx_vals[] = {
++ {0, "The MSs may use uplink discontinuous transmission"},
++ {1, "The MSs shall use uplink discontinuous transmission"},
++ {2, "The MSs shall not use uplink discontinuous transmission"},
++ {0, 0}
++ };
++
++
++ static guint8 de_rr_co_bcch(tvbuff_t *tvb, proto_tree *tree,
++ guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) {
++
++ guint32 curr_offset;
++ guint8 oct;
++ int rl_timeout;
++ proto_tree *subtree;
++ proto_item *item;
++
++ len = len;
++ curr_offset = offset;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, 1, gsm_dtap_elem_strings[DE_RR_CO_BCCH].strptr);
++ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_CO_BCCH]);
++ proto_tree_add_item(subtree, hf_gsm_a_rr_co_bcch_dn_ind, tvb, curr_offset, 1, FALSE);
++ proto_tree_add_item(subtree, hf_gsm_a_rr_co_bcch_pwrc, tvb, curr_offset, 1, FALSE);
++ proto_tree_add_item(subtree, hf_gsm_a_rr_co_bcch_dtx, tvb, curr_offset, 1, FALSE);
++
++ oct = tvb_get_guint8(tvb, curr_offset);
++ rl_timeout = ((oct & 0xf) + 1) * 4;
++ proto_tree_add_text(subtree, tvb, curr_offset, 1, "radio-link timeout %d", rl_timeout);
++
++ curr_offset++;
++
++ return curr_offset - offset;
++ }
++
++
++ /*
+ * [3] 10.5.2.3a Cell Options (SACCH)
++ */
++
++ /* // jl
+ * [3] 10.5.2.4 Cell Selection Parameters
++ *
++ * CELL-RESELECT-HYSTERESIS (octet 2)
++ * The usage of this information is defined in 3GPP TS 45.008
++ *
++ * 8 7 6
++ * 0 0 0 0 dB RXLEV hysteresis for LA re-selection
++ * 0 0 1 2 dB RXLEV hysteresis for LA re-selection
++ * 0 1 0 4 dB RXLEV hysteresis for LA re-selection
++ * 0 1 1 6 dB RXLEV hysteresis for LA re-selection
++ * 1 0 0 8 dB RXLEV hysteresis for LA re-selection
++ * 1 0 1 10 dB RXLEV hysteresis for LA re-selection
++ * 1 1 0 12 dB RXLEV hysteresis for LA re-selection
++ * 1 1 1 14 dB RXLEV hysteresis for LA re-selection
++ *
++ * MS-TXPWR-MAX-CCH (octet 2)
++ * Bits 5 - 1:
++ * The MS-TXPWR-MAX-CCH field is coded as the binary representation
++ * of the "power control level" in 3GPP TS 45.005 corresponding to
++ * the maximum TX power level an MS may use when accessing on a
++ * Control Channel CCH. This value shall be used by the Mobile
++ * Station according to 3GPP TS 45.008.
++ *
++ * Range: 0 to 31.
++ *
++ * ACS, ADDITIONAL RESELECT PARAM IND (octet 3)
++ * Bit 8: In System Information type 3 message:
++ * 0 System information type 16 and 17 are not broadcast on the BCCH.
++ * 1 System information type 16 and 17 are broadcast on the
++ * BCCH. A mobile station which does not support System
++ * information type 16 and 17 may consider this bit as "0".
++ *
++ * In System Information type 4 message:
++ * 0 The SI 4 rest octets, if present, and SI 7 and SI 8 rest octets, if
++ * so indicated in the SI 4 rest octets shall be used to derive the value
++ * of PI and possibly C2 parameters and/or other parameters
++ * 1 The value of PI and possibly C2 parameters and/or other parameters
++ * in a System information type 7 or type 8 message shall be used
++ *
++ * NECI: HALF RATE SUPPORT (octet 3)
++ * Bit 7:
++ * 0 New establishment causes are not supported
++ * 1 New establishment causes are supported
++ *
++ * RXLEV-ACCESS-MIN (octet 3)
++ * Bits 6 - 1:
++ * The RXLEV-ACCESS-MIN field is coded as the binary representation
++ * of the minimum received signal level at the MS for which it is
++ * permitted to access the system.
++ *
++ * Range: 0 to 63. (See 3GPP TS 45.008).
++ */
++ static guint8 de_rr_cell_sel_param(tvbuff_t *tvb, proto_tree *tree,
++ guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) {
++
++ guint32 curr_offset;
++ guint8 oct;
++ proto_tree *subtree;
++ proto_item *item;
++ int crh, mtmc, acs, hrs, ram;
++
++ len = len;
++ curr_offset = offset;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, 2, gsm_dtap_elem_strings[DE_RR_CELL_SEL_PARAM].strptr);
++ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_CELL_SEL_PARAM]);
++
++ oct = tvb_get_guint8(tvb, curr_offset);
++
++ // CELL-RESELECT-HYSTERESIS
++ crh = ((oct & 0xe0) >> 5) * 2;
++ proto_tree_add_text(subtree, tvb, curr_offset, 1, "Cell Reselect Hysteresis: %d dB RXLEV hysteresis for LA re-selection", crh);
++
++ // MS-TXPWR-MAX-CCH (octet 2)
++ mtmc = (oct & 0x1f);
++ proto_tree_add_text(subtree, tvb, curr_offset, 1, "Maximum TX power level an MS may use when accessing on a Control Channel CCH: %d", mtmc);
++
++ curr_offset++;
++ oct = tvb_get_guint8(tvb, curr_offset);
++
++ // ACS, System Information Type 3
++ acs = (oct & 0x80) >> 7;
++ item = proto_tree_add_text(subtree, tvb, curr_offset, 1, "In System Information Type 3: ");
++ if(!acs)
++ proto_item_append_text(item, "System Information Types 16 and 17 are not broadcast on the BCCH");
++ else
++ proto_item_append_text(item, "System Information Types 16 and 17 are broadcast on the BCCH");
++
++ item = proto_tree_add_text(subtree, tvb, curr_offset, 1, "In System Information Type 4: ");
++ if(!acs)
++ proto_item_append_text(item, "The SI 4, SI 7, and SI 8 rest octets shall be used to derive the value of PI and possibly C2 parameters");
++ else
++ proto_item_append_text(item, "The value of PI and possibly C2 parameters in a System Information Type 7 or 8 message shall be used");
++
++ // NECI: HALF RATE SUPPORT (octet 3)
++ hrs = (oct & 0x40) >> 6;
++ item = proto_tree_add_text(subtree, tvb, curr_offset, 1, "Half Rate Support: ");
++ if(!hrs)
++ proto_item_append_text(item, "New establishment causes are not supported");
++ else
++ proto_item_append_text(item, "New establishment causes are supported");
++
++ // RXLEV-ACCESS-MIN (octet 3)
++ ram = oct & 0x3f;
++ proto_tree_add_text(subtree, tvb, curr_offset, 1, "RXLEV-ACCESS-MIN: Minimum received signal level at the MS for which it is permitted to access "
++ "the system: %d", ram);
++
++ curr_offset++;
++
++ return curr_offset - offset;
++ }
++
++
++ /*
+ * [3] 10.5.2.4a MAC Mode and Channel Coding Requested
+ * [3] 10.5.2.5 Channel Description
+ */
+***************
+*** 4207,4212 ****
+--- 4571,4578 ----
+ }
+ else
+ {
++ subchannel = 0;
++ str = "";
+ if ((oct8 & 0xf0) == 0x10)
+ {
+ str = "TCH/H + ACCHs, Subchannel";
+***************
+*** 4309,4314 ****
+--- 4675,4682 ----
+ }
+ else
+ {
++ subchannel = 0;
++ str = "";
+ if ((oct8 & 0xf0) == 0x10)
+ {
+ str = "TCH/H + ACCHs, Subchannel";
+***************
+*** 4517,4534 ****
+ guint8
+ de_rr_chnl_needed(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
+ {
+! guint32 curr_offset;
+
+! len = len;
+! curr_offset = offset;
+!
+! proto_tree_add_item(tree, hf_gsm_a_rr_chnl_needed_ch1, tvb, curr_offset, 1, FALSE);
+! proto_tree_add_item(tree, hf_gsm_a_rr_chnl_needed_ch2, tvb, curr_offset, 1, FALSE);
+
+ curr_offset = curr_offset + 1;
+
+! return(curr_offset - offset);
+ }
+ /*
+ * [3] 10.5.2.8a Channel Request Description
+ * [3] 10.5.2.8b Channel Request Description 2
+--- 4885,4910 ----
+ guint8
+ de_rr_chnl_needed(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
+ {
+! proto_tree *subtree;
+! proto_item *item;
+! guint32 curr_offset;
+
+! len = len;
+! curr_offset = offset;
+!
+! item = proto_tree_add_text(tree, tvb, curr_offset, 1, gsm_dtap_elem_strings[DE_RR_CHNL_NEEDED].strptr);
+! subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_CHNL_NEEDED]);
+! proto_tree_add_item(subtree, hf_gsm_a_rr_chnl_needed_ch1, tvb, curr_offset, 1, FALSE);
+! proto_tree_add_item(subtree, hf_gsm_a_rr_chnl_needed_ch2, tvb, curr_offset, 1, FALSE);
+!
+! // we're assuming that this is the second half octet, so go
+! // ahead and increase curr_offset.
+
+ curr_offset = curr_offset + 1;
+
+! return(curr_offset - offset);
+ }
++
+ /*
+ * [3] 10.5.2.8a Channel Request Description
+ * [3] 10.5.2.8b Channel Request Description 2
+***************
+*** 4573,4579 ****
+ }
+ /*
+ * [3] 10.5.2.10 Cipher Response
+! * [3] 10.5.2.11 Control Channel Description
+ * [3] 10.5.2.11a DTM Information Details
+ */
+ /*
+--- 4949,5079 ----
+ }
+ /*
+ * [3] 10.5.2.10 Cipher Response
+! */
+!
+!
+! /*
+! * [3] 10.5.2.11 Control Channel Description // jl
+! */
+!
+! static const true_false_string gsm_a_rr_cc_dsc_mscr_tfs = {
+! "MSC is Release 1999 onwards.",
+! "MSC is Release 1998 or older."
+! };
+!
+! static const true_false_string gsm_a_rr_cc_dsc_att_tfs = {
+! "MSs in the cell shall apply IMSI attach and detach procedure.",
+! "MSs in the cell are not allowed to apply IMSI attach and detach "
+! "procedure."
+! };
+!
+! static const value_string gsm_a_rr_cc_dsc_cbq3_vals[] = {
+! {0, "Iu mode not supported."},
+! {1, "Iu mode capable MSs barred."},
+! {2, "Iu mode supported, cell not barred."},
+! {3, "Iu mode supported, cell not barred. The network shall not use "
+! "this value."},
+! {0, 0}
+! };
+!
+! static const value_string gsm_a_rr_cc_dsc_ccch_vals[] = {
+! {0, "1 basic physical channel used for CCCH, not combined with "
+! "SDCCHs"},
+! {1, "1 basic physical channel used for CCCH, combined with SDCCHs"},
+! {2, "2 basic physical channels used for CCCH, not combined with "
+! "SDCCHs"},
+! {3, "reserved"},
+! {4, "3 basic physical channels used for CCCH, not combined with "
+! "SDCCHs"},
+! {5, "reserved"},
+! {6, "4 basic physical channels used for CCCH, not combined with "
+! "SDCCHs"},
+! {7, "reserved"},
+! {0, 0}
+! };
+!
+! static guint8 de_rr_cc_dsc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) {
+!
+! guint32 curr_offset;
+! guint8 oct;
+! guint curr_len;
+! proto_tree *subtree;
+! proto_item *item;
+! int bsagblksres, ccchconf, bspamfrms, psch;
+! float t3212;
+!
+! curr_offset = offset;
+! curr_len = len;
+!
+! item = proto_tree_add_text(tree, tvb, curr_offset, 3,
+! gsm_dtap_elem_strings[DE_RR_CC_DSC].strptr);
+! subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_CC_DSC]);
+!
+! proto_tree_add_item(subtree, hf_gsm_a_rr_cc_dsc_mscr, tvb, curr_offset,
+! 1, FALSE);
+! proto_tree_add_item(subtree, hf_gsm_a_rr_cc_dsc_att, tvb, curr_offset,
+! 1, FALSE);
+!
+! oct = tvb_get_guint8(tvb, curr_offset);
+!
+! // BS-AG-BLKS-RES
+! bsagblksres = (oct & 0x38) >> 3;
+!
+! // CCCH-CONF
+! ccchconf = (oct & 7);
+!
+! item = proto_tree_add_text(subtree, tvb, curr_offset, 1,
+! "BS-AG-BLKS-RES: ");
+!
+! if((ccchconf == 1) && (bsagblksres > 2))
+! proto_item_append_text(item, "reserved");
+! else
+! proto_item_append_text(item, "%d", bsagblksres);
+!
+! proto_tree_add_item(subtree, hf_gsm_a_rr_cc_dsc_ccch, tvb, curr_offset,
+! 1, FALSE);
+!
+! curr_offset++; curr_len--;
+! proto_tree_add_item(subtree, hf_gsm_a_rr_cc_dsc_cbq3, tvb, curr_offset,
+! 1, FALSE);
+!
+! oct = tvb_get_guint8(tvb, curr_offset);
+!
+! // BS-PA-MFRMS
+! bspamfrms = (oct & 0x7) + 2;
+! proto_tree_add_text(subtree, tvb, curr_offset, 1, "BS-PA-MFRMS: %d "
+! "multiframes period for transmission of PAGING REQUEST messages "
+! "to the same paging subgroup", bspamfrms);
+!
+! curr_offset++; curr_len--;
+! oct = tvb_get_guint8(tvb, curr_offset);
+!
+! // T3212
+! t3212 = (float)oct / 10.0;
+! item = proto_tree_add_text(subtree, tvb, curr_offset, 1, "T3212 "
+! "timeout value: ");
+! if(oct)
+! proto_item_append_text(item, "%.1f hours (%d minutes)",
+! t3212, (int)oct * 6);
+! else
+! proto_item_append_text(item, "infinite (periodic updating "
+! "shall not be used within the cell)");
+!
+! item = proto_tree_add_text(subtree, tvb, curr_offset - 2, 2,
+! "The number of different paging subchannels on the CCCH is ");
+! if(ccchconf == 1)
+! psch = MAX(1, (3 - bsagblksres)) * bspamfrms;
+! else
+! psch = (9 - bsagblksres) * bspamfrms;
+! proto_item_append_text(item, "%d", psch);
+!
+! curr_offset++; curr_len--;
+!
+! return curr_offset - offset;
+! }
+!
+!
+! /*
+ * [3] 10.5.2.11a DTM Information Details
+ */
+ /*
+***************
+*** 4755,4762 ****
+--- 5255,5288 ----
+
+ return(curr_offset - offset);
+ }
++
++
+ /*
+ * [3] 10.5.2.16 IA Rest Octets
++ *
++ * XXX not done
++ */
++ static guint8 de_rr_ia_rest_octets(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
++ {
++ guint32 curr_offset;
++ guint curr_len;
++ // proto_tree *subtree;
++ proto_item *item;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, curr_len, gsm_dtap_elem_strings[DE_RR_IA_REST_OCTETS].strptr);
++ // subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_IA_REST_OCTETS]);
++
++ // len is -1 for mandatory, so can't increase by this.
++ // curr_offset += curr_len;
++
++ return curr_offset - offset;
++ }
++
++
++ /*
+ * [3] 10.5.2.17 IAR Rest Octets
+ * [3] 10.5.2.18 IAX Rest Octets
+ * [3] 10.5.2.19 L2 Pseudo Length
+***************
+*** 4900,4925 ****
+ return(curr_offset - offset);
+
+ }
+ /*
+ * [3] 10.5.2.21c NC mode
+! * [3] 10.5.2.22 Neighbour Cell Description
+ * [3] 10.5.2.22a Neighbour Cell Description 2
+ * [3] 10.5.2.22b (void)
+ * [3] 10.5.2.22c NT/N Rest Octets
+ * [3] 10.5.2.23 P1 Rest Octets
+ * [3] 10.5.2.24 P2 Rest Octets
+ * [3] 10.5.2.25 P3 Rest Octets
+ * [3] 10.5.2.25a Packet Channel Description
+ * [3] 10.5.2.25b Dedicated mode or TBF
+ * [3] 10.5.2.25c RR Packet Uplink Assignment
+ * [3] 10.5.2.25d RR Packet Downlink Assignment
+ * [3] 10.5.2.26 Page Mode
+ * [3] 10.5.2.26a (void)
+ * [3] 10.5.2.26b (void)
+ * [3] 10.5.2.26c (void)
+ * [3] 10.5.2.26d (void)
+- * [3] 10.5.2.27 NCC Permitted
+ */
+ /*
+ * [3] 10.5.2.28 Power Command
+ *
+--- 5426,5786 ----
+ return(curr_offset - offset);
+
+ }
++
++
+ /*
+ * [3] 10.5.2.21c NC mode
+! */
+!
+!
+! /*
+! * [3] 10.5.2.22 Neighbour Cell Description // jl
+! *
+! * The purpose of the Neighbour Cell Description information
+! * element is to provide the absolute radio frequency channel
+! * numbers of the BCCH carriers to be monitored by the mobile
+! * stations in the cell.
+! *
+! * The Neighbour Cell Description information element is coded as
+! * the Cell Channel Description information element, as specified
+! * in sub-clause 10.5.2.1b, with the exception of bits 5 and 6 of
+! * octet 2. Figure 10.5.2.22.1 and table 10.5.2.22.1: contains the
+! * difference of specifications.
+! */
+!
+! static const true_false_string gsm_a_rr_neigh_cell_dsc_ext_tfs = {
+! "The information element carries only a part of the BA",
+! "The information element carries the complete BA"
+! };
+!
+! static const true_false_string gsm_a_rr_neigh_cell_dsc_ba_tfs = {
+! "Base Allocation for SACCH",
+! "Base Allocation for BCCH"
+! };
+!
+! static guint8 de_rr_neigh_cell_dsc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
+! {
+! guint32 curr_offset;
+! guint curr_len;
+! proto_tree *subtree;
+! proto_item *item;
+!
+! curr_offset = offset;
+! curr_len = len;
+!
+! item = proto_tree_add_text(tree, tvb, curr_offset, 16,
+! gsm_dtap_elem_strings[DE_RR_NEIGH_CELL_DSC].strptr);
+! subtree = proto_item_add_subtree(item,
+! ett_gsm_dtap_elem[DE_RR_NEIGH_CELL_DSC]);
+!
+! proto_tree_add_item(subtree, hf_gsm_a_rr_neigh_cell_dsc_ext, tvb,
+! curr_offset, 1, FALSE);
+! proto_tree_add_item(subtree, hf_gsm_a_rr_neigh_cell_dsc_ba, tvb,
+! curr_offset, 1, FALSE);
+!
+! return de_rr_cell_ch_dsc(tvb, tree, curr_offset, curr_len, add_string,
+! string_len);
+! }
+!
+!
+! /*
+ * [3] 10.5.2.22a Neighbour Cell Description 2
+ * [3] 10.5.2.22b (void)
+ * [3] 10.5.2.22c NT/N Rest Octets
++ */
++
++
++ /* // jl
+ * [3] 10.5.2.23 P1 Rest Octets
++ *
++ * XXX not done
++ */
++ static guint8 de_rr_p1_rest_octets(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
++ {
++ guint32 curr_offset;
++ guint curr_len;
++ // proto_tree *subtree;
++ proto_item *item;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, curr_len, gsm_dtap_elem_strings[DE_RR_P1_REST_OCTETS].strptr);
++ // subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_P1_REST_OCTETS]);
++
++ // mandatory elements get len == -1, so we can't increase this
++ // curr_offset += curr_len;
++ return curr_offset - offset;
++ }
++
++
++ /*
+ * [3] 10.5.2.24 P2 Rest Octets
+ * [3] 10.5.2.25 P3 Rest Octets
++ */
++
++
++ /* // jl
+ * [3] 10.5.2.25a Packet Channel Description
++ *
++ * < Packet Channel Description > ::=
++ * < Channel type : bit (5) >
++ * < TN : bit (3) >
++ * < TSC : bit (3) >
++ * { 0
++ * { 0
++ * < spare bit >
++ * < ARFCN : bit (10) > -- non-hopping RF channel configuraion
++ * | 1
++ * < spare bit >
++ * < MAIO : bit (6) > -- indirect encoding of hopping RF channel configuration
++ * < MA_NUMBER_IND : bit >
++ * { 0
++ * < spare bits : bit (2) >
++ * | 1
++ * < CHANGE_MARK_1 : bit (2) >
++ * }
++ * }
++ * | 1
++ * < MAIO : bit (6) > -- direct encoding of hopping RF channel configuration
++ * < HSN : bit (6) >
++ * };
++ *
++ * 5 + 3 + 3 + 1 + 12 = 24
++ */
++ static guint8 de_rr_pcd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, char *add_string _U_, int string_len _U_) {
++
++ guint32 curr_offset;
++ guint curr_len;
++ proto_tree *subtree;
++ proto_item *item;
++ int val, v;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, 3, gsm_dtap_elem_strings[DE_RR_PCD].strptr);
++ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_PCD]);
++
++ val = tvb_get_ntoh24(tvb, curr_offset);
++
++ // channel type
++ other_decode_bitfield_value(a_bigbuf, val, 0x1f0000, 24);
++ proto_tree_add_text(subtree, tvb, curr_offset, 1, "%s : Channel Type: %x", a_bigbuf, (val >> 16) & 0x1f);
++
++ // TN
++ other_decode_bitfield_value(a_bigbuf, val, 0xe00000, 24);
++ proto_tree_add_text(subtree, tvb, curr_offset, 1, "%s : Timeslot Number: %d", a_bigbuf, ((val >> 16) & 0xe0) >> 5);
++
++ curr_offset++;
++ curr_len--;
++
++ // TSC
++ other_decode_bitfield_value(a_bigbuf, val, 0x700, 24);
++ proto_tree_add_text(subtree, tvb, curr_offset, 1, "%s : Training Sequence Code: %d", a_bigbuf, (val >> 8) & 0x7);
++
++ if(!(val & 0x800)) {
++ if(!(val & 0x1000)) {
++ other_decode_bitfield_value(a_bigbuf, val, 0xc0ff, 24);
++ v = ((val & 0xc000) >> 6) | (val & 0xff);
++ proto_tree_add_text(subtree, tvb, curr_offset, 2, "%s : RF Channel Number: %d", a_bigbuf, v);
++
++ curr_offset += 2;
++ curr_len -= 2;
++ } else {
++ other_decode_bitfield_value(a_bigbuf, val, 0xc00f, 24);
++ v = ((val & 0xc000) >> 10) | (val & 0x0f);
++ proto_tree_add_text(subtree, tvb, curr_offset, 2, "%s : Mobile Allocation Index Offset: %d", a_bigbuf, v);
++
++ curr_offset++;
++ curr_len--;
++
++ other_decode_bitfield_value(a_bigbuf, val, 0x10, 24);
++ proto_tree_add_text(subtree, tvb, curr_offset, 1, "%s : MA_NUMBER = %d", a_bigbuf, (val & 0x10)? 15 : 14);
++
++ if(val & 0x20) {
++ other_decode_bitfield_value(a_bigbuf, val, 0xc0, 24);
++ proto_tree_add_text(subtree, tvb, curr_offset, 1, "%s : CHANGE_MARK_1 = %d", a_bigbuf, (val & 0xc0) >> 6);
++
++ curr_offset++;
++ curr_len--;
++ }
++ }
++ } else {
++ other_decode_bitfield_value(a_bigbuf, val, 0xf003, 24);
++ v = ((val & 0xf000) >> 10) | (val & 0x3);
++ proto_tree_add_text(subtree, tvb, curr_offset, 2, "%s : Mobile Allocation Index Offset: %d", a_bigbuf, v);
++
++ curr_offset++;
++ curr_len--;
++
++ other_decode_bitfield_value(a_bigbuf, val, 0xfc, 24);
++ proto_tree_add_text(subtree, tvb, curr_offset, 1, "%s : Hopping Sequence Number: %d", a_bigbuf, (val & 0xfc) >> 2);
++
++ curr_offset++;
++ curr_len--;
++ }
++
++ return curr_offset - offset;
++ }
++
++
++ /* // jl
++ *
+ * [3] 10.5.2.25b Dedicated mode or TBF
++ */
++ static const value_string gsm_a_rr_dm_or_tbf_vals[] = {
++ {0, "This message assigns a dedicated resource"},
++ {2, "Not Used (error)"},
++ {4, "Not Used (error)"},
++ {6, "Not Used (error)"},
++ {1, "This message assigns an uplink TBF or is the second message of two in a two-message assignment of an uplink or downlink TBF"},
++ {3, "This message assigns a downlink TBF to the mobile station identified in the IA Rest Octets IE"},
++ {5, "This message is the first message of two in a two-message assignment of an uplink TBF"},
++ {7, "This message is the first message of two in a two-message assignment of a downlink TBF to the mobile station identified in the IA Rest Octets IE"},
++ {0, 0}
++ };
++
++ static int ia_dedicated_mode_resource = 0;
++ static int ia_tbf = 0;
++
++ static guint8 de_rr_dm_or_tbf(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) {
++
++ guint32 curr_offset;
++ guint curr_len;
++ proto_tree *subtree;
++ proto_item *item;
++ guint8 oct;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, 1, gsm_dtap_elem_strings[DE_RR_DM_OR_TBF].strptr);
++ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_DM_OR_TBF]);
++
++ proto_tree_add_item(subtree, hf_gsm_a_rr_dm_or_tbf, tvb, curr_offset, 1, FALSE);
++ oct = tvb_get_guint8(tvb, curr_offset);
++ if(!(oct & 0x10))
++ ia_dedicated_mode_resource = 1;
++ else
++ ia_tbf = 1;
++
++ // XXX assuming 2nd half of the octet, increasing curr_offset
++ curr_offset++;
++ curr_len--;
++
++ return curr_offset - offset;
++ }
++
++
++ /*
+ * [3] 10.5.2.25c RR Packet Uplink Assignment
+ * [3] 10.5.2.25d RR Packet Downlink Assignment
++ */
++
++ /* // jl
+ * [3] 10.5.2.26 Page Mode
++ *
++ * PM (octet 1)
++ * 2 1
++ * 0 0 Normal paging.
++ * 0 1 Extended paging.
++ * 1 0 Paging reorganization.
++ * 1 1 Same as before.
++ *
++ * NOTE: The value "same as before" has been defined instead of
++ * "reserved" to allow the use of this coding with another meaning in an
++ * upwards compatible way in later phases of the GSM system.
++ */
++ static guint8 de_rr_page_mode(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) {
++
++ guint32 curr_offset;
++ guint curr_len;
++ proto_tree *subtree;
++ proto_item *item;
++ guint8 oct;
++ int pm;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, 1, gsm_dtap_elem_strings[DE_RR_PAGE_MODE].strptr);
++ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_PAGE_MODE]);
++
++ /*
++ * XXX
++ *
++ * The page mode IE is a half octet. We're assuming that it
++ * comes in the bottom half octet. (That is, we assume that it
++ * is the first message at the start of an octet boundary.)
++ */
++ oct = tvb_get_guint8(tvb, curr_offset);
++ pm = (oct & 3);
++ item = proto_tree_add_text(subtree, tvb, curr_offset, 1, "Page Mode: ");
++ switch(pm) {
++ case 0:
++ proto_item_append_text(item, "Normal paging");
++ break;
++ case 1:
++ proto_item_append_text(item, "Extended paging");
++ break;
++ case 2:
++ proto_item_append_text(item, "Paging reorganization");
++ break;
++ case 3:
++ proto_item_append_text(item, "Same as before");
++ break;
++ }
++
++ // we didn't really grab the whole octet, so curr_offset
++ // is not increased.
++
++ return curr_offset - offset;
++ }
++
++
++ /*
+ * [3] 10.5.2.26a (void)
+ * [3] 10.5.2.26b (void)
+ * [3] 10.5.2.26c (void)
+ * [3] 10.5.2.26d (void)
+ */
++
++
++ /* // jl
++ * [3] 10.5.2.27 NCC Permitted
++ *
++ * The NCC permitted field is coded as a bit map, i.e. bit N is
++ * coded with a "0" if the BCCH carrier with NCC = N - 1 is not
++ * permitted for monitoring and with a "1" if the BCCH carrier with
++ * NCC = N - 1 is permitted for monitoring; N = 1, 2, .., 8.
++ */
++ static guint8 de_rr_ncc_permitted(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
++ {
++ guint32 curr_offset;
++ guint curr_len;
++ proto_tree *subtree;
++ proto_item *item;
++ guint8 oct;
++ int bit;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, 1, gsm_dtap_elem_strings[DE_RR_NCC_PERMITTED].strptr);
++ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_NCC_PERMITTED]);
++
++ item = proto_tree_add_text(subtree, tvb, curr_offset, 1, "Allowed NCC on BCCH carriers:");
++ oct = tvb_get_guint8(tvb, curr_offset++);
++
++ for(bit = 0; bit < 8; bit++)
++ if(oct & (1 << bit))
++ proto_item_append_text(item, " %d", bit);
++
++ return curr_offset - offset;
++ }
++
++
+ /*
+ * [3] 10.5.2.28 Power Command
+ *
+***************
+*** 4978,5049 ****
+ proto_item *item;
+ guint32 curr_offset;
+
+! len = len;
+! curr_offset = offset;
+
+! item =
+! proto_tree_add_text(tree,
+! tvb, curr_offset, 1,
+! gsm_dtap_elem_strings[DE_RR_POW_CMD].strptr);
+
+! subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_POW_CMD]);
+
+! proto_tree_add_item(subtree, hf_gsm_a_b8spare, tvb, curr_offset, 1, FALSE);
+! /*EPC mode */
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_epc, tvb, curr_offset, 1, FALSE);
+! /*FPC_EPC*/
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_fpcepc, tvb, curr_offset, 1, FALSE);
+! /*POWER LEVEL*/
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_powlev, tvb, curr_offset, 1, FALSE);
+!
+! curr_offset = curr_offset + 1;
+
+! return(curr_offset - offset);
+ }
+
+ /*
+! * [3] 10.5.2.28a Power Command and access type
+ */
+! static guint8
+! de_rr_pow_cmd_and_acc_type(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
+! {
+! proto_tree *subtree;
+! proto_item *item;
+! guint32 curr_offset;
+
+! len = len;
+! curr_offset = offset;
+
+! item =
+! proto_tree_add_text(tree,
+! tvb, curr_offset, 1,
+! gsm_dtap_elem_strings[DE_RR_POW_CMD_AND_ACC_TYPE].strptr);
+
+! subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_POW_CMD_AND_ACC_TYPE]);
+
+! /*ATC */
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_atc, tvb, curr_offset, 1, FALSE);
+! /*EPC mode */
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_epc, tvb, curr_offset, 1, FALSE);
+! /*FPC_EPC*/
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_fpcepc, tvb, curr_offset, 1, FALSE);
+! /*POWER LEVEL*/
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_powlev, tvb, curr_offset, 1, FALSE);
+!
+! curr_offset = curr_offset + 1;
+
+! return(curr_offset - offset);
+ }
+! /*
+! * [3] 10.5.2.29 RACH Control Parameters
+! * [3] 10.5.2.30 Request Reference
+! */
+
+ /*
+ * [3] 10.5.2.31
+ */
+! guint8
+! de_rr_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
+ {
+ guint32 curr_offset;
+
+--- 5839,6099 ----
+ proto_item *item;
+ guint32 curr_offset;
+
+! len = len;
+! curr_offset = offset;
+!
+! item =
+! proto_tree_add_text(tree,
+! tvb, curr_offset, 1,
+! gsm_dtap_elem_strings[DE_RR_POW_CMD].strptr);
+!
+! subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_POW_CMD]);
+!
+! proto_tree_add_item(subtree, hf_gsm_a_b8spare, tvb, curr_offset, 1, FALSE);
+! /*EPC mode */
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_epc, tvb, curr_offset, 1, FALSE);
+! /*FPC_EPC*/
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_fpcepc, tvb, curr_offset, 1, FALSE);
+! /*POWER LEVEL*/
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_powlev, tvb, curr_offset, 1, FALSE);
+!
+! curr_offset = curr_offset + 1;
+!
+! return(curr_offset - offset);
+! }
+!
+! /*
+! * [3] 10.5.2.28a Power Command and access type
+! */
+! static guint8
+! de_rr_pow_cmd_and_acc_type(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
+! {
+! proto_tree *subtree;
+! proto_item *item;
+! guint32 curr_offset;
+!
+! len = len;
+! curr_offset = offset;
+!
+! item =
+! proto_tree_add_text(tree,
+! tvb, curr_offset, 1,
+! gsm_dtap_elem_strings[DE_RR_POW_CMD_AND_ACC_TYPE].strptr);
+!
+! subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_POW_CMD_AND_ACC_TYPE]);
+!
+! /*ATC */
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_atc, tvb, curr_offset, 1, FALSE);
+! /*EPC mode */
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_epc, tvb, curr_offset, 1, FALSE);
+! /*FPC_EPC*/
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_fpcepc, tvb, curr_offset, 1, FALSE);
+! /*POWER LEVEL*/
+! proto_tree_add_item(subtree, hf_gsm_a_rr_pow_cmd_powlev, tvb, curr_offset, 1, FALSE);
+!
+! curr_offset = curr_offset + 1;
+!
+! return(curr_offset - offset);
+! }
+!
+!
+! /*
+! * [3] 10.5.2.29 RACH Control Parameters
+! *
+! * Max retrans, Maximum number of retransmissions (octet 2)
+! *
+! * Bits
+! * 8 7
+! * 0 0 Maximum 1 retransmission
+! * 0 1 Maximum 2 retransmissions
+! * 1 0 Maximum 4 retransmissions
+! * 1 1 Maximum 7 retransmissions
+! */
+! static const value_string gsm_a_rr_rach_cp_max_retrans_vals[] = {
+! {0, "Maximum 1 retransmission"},
+! {1, "Maximum 2 retransmissions"},
+! {2, "Maximum 4 retransmissions"},
+! {3, "Maximum 7 retransmissions"},
+! {0, 0},
+! };
+!
+!
+! /*
+! * Tx-integer, Number of slots to spread transmission (octet 2)
+! *
+! * Bits
+! * 6 5 4 3
+! * 0 0 0 0 3 slots used to spread transmission
+! * 0 0 0 1 4 slots used to spread transmission
+! * 0 0 1 0 5 slots used to spread transmission
+! * 0 0 1 1 6 slots used to spread transmission
+! * 0 1 0 0 7 slots used to spread transmission
+! * 0 1 0 1 8 slots used to spread transmission
+! * 0 1 1 0 9 slots used to spread transmission
+! * 0 1 1 1 10 slots used to spread transmission
+! * 1 0 0 0 11 slots used to spread transmission
+! * 1 0 0 1 12 slots used to spread transmission
+! * 1 0 1 0 14 slots used to spread transmission
+! * 1 0 1 1 16 slots used to spread transmission
+! * 1 1 0 0 20 slots used to spread transmission
+! * 1 1 0 1 25 slots used to spread transmission
+! * 1 1 1 0 32 slots used to spread transmission
+! * 1 1 1 1 50 slots used to spread transmission
+! */
+! static const value_string gsm_a_rr_rach_cp_tx_integer_vals[] = {
+! {0, "3 slots used to spread transmission"},
+! {1, "4 slots used to spread transmission"},
+! {2, "5 slots used to spread transmission"},
+! {3, "6 slots used to spread transmission"},
+! {4, "7 slots used to spread transmission"},
+! {5, "8 slots used to spread transmission"},
+! {6, "9 slots used to spread transmission"},
+! {7, "10 slots used to spread transmission"},
+! {8, "11 slots used to spread transmission"},
+! {9, "12 slots used to spread transmission"},
+! {10, "14 slots used to spread transmission"},
+! {11, "16 slots used to spread transmission"},
+! {12, "20 slots used to spread transmission"},
+! {13, "25 slots used to spread transmission"},
+! {14, "32 slots used to spread transmission"},
+! {15, "50 slots used to spread transmission"},
+! {0, 0},
+! };
+!
+! /*
+! * CELL_BAR_ACCESS, Cell Barred for Access (octet 2)
+! *
+! * Bit 2
+! * 0 The cell is not barred, see 3GPP TS 23.022
+! * 1 The cell is barred, see 3GPP TS 23.022
+! */
+! static const true_false_string gsm_a_rr_rach_cp_cell_bar_access_tfs = {
+! "The cell is barred, see 3GPP TS 23.022",
+! "The cell is not barred, see 3GPP TS 23.022"
+! };
+!
+! static const value_string gsm_a_rr_rach_cp_cell_bar_access_vals[] = {
+! {0, "The cell is not barred"},
+! {1, "The cell is barred"},
+! {0, 0},
+! };
+!
+! /*
+! * RE, Call reestablishment allowed (octet 2)
+! *
+! * Bit 1
+! * 0 Call Reestablishment allowed in the cell
+! * 1 Call Reestablishment not allowed in the cell
+! */
+! static const true_false_string gsm_a_rr_rach_cp_re_tfs = {
+! "Call Reestablishment not allowed in the cell",
+! "Call Reestablishment allowed in the cell"
+! };
+!
+! static const value_string gsm_a_rr_rach_cp_re_vals[] = {
+! {0, "Call Reestablishment is allowed in the cell"},
+! {1, "Call Reestablishment is not allowed in the cell"},
+! {0, 0},
+! };
+!
+! /*
+! * EC Emergency Call allowed (octet 3 bit 3)
+! *
+! * Bit 3
+! * 0 Emergency call allowed in the cell to all MSs
+! * 1 Emergency call not allowed in the cell except for the MSs that belong to one of the classes between 11 to 15.
+! */
+! static const true_false_string gsm_a_rr_rach_cp_ec_tfs = {
+! "Emergency call not allowed in the cell except for the MSs that belong to one of the classes between 11 to 15.",
+! "Emergency call allowed in the cell to all MSs"
+! };
+!
+! static const value_string gsm_a_rr_rach_cp_ec_vals[] = {
+! {0, "Emergency call allowed in the cell to all MSs"},
+! {1, "Emergency call not allowed in the cell except for the MSs that belong to one of the classes between 11 and 15"},
+! {0, 0},
+! };
+!
+! /* AC CN, Access Control Class N (octet 3 (except bit 3) and octet 4)
+! *
+! * For a mobile station with AC C = N access is not barred if the AC CN bit is coded with a "0"; N = 0, 1, .. 9,11, .., 15.
+! */
+!
+! static guint8 de_rr_rach_cp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) {
+
+! proto_tree *subtree;
+! proto_item *item;
+! guint16 accn;
+! guint32 curr_offset;
+! guint curr_len;
+! guint bit;
+
+! curr_len = len;
+! curr_offset = offset;
+
+! item = proto_tree_add_text(tree, tvb, curr_offset, 3, gsm_dtap_elem_strings[DE_RR_RACH_CP].strptr);
+! subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_RACH_CP]);
+
+! proto_tree_add_item(subtree, hf_gsm_a_rr_rach_cp_max_retrans, tvb, curr_offset, 1, FALSE);
+! proto_tree_add_item(subtree, hf_gsm_a_rr_rach_cp_tx_integer, tvb, curr_offset, 1, FALSE);
+! proto_tree_add_item(subtree, hf_gsm_a_rr_rach_cp_cell_bar_access, tvb, curr_offset, 1, FALSE);
+! proto_tree_add_item(subtree, hf_gsm_a_rr_rach_cp_re, tvb, curr_offset, 1, FALSE);
+! proto_tree_add_item(subtree, hf_gsm_a_rr_rach_cp_ec, tvb, curr_offset + 1, 1, FALSE);
+!
+! curr_offset++;
+! accn = tvb_get_ntohs(tvb, curr_offset);
+! item = proto_tree_add_text(subtree, tvb, curr_offset, 2, "Access Classes not barred:");
+! bit = 16;
+! while(bit-- > 0)
+! if(bit != 10)
+! if((accn & (1 << bit)) == 0)
+! proto_item_append_text(item, " %d", bit);
+!
+! curr_offset += 2;
+! return curr_offset - offset;
+ }
+
++
+ /*
+! * [3] 10.5.2.30 Request Reference
+ */
+! static guint8 de_rr_req_ref(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_) {
+
+! proto_tree *subtree;
+! proto_item *item;
+! guint32 curr_offset;
+! guint curr_len;
+! int v, t1p, t2, t3;
+
+! curr_len = len;
+! curr_offset = offset;
+
+! item = proto_tree_add_text(tree, tvb, curr_offset, 3, gsm_dtap_elem_strings[DE_RR_REQ_REF].strptr);
+! subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_REQ_REF]);
+
+! v = tvb_get_guint8(tvb, curr_offset);
+! proto_tree_add_text(subtree, tvb, curr_offset, 1, "Random Access Information: %x", v);
+
+! curr_offset++;
+! curr_len--;
+!
+! v = tvb_get_ntohs(tvb, curr_offset);
+! t1p = (v & 0xf800) >> 11;
+! t3 = ((v & 0x700) >> 5) | ((v & 0xe0) >> 5);
+! t2 = v & 0x1f;
+! proto_tree_add_text(subtree, tvb, curr_offset, 2, "FN modulo 42432: %d", 51 * ((t3 - t2) % 26) + t3 + 51 * 26 * t1p);
+!
+! curr_offset += 2;
+! curr_len -= 2;
+!
+! return curr_offset - offset;
+ }
+!
+
+ /*
+ * [3] 10.5.2.31
+ */
+! guint8 de_rr_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
+ {
+ guint32 curr_offset;
+
+***************
+*** 5056,5068 ****
+
+ return(curr_offset - offset);
+ }
+ /*
+- * [3] 10.5.2.32 SI 1 Rest Octets
+ * [3] 10.5.2.33 SI 2bis Rest Octets
+ * [3] 10.5.2.33a SI 2ter Rest Octets
+ * [3] 10.5.2.33b SI 2quater Rest Octets
+ * [3] 10.5.2.34 SI 3 Rest Octets
+ * [3] 10.5.2.35 SI 4 Rest Octets
+ * [3] 10.5.2.35a SI 6 Rest Octets
+ * [3] 10.5.2.36 SI 7 Rest Octets
+ * [3] 10.5.2.37 SI 8 Rest Octets
+--- 6106,6288 ----
+
+ return(curr_offset - offset);
+ }
++
++
++ /*
++ * [4] 10.5.2.32 SI 1 Rest Octets
++ *
++ * NCH Position (5 bits) | Band Indicator | Spare
++ *
++ * NCH Position on the CCCH
++ *
++ * The values in the NCH Position field indicates the block
++ * number of the CCCH block which is used for the first NCH
++ * block and the number of blocks used for the NCH. (The
++ * block numbering corresponds to table 5 in clause 7 of
++ * 3GPP TS 45.002) The absence of the NCH position field
++ * indicates that there is no NCH in the cell/on the
++ * carrying CCCH slot The following coding applies if 1 or
++ * more basic physical channels are used for CCCH, not
++ * combined with SDCCHs.
++ *
++ * Value # blocks # of 1 block
++ * 00000 1 0
++ * 00001 1 1
++ * 00010 1 2
++ * 00011 1 3
++ * 00100 1 4
++ * 00101 1 5
++ * 00110 1 6
++ * 00111 2 0
++ * 01000 2 1
++ * 01001 2 2
++ * 01010 2 3
++ * 01011 2 4
++ * 01100 2 5
++ * 01101 3 0
++ * 01110 3 1
++ * 01111 3 2
++ * 10000 3 3
++ * 10001 3 4
++ * 10010 4 0
++ * 10011 4 1
++ * 10100 4 2
++ * 10101 4 3
++ * 10110 5 0
++ * 10111 5 1
++ * 11000 5 2
++ * 11001 6 0
++ * 11010 6 1
++ * 11011 7 0
++ *
++ * Other values are reserved for future use. A mobile
++ * station receiving a reserved value shall behave as if
++ * the NCH position was not present
++ *
++ * Band Indicator
++ *
++ * 0 ARFCN indicates 1800 band
++ * 1 ARFCN indicates 1900 band
++ */
++ static const value_string gsm_a_rr_si_1_rest_octets_vals[] = {
++ {0x0, "NCH position on the CCCH: 1 block starting at block 0"},
++ {0x1, "NCH position on the CCCH: 1 block starting at block 1"},
++ {0x2, "NCH position on the CCCH: 1 block starting at block 2"},
++ {0x3, "NCH position on the CCCH: 1 block starting at block 3"},
++ {0x4, "NCH position on the CCCH: 1 block starting at block 4"},
++ {0x5, "NCH position on the CCCH: 1 block starting at block 5"},
++ {0x6, "NCH position on the CCCH: 1 block starting at block 6"},
++ {0x7, "NCH position on the CCCH: 2 blocks starting at block 0"},
++ {0x8, "NCH position on the CCCH: 2 blocks starting at block 1"},
++ {0x9, "NCH position on the CCCH: 2 blocks starting at block 2"},
++ {0xa, "NCH position on the CCCH: 2 blocks starting at block 3"},
++ {0xb, "NCH position on the CCCH: 2 blocks starting at block 4"},
++ {0xc, "NCH position on the CCCH: 2 blocks starting at block 5"},
++ {0xd, "NCH position on the CCCH: 3 blocks starting at block 0"},
++ {0xe, "NCH position on the CCCH: 3 blocks starting at block 1"},
++ {0xf, "NCH position on the CCCH: 3 blocks starting at block 2"},
++ {0x10, "NCH position on the CCCH: 3 blocks starting at block 3"},
++ {0x11, "NCH position on the CCCH: 3 blocks starting at block 4"},
++ {0x12, "NCH position on the CCCH: 4 blocks starting at block 0"},
++ {0x13, "NCH position on the CCCH: 4 blocks starting at block 1"},
++ {0x14, "NCH position on the CCCH: 4 blocks starting at block 2"},
++ {0x15, "NCH position on the CCCH: 4 blocks starting at block 3"},
++ {0x16, "NCH position on the CCCH: 5 blocks starting at block 0"},
++ {0x17, "NCH position on the CCCH: 5 blocks starting at block 1"},
++ {0x18, "NCH position on the CCCH: 5 blocks starting at block 2"},
++ {0x19, "NCH position on the CCCH: 6 blocks starting at block 0"},
++ {0x1a, "NCH position on the CCCH: 6 blocks starting at block 1"},
++ {0x1b, "NCH position on the CCCH: 7 blocks starting at block 0"},
++ {0, 0},
++ };
++
++ static guint8 de_rr_si_1_rest_octets(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
++ {
++ proto_tree *subtree;
++ proto_item *item;
++ guint32 curr_offset;
++ guint curr_len;
++ guint8 oct;
++
++ curr_len = len;
++ curr_offset = offset;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, 1, gsm_dtap_elem_strings[DE_RR_SI_1_REST_OCTETS].strptr);
++ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_SI_1_REST_OCTETS]);
++ proto_tree_add_item(subtree, hf_gsm_a_rr_si_1_rest_octets, tvb, curr_offset, 1, FALSE);
++
++ // ??? oct = tvb_get_guint8(tvb, curr_offset) & 0x4;
++ oct = tvb_get_guint8(tvb, curr_offset) & 0x20;
++
++ item = proto_tree_add_text(subtree, tvb, curr_offset, 1, "ARFCN: ");
++ if(!oct)
++ proto_item_append_text(item, "1800 band");
++ else
++ proto_item_append_text(item, "1900 band");
++
++ curr_offset++;
++
++ return curr_offset - offset;
++ }
++
++
+ /*
+ * [3] 10.5.2.33 SI 2bis Rest Octets
+ * [3] 10.5.2.33a SI 2ter Rest Octets
+ * [3] 10.5.2.33b SI 2quater Rest Octets
++ */
++
++ /* // jl
+ * [3] 10.5.2.34 SI 3 Rest Octets
++ *
++ * XXX not done
++ */
++ static guint8 de_rr_si_3_rest_octets(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
++ {
++ proto_item *item;
++ // proto_tree *subtree;
++ guint32 curr_offset;
++ guint curr_len;
++
++ curr_len = len;
++ curr_offset = offset;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, 4, gsm_dtap_elem_strings[DE_RR_SI_3_REST_OCTETS].strptr);
++ // subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_SI_3_REST_OCTETS]);
++
++ curr_offset += 4;
++
++ return curr_offset - offset;
++ }
++
++
++ /* // jl
+ * [3] 10.5.2.35 SI 4 Rest Octets
++ *
++ * XXX not done
++ */
++ static guint8 de_rr_si_4_rest_octets(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
++ {
++ // proto_tree *subtree;
++ proto_item *item;
++ guint32 curr_offset;
++ guint curr_len;
++
++ curr_len = len;
++ curr_offset = offset;
++
++ item = proto_tree_add_text(tree, tvb, curr_offset, curr_len, gsm_dtap_elem_strings[DE_RR_SI_4_REST_OCTETS].strptr);
++ // subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_RR_SI_4_REST_OCTETS]);
++
++ // len is -1 on mandatory elements, so we can't increase by
++ // this.
++ //curr_offset += curr_len;
++
++ return curr_offset - offset;
++ }
++
++
++ /*
+ * [3] 10.5.2.35a SI 6 Rest Octets
+ * [3] 10.5.2.36 SI 7 Rest Octets
+ * [3] 10.5.2.37 SI 8 Rest Octets
+***************
+*** 12736,12745 ****
+ * [3] 10.5.2.1e Cell selection indicator after release of all TCH and SDCCH IE
+ */
+ de_rr_cell_dsc, /* 10.5.2.2 RR Cell Description */
+ /*
+- * [3] 10.5.2.3 Cell Options (BCCH)
+ * [3] 10.5.2.3a Cell Options (SACCH)
+! * [3] 10.5.2.4 Cell Selection Parameters
+ * [3] 10.5.2.4a (void)
+ */
+ de_rr_ch_dsc, /* [3] 10.5.2.5 Channel Description */
+--- 13956,13967 ----
+ * [3] 10.5.2.1e Cell selection indicator after release of all TCH and SDCCH IE
+ */
+ de_rr_cell_dsc, /* 10.5.2.2 RR Cell Description */
++ de_rr_co_bcch, /* [3] 10.5.2.3 Cell Options (BCCH) */
+ /*
+ * [3] 10.5.2.3a Cell Options (SACCH)
+! */
+! de_rr_cell_sel_param, /* [3] 10.5.2.4 Cell Selection Parameters */
+! /*
+ * [3] 10.5.2.4a (void)
+ */
+ de_rr_ch_dsc, /* [3] 10.5.2.5 Channel Description */
+***************
+*** 12757,12765 ****
+ * [3] 10.5.2.8b Channel Request Description 2 */
+ /* Pos 20 */
+ de_rr_cip_mode_set, /* [3] 10.5.2.9 Cipher Mode Setting */
+! /* [3] 10.5.2.10 Cipher Response
+! * [3] 10.5.2.11 Control Channel Description
+! * [3] 10.5.2.11a DTM Information Details */
+ de_rr_dyn_arfcn_map, /* [3] 10.5.2.11b Dynamic ARFCN Mapping */
+ de_rr_freq_ch_seq, /* [3] 10.5.2.12 Frequency Channel Sequence */
+ de_rr_freq_list, /* [3] 10.5.2.13 Frequency List */
+--- 13979,13987 ----
+ * [3] 10.5.2.8b Channel Request Description 2 */
+ /* Pos 20 */
+ de_rr_cip_mode_set, /* [3] 10.5.2.9 Cipher Mode Setting */
+! /* [3] 10.5.2.10 Cipher Response */
+! de_rr_cc_dsc, /* [3] 10.5.2.11 Control Channel Description */
+! /* [3] 10.5.2.11a DTM Information Details */
+ de_rr_dyn_arfcn_map, /* [3] 10.5.2.11b Dynamic ARFCN Mapping */
+ de_rr_freq_ch_seq, /* [3] 10.5.2.12 Frequency Channel Sequence */
+ de_rr_freq_list, /* [3] 10.5.2.13 Frequency List */
+***************
+*** 12771,12778 ****
+ * [3] 10.5.2.14e Enhanced DTM CS Release Indication
+ */
+ de_rr_ho_ref, /* 10.5.2.15 Handover Reference */
+ /*
+- * [3] 10.5.2.16 IA Rest Octets
+ * [3] 10.5.2.17 IAR Rest Octets
+ * [3] 10.5.2.18 IAX Rest Octets
+ * [3] 10.5.2.19 L2 Pseudo Length
+--- 13993,14000 ----
+ * [3] 10.5.2.14e Enhanced DTM CS Release Indication
+ */
+ de_rr_ho_ref, /* 10.5.2.15 Handover Reference */
++ de_rr_ia_rest_octets, /* [3] 10.5.2.16 IA Rest Octets */
+ /*
+ * [3] 10.5.2.17 IAR Rest Octets
+ * [3] 10.5.2.18 IAX Rest Octets
+ * [3] 10.5.2.19 L2 Pseudo Length
+***************
+*** 12786,12823 ****
+ de_rr_mult_all, /* [3] 10.5.2.21b Multislot Allocation */
+ /*
+ * [3] 10.5.2.21c NC mode
+! * [3] 10.5.2.22 Neighbour Cell Description
+ * [3] 10.5.2.22a Neighbour Cell Description 2
+ * [3] 10.5.2.22b (void)
+ * [3] 10.5.2.22c NT/N Rest Octets
+! * [3] 10.5.2.23 P1 Rest Octets
+ * [3] 10.5.2.24 P2 Rest Octets
+ * [3] 10.5.2.25 P3 Rest Octets
+! * [3] 10.5.2.25a Packet Channel Description
+! * [3] 10.5.2.25b Dedicated mode or TBF
+ * [3] 10.5.2.25c RR Packet Uplink Assignment
+ * [3] 10.5.2.25d RR Packet Downlink Assignment
+! * [3] 10.5.2.26 Page Mode
+ * [3] 10.5.2.26a (void)
+ * [3] 10.5.2.26b (void)
+ * [3] 10.5.2.26c (void)
+ * [3] 10.5.2.26d (void)
+- * [3] 10.5.2.27 NCC Permitted
+- */
+- de_rr_pow_cmd, /* 10.5.2.28 Power Command */
+- de_rr_pow_cmd_and_acc_type, /* 10.5.2.28a Power Command and access type */
+- /*
+- * [3] 10.5.2.29 RACH Control Parameters
+- * [3] 10.5.2.30 Request Reference
+ */
+! de_rr_cause, /* 10.5.2.31 RR Cause */
+! de_rr_sync_ind, /* 10.5.2.39 Synchronization Indication */
+ /* [3] 10.5.2.32 SI 1 Rest Octets
+ * [3] 10.5.2.33 SI 2bis Rest Octets
+ * [3] 10.5.2.33a SI 2ter Rest Octets
+ * [3] 10.5.2.33b SI 2quater Rest Octets
+! * [3] 10.5.2.34 SI 3 Rest Octets
+! * [3] 10.5.2.35 SI 4 Rest Octets
+ * [3] 10.5.2.35a SI 6 Rest Octets
+ * [3] 10.5.2.36 SI 7 Rest Octets
+ * [3] 10.5.2.37 SI 8 Rest Octets
+--- 14008,14054 ----
+ de_rr_mult_all, /* [3] 10.5.2.21b Multislot Allocation */
+ /*
+ * [3] 10.5.2.21c NC mode
+! */
+! de_rr_neigh_cell_dsc, /* [3] 10.5.2.22 Neighbour Cell Description */ // jl
+! /*
+ * [3] 10.5.2.22a Neighbour Cell Description 2
+ * [3] 10.5.2.22b (void)
+ * [3] 10.5.2.22c NT/N Rest Octets
+! */
+! de_rr_p1_rest_octets, /* [3] 10.5.2.23 P1 Rest Octets */ // jl
+! /*
+ * [3] 10.5.2.24 P2 Rest Octets
+ * [3] 10.5.2.25 P3 Rest Octets
+! */
+! de_rr_pcd, /* [3] 10.5.2.25a Packet Channel Description */
+! de_rr_dm_or_tbf, /* [3] 10.5.2.25b Dedicated mode or TBF */
+! /*
+ * [3] 10.5.2.25c RR Packet Uplink Assignment
+ * [3] 10.5.2.25d RR Packet Downlink Assignment
+! */
+! de_rr_page_mode, /* [3] 10.5.2.26 Page Mode */ // jl
+! /*
+ * [3] 10.5.2.26a (void)
+ * [3] 10.5.2.26b (void)
+ * [3] 10.5.2.26c (void)
+ * [3] 10.5.2.26d (void)
+ */
+! de_rr_ncc_permitted, /* [3] 10.5.2.27 NCC Permitted */
+! de_rr_pow_cmd, /* [3] 10.5.2.28 Power Command */
+! de_rr_pow_cmd_and_acc_type, /* [3] 10.5.2.28a Power Command and access type */
+! de_rr_rach_cp, /* [3] 10.5.2.29 RACH Control Parameters */ // jl
+! de_rr_req_ref, /* [3] 10.5.2.30 Request Reference */
+! de_rr_cause, /* [3] 10.5.2.31 RR Cause */
+! de_rr_sync_ind, /* [3] 10.5.2.39 Synchronization Indication */
+! de_rr_si_1_rest_octets, /* [3] 10.5.2.32 SI 1 Rest Octets */
+ /* [3] 10.5.2.32 SI 1 Rest Octets
+ * [3] 10.5.2.33 SI 2bis Rest Octets
+ * [3] 10.5.2.33a SI 2ter Rest Octets
+ * [3] 10.5.2.33b SI 2quater Rest Octets
+! */
+! de_rr_si_3_rest_octets, /* [3] 10.5.2.34 SI 3 Rest Octets */
+! de_rr_si_4_rest_octets, /* [3] 10.5.2.35 SI 4 Rest Octets */
+! /*
+ * [3] 10.5.2.35a SI 6 Rest Octets
+ * [3] 10.5.2.36 SI 7 Rest Octets
+ * [3] 10.5.2.37 SI 8 Rest Octets
+***************
+*** 15275,15280 ****
+--- 16506,16556 ----
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+ }
++
++
++ /* // jl
++ *
++ * 44.018 9.1.18 Immediate Assignment
++ *
++ * 10.5.2.26 Page Mode M V .5
++ * 10.5.2.25b Dedicated Mode or TBF M V .5
++ * 10.5.2.5 Channel Description C V 3
++ * 10.5.2.25a Packet Channel Description C V 3
++ * 10.5.2.30 Request Reference M V 3
++ * 10.5.2.40 Timing Advance M V 1
++ * 10.5.2.21 Mobile Allocation M LV 1-9
++ * 10.5.2.38 Starting Time O TV 3 (0x7c)
++ * 10.5.2.16 IA Rest Octets M V 0-11
++ */
++
++ void dtap_rr_immediate_assignment(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) {
++
++ guint32 curr_offset;
++ guint32 consumed;
++ guint curr_len;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_PAGE_MODE);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_DM_OR_TBF);
++ if(ia_dedicated_mode_resource) {
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_CELL_CH_DSC);
++ ia_dedicated_mode_resource = 0;
++ } else if(ia_tbf) {
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_PCD);
++ ia_tbf = 0;
++ }
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_REQ_REF);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_TIMING_ADV);
++ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RR_MOB_ALL, " - Immediate Assignment Mobile Allocation");
++ ELEM_OPT_TV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_RR_STARTING_TIME, " - Immediate Assignment Starting Time");
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_IA_REST_OCTETS);
++
++ // EXTRANEOUS_DATA_CHECK(curr_len, 0);
++ }
++
++
+ /* 3GPP TS 24.008 version 4.7.0 Release 4
+ * [3] 9.1.15
+ */
+***************
+*** 15404,15409 ****
+--- 16680,16715 ----
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ }
++
++
++ /* // jl
++ * 44.018 9.1.22 Paging Request Type 1
++ *
++ * 10.5.2.26 Page Mode M V .5
++ * 10.5.2.8 Channels Needed M V .5
++ * 10.5.1.4 Mobile Identity 1 M LV 2 - 9
++ * 10.5.1.4 Mobile Identity 2 O TLV 3 - 10 (0x17)
++ * 10.5.2.23 P1 Rest Octets M V 0-17
++ */
++ static void dtap_rr_paging_req_1(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) {
++
++ guint32 curr_offset;
++ guint32 consumed;
++ guint curr_len;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_PAGE_MODE);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_CHNL_NEEDED);
++ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, " 1");
++ ELEM_OPT_TLV(0x17, BSSAP_PDU_TYPE_DTAP, DE_MID, " 2");
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_P1_REST_OCTETS);
++
++ // EXTRANEOUS_DATA_CHECK(curr_len, 0);
++ }
++
++
+ /*
+ * [4] 9.1.25
+ */
+***************
+*** 15498,15503 ****
+--- 16804,16930 ----
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+ }
+
++
++ /*
++ * 44.018 9.1.31 System Information Type 1
++ *
++ * 10.5.2.19 L2 pseudo length M V 1
++ * 10.2 RR Protocol Discriminator M V .5
++ * 10.3.1 Skip Indicator M V .5
++ * 10.4 System Information Type 1 Message Type M V 1
++ * 10.5.2.1b Cell Channel Description M V 16
++ * 10.5.2.29 RACH Control Parameters M V 3
++ * 10.5.2.32 SI 1 Rest Octects M V 1
++ */
++ static void dtap_rr_system_information_1(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) {
++
++ guint32 curr_offset;
++ guint32 consumed;
++ guint curr_len;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_CELL_CH_DSC);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_RACH_CP);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_SI_1_REST_OCTETS);
++
++ EXTRANEOUS_DATA_CHECK(curr_len, 0);
++ }
++
++
++ /*
++ * 44.018 9.1.32 System Information Type 2
++ *
++ *
++ * 10.5.2.19 L2 pseudo length M V 1
++ * 10.2 RR Protocol Discriminator M V .5
++ * 10.3.1 Skip Indicator M V .5
++ * 10.4 System Information Type 1 Message Type M V 1
++ * 10.5.2.22 BCCH Frequency List Neighbor Cell Desc M V 16
++ * 10.5.2.27 NCC Permitted M V 1
++ * 10.5.2.29 RACH Control Parameters M V 3
++ */
++ static void dtap_rr_system_information_2(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) {
++
++ guint32 curr_offset;
++ guint32 consumed;
++ guint curr_len;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_NEIGH_CELL_DSC);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_NCC_PERMITTED);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_RACH_CP);
++
++ EXTRANEOUS_DATA_CHECK(curr_len, 0);
++ }
++
++
++ /*
++ * 44.018 9.1.35 System Information Type 3
++ *
++ * 10.5.1.1 Cell Identity M V 2
++ * 10.5.1.3 Location Area Identification M V 5
++ * 10.5.2.11 Control Channel Description M V 3
++ * 10.5.2.3 Cell Options BCCH M V 1
++ * 10.5.2.4 Cell Selection Parameters M V 2
++ * 10.5.2.29 RACH Control Parameters M V 3
++ * 10.5.2.34 SI 3 Rest Octets M V 4
++ */
++ static void dtap_rr_system_information_3(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) {
++
++ guint32 curr_offset;
++ guint32 consumed;
++ guint curr_len;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_CELL_ID);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_LAI);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_CC_DSC);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_CO_BCCH);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_CELL_SEL_PARAM);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_RACH_CP);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_SI_3_REST_OCTETS);
++
++ EXTRANEOUS_DATA_CHECK(curr_len, 0);
++ }
++
++
++ /*
++ * 44.018 9.1.36 System Information Type 4
++ *
++ * 10.5.1.3 Location Area Identification M V 5
++ * 10.5.2.4 Cell Selection Parameters M V 2
++ * 10.5.2.29 RACH Control Parameters M V 3
++ * 10.5.2.5 CBCH Channel Description O TV 4 (64)
++ * 10.5.2.21 CBCH Mobile Allocation C TLV 3-6 (72)
++ * 10.5.2.35 SI 4 Rest Octets M V 0-10
++ */
++ static void dtap_rr_system_information_4(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) {
++
++ guint32 curr_offset;
++ guint32 consumed;
++ guint curr_len;
++
++ curr_offset = offset;
++ curr_len = len;
++
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_LAI);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_CELL_SEL_PARAM);
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_RACH_CP);
++ ELEM_OPT_TV(0x64, BSSAP_PDU_TYPE_DTAP, DE_RR_CH_DSC, "CBCH Channel Description");
++ // next is actually conditional
++ ELEM_OPT_TLV(0x72, BSSAP_PDU_TYPE_DTAP, DE_RR_MOB_ALL, "CBCH Mobile Allocation");
++ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_SI_4_REST_OCTETS);
++
++ // EXTRANEOUS_DATA_CHECK(curr_len, 0);
++ }
++
++
+ /*
+ * [4] 9.3.1
+ */
+***************
+*** 17738,17744 ****
+ static void (*dtap_msg_rr_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ NULL, /* RR Initialisation Request */
+ NULL, /* Additional Assignment */
+! NULL, /* Immediate Assignment */
+ NULL, /* Immediate Assignment Extended */
+ NULL, /* Immediate Assignment Reject */
+
+--- 19165,19171 ----
+ static void (*dtap_msg_rr_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ NULL, /* RR Initialisation Request */
+ NULL, /* Additional Assignment */
+! dtap_rr_immediate_assignment, /* Immediate Assignment */
+ NULL, /* Immediate Assignment Extended */
+ NULL, /* Immediate Assignment Reject */
+
+***************
+*** 17771,17777 ****
+ NULL, /* Partial Release */
+ NULL, /* Partial Release Complete */
+
+! NULL, /* Paging Request Type 1 */
+ NULL, /* Paging Request Type 2 */
+ NULL, /* Paging Request Type 3 */
+ dtap_rr_paging_resp, /* Paging Response */
+--- 19198,19204 ----
+ NULL, /* Partial Release */
+ NULL, /* Partial Release Complete */
+
+! dtap_rr_paging_req_1, /* Paging Request Type 1 */
+ NULL, /* Paging Request Type 2 */
+ NULL, /* Paging Request Type 3 */
+ dtap_rr_paging_resp, /* Paging Response */
+***************
+*** 17788,17797 ****
+ NULL, /* Inter System to cdma2000 Handover Command */
+
+ NULL, /* System Information Type 8 */
+! NULL, /* System Information Type 1 */
+! NULL, /* System Information Type 2 */
+! NULL, /* System Information Type 3 */
+! NULL, /* System Information Type 4 */
+ NULL, /* System Information Type 5 */
+ NULL, /* System Information Type 6 */
+ NULL, /* System Information Type 7 */
+--- 19215,19224 ----
+ NULL, /* Inter System to cdma2000 Handover Command */
+
+ NULL, /* System Information Type 8 */
+! dtap_rr_system_information_1, /* System Information Type 1 */ // jl
+! dtap_rr_system_information_2, /* System Information Type 2 */ // jl
+! dtap_rr_system_information_3, /* System Information Type 3 */ // jl
+! dtap_rr_system_information_4, /* System Information Type 4 */ // jl
+ NULL, /* System Information Type 5 */
+ NULL, /* System Information Type 6 */
+ NULL, /* System Information Type 7 */
+***************
+*** 18203,18212 ****
+--- 19630,19649 ----
+ return;
+ }
+
++ /*
++ * XXX assuming GNU Radio input
++ */
++ if(check_col(pinfo->cinfo, COL_PROTOCOL))
++ col_set_str(pinfo->cinfo, COL_PROTOCOL, "GSM");
++ if(check_col(pinfo->cinfo, COL_INFO))
++ col_clear(pinfo->cinfo, COL_INFO);
++
++ /* XXX orig
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, "(DTAP) ");
+ }
++ */
+
+ /*
+ * set tap record pointer
+***************
+*** 18460,18465 ****
+--- 19897,20061 ----
+
+ static hf_register_info hf[] =
+ {
++ // jl
++ {
++ &hf_gsm_a_rr_rach_cp_max_retrans,
++ {
++ "Maximum number of retransmissions",
++ "gsm_a.rr.rach_cp.max_retrans", FT_UINT8,
++ BASE_HEX,
++ VALS(gsm_a_rr_rach_cp_max_retrans_vals),
++ 0xc0, "Maximum number of retransmissions",
++ HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_rach_cp_tx_integer,
++ {
++ "Number of slots to spread transmissions",
++ "gsm_a.rr.rach_cp.tx_integer", FT_UINT8,
++ BASE_HEX,
++ VALS(gsm_a_rr_rach_cp_tx_integer_vals),
++ 0x3c, "Tx-integer, Number of slots to "
++ "spread tranmissions", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_rach_cp_cell_bar_access,
++ {
++ "Cell Barred for Access",
++ "gsm_a.rr.rach_cp.cell_bar_access",
++ FT_UINT8, 1,
++ VALS(
++ &gsm_a_rr_rach_cp_cell_bar_access_vals),
++ 0x2,
++ "CELL_BAR_ACCESS, Cell Barred for Access",
++ HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_rach_cp_re,
++ {
++ "Call reestablishment allowed",
++ "gsm_a.rr.rach_cp.re", FT_UINT8, 1,
++ VALS(&gsm_a_rr_rach_cp_re_vals), 0x1,
++ "RE, Call reestablishment allowed", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_si_1_rest_octets,
++ {
++ "SI 1 Rest Octets",
++ "gsm_a.rr.si_1.rest_octets", FT_UINT8,
++ BASE_HEX,
++ VALS(gsm_a_rr_si_1_rest_octets_vals), 0x1f,
++ "SI 1 Rest Octets", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_neigh_cell_dsc_ext,
++ {
++ "Extension Indication",
++ "gsm_a.rr.neigh_cell_dsc.ext", FT_BOOLEAN,
++ 1, TFS(&gsm_a_rr_neigh_cell_dsc_ext_tfs),
++ 0x20, "Extension Indication", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_neigh_cell_dsc_ba,
++ {
++ "BACCH allocation sequence number indication",
++ "gsm_a.rr.neigh_cell_dsc.ba", FT_BOOLEAN, 1,
++ TFS(&gsm_a_rr_neigh_cell_dsc_ba_tfs), 0x10,
++ "BACCH allocation sequence number "
++ "indication", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_cc_dsc_mscr,
++ {
++ "MSC Release", "gsm_a.rr.cc_dsc.mscr",
++ FT_BOOLEAN, 1,
++ TFS(&gsm_a_rr_cc_dsc_mscr_tfs), 0x80,
++ "MSC Release", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_cc_dsc_att,
++ {
++ "Attach-detach allowed", "gsm_a.rr.cc_dsc.att",
++ FT_BOOLEAN, 1,
++ TFS(&gsm_a_rr_cc_dsc_att_tfs), 0x40,
++ "Attach-detach allowed", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_cc_dsc_cbq3,
++ {
++ "Cell Bar Qualify 3", "gsm_a.rr.cc_dsc.cbq3",
++ FT_UINT8, BASE_HEX,
++ VALS(gsm_a_rr_cc_dsc_cbq3_vals), 0x60,
++ "Cell Bar Qualify 3", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_cc_dsc_ccch,
++ {
++ "CCCH Configuration", "gsm_a.rr.cc_dsc.ccch",
++ FT_UINT8, BASE_HEX,
++ VALS(gsm_a_rr_cc_dsc_ccch_vals), 0x7,
++ "CCCH Configuration", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_co_bcch_dn_ind,
++ {
++ "DN-IND Dynamic ARFCN mapping indicator", "gsm_a.rr.co_bcch.dn_ind",
++ FT_UINT8, BASE_HEX, VALS(gsm_a_rr_co_bcch_dn_ind_vals), 0x80,
++ "Dynamic ARFCN mapping indicator", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_co_bcch_pwrc,
++ {
++ "PWRC Power Control indicator", "gsm_a.rr.co_bcch.pwrc",
++ FT_UINT8, BASE_HEX, VALS(gsm_a_rr_co_bcch_pwrc_vals), 0x40,
++ "Power Control indicator", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_co_bcch_dtx,
++ {
++ "DTX indicator", "gsm_a.rr.co_bcch.dtx",
++ FT_UINT8, BASE_HEX, VALS(gsm_a_rr_co_bcch_dtx_vals), 0x30,
++ "DTX indicator", HFILL
++ }
++ },
++ // jl
++ {
++ &hf_gsm_a_rr_dm_or_tbf,
++ {
++ "Dedicated Mode or Temporary Block Flow", "gsm_a.rr.dm_or_tbf",
++ FT_UINT8, BASE_HEX, VALS(gsm_a_rr_dm_or_tbf_vals), 0x70, // assuming this is the 2nd IE in octet
++ "Dedicated Mode or TBF", HFILL
++ }
++ },
++
++ // ----------------------------------
++
+ { &hf_gsm_a_bssmap_msg_type,
+ { "BSSMAP Message Type", "gsm_a.bssmap_msgtype",
+ FT_UINT8, BASE_HEX, VALS(gsm_a_bssmap_msg_strings), 0x0,
+***************
+*** 18875,18880 ****
+--- 20471,20488 ----
+ FT_UINT8,BASE_DEC, VALS(gsm_a_gmm_cn_spec_drs_cycle_len_coef_strings), 0xf0,
+ "CN Specific DRX cycle length coefficient", HFILL }
+ },
++
++ // jl
++ {
++ &hf_gsm_a_rr_rach_cp_ec,
++ {
++ "Emergency Call allowed", "gsm_a.rr.rach_cp_ec",
++ FT_BOOLEAN, 1, TFS(&gsm_a_rr_rach_cp_ec_tfs), 0x4,
++ "EC, Emergency Call allowed", HFILL
++ }
++ },
++ //
++
+ { &hf_gsm_a_rr_RR_cause,
+ { "RR cause value","gsm_a.rr.RRcause",
+ FT_UINT8,BASE_DEC, VALS(gsm_a_rr_RR_cause_vals), 0x0,
+***************
+*** 19338,19343 ****
+--- 20946,20955 ----
+ dissector_add("bssap.pdu_type", BSSAP_PDU_TYPE_DTAP, dtap_handle);
+ dissector_add("ranap.nas_pdu", BSSAP_PDU_TYPE_DTAP, dtap_handle);
+ dissector_add("llcgprs.sapi", 1 , dtap_handle);
++
++ // GNU Radio
++ dissector_add("ethertype", 0xfed5, dtap_handle);
++
+ data_handle = find_dissector("data");
+ }
+
diff --git a/gssm/src/Makefile.am b/gssm/src/Makefile.am
new file mode 100644
index 0000000..afa6595
--- /dev/null
+++ b/gssm/src/Makefile.am
@@ -0,0 +1,4 @@
+include $(top_srcdir)/Makefile.common
+
+SUBDIRS = lib mktun
+DIST_SUBDIRS = lib mktun
diff --git a/gssm/src/lib/Makefile.am b/gssm/src/lib/Makefile.am
new file mode 100644
index 0000000..be3775c
--- /dev/null
+++ b/gssm/src/lib/Makefile.am
@@ -0,0 +1,44 @@
+# $Id: Makefile.am,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+include $(top_srcdir)/Makefile.common
+
+ourpythondir = $(pythondir)
+ourlibdir = $(pyexecdir)
+
+INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS)
+
+SWIGCPPPYTHONARGS = -c++ -python $(PYTHON_CPPFLAGS) -I$(swigincludedir) -I$(grincludedir)
+
+LOCAL_IFILES = gssm.i
+NON_LOCAL_IFILES = $(GNURADIO_CORE_INCLUDEDIR)/swig/gnuradio.i
+ALL_IFILES = $(LOCAL_IFILES) $(NON_LOCAL_IFILES)
+
+BUILT_SOURCES = gssm_glue.cc gssm.py
+
+ourpython_PYTHON = gssm.py
+
+ourlib_LTLIBRARIES = _gssm.la
+
+# source files that go into the shared library
+_gssm_la_SOURCES = \
+ gssm_glue.cc \
+ gssm_sink.cc \
+ bursts.cc \
+ sch.cc \
+ cch.cc \
+ rr_decode.cc \
+ tun.cc \
+ display.cc
+
+_gssm_la_LDFLAGS = -module -avoid-version
+
+_gssm_la_LIBADD = $(PYTHON_LDFLAGS) -lstdc++
+
+gssm_glue.cc gssm.py: gssm.i $(ALL_IFILES)
+ $(SWIG) $(SWIGCPPPYTHONARGS) -module gssm -o gssm_glue.cc $<
+
+grinclude_HEADERS = gssm_sink.h
+
+swiginclude_HEADERS = $(LOCAL_IFILES)
+
+MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc
diff --git a/gssm/src/lib/buffer.h b/gssm/src/lib/buffer.h
new file mode 100644
index 0000000..038cba6
--- /dev/null
+++ b/gssm/src/lib/buffer.h
@@ -0,0 +1,4 @@
+#pragma once
+
+static const int BUFFER_QD_SIZE = 16384;
+static const int BUFFER_MM_SIZE = 16384;
diff --git a/gssm/src/lib/burst_types.h b/gssm/src/lib/burst_types.h
new file mode 100644
index 0000000..fc8fa4a
--- /dev/null
+++ b/gssm/src/lib/burst_types.h
@@ -0,0 +1,217 @@
+// $Id: burst_types.h,v 1.2 2007-07-07 16:31:42 jl Exp $
+
+#pragma once
+
+#include "gsm_constants.h"
+
+static const int TB_LEN = 3;
+static const int TB_OS1 = 0;
+static const int TB_OS2 = 145;
+static const unsigned char tail_bits[TB_LEN] = {0, 0, 0};
+
+/*
+ * The normal burst is used to carry information on traffic and control
+ * channels.
+ */
+static const int N_TSC_NUM = 8; // number of training sequence codes
+static const int N_TSC_CODE_LEN = 26; // length of tsc
+static const int N_TSC_OS = 61; // tsc offset
+static const int N_EDATA_LEN_1 = 58; // length of first data section
+static const int N_EDATA_OS_1 = 3; // offset of first data section
+static const int N_EDATA_LEN_2 = 58; // length of second data section
+static const int N_EDATA_OS_2 = 87; // offset of second data section
+static const unsigned char n_tsc[N_TSC_NUM][N_TSC_CODE_LEN] = {
+/* 0 */ {
+ 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1
+ },
+/* 1 */ {
+ 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1,
+ 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1
+ },
+/* 2 */ {
+ 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1,
+ 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0
+ },
+/* 3 */ {
+ 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0
+ },
+/* 4 */ {
+ 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1
+ },
+/* 5 */ {
+ 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0
+ },
+/* 6 */ {
+ 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1,
+ 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1
+ },
+/* 7 */ {
+ 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0
+ }
+};
+
+
+/*
+ * The frequency correction burst is used for frequency synchronization
+ * of the mobile. This is broadcast in TS0 together with the SCH and
+ * BCCH.
+ *
+ * Modulating the bits below causes a spike at 62.5kHz above (below for
+ * COMPACT) the center frequency. One can use this spike with a narrow
+ * band filter to accurately determine the center of the channel.
+ */
+static const int FC_CODE_LEN = 142;
+static const int FC_OS = 3;
+static const unsigned char fc_fb[FC_CODE_LEN] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const unsigned char fc_fb_de[TB_LEN + FC_CODE_LEN + TB_LEN] = {
+ 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1
+};
+
+static const unsigned char fc_compact_fb[FC_CODE_LEN] = {
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0
+};
+
+
+/*
+ * The synchronization burst is used for time synchronization of the
+ * mobile. The bits given below were chosen for their correlation
+ * properties. The synchronization channel (SCH) contains a long
+ * training sequence (given below) and carries the TDMA frame number and
+ * base station identity code. It is broadcast in TS0 in the frame
+ * following the frequency correction burst.
+ */
+static const int SB_CODE_LEN = 64;
+static const int SB_ETS_OS = 42;
+static const int SB_EDATA_LEN_1 = 39;
+static const int SB_EDATA_OS_1 = 3;
+static const int SB_EDATA_LEN_2 = 39;
+static const int SB_EDATA_OS_2 = 106;
+static const unsigned char sb_etsc[SB_CODE_LEN] = {
+ 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1,
+ 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1
+};
+
+static const unsigned char sb_cts_etsc[SB_CODE_LEN] = {
+ 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1,
+ 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0,
+ 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1
+};
+
+static const unsigned char sb_compact_etsc[SB_CODE_LEN] = {
+ 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
+ 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0
+};
+
+
+/*
+ * A base tranceiver station must transmit a burst in every timeslot of
+ * every TDMA frame in channel C0. The dummy burst will be transmitted
+ * on all timeslots of all TDMA frames for which no other channel
+ * requires a burst to be transmitted.
+ */
+static const int D_CODE_LEN = 142;
+static const int D_MB_OS = 3;
+static const unsigned char d_mb[D_CODE_LEN] = {
+ 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
+ 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1,
+ 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0
+};
+
+
+/*
+ * The access burst is used for random access from a mobile.
+ */
+static const int AB_ETB_CODE_LEN = 8;
+static const int AB_ETB_OS = 0;
+static const unsigned char ab_etb[AB_ETB_CODE_LEN] = {
+ 0, 0, 1, 1, 1, 0, 1, 0
+};
+
+static const int AB_SSB_CODE_LEN = 41;
+static const int AB_SSB_OS = 8;
+static const unsigned char ab_ssb[AB_SSB_CODE_LEN] = {
+ 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0,
+ 0, 0, 1, 1, 1, 1, 0, 0, 0
+};
+
+static const unsigned char ab_ts1_ssb[AB_SSB_CODE_LEN] = {
+ 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0, 1, 1, 0, 1
+};
+
+static const unsigned char ab_ts2_ssb[AB_SSB_CODE_LEN] = {
+ 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1,
+ 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1,
+ 1, 0, 1, 1, 1, 0, 1, 1, 1
+};
+
+
+typedef enum {
+ burst_n_0,
+ burst_n_1,
+ burst_n_2,
+ burst_n_3,
+ burst_n_4,
+ burst_n_5,
+ burst_n_6,
+ burst_n_7,
+ burst_fc,
+ burst_fc_c,
+ burst_s,
+ burst_s_cts,
+ burst_s_c,
+ burst_d,
+ burst_a,
+ burst_a_ts1,
+ burst_a_ts2,
+ burst_not_a_burst
+} burst_t;
+
+static const int N_BURST_TYPES = ((int)(burst_not_a_burst) + 1);
diff --git a/gssm/src/lib/bursts.cc b/gssm/src/lib/bursts.cc
new file mode 100644
index 0000000..cd35382
--- /dev/null
+++ b/gssm/src/lib/bursts.cc
@@ -0,0 +1,153 @@
+// $Id: bursts.cc,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "burst_types.h"
+
+void display_burst_type(burst_t t) {
+
+ switch(t) {
+ case burst_n_0:
+ case burst_n_1:
+ case burst_n_2:
+ case burst_n_3:
+ case burst_n_4:
+ case burst_n_5:
+ case burst_n_6:
+ case burst_n_7:
+ printf("normal burst %d", t);
+ break;
+ case burst_fc:
+ printf("frequency correction burst");
+ break;
+ case burst_fc_c:
+ printf("frequency correction burst (COMPACT)");
+ break;
+ case burst_s:
+ printf("synchronization burst");
+ break;
+ case burst_s_cts:
+ printf("synchronization burst (CTS)");
+ break;
+ case burst_s_c:
+ printf("synchronization burst (COMPACT)");
+ break;
+ case burst_d:
+ printf("dummy burst");
+ break;
+ case burst_a:
+ printf("access burst");
+ break;
+ case burst_a_ts1:
+ printf("access burst (TS1)");
+ break;
+ case burst_a_ts2:
+ printf("access burst (TS2)");
+ break;
+ default:
+ printf("unknown burst type");
+ break;
+ }
+}
+
+
+static int burst_diff(const unsigned char *b1, const unsigned char *b2,
+ unsigned int l) {
+
+ int d = 0;
+ unsigned int i;
+
+ for(i = 0; i < l; i++)
+ d += (b1[i] ^ b2[i]);
+ return d;
+}
+
+
+int search_fc(unsigned char *buf) {
+
+ return !(burst_diff(buf + TB_OS1, tail_bits, TB_LEN) +
+ burst_diff(buf + TB_OS2, tail_bits, TB_LEN) +
+ burst_diff(buf + FC_OS, fc_fb, FC_CODE_LEN));
+}
+
+
+int is_dummy_burst(const unsigned char *buf) {
+
+ int i;
+
+ for(i = 0; i < D_CODE_LEN; i++)
+ if(buf[i + D_MB_OS] != d_mb[i])
+ return 0;
+ return 1;
+}
+
+
+burst_t search_burst(unsigned char *buf, int max_burst_errors, int *rmin_o) {
+
+ int i, d_burst[N_BURST_TYPES], t_d, d_min, rmin;
+ burst_t bt_min;
+
+ for(i = 0; i < N_BURST_TYPES; i++)
+ d_burst[i] = max_burst_errors + 1;
+
+ // access burst (uplink only)
+ t_d = burst_diff(buf + AB_ETB_OS, ab_etb, AB_ETB_CODE_LEN);
+ d_burst[(int)burst_a] =
+ t_d + burst_diff(buf + AB_SSB_OS, ab_ssb, AB_SSB_CODE_LEN);
+
+ d_burst[(int)burst_a_ts1] =
+ t_d + burst_diff(buf + AB_SSB_OS, ab_ts1_ssb, AB_SSB_CODE_LEN);
+
+ d_burst[(int)burst_a_ts2] =
+ t_d + burst_diff(buf + AB_SSB_OS, ab_ts2_ssb, AB_SSB_CODE_LEN);
+
+ // check tail bits
+ t_d =
+ burst_diff(buf + TB_OS1, tail_bits, TB_LEN) +
+ burst_diff(buf + TB_OS2, tail_bits, TB_LEN);
+
+ // normal bursts
+ for(i = 0; i < N_TSC_NUM; i++)
+ d_burst[(int)burst_n_0 + i] =
+ t_d + burst_diff(buf + N_TSC_OS, n_tsc[i], N_TSC_CODE_LEN);
+
+ // frequency correction
+ d_burst[(int)burst_fc] =
+ t_d + burst_diff(buf + FC_OS, fc_fb, FC_CODE_LEN);
+
+ d_burst[(int)burst_fc_c] =
+ t_d + burst_diff(buf + FC_OS, fc_compact_fb, FC_CODE_LEN);
+
+ // synchronization burst
+ d_burst[(int)burst_s] =
+ t_d + burst_diff(buf + SB_ETS_OS, sb_etsc, SB_CODE_LEN);
+
+ d_burst[(int)burst_s_cts] =
+ t_d + burst_diff(buf + SB_ETS_OS, sb_cts_etsc, SB_CODE_LEN);
+
+ d_burst[(int)burst_s_c] =
+ t_d + burst_diff(buf + SB_ETS_OS, sb_compact_etsc, SB_CODE_LEN);
+
+ // dummy
+ d_burst[(int)burst_d] =
+ t_d + burst_diff(buf + D_MB_OS, d_mb, D_CODE_LEN);
+
+ d_burst[(int)burst_not_a_burst] = max_burst_errors;
+
+ rmin = BURST_LENGTH;
+ d_min = max_burst_errors + 1;
+ bt_min = burst_not_a_burst;
+ for(i = 0; i < N_BURST_TYPES; i++) {
+ if(d_burst[i] < d_min) {
+ bt_min = (burst_t)i;
+ d_min = d_burst[i];
+ }
+ if((d_burst[i] < rmin) && ((burst_t)i != burst_not_a_burst))
+ rmin = d_burst[i];
+ }
+ if(rmin_o)
+ *rmin_o = rmin;
+ return bt_min;
+}
diff --git a/gssm/src/lib/bursts.h b/gssm/src/lib/bursts.h
new file mode 100644
index 0000000..c8a5096
--- /dev/null
+++ b/gssm/src/lib/bursts.h
@@ -0,0 +1,10 @@
+// $Id: bursts.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+#pragma once
+
+#include "burst_types.h"
+
+void display_burst_type(burst_t);
+burst_t search_burst(unsigned char *, int, int *);
+int search_fc(unsigned char *);
+int is_dummy_burst(const unsigned char *);
diff --git a/gssm/src/lib/cch.cc b/gssm/src/lib/cch.cc
new file mode 100644
index 0000000..5659440
--- /dev/null
+++ b/gssm/src/lib/cch.cc
@@ -0,0 +1,460 @@
+// $Id: cch.cc,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <exception>
+#include <stdexcept>
+
+#include "burst_types.h"
+#include "cch.h"
+
+/*
+ * GSM SACCH -- Slow Associated Control Channel
+ *
+ * These messages are encoded exactly the same as on the BCCH.
+ * (Broadcast Control Channel.)
+ *
+ * Input: 184 bits
+ *
+ * 1. Add parity and flushing bits.
+ * 2. Convolutional encode.
+ * 3. Interleave.
+ * 4. Map on bursts.
+ */
+
+
+/*
+ * Parity (FIRE) for the GSM SACCH channel.
+ *
+ * g(x) = (x^23 + 1)(x^17 + x^3 + 1)
+ * = x^40 + x^26 + x^23 + x^17 + x^3 + 1
+ */
+
+static const unsigned char parity_polynomial[PARITY_SIZE + 1] = {
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 1, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0,
+ 1
+};
+
+// remainder after dividing data polynomial by g(x)
+static const unsigned char parity_remainder[PARITY_SIZE] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+
+/*
+static void parity_encode(unsigned char *d, unsigned char *p) {
+
+ int i;
+ unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
+
+ memcpy(buf, d, DATA_BLOCK_SIZE);
+ memset(buf + DATA_BLOCK_SIZE, 0, PARITY_SIZE);
+
+ for(q = buf; q < buf + DATA_BLOCK_SIZE; q++)
+ if(*q)
+ for(i = 0; i < PARITY_SIZE + 1; i++)
+ q[i] ^= parity_polynomial[i];
+ for(i = 0; i < PARITY_SIZE; i++)
+ p[i] = !buf[DATA_BLOCK_SIZE + i];
+}
+ */
+
+
+static int parity_check(unsigned char *d) {
+
+ unsigned int i;
+ unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
+
+ memcpy(buf, d, DATA_BLOCK_SIZE + PARITY_SIZE);
+
+ for(q = buf; q < buf + DATA_BLOCK_SIZE; q++)
+ if(*q)
+ for(i = 0; i < PARITY_SIZE + 1; i++)
+ q[i] ^= parity_polynomial[i];
+ return memcmp(buf + DATA_BLOCK_SIZE, parity_remainder, PARITY_SIZE);
+}
+
+
+/*
+ * Convolutional encoding and Viterbi decoding for the GSM SACCH channel.
+ */
+
+/*
+ * Convolutional encoding:
+ *
+ * G_0 = 1 + x^3 + x^4
+ * G_1 = 1 + x + x^3 + x^4
+ *
+ * i.e.,
+ *
+ * c_{2k} = u_k + u_{k - 3} + u_{k - 4}
+ * c_{2k + 1} = u_k + u_{k - 1} + u_{k - 3} + u_{k - 4}
+ */
+#define K 5
+#define MAX_ERROR (2 * CONV_INPUT_SIZE + 1)
+
+
+/*
+ * Given the current state and input bit, what are the output bits?
+ *
+ * encode[current_state][input_bit]
+ */
+static const unsigned int encode[1 << (K - 1)][2] = {
+ {0, 3}, {3, 0}, {3, 0}, {0, 3},
+ {0, 3}, {3, 0}, {3, 0}, {0, 3},
+ {1, 2}, {2, 1}, {2, 1}, {1, 2},
+ {1, 2}, {2, 1}, {2, 1}, {1, 2}
+};
+
+
+/*
+ * Given the current state and input bit, what is the next state?
+ *
+ * next_state[current_state][input_bit]
+ */
+static const unsigned int next_state[1 << (K - 1)][2] = {
+ {0, 8}, {0, 8}, {1, 9}, {1, 9},
+ {2, 10}, {2, 10}, {3, 11}, {3, 11},
+ {4, 12}, {4, 12}, {5, 13}, {5, 13},
+ {6, 14}, {6, 14}, {7, 15}, {7, 15}
+};
+
+
+/*
+ * Given the previous state and the current state, what input bit caused
+ * the transition? If it is impossible to transition between the two
+ * states, the value is 2.
+ *
+ * prev_next_state[previous_state][current_state]
+ */
+static const unsigned int prev_next_state[1 << (K - 1)][1 << (K - 1)] = {
+ { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
+ { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
+ { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
+ { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
+ { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
+ { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
+ { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
+ { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
+ { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
+ { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
+ { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
+ { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
+ { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
+ { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
+ { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1},
+ { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1}
+};
+
+
+static inline unsigned int hamming_distance2(unsigned int w) {
+
+ return (w & 1) + !!(w & 2);
+}
+
+
+/*
+static void conv_encode(unsigned char *data, unsigned char *output) {
+
+ unsigned int i, state = 0, o;
+
+ // encode data
+ for(i = 0; i < CONV_INPUT_SIZE; i++) {
+ o = encode[state][data[i]];
+ state = next_state[state][data[i]];
+ *output++ = !!(o & 2);
+ *output++ = o & 1;
+ }
+}
+ */
+
+
+static int conv_decode(unsigned char *output, unsigned char *data) {
+
+ int i, t;
+ unsigned int rdata, state, nstate, b, o, distance, accumulated_error,
+ min_state, min_error, cur_state;
+
+ unsigned int ae[1 << (K - 1)];
+ unsigned int nae[1 << (K - 1)]; // next accumulated error
+ unsigned int state_history[1 << (K - 1)][CONV_INPUT_SIZE + 1];
+
+ // initialize accumulated error, assume starting state is 0
+ for(i = 0; i < (1 << (K - 1)); i++)
+ ae[i] = nae[i] = MAX_ERROR;
+ ae[0] = 0;
+
+ // build trellis
+ for(t = 0; t < CONV_INPUT_SIZE; t++) {
+
+ // get received data symbol
+ rdata = (data[2 * t] << 1) | data[2 * t + 1];
+
+ // for each state
+ for(state = 0; state < (1 << (K - 1)); state++) {
+
+ // make sure this state is possible
+ if(ae[state] >= MAX_ERROR)
+ continue;
+
+ // find all states we lead to
+ for(b = 0; b < 2; b++) {
+
+ // get next state given input bit b
+ nstate = next_state[state][b];
+
+ // find output for this transition
+ o = encode[state][b];
+
+ // calculate distance from received data
+ distance = hamming_distance2(rdata ^ o);
+
+ // choose surviving path
+ accumulated_error = ae[state] + distance;
+ if(accumulated_error < nae[nstate]) {
+
+ // save error for surviving state
+ nae[nstate] = accumulated_error;
+
+ // update state history
+ state_history[nstate][t + 1] = state;
+ }
+ }
+ }
+
+ // get accumulated error ready for next time slice
+ for(i = 0; i < (1 << (K - 1)); i++) {
+ ae[i] = nae[i];
+ nae[i] = MAX_ERROR;
+ }
+ }
+
+ // the final state is the state with the fewest errors
+ min_state = (unsigned int)-1;
+ min_error = MAX_ERROR;
+ for(i = 0; i < (1 << (K - 1)); i++) {
+ if(ae[i] < min_error) {
+ min_state = i;
+ min_error = ae[i];
+ }
+ }
+
+ // trace the path
+ cur_state = min_state;
+ for(t = CONV_INPUT_SIZE; t >= 1; t--) {
+ min_state = cur_state;
+ cur_state = state_history[cur_state][t]; // get previous
+ output[t - 1] = prev_next_state[cur_state][min_state];
+ }
+
+ // return the number of errors detected (hard-decision)
+ return min_error;
+}
+
+
+/*
+ * GSM SACCH interleaving and burst mapping
+ *
+ * Interleaving:
+ *
+ * Given 456 coded input bits, form 4 blocks of 114 bits:
+ *
+ * i(B, j) = c(n, k) k = 0, ..., 455
+ * n = 0, ..., N, N + 1, ...
+ * B = B_0 + 4n + (k mod 4)
+ * j = 2(49k mod 57) + ((k mod 8) div 4)
+ *
+ * Mapping on Burst:
+ *
+ * e(B, j) = i(B, j)
+ * e(B, 59 + j) = i(B, 57 + j) j = 0, ..., 56
+ * e(B, 57) = h_l(B)
+ * e(B, 58) = h_n(B)
+ *
+ * Where h_l(B) and h_n(B) are bits in burst B indicating flags.
+ */
+
+/*
+static void interleave(unsigned char *data, unsigned char *iBLOCK) {
+
+ int j, k, B;
+
+ // for each bit in input data
+ for(k = 0; k < CONV_SIZE; k++) {
+ B = k % 4;
+ j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
+ iBLOCK[B * iBLOCK_SIZE + j] = data[k];
+ }
+}
+ */
+
+
+static void decode_interleave(unsigned char *data, unsigned char *iBLOCK) {
+
+ int j, k, B;
+
+ for(k = 0; k < CONV_SIZE; k++) {
+ B = k % 4;
+ j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
+ data[k] = iBLOCK[B * iBLOCK_SIZE + j];
+ }
+}
+
+
+/*
+static void burstmap(unsigned char *iBLOCK, unsigned char *eBLOCK,
+ unsigned char hl, unsigned char hn) {
+
+ int j;
+
+ for(j = 0; j < 57; j++) {
+ eBLOCK[j] = iBLOCK[j];
+ eBLOCK[j + 59] = iBLOCK[j + 57];
+ }
+ eBLOCK[57] = hl;
+ eBLOCK[58] = hn;
+}
+ */
+
+
+static void decode_burstmap(unsigned char *iBLOCK, unsigned char *eBLOCK,
+ unsigned char *hl, unsigned char *hn) {
+
+ int j;
+
+ for(j = 0; j < 57; j++) {
+ iBLOCK[j] = eBLOCK[j];
+ iBLOCK[j + 57] = eBLOCK[j + 59];
+ }
+ *hl = eBLOCK[57];
+ *hn = eBLOCK[58];
+}
+
+
+/*
+ * Transmitted bits are sent least-significant first.
+ */
+static int compress_bits(unsigned char *dbuf, unsigned int dbuf_len,
+ unsigned char *sbuf, unsigned int sbuf_len) {
+
+ unsigned int i, j, c, pos = 0;
+
+ if(dbuf_len < ((sbuf_len + 7) >> 3))
+ return -1;
+
+ for(i = 0; i < sbuf_len; i += 8) {
+ for(j = 0, c = 0; (j < 8) && (i + j < sbuf_len); j++)
+ c |= (!!sbuf[i + j]) << j;
+ dbuf[pos++] = c & 0xff;
+ }
+ return pos;
+}
+
+
+int get_ns_l3_len(unsigned char *data, unsigned int datalen) {
+
+ if((data[0] & 3) != 1) {
+ fprintf(stderr, "error: get_ns_l3_len: pseudo-length reserved "
+ "bits bad (%2.2x)\n", data[0] & 3);
+ return -1;
+ }
+ return (data[0] >> 2);
+}
+
+
+static unsigned char *decode_sacch(unsigned char *e0, unsigned char *e1,
+ unsigned char *e2, unsigned char *e3, unsigned int *datalen) {
+
+ int errors, len, data_size = (DATA_BLOCK_SIZE + 7) >> 3;
+ unsigned char conv_data[CONV_SIZE], iBLOCK[BLOCKS][iBLOCK_SIZE],
+ hl, hn, decoded_data[PARITY_OUTPUT_SIZE], *data;
+
+ if(!(data = (unsigned char *)malloc(data_size))) {
+ throw std::runtime_error("error: decode_cch: malloc");
+ }
+
+ if(datalen)
+ *datalen = 0;
+
+ // unmap the bursts
+ decode_burstmap(iBLOCK[0], e0, &hl, &hn); // XXX ignore stealing bits
+ decode_burstmap(iBLOCK[1], e1, &hl, &hn);
+ decode_burstmap(iBLOCK[2], e2, &hl, &hn);
+ decode_burstmap(iBLOCK[3], e3, &hl, &hn);
+
+ // remove interleave
+ decode_interleave(conv_data, (unsigned char *)iBLOCK);
+
+ // Viterbi decode
+ errors = conv_decode(decoded_data, conv_data);
+
+ // check parity
+ if(errors || parity_check(decoded_data)) {
+ // fprintf(stderr, "error: sacch: parity error (%d)\n", errors);
+ return 0;
+ }
+ if((len = compress_bits(data, data_size, decoded_data,
+ DATA_BLOCK_SIZE)) < 0) {
+ fprintf(stderr, "error: compress_bits\n");
+ return 0;
+ }
+ if((unsigned int)len < data_size) {
+ fprintf(stderr, "error: buf too small (%d < %d)\n",
+ sizeof(data), len);
+ return 0;
+ }
+
+ if(datalen)
+ *datalen = (unsigned int)len;
+ return data;
+}
+
+
+/*
+ * decode_cch
+ *
+ * Decode a "common" control channel. Most control channels use
+ * the same burst, interleave, Viterbi and parity configuration.
+ * The documentation for the control channels defines SACCH first
+ * and then just keeps referring to that.
+ *
+ * The current (investigated) list is as follows:
+ *
+ * BCCH Norm
+ * BCCH Ext
+ * PCH
+ * AGCH
+ * CBCH (SDCCH/4)
+ * CBCH (SDCCH/8)
+ * SDCCH/4
+ * SACCH/C4
+ * SDCCH/8
+ * SACCH/C8
+ *
+ * We provide two functions, one for where all four bursts are
+ * contiguous, and one where they aren't.
+ */
+unsigned char *decode_cch(unsigned char *e0, unsigned char *e1,
+ unsigned char *e2, unsigned char *e3, unsigned int *datalen) {
+
+ return decode_sacch(e0, e1, e2, e3, datalen);
+}
+
+
+unsigned char *decode_cch(unsigned char *e, unsigned int *datalen) {
+
+ return decode_sacch(e, e + eBLOCK_SIZE, e + 2 * eBLOCK_SIZE,
+ e + 3 * eBLOCK_SIZE, datalen);
+}
diff --git a/gssm/src/lib/cch.h b/gssm/src/lib/cch.h
new file mode 100644
index 0000000..bb1d629
--- /dev/null
+++ b/gssm/src/lib/cch.h
@@ -0,0 +1,42 @@
+// $Id: cch.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+/*
+ * decode_cch
+ *
+ * Decode a "common" control channel. Most control channels use
+ * the same burst, interleave, Viterbi and parity configuration.
+ * The documentation for the control channels defines SACCH first
+ * and then just keeps referring to that.
+ *
+ * The current (investigated) list is as follows:
+ *
+ * BCCH Norm
+ * BCCH Ext
+ * PCH
+ * AGCH
+ * CBCH (SDCCH/4)
+ * CBCH (SDCCH/8)
+ * SDCCH/4
+ * SACCH/C4
+ * SDCCH/8
+ * SACCH/C8
+ *
+ * We provide two functions, one for where all four bursts are
+ * contiguous, and one where they aren't.
+ */
+
+#define DATA_BLOCK_SIZE 184
+#define PARITY_SIZE 40
+#define FLUSH_BITS_SIZE 4
+#define PARITY_OUTPUT_SIZE (DATA_BLOCK_SIZE + PARITY_SIZE + FLUSH_BITS_SIZE)
+
+#define CONV_INPUT_SIZE PARITY_OUTPUT_SIZE
+#define CONV_SIZE (2 * CONV_INPUT_SIZE)
+
+#define BLOCKS 4
+#define iBLOCK_SIZE (CONV_SIZE / BLOCKS)
+#define eBLOCK_SIZE (iBLOCK_SIZE + 2)
+
+unsigned char *decode_cch(unsigned char *, unsigned char *, unsigned char *,
+ unsigned char *, unsigned int *);
+unsigned char *decode_cch(unsigned char *, unsigned int *);
diff --git a/gssm/src/lib/display.cc b/gssm/src/lib/display.cc
new file mode 100644
index 0000000..086b48a
--- /dev/null
+++ b/gssm/src/lib/display.cc
@@ -0,0 +1,46 @@
+// $Id: display.cc,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+void dump_raw(unsigned char *buf, unsigned int len) {
+
+ unsigned int i;
+
+ for(i = 0; i < len; i++) {
+ printf("%2.2x", buf[i]);
+ if(!((i + 1) % 4))
+ printf(" ");
+ }
+ printf("\n");
+}
+
+
+void display_raw(unsigned char *buf, unsigned int len) {
+
+ unsigned int i, j, c;
+ unsigned long long v;
+
+ for(i = 0; i < len; i += 64) {
+ v = 0;
+ for(j = 0; (j < 64) && (i + j < len); j++) {
+ printf("%d", buf[i + j]);
+ if(!((j + 1) % 4))
+ printf(" ");
+ v = (v << 1) | buf[i + j];
+ }
+ for(; j < 64; j++) {
+ printf(" ");
+ if(!((j + 1) % 4))
+ printf(" ");
+ v <<= 1;
+ }
+ printf("\t");
+ for(j = 0; j < 8; j++) {
+ c = (v >> (8 * (7 - j))) & 0xff;
+ printf("%2.2x ", c);
+ }
+ printf("\n");
+ }
+}
diff --git a/gssm/src/lib/display.h b/gssm/src/lib/display.h
new file mode 100644
index 0000000..cacd931
--- /dev/null
+++ b/gssm/src/lib/display.h
@@ -0,0 +1,4 @@
+// $Id: display.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+void dump_raw(unsigned char *, unsigned int);
+void display_raw(unsigned char *, unsigned int);
diff --git a/gssm/src/lib/gsm_constants.h b/gssm/src/lib/gsm_constants.h
new file mode 100644
index 0000000..6f4f07e
--- /dev/null
+++ b/gssm/src/lib/gsm_constants.h
@@ -0,0 +1,76 @@
+// $Id: gsm_constants.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+#pragma once
+
+static const double QN_TIME = 12.0l / 13.0l / 1000000.0l;
+static const double BN_TIME = 4.0l * QN_TIME;
+static const double TN_TIME = 156.25l * BN_TIME;
+static const double FN_TIME = 8.0l * TN_TIME;
+
+static const double GSM_RATE = 812500.0l / 3.0l;
+static const int MAX_FN = 26 * 51 * 2048;
+
+static const int BURST_LENGTH = 156;
+
+
+/*
+ * frequency correction:
+ * tn = 0 fnm51 = 0
+ *
+ * sync:
+ * tn = 0 fnm51 = 1
+ * tn = 0 fnm51 = 11
+ * tn = 0 fnm51 = 21
+ * tn = 0 fnm51 = 31
+ * tn = 0 fnm51 = 41
+ *
+ * bcch:
+ * tn = 0 fnm51 = 2, 3, 4, 5
+ * tn = 2 fnm51 = 2, 3, 4, 5
+ * tn = 4 fnm51 = 2, 3, 4, 5
+ * tn = 6 fnm51 = 2, 3, 4, 5
+ *
+ * bcch_ext:
+ * tn = 0 fnm51 = 6, 7, 8, 9
+ * tn = 2 fnm51 = 6, 7, 8, 9
+ * tn = 4 fnm51 = 6, 7, 8, 9
+ * tn = 6 fnm51 = 6, 7, 8, 9
+ *
+ * pch and agch:
+ * tn = 0 fnm51 = 6, 7, 8, 9
+ * tn = 0 fnm51 = 12, 13, 14, 15
+ * tn = 0 fnm51 = 16, 17, 18, 19
+ * tn = 0 fnm51 = 22, 23, 24, 25
+ * tn = 0 fnm51 = 26, 27, 28, 29
+ * tn = 0 fnm51 = 32, 33, 34, 35
+ * tn = 0 fnm51 = 36, 37, 38, 39
+ * tn = 0 fnm51 = 42, 43, 44, 45
+ * tn = 0 fnm51 = 46, 47, 48, 49
+ * tn = 2 fnm51 = 6, 7, 8, 9
+ * tn = 2 fnm51 = 12, 13, 14, 15
+ * tn = 2 fnm51 = 16, 17, 18, 19
+ * tn = 2 fnm51 = 22, 23, 24, 25
+ * tn = 2 fnm51 = 26, 27, 28, 29
+ * tn = 2 fnm51 = 32, 33, 34, 35
+ * tn = 2 fnm51 = 36, 37, 38, 39
+ * tn = 2 fnm51 = 42, 43, 44, 45
+ * tn = 2 fnm51 = 46, 47, 48, 49
+ * tn = 4 fnm51 = 6, 7, 8, 9
+ * tn = 4 fnm51 = 12, 13, 14, 15
+ * tn = 4 fnm51 = 16, 17, 18, 19
+ * tn = 4 fnm51 = 22, 23, 24, 25
+ * tn = 4 fnm51 = 26, 27, 28, 29
+ * tn = 4 fnm51 = 32, 33, 34, 35
+ * tn = 4 fnm51 = 36, 37, 38, 39
+ * tn = 4 fnm51 = 42, 43, 44, 45
+ * tn = 4 fnm51 = 46, 47, 48, 49
+ * tn = 6 fnm51 = 6, 7, 8, 9
+ * tn = 6 fnm51 = 12, 13, 14, 15
+ * tn = 6 fnm51 = 16, 17, 18, 19
+ * tn = 6 fnm51 = 22, 23, 24, 25
+ * tn = 6 fnm51 = 26, 27, 28, 29
+ * tn = 6 fnm51 = 32, 33, 34, 35
+ * tn = 6 fnm51 = 36, 37, 38, 39
+ * tn = 6 fnm51 = 42, 43, 44, 45
+ * tn = 6 fnm51 = 46, 47, 48, 49
+ */
diff --git a/gssm/src/lib/gssm.i b/gssm/src/lib/gssm.i
new file mode 100644
index 0000000..fbac240
--- /dev/null
+++ b/gssm/src/lib/gssm.i
@@ -0,0 +1,28 @@
+// $Id: gssm.i,v 1.2 2007-07-07 16:31:42 jl Exp $
+
+%include "exception.i"
+%import "gnuradio.i"
+
+%{
+#include "gnuradio_swig_bug_workaround.h"
+#include "gssm_sink.h"
+#include <stdexcept>
+%}
+
+
+GR_SWIG_BLOCK_MAGIC(gssm, sink);
+gssm_sink_sptr gssm_make_sink(double);
+
+class gssm_sink : public gr_sync_block {
+
+public:
+ int d_search_fc_count;
+ int d_found_fc_count;
+ int d_valid_s;
+ int d_invalid_s;
+
+ void stats();
+
+private:
+ gssm_sink(double);
+};
diff --git a/gssm/src/lib/gssm_sink.cc b/gssm/src/lib/gssm_sink.cc
new file mode 100644
index 0000000..307e3c8
--- /dev/null
+++ b/gssm/src/lib/gssm_sink.cc
@@ -0,0 +1,764 @@
+/*
+ * $Id: gssm_sink.cc,v 1.2 2007-07-07 16:31:42 jl Exp $
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <exception>
+#include <stdexcept>
+
+#include <gr_io_signature.h>
+#include <gr_buffer.h>
+#include <gr_math.h>
+
+#include "gssm_sink.h"
+#include "gsm_constants.h"
+#include "burst_types.h"
+#include "bursts.h"
+#include "sch.h"
+#include "cch.h"
+#include "gssm_state.h"
+#include "tun.h"
+#include "rr_decode.h"
+#include "display.h"
+#include "buffer.h"
+
+
+gssm_sink_sptr gssm_make_sink(double sps) {
+
+ return gssm_sink_sptr(new gssm_sink(sps));
+}
+
+
+static const char *chan_name = "gsm"; // GSM TUN interface name
+
+
+gssm_sink::gssm_sink(double sps) :
+ gr_sync_block("gssm_sink",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(0, 0, 0)) {
+
+ if((d_tunfd = mktun(chan_name, d_ether_addr)) == -1) {
+ fprintf(stderr, "warning: was not able to open TUN device, "
+ "disabling Wireshark interface\n");
+ // throw std::runtime_error("cannot open TUN device");
+ }
+
+ // allocate memory for physical channel to logical channel mapping
+ if(!(d_phy_buf = (unsigned char *)malloc(8 * 51 * eBLOCK_SIZE))) {
+ perror("malloc");
+ close(d_tunfd);
+ throw std::runtime_error("cannot allocate buffer memory");
+ }
+
+ // allocate memory to specify which physical data is present
+ if(!(d_phy_ind = (int *)malloc(8 * 51 * sizeof(int)))) {
+ perror("malloc");
+ close(d_tunfd);
+ throw std::runtime_error("cannot allocate index memory");
+ }
+ memset(d_phy_ind, 0, 8 * 51 * sizeof(int));
+
+ // buffers to hold quadrature demod and clock recovery output
+ d_buf_qd = gr_make_buffer(BUFFER_QD_SIZE, sizeof(float));
+ d_qd_reader = gr_buffer_add_reader(d_buf_qd, 0);
+ d_buf_mm = gr_make_buffer(BUFFER_MM_SIZE, sizeof(float));
+ d_mm_reader = gr_buffer_add_reader(d_buf_mm, 0);
+
+ // indicate to clock recovery that we are not sync'ed
+ d_bitno = -1;
+
+ // set samples per second and symbol
+ d_sps = sps;
+ d_samples_per_symbol = d_sps / GSM_RATE;
+
+ // initial program state
+ d_state = state_fc;
+
+ // initial base station synchronization
+ d_tn = -1;
+ d_fn = -1;
+ d_bsic = -1;
+
+ // stats
+ d_search_fc_count = d_found_fc_count = d_valid_s = d_invalid_s =
+ d_invalid_s_1 = d_valid_bcch = d_invalid_bcch = d_valid_ia =
+ d_invalid_ia = d_valid_sdcch4 = d_invalid_sdcch4 =
+ d_valid_sacchc4 = d_invalid_sacchc4 = d_valid_sdcch8 =
+ d_invalid_sdcch8 = d_valid_sacchc8 = d_invalid_sacchc8 = 0;
+
+ // interpolator
+ d_interp = new gri_mmse_fir_interpolator();
+
+ // M&M clock recovery
+ reset_clock();
+
+ // set quad demod constants
+ d_qd_last = 0;
+ d_qd_gain = M_PI_2l / d_samples_per_symbol; // rate at quad demod
+
+ // we always want multiples of the burst length
+ set_output_multiple(
+ (int)ceil((BURST_LENGTH + 1) * d_samples_per_symbol)
+ + d_interp->ntaps() + 10);
+}
+
+
+gssm_sink::~gssm_sink() {
+
+ // close TUN interface
+ close(d_tunfd);
+
+ // free phy memory
+ free(d_phy_buf);
+ free(d_phy_ind);
+}
+
+
+int gssm_sink::check_logical_channel(int b1, int b2, int b3, int b4) {
+
+ int r = 0;
+ unsigned int data_len;
+ unsigned char *data;
+
+ if(d_phy_ind[b1] && d_phy_ind[b2] && d_phy_ind[b3] &&
+ d_phy_ind[b4]) {
+ // channel data present
+ data = decode_cch(
+ d_phy_buf + b1 * eBLOCK_SIZE,
+ d_phy_buf + b2 * eBLOCK_SIZE,
+ d_phy_buf + b3 * eBLOCK_SIZE,
+ d_phy_buf + b4 * eBLOCK_SIZE,
+ &data_len);
+ if(data) {
+ write_interface(d_tunfd, data + 1, data_len - 1,
+ d_ether_addr);
+
+ // since we decoded this data, clear present flag
+ d_phy_ind[b1] = d_phy_ind[b2] = d_phy_ind[b3] =
+ d_phy_ind[b4] = 0;
+
+ free(data);
+
+ return 0;
+ }
+ return -1;
+ }
+
+ return -2; // channel data not present
+}
+
+
+void gssm_sink::check_logical_channels() {
+
+ int o, o_s, ts, rl, fn_s;
+
+ // do we have complete data for various logical channels?
+
+ // BCCH Norm
+ rl = 51;
+ fn_s = 2;
+ for(ts = 0; ts < 8; ts += 2) {
+ o = ts * rl + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: BCCH Norm (%d, %d)\n", ts,
+ fn_s);
+ }
+
+ // BCCH Ext
+ rl = 51;
+ fn_s = 6;
+ for(ts = 0; ts < 8; ts += 2) {
+ o = ts * rl + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: BCCH Ext (%d, %d)\n", ts,
+ fn_s);
+ }
+
+ // PCH, AGCH, SDCCH, SACCHC4
+ rl = 51;
+ for(ts = 0; ts < 8; ts += 2) {
+ o_s = ts * rl;
+
+ fn_s = 6;
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: PCH, AGCH (%d, %d)\n", ts,
+ fn_s);
+
+ fn_s = 12;
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: PCH, AGCH (%d, %d)\n", ts,
+ fn_s);
+
+ fn_s = 16;
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: PCH, AGCH (%d, %d)\n", ts,
+ fn_s);
+
+ fn_s = 22;
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: PCH, AGCH (%d, %d)\n", ts,
+ fn_s);
+
+ fn_s = 26;
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: PCH, AGCH (%d, %d)\n", ts,
+ fn_s);
+
+ fn_s = 32;
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: PCH, AGCH (%d, %d)\n", ts,
+ fn_s);
+
+ fn_s = 36;
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: PCH, AGCH (%d, %d)\n", ts,
+ fn_s);
+
+ fn_s = 42;
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: PCH, AGCH (%d, %d)\n", ts,
+ fn_s);
+
+ fn_s = 46;
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: PCH, AGCH (%d, %d)\n", ts,
+ fn_s);
+ }
+
+ // SDCCH8
+ rl = 51;
+ for(ts = 0; ts < 8; ts++) {
+ o_s = ts * rl;
+ for(fn_s = 0; fn_s < 32; fn_s += 4) {
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: SDCCH8 (%d, %d)\n",
+ ts, fn_s);
+ }
+ }
+
+ // SACCHC8
+ // XXX ignoring subchannel numbers
+ rl = 51;
+ for(ts = 0; ts < 8; ts++) {
+ o_s = ts * rl;
+ for(fn_s = 32; fn_s < 48; fn_s += 4) {
+ o = o_s + fn_s;
+ if(check_logical_channel(o, o + 1, o + 2, o + 3) == -1)
+ fprintf(stderr, "error: SACCH8 (%d, %d)\n",
+ ts, fn_s);
+ }
+ }
+
+}
+
+
+void gssm_sink::next_timeslot() {
+
+ d_tn++;
+ if(d_tn >= 8) {
+ d_tn %= 8;
+ d_fn = (d_fn + 1) % MAX_FN;
+ d_fnm51 = d_fn % 51;
+ d_fnm102 = d_fn % 102;
+ }
+}
+
+
+static void differential_decode(const unsigned char *in, unsigned char *out) {
+
+ int i;
+ unsigned char is = 1;
+
+ for(i = 0; i < BURST_LENGTH; i++)
+ is = out[i] = !in[i] ^ is;
+}
+
+
+static void differential_decode(const float *in, unsigned char *out) {
+
+ int i;
+ unsigned char is = 1;
+
+ for(i = 0; i < BURST_LENGTH; i++)
+ is = out[i] = (in[i] < 0) ^ is;
+}
+
+
+static const unsigned int MAX_INVALID_S = 10;
+//static const unsigned int MAX_INVALID_S = 1;
+
+int gssm_sink::check_num_invalid_s() {
+
+ if(d_invalid_s - d_invalid_s_1 >= MAX_INVALID_S) {
+ d_invalid_s_1 = d_invalid_s;
+ memset(d_phy_ind, 0, 8 * 51 * sizeof(int));
+
+ return 1;
+ }
+ return 0;
+}
+
+
+int gssm_sink::handle_sch(const unsigned char *buf, int *fn, int *bsic) {
+
+ int ret;
+
+ if(ret = !decode_sch(buf, fn, bsic)) {
+ d_valid_s++;
+ d_invalid_s_1 = d_invalid_s;
+ } else {
+ d_invalid_s++;
+ }
+ return ret;
+}
+
+
+/*
+ * search_s
+ *
+ * Searches for the synchronization packet. We assume that we have
+ * just seen the frequency correction packet. Hence:
+ *
+ * 1. We first enter with tn = 1.
+ * 2. The sync burst is the next burst in this channel.
+ */
+int gssm_sink::search_state_s(const float *in, int nitems) {
+
+ int i, imax, wl;
+ unsigned char buf[BURST_LENGTH];
+ float fbuf[BURST_LENGTH];
+
+ // assume that we are at the start of a burst
+
+ imax = nitems - (int)ceil((BURST_LENGTH + 1) * d_samples_per_symbol) -
+ d_interp->ntaps() - (int)d_mu;
+
+ for(i = 0; i < imax;) {
+ wl = BURST_LENGTH;
+ i += mm_demod(in + i, nitems - i, fbuf, wl);
+ if(!d_tn) {
+ differential_decode(fbuf, buf);
+ if(handle_sch(buf, &d_fn, &d_bsic)) {
+
+ d_fnm51 = d_fn % 51;
+ d_fnm102 = d_fn % 102;
+
+ next_timeslot();
+
+ d_state = state_data;
+
+ return i;
+ } else if(check_num_invalid_s()) {
+ reset_state();
+ return 0;
+ }
+ }
+ next_timeslot();
+ }
+ return i;
+}
+
+
+static int is_sch(int tn, int fnm51) {
+
+ return ((!tn) && ((fnm51 == 1) || (fnm51 == 11) || (fnm51 == 21) ||
+ (fnm51 == 31) || (fnm51 == 41)));
+}
+
+
+void gssm_sink::search_sch(const unsigned char *buf) {
+
+ int fn, bsic;
+
+ if(is_sch(d_tn, d_fnm51)) {
+ if(handle_sch(buf, &fn, &bsic)) {
+ if(d_fn != fn) {
+ fprintf(stderr, "error: lost sync "
+ "(%d != %d [%d])\n", fn, d_fn, fn - d_fn);
+ d_fn = fn;
+ d_fnm51 = fn % 51;
+ d_fnm102 = fn % 102;
+ }
+ if(d_bsic != bsic) {
+ fprintf(stderr, "warning: bsic changed "
+ "(%d -> %d)\n", d_bsic, bsic);
+ d_bsic = bsic;
+ }
+
+ } else {
+ if(check_num_invalid_s()) {
+ reset_state();
+ }
+ }
+ }
+}
+
+
+int gssm_sink::search_state_data(const float *in, int nitems) {
+
+ int i, imax, wl;
+ unsigned int offset, offset_i;
+ unsigned char buf[BURST_LENGTH];
+ float fbuf[BURST_LENGTH];
+
+ imax = nitems - (int)ceil((BURST_LENGTH + 1) * d_samples_per_symbol) -
+ d_interp->ntaps() - (int)d_mu;
+
+ for(i = 0; i < imax;) {
+ wl = BURST_LENGTH;
+ i += mm_demod(in + i, nitems - i, fbuf, wl);
+
+ differential_decode(fbuf, buf);
+
+ /*
+ for(int ii = 0; ii < BURST_LENGTH; ii++)
+ printf("%f\n", fbuf[ii]);
+ */
+
+ /*
+ if(is_sch(d_tn, d_fnm51))
+ printf("S");
+ else
+ printf(" ");
+ printf("%2d:%d: ", d_fnm51, d_tn);
+ for(int ii = 0; ii < BURST_LENGTH; ii++)
+ printf("%d", buf[ii]);
+ printf("\n");
+ */
+
+ /*
+ if((buf[0] == 1) || (buf[1] == 1) || (buf[2] == 1))
+ printf("%2d:%d: %d%d%d:%d%d%d %f %f %f : %f %f %f\n",
+ d_fnm51, d_tn, buf[0], buf[1], buf[2], buf[145],
+ buf[146], buf[147], fbuf[0], fbuf[1], fbuf[2],
+ fbuf[145], fbuf[146], fbuf[147]);
+ */
+
+ search_sch(buf);
+ if(d_state != state_data)
+ return 0;
+
+ if(!is_dummy_burst(buf)) {
+ offset_i = (d_tn * 51 + (d_fn % 51));
+ offset = offset_i * eBLOCK_SIZE;
+ memcpy(d_phy_buf + offset, buf + N_EDATA_OS_1,
+ N_EDATA_LEN_1);
+ memcpy(d_phy_buf + offset + N_EDATA_LEN_1,
+ buf + N_EDATA_OS_2, N_EDATA_LEN_2);
+ d_phy_ind[offset_i] = 1;
+ }
+
+ // check_logical_channels();
+
+ if((!d_tn) && (!d_fnm51)) {
+ check_logical_channels();
+ memset(d_phy_ind, 0, 8 * 51 * sizeof(int));
+ }
+
+ next_timeslot();
+ }
+ return i;
+}
+
+
+static int slice(float f) {
+
+ return (f >= 0);
+}
+
+
+int gssm_sink::mm_demod(const float *in, int nitems, float *out, int &nitems_out) {
+ int i, o;
+ float mm_val, v, f;
+
+ f = floor(d_mu);
+ i = (int)f;
+ d_mu -= f;
+
+ for(o = 0; (i < nitems - d_interp->ntaps()) && (o < nitems_out); o++) {
+ /*
+ * Produce output sample interpolated by d_mu where d_mu
+ * represents the normalized distance between the first and
+ * second sample of the given sequence.
+ *
+ * For example, d_mu = 0.5 interpolates a sample halfway
+ * in-between the current sample and the next.
+ */
+ v = d_interp->interpolate(&in[i], d_mu);
+
+ // adjust how fast and in which direction we modify omega
+ mm_val = slice(d_last_sample) * v - slice(v) * d_last_sample;
+
+ // write output
+ // out[o] = (d_last_sample = v) >= 0; // hard decision
+ out[o] = d_last_sample = v; // soft decision
+
+ // adjust the sample time for the next symbol
+ d_omega = d_omega + d_gain_omega * mm_val;
+
+ // don't allow it to exceed extrema
+ if(d_omega > d_max_omega)
+ d_omega = d_max_omega;
+ else if(d_omega < d_min_omega)
+ d_omega = d_min_omega;
+
+ // advance to next symbol
+ d_mu += d_omega + d_gain_mu * mm_val;
+
+ // if we're sync'ed
+ if(d_bitno > -1) {
+ d_bitno++;
+
+ // skip the quarter-bit at the end of a burst
+ if(d_bitno >= BURST_LENGTH) {
+ d_mu += d_omega / 4.0l;
+ d_bitno = 0;
+ }
+ }
+
+ // d_mu is now the number of samples to the next symbol
+ f = floor(d_mu);
+ i += (int)f; // integer advance
+ d_mu -= f; // fractional advance
+ }
+
+ // we may have advanced past the buffer
+ i -= (int)f;
+ d_mu += f;
+
+ nitems_out = o;
+
+ return i; // returns number consumed
+}
+
+
+int gssm_sink::quad_demod(const gr_complex *in, int nitems, float *out, int &nitems_out) {
+
+ int r, M;
+ gr_complex product;
+
+ M = std::min(nitems, nitems_out);
+ for(r = 0; r < M; r++) {
+ product = in[r] * conj(d_qd_last);
+ d_qd_last = in[r];
+ out[r] = d_qd_gain * gr_fast_atan2f(imag(product), real(product));
+ }
+
+ nitems_out = r;
+ return r; // returns number consumed
+}
+
+
+int gssm_sink::process_input(const gr_complex *in, const int nitems) {
+
+ float *w;
+ const float *r;
+ int wl, rl, rrl, ret;
+
+ w = (float *)d_buf_qd->write_pointer();
+ wl = d_buf_qd->space_available();
+ ret = quad_demod(in, nitems, w, wl);
+ d_buf_qd->update_write_pointer(wl);
+
+ r = (const float *)d_qd_reader->read_pointer();
+ rl = d_qd_reader->items_available();
+ w = (float *)d_buf_mm->write_pointer();
+ wl = d_buf_mm->space_available();
+ rrl = mm_demod(r, rl, w, wl);
+ d_qd_reader->update_read_pointer(rrl);
+ d_buf_mm->update_write_pointer(wl);
+
+ return ret;
+}
+
+
+void gssm_sink::flush_buffers() {
+
+ d_qd_reader->update_read_pointer(d_qd_reader->items_available());
+ d_mm_reader->update_read_pointer(d_mm_reader->items_available());
+}
+
+
+void gssm_sink::save_clock() {
+
+ d_mu_bak = d_mu;
+ d_omega_bak = d_omega;
+ d_last_sample_bak = d_last_sample;
+}
+
+
+void gssm_sink::restore_clock() {
+
+ d_mu = d_mu_bak;
+ d_omega = d_omega_bak;
+ d_last_sample = d_last_sample_bak;
+}
+
+
+void gssm_sink::reset_state() {
+
+ d_state = state_fc;
+ d_bitno = -1;
+ flush_buffers();
+ d_tn = -1;
+ d_fn = -1;
+ d_fnm51 = -1;
+ d_fnm102 = -1;
+ d_bsic = -1;
+
+ reset_clock();
+}
+
+
+void gssm_sink::reset_clock() {
+
+ // M&M clock recovery
+ d_mu = 0.0;
+ d_gain_mu = 0.01;
+ d_omega = d_samples_per_symbol;
+ //d_omega_relative_limit = 0.01;
+ d_omega_relative_limit = 0.3;
+ d_max_omega = d_omega * (1.0 + d_omega_relative_limit);
+ d_min_omega = d_omega * (1.0 - d_omega_relative_limit);
+ d_gain_omega = 0.25 * d_gain_mu * d_gain_mu;
+}
+
+
+/*
+ * search_fc
+ *
+ * Searches for the frequency correction burst.
+ */
+int gssm_sink::search_state_fc(const float *in, int nitems) {
+
+ int i, j, slen = sizeof(fc_fb_de) / sizeof(*fc_fb_de),
+ imax, c, nbits;
+ float w[BURST_LENGTH];
+ double f;
+ const unsigned char *s = fc_fb_de;
+
+ f = floor(d_mu);
+ i = (int)f;
+ d_mu -= f;
+
+ imax = nitems - (int)ceil((BURST_LENGTH + 1) * d_samples_per_symbol) -
+ d_interp->ntaps() - i;
+
+ while(i < imax) {
+
+ // update stats
+ d_search_fc_count++;
+
+ // save current clock parameters
+ save_clock();
+
+ // calculate burst
+ nbits = BURST_LENGTH;
+ c = mm_demod(in + i, nitems - i, w, nbits);
+
+ // compare fixed and tail bits
+ for(j = 0; j < std::min(slen, nbits); j++)
+ if(slice(w[j]) != s[j])
+ break;
+
+ // was the fc burst detected?
+ if(j == slen) {
+
+ // update stats
+ d_found_fc_count++;
+
+ d_mu += d_omega / 4.0l; // advance quarter-bit
+ d_bitno = 0; // burst sync'ed now
+ d_tn = 0; // fc always in timeslot 0
+ next_timeslot();
+ d_state = state_s;
+
+ return i + c;
+ }
+
+ // restore clock to start of attempt
+ restore_clock();
+
+ // skip 1 bit and start again
+ nbits = 1;
+ i += mm_demod(in + i, nitems - i, w, nbits);
+ }
+
+ return i;
+}
+
+
+void gssm_sink::stats() {
+
+ printf("search fc:\t%d\n", d_search_fc_count);
+ printf("found fc:\t%d\n", d_found_fc_count);
+ printf("valid s:\t%d\n", d_valid_s);
+ printf("invalid s:\t%d\n", d_invalid_s);
+}
+
+
+int gssm_sink::process_qd(const gr_complex *in, int nitems) {
+
+ float *w;
+ int wl, ret;
+
+ w = (float *)d_buf_qd->write_pointer();
+ wl = d_buf_qd->space_available();
+ ret = quad_demod(in, nitems, w, wl);
+ d_buf_qd->update_write_pointer(wl);
+
+ return ret;
+}
+
+
+int gssm_sink::work(int nitems, gr_vector_const_void_star &input_items,
+ gr_vector_void_star &) {
+
+ const gr_complex *in = (gr_complex *)input_items[0];
+ const float *r;
+ int rl, ret, i, imax, n;
+
+ ret = process_qd(in, nitems);
+
+ r = (const float *)d_qd_reader->read_pointer();
+ rl = d_qd_reader->items_available();
+
+ imax = rl -
+ (int)(ceil((BURST_LENGTH + 1) * d_samples_per_symbol + d_mu) +
+ d_interp->ntaps());
+
+ for(i = 0; i < imax;) {
+ switch(d_state) {
+ case state_fc:
+ n = search_state_fc(r + i, rl - i);
+ break;
+ case state_s:
+ n = search_state_s(r + i, rl - i);
+ break;
+ case state_data:
+ n = search_state_data(r + i, rl - i);
+ break;
+ default:
+ fprintf(stderr, "error: bad state\n");
+ reset_state();
+ return 0;
+ }
+ i += n;
+ }
+ d_qd_reader->update_read_pointer(i);
+
+ return ret;
+}
diff --git a/gssm/src/lib/gssm_sink.h b/gssm/src/lib/gssm_sink.h
new file mode 100644
index 0000000..3e8a57f
--- /dev/null
+++ b/gssm/src/lib/gssm_sink.h
@@ -0,0 +1,125 @@
+// $Id: gssm_sink.h,v 1.2 2007-07-07 16:31:42 jl Exp $
+
+#pragma once
+
+#include <linux/if_ether.h>
+#include <gr_sync_block.h>
+#include <gri_mmse_fir_interpolator.h>
+#include "gssm_state.h"
+
+class gssm_sink;
+typedef boost::shared_ptr<gssm_sink> gssm_sink_sptr;
+gssm_sink_sptr gssm_make_sink(double);
+
+class gssm_sink : public gr_sync_block {
+
+public:
+ ~gssm_sink(void);
+
+ int work(int nitems, gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+private:
+ // sample speeds
+ double d_sps; // samples per second
+ double d_samples_per_symbol;
+
+ // M&M clock recovery
+ gri_mmse_fir_interpolator *d_interp;
+ double d_mu;
+ double d_gain_mu;
+ double d_omega;
+ double d_gain_omega;
+ double d_omega_relative_limit;
+ double d_max_omega;
+ double d_min_omega;
+ float d_last_sample;
+
+ double d_mu_bak;
+ double d_omega_bak;
+ double d_last_sample_bak;
+
+ int d_bitno;
+
+ // buffers
+ gr_buffer_sptr d_buf_qd;
+ gr_buffer_reader_sptr d_qd_reader;
+ gr_buffer_sptr d_buf_mm;
+ gr_buffer_reader_sptr d_mm_reader;
+
+ // quad demod
+ gr_complex d_qd_last;
+ double d_qd_gain;
+
+ // GSM BTS timing
+ int d_tn; // time slot
+ int d_fn; // frame number
+ int d_fnm51; // frame number mod 51
+ int d_fnm102; // frame number mod 102
+ int d_bsic; // current bsic
+
+ // program state
+ gssm_state_t d_state;
+
+ // buffer to hold physical data
+ unsigned char * d_phy_buf;
+ int * d_phy_ind;
+
+ // Wireshark interface
+ int d_tunfd; // TUN fd
+ unsigned char d_ether_addr[ETH_ALEN];
+
+ /*******************************************************************/
+
+ friend gssm_sink_sptr gssm_make_sink(double);
+ gssm_sink(double);
+
+ int search_state_fc(const float *, int);
+ int search_state_s(const float *, int);
+ int search_state_data(const float *, int);
+
+ void search_sch(const unsigned char *);
+ int handle_sch(const unsigned char *, int *, int *);
+
+ void next_timeslot(void);
+
+ int check_logical_channel(int, int, int, int);
+ void check_logical_channels(void);
+
+ int mm_demod(const float *, int, float *, int &);
+ int quad_demod(const gr_complex *, int, float *, int &);
+ int process_input(const gr_complex *, int);
+ int process_qd(const gr_complex *, int);
+
+ void save_clock();
+ void restore_clock();
+ void reset_clock();
+ void flush_buffers();
+ void reset_state();
+
+
+ /*******************************************************************/
+ // Debug
+
+ int check_num_invalid_s();
+
+public:
+ int d_search_fc_count,
+ d_found_fc_count,
+ d_valid_s,
+ d_invalid_s,
+ d_invalid_s_1,
+ d_valid_bcch,
+ d_invalid_bcch,
+ d_valid_ia,
+ d_invalid_ia,
+ d_valid_sdcch4,
+ d_invalid_sdcch4,
+ d_valid_sacchc4,
+ d_invalid_sacchc4,
+ d_valid_sdcch8,
+ d_invalid_sdcch8,
+ d_valid_sacchc8,
+ d_invalid_sacchc8;
+ void stats();
+};
diff --git a/gssm/src/lib/gssm_state.h b/gssm/src/lib/gssm_state.h
new file mode 100644
index 0000000..44400a2
--- /dev/null
+++ b/gssm/src/lib/gssm_state.h
@@ -0,0 +1,9 @@
+// $Id: gssm_state.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+#pragma once
+
+typedef enum {
+ state_fc,
+ state_s,
+ state_data
+} gssm_state_t;
diff --git a/gssm/src/lib/rr_decode.cc b/gssm/src/lib/rr_decode.cc
new file mode 100644
index 0000000..312c883
--- /dev/null
+++ b/gssm/src/lib/rr_decode.cc
@@ -0,0 +1,236 @@
+// $Id: rr_decode.cc,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static char *pd_string(unsigned char pd) {
+
+ switch(pd) {
+ case 0:
+ return "group call control";
+ case 1:
+ return "broadcast call control";
+ case 2:
+ return "reserved (PDSS1 in earlier phases)";
+ case 3:
+ return "call control; call related SS messages";
+ case 4:
+ return "GPRS Transparent Transport Protocol (GTTP)";
+ case 5:
+ return "mobility management messages";
+ case 6:
+ return "radio resources management messages";
+ case 8:
+ return "GPRS mobility management messages";
+ case 9:
+ return "SMS messages";
+ case 10:
+ return "GPRS session management messages";
+ case 11:
+ return "non-call related SS messages";
+ case 12:
+ return "location services";
+ case 14:
+ return "reserved for extension of the PD";
+ case 15:
+ return "reserved for tests procedures";
+ default:
+ return "unknown PD";
+ }
+}
+
+
+static char *message_type_rrm_string(unsigned char mt) {
+
+ switch(mt) {
+ case 0x3c:
+ return "channel establishment message: RR "
+ "initialization request";
+ case 0x3b:
+ return "channel establishment message: aditional "
+ "assignment";
+ case 0x3f:
+ return "channel establishment message: immediate "
+ "assignment";
+ case 0x39:
+ return "channel establishment message: immediate "
+ "assignment extended";
+ case 0x3a:
+ return "channel establishment message: immediate "
+ "assignment reject";
+
+ case 0x35:
+ return "ciphering message: ciphering mode command";
+ case 0x32:
+ return "ciphering message: ciphering mode complete";
+
+ case 0x30:
+ return "configuration change message: configuration "
+ "change command";
+ case 0x31:
+ return "configuration change message: configuration "
+ "change acknowledgement";
+ case 0x33:
+ return "configuration change message: configuration "
+ "change reject";
+
+ case 0x2e:
+ return "handover message: assignment command";
+ case 0x29:
+ return "handover message: assignment complete";
+ case 0x2f:
+ return "handover message: assignment failure";
+ case 0x2b:
+ return "handover message: handover command";
+ case 0x2c:
+ return "handover message: handover complete";
+ case 0x28:
+ return "handover message: handover failure";
+ case 0x2d:
+ return "handover message: physical information";
+
+ case 0x08:
+ return "RR-cell change order";
+
+ case 0x23:
+ return "PDCH assignment command";
+
+ case 0x0d:
+ return "channel release message: channel release";
+ case 0x0a:
+ return "channel release message: partial release";
+ case 0x0f:
+ return "channel release message: partial release "
+ "complete";
+
+ case 0x21:
+ return "paging and notification message: paging "
+ "request type 1";
+ case 0x22:
+ return "paging and notification message: paging "
+ "request type 2";
+ case 0x24:
+ return "paging and notification message: paging "
+ "request type 3";
+ case 0x27:
+ return "paging and notification message: paging "
+ "response";
+ case 0x20:
+ return "paging and notification message: "
+ "notification / NCH";
+ case 0x25:
+ return "paging and notification message: "
+ "notification / FACCH";
+ case 0x26:
+ return "paging and notification message: "
+ "notification response";
+
+ case 0x0b:
+ return "reserved";
+
+ case 0x18:
+ return "system information message: type 8";
+ case 0x19:
+ return "system information message: type 1";
+ case 0x1a:
+ return "system information message: type 2";
+ case 0x1b:
+ return "system information message: type 3";
+ case 0x1c:
+ return "system information message: type 4";
+ case 0x1d:
+ return "system information message: type 5";
+ case 0x1e:
+ return "system information message: type 6";
+ case 0x1f:
+ return "system information message: type 7";
+ case 0x02:
+ return "system information message: type 2bis";
+ case 0x03:
+ return "system information message: type 2ter";
+ case 0x05:
+ return "system information message: type 5bis";
+ case 0x06:
+ return "system information message: type 5ter";
+ case 0x04:
+ return "system information message: type 9";
+ case 0x00:
+ return "system information message: type 13";
+ case 0x3d:
+ return "system information message: type 16";
+ case 0x3e:
+ return "system information message: type 17";
+
+ case 0x10:
+ return "miscellaneous message: channel mode modify";
+ case 0x12:
+ return "miscellaneous message: RR status";
+ case 0x17:
+ return "miscellaneous message: channel mode modify "
+ "acknowledge";
+ case 0x14:
+ return "miscellaneous message: frequency redefinition";
+ case 0x15:
+ return "miscellaneous message: measurement report";
+ case 0x16:
+ return "miscellaneous message: classmark change";
+ case 0x13:
+ return "miscellaneous message: classmark enquiry";
+ case 0x36:
+ return "miscellaneous message: extended measurement "
+ "report";
+ case 0x37:
+ return "miscellaneous message: extended measurement "
+ "order";
+ case 0x34:
+ return "miscellaneous message: GPRS suspension request";
+
+ case 0x09:
+ return "VGCS uplink control message: uplink grant";
+ case 0x0e:
+ return "VGCS uplink control message: uplink release";
+ case 0x0c:
+ return "VGCS uplink control message: uplink free";
+ case 0x2a:
+ return "VGCS uplink control message: uplink busy";
+ case 0x11:
+ return "VGCS uplink control message: talker indication";
+
+ case 0x38:
+ return "application message: application information";
+
+ default:
+ return "unknown radio resource management message "
+ "type";
+ }
+}
+
+
+void display_l3(unsigned char *buf, unsigned int buflen) {
+
+ printf("(%d) PD: %s: (%2.2x) %s\n", buflen, pd_string(buf[0] & 0xf),
+ buf[1], message_type_rrm_string(buf[1]));
+}
+
+
+void display_ns_l3(unsigned char *data, unsigned int datalen) {
+
+ int len;
+
+ // bit 1 == 1, bit 2 == 0
+ if((data[0] & 3) != 1) {
+ fprintf(stderr, "error: display_ns_l3: pseudo-length reserved "
+ "bits bad (%2.2x)\n", data[0] & 3);
+ return;
+ }
+ len = data[0] >> 2;
+ if(datalen < len) {
+ fprintf(stderr, "error: display_ns_l3: bad data length "
+ "(%d < %d)\n", datalen, len);
+ return;
+ }
+
+ printf("L3 length: %d\n", len);
+ display_l3(data + 1, datalen - 1);
+}
diff --git a/gssm/src/lib/rr_decode.h b/gssm/src/lib/rr_decode.h
new file mode 100644
index 0000000..42d6266
--- /dev/null
+++ b/gssm/src/lib/rr_decode.h
@@ -0,0 +1,4 @@
+// $Id: rr_decode.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+void display_l3(unsigned char *, unsigned int);
+void display_ns_l3(unsigned char *, unsigned int);
diff --git a/gssm/src/lib/rrm.h b/gssm/src/lib/rrm.h
new file mode 100644
index 0000000..52be6a5
--- /dev/null
+++ b/gssm/src/lib/rrm.h
@@ -0,0 +1,22 @@
+// $Id: rrm.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+#pragma once
+
+typedef struct {
+ unsigned char b0:1,
+ b1:1,
+ len:6;
+} l2_pseudo_length_s;
+
+typedef union {
+ unsigned char v;
+ l2_pseudo_length_s b;
+} l2_pseudo_length_t;
+
+
+typedef struct {
+ unsigned char pd:4,
+ si:4;
+ unsigned char mt;
+ unsigned char ie[0];
+} l3_h_t;
diff --git a/gssm/src/lib/sch.cc b/gssm/src/lib/sch.cc
new file mode 100644
index 0000000..c336dc1
--- /dev/null
+++ b/gssm/src/lib/sch.cc
@@ -0,0 +1,320 @@
+// $Id: sch.cc,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "burst_types.h"
+
+/*
+ * Synchronization channel.
+ *
+ * Timeslot Repeat length Frame Number (mod repeat length)
+ * 0 51 1, 11, 21, 31, 41
+ */
+
+/*
+ * Parity (FIRE) for the GSM SCH.
+ *
+ * g(x) = x^10 + x^8 + x^6 + x^5 + x^4 + x^2 + 1
+ */
+#define DATA_BLOCK_SIZE 25
+#define PARITY_SIZE 10
+#define TAIL_BITS_SIZE 4
+#define PARITY_OUTPUT_SIZE (DATA_BLOCK_SIZE + PARITY_SIZE + TAIL_BITS_SIZE)
+
+static const unsigned char parity_polynomial[PARITY_SIZE + 1] = {
+ 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1
+};
+
+static const unsigned char parity_remainder[PARITY_SIZE] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+
+static void parity_encode(unsigned char *d, unsigned char *p) {
+
+ unsigned int i;
+ unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
+
+ memcpy(buf, d, DATA_BLOCK_SIZE);
+ memset(buf + DATA_BLOCK_SIZE, 0, PARITY_SIZE);
+
+ for(q = buf; q < buf + DATA_BLOCK_SIZE; q++)
+ if(*q)
+ for(i = 0; i < PARITY_SIZE + 1; i++)
+ q[i] ^= parity_polynomial[i];
+ for(i = 0; i < PARITY_SIZE; i++)
+ p[i] = !buf[DATA_BLOCK_SIZE + i];
+}
+
+
+static int parity_check(unsigned char *d) {
+
+ unsigned int i;
+ unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
+
+ memcpy(buf, d, DATA_BLOCK_SIZE + PARITY_SIZE);
+
+ for(q = buf; q < buf + DATA_BLOCK_SIZE; q++)
+ if(*q)
+ for(i = 0; i < PARITY_SIZE + 1; i++)
+ q[i] ^= parity_polynomial[i];
+ return memcmp(buf + DATA_BLOCK_SIZE, parity_remainder, PARITY_SIZE);
+}
+
+
+/*
+ * Convolutional encoding and Viterbi decoding for the GSM SCH.
+ * (Equivalent to the GSM SACCH.)
+ *
+ * G_0 = 1 + x^3 + x^4
+ * G_1 = 1 + x + x^3 + x^4
+ *
+ * i.e.,
+ *
+ * c_{2k} = u_k + u_{k - 3} + u_{k - 4}
+ * c_{2k + 1} = u_k + u_{k - 1} + u_{k - 3} + u_{k - 4}
+ */
+#define CONV_INPUT_SIZE PARITY_OUTPUT_SIZE
+#define CONV_SIZE (2 * CONV_INPUT_SIZE)
+#define K 5
+#define MAX_ERROR (2 * CONV_INPUT_SIZE + 1)
+
+
+/*
+ * Given the current state and input bit, what are the output bits?
+ *
+ * encode[current_state][input_bit]
+ */
+static const unsigned int encode[1 << (K - 1)][2] = {
+ {0, 3}, {3, 0}, {3, 0}, {0, 3},
+ {0, 3}, {3, 0}, {3, 0}, {0, 3},
+ {1, 2}, {2, 1}, {2, 1}, {1, 2},
+ {1, 2}, {2, 1}, {2, 1}, {1, 2}
+};
+
+
+/*
+ * Given the current state and input bit, what is the next state?
+ *
+ * next_state[current_state][input_bit]
+ */
+static const unsigned int next_state[1 << (K - 1)][2] = {
+ {0, 8}, {0, 8}, {1, 9}, {1, 9},
+ {2, 10}, {2, 10}, {3, 11}, {3, 11},
+ {4, 12}, {4, 12}, {5, 13}, {5, 13},
+ {6, 14}, {6, 14}, {7, 15}, {7, 15}
+};
+
+
+/*
+ * Given the previous state and the current state, what input bit caused
+ * the transition? If it is impossible to transition between the two
+ * states, the value is 2.
+ *
+ * prev_next_state[previous_state][current_state]
+ */
+static const unsigned int prev_next_state[1 << (K - 1)][1 << (K - 1)] = {
+ { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
+ { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
+ { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
+ { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
+ { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
+ { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
+ { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
+ { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
+ { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
+ { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
+ { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
+ { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
+ { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
+ { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
+ { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1},
+ { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1}
+};
+
+
+static inline unsigned int hamming_distance2(unsigned int w) {
+
+ return (w & 1) + !!(w & 2);
+}
+
+
+static void conv_encode(unsigned char *data, unsigned char *output) {
+
+ unsigned int i, state = 0, o;
+
+ // encode data
+ for(i = 0; i < CONV_INPUT_SIZE; i++) {
+ o = encode[state][data[i]];
+ state = next_state[state][data[i]];
+ *output++ = !!(o & 2);
+ *output++ = o & 1;
+ }
+}
+
+
+static int conv_decode(unsigned char *data, unsigned char *output) {
+
+ int i, t;
+ unsigned int rdata, state, nstate, b, o, distance, accumulated_error,
+ min_state, min_error, cur_state;
+
+ unsigned int ae[1 << (K - 1)];
+ unsigned int nae[1 << (K - 1)]; // next accumulated error
+ unsigned int state_history[1 << (K - 1)][CONV_INPUT_SIZE + 1];
+
+ // initialize accumulated error, assume starting state is 0
+ for(i = 0; i < (1 << (K - 1)); i++)
+ ae[i] = nae[i] = MAX_ERROR;
+ ae[0] = 0;
+
+ // build trellis
+ for(t = 0; t < CONV_INPUT_SIZE; t++) {
+
+ // get received data symbol
+ rdata = (data[2 * t] << 1) | data[2 * t + 1];
+
+ // for each state
+ for(state = 0; state < (1 << (K - 1)); state++) {
+
+ // make sure this state is possible
+ if(ae[state] >= MAX_ERROR)
+ continue;
+
+ // find all states we lead to
+ for(b = 0; b < 2; b++) {
+
+ // get next state given input bit b
+ nstate = next_state[state][b];
+
+ // find output for this transition
+ o = encode[state][b];
+
+ // calculate distance from received data
+ distance = hamming_distance2(rdata ^ o);
+
+ // choose surviving path
+ accumulated_error = ae[state] + distance;
+ if(accumulated_error < nae[nstate]) {
+
+ // save error for surviving state
+ nae[nstate] = accumulated_error;
+
+ // update state history
+ state_history[nstate][t + 1] = state;
+ }
+ }
+ }
+
+ // get accumulated error ready for next time slice
+ for(i = 0; i < (1 << (K - 1)); i++) {
+ ae[i] = nae[i];
+ nae[i] = MAX_ERROR;
+ }
+ }
+
+ // the final state is the state with the fewest errors
+ min_state = (unsigned int)-1;
+ min_error = MAX_ERROR;
+ for(i = 0; i < (1 << (K - 1)); i++) {
+ if(ae[i] < min_error) {
+ min_state = i;
+ min_error = ae[i];
+ }
+ }
+
+ // trace the path
+ cur_state = min_state;
+ for(t = CONV_INPUT_SIZE; t >= 1; t--) {
+ min_state = cur_state;
+ cur_state = state_history[cur_state][t]; // get previous
+ output[t - 1] = prev_next_state[cur_state][min_state];
+ }
+
+ // return the number of errors detected (hard-decision)
+ return min_error;
+}
+
+
+int decode_sch(const unsigned char *buf, int *fn_o, int *bsic_o) {
+
+ int errors, bsic, t1, t2, t3p, t3, fn, tt;
+ unsigned char data[CONV_SIZE], decoded_data[PARITY_OUTPUT_SIZE];
+
+ // extract encoded data from synchronization burst
+ memcpy(data, buf + SB_EDATA_OS_1, SB_EDATA_LEN_1);
+ memcpy(data + SB_EDATA_LEN_1, buf + SB_EDATA_OS_2, SB_EDATA_LEN_2);
+
+ // Viterbi decode
+ if(errors = conv_decode(data, decoded_data)) {
+ // fprintf(stderr, "error: sch: conv_decode (%d)\n", errors);
+ return errors;
+ }
+
+ // check parity
+ if(parity_check(decoded_data)) {
+ // fprintf(stderr, "error: sch: parity failed\n");
+ return 1;
+ }
+
+ // Synchronization channel information, 44.018 page 171. (V7.2.0)
+ bsic =
+ (decoded_data[ 7] << 5) |
+ (decoded_data[ 6] << 4) |
+ (decoded_data[ 5] << 3) |
+ (decoded_data[ 4] << 2) |
+ (decoded_data[ 3] << 1) |
+ (decoded_data[ 2] << 0);
+ t1 =
+ (decoded_data[ 1] << 10) |
+ (decoded_data[ 0] << 9) |
+ (decoded_data[15] << 8) |
+ (decoded_data[14] << 7) |
+ (decoded_data[13] << 6) |
+ (decoded_data[12] << 5) |
+ (decoded_data[11] << 4) |
+ (decoded_data[10] << 3) |
+ (decoded_data[ 9] << 2) |
+ (decoded_data[ 8] << 1) |
+ (decoded_data[23] << 0);
+ t2 =
+ (decoded_data[22] << 4) |
+ (decoded_data[21] << 3) |
+ (decoded_data[20] << 2) |
+ (decoded_data[19] << 1) |
+ (decoded_data[18] << 0);
+ t3p =
+ (decoded_data[17] << 2) |
+ (decoded_data[16] << 1) |
+ (decoded_data[24] << 0);
+
+ t3 = 10 * t3p + 1;
+
+ // modulo arithmetic
+ tt = t3;
+ while(tt < t2)
+ tt += 26;
+ tt = (tt - t2) % 26;
+ fn = (51 * 26 * t1) + (51 * tt) + t3;
+
+ /*
+ * BSIC: Base Station Identification Code
+ * BCC: Base station Color Code
+ * NCC: Network Color Code
+ *
+ * FN: Frame Number
+ */
+ /*
+ printf("bsic: %x (bcc: %u; ncc: %u)\tFN: %u\n", bsic, bsic & 7,
+ (bsic >> 3) & 7, fn);
+ */
+
+ if(fn_o)
+ *fn_o = fn;
+ if(bsic_o)
+ *bsic_o = bsic;
+
+ return 0;
+}
diff --git a/gssm/src/lib/sch.h b/gssm/src/lib/sch.h
new file mode 100644
index 0000000..5f8b217
--- /dev/null
+++ b/gssm/src/lib/sch.h
@@ -0,0 +1,3 @@
+// $Id: sch.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+int decode_sch(const unsigned char *, int *, int *);
diff --git a/gssm/src/lib/tun.cc b/gssm/src/lib/tun.cc
new file mode 100644
index 0000000..2abda90
--- /dev/null
+++ b/gssm/src/lib/tun.cc
@@ -0,0 +1,125 @@
+// $Id: tun.cc,v 1.2 2007-07-07 16:31:42 jl Exp $
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <libgen.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if_tun.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <arpa/inet.h>
+
+int mktun(const char *chan_name, unsigned char *ether_addr) {
+
+ struct ifreq ifr;
+ // struct ifreq ifw;
+ char if_name[IFNAMSIZ];
+ int fd, one = 1;
+ // int sd;
+
+ // construct TUN interface
+ if((fd = open("/dev/net/tun", O_RDWR)) == -1) {
+ perror("open");
+ return -1;
+ }
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", chan_name);
+ if(ioctl(fd, TUNSETIFF, (void *)&ifr) == -1) {
+ perror("TUNSETIFF");
+ close(fd);
+ return -1;
+ }
+
+ // save actual name
+ memcpy(if_name, ifr.ifr_name, IFNAMSIZ);
+
+ // get ether addr
+ memset(&ifr, 0, sizeof(ifr));
+ memcpy(ifr.ifr_name, if_name, IFNAMSIZ);
+ if(ioctl(fd, SIOCGIFHWADDR, (void *)&ifr) == -1) {
+ perror("SIOCGIFHWADDR");
+ close(fd);
+ return -1;
+ }
+ memcpy(ether_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+ // set persistent
+ if(ioctl(fd, TUNSETPERSIST, (void *)&one) == -1) {
+ perror("TUNSETPERSIST");
+ close(fd);
+ return -1;
+ }
+
+ // set interface up
+ /* XXX must be root
+ if((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+ perror("socket");
+ close(fd);
+ return -1;
+ }
+
+ // get current flags
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
+ if(ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) {
+ perror("SIOCGIFFLAGS");
+ close(sd);
+ close(fd);
+ return -1;
+ }
+
+ // set up
+ memset(&ifw, 0, sizeof(ifw));
+ strncpy(ifw.ifr_name, if_name, IFNAMSIZ - 1);
+ ifw.ifr_flags = ifr.ifr_flags | IFF_UP | IFF_RUNNING;
+ if(ioctl(sd, SIOCSIFFLAGS, &ifw) == -1) {
+ perror("SIOCSIFFLAGS");
+ close(sd);
+ close(fd);
+ return -1;
+ }
+ close(sd);
+ */
+
+ return fd;
+}
+
+
+static inline int min(int a, int b) {
+
+ return (a < b)? a : b;
+}
+
+
+static const unsigned int DEFAULT_MTU = 1500;
+static const unsigned short ether_type = 0xfed5; // current dtap ethertype
+
+int write_interface(int fd, unsigned char *data, unsigned int data_len,
+ unsigned char *ether_addr) {
+
+ unsigned char frame[DEFAULT_MTU]; // XXX buffer overflow?
+ struct ethhdr eh;
+
+ if(fd < 0)
+ return data_len;
+
+ memcpy(eh.h_dest, ether_addr, ETH_ALEN);
+ memcpy(eh.h_source, ether_addr, ETH_ALEN);
+ eh.h_proto = htons(ether_type);
+
+ memcpy(frame, &eh, sizeof(eh));
+ memcpy(frame + sizeof(eh), data,
+ min(data_len, sizeof(frame) - sizeof(eh)));
+
+ if(write(fd, frame, sizeof(eh) + data_len) == -1) {
+ perror("write");
+ return -1;
+ }
+
+ return data_len;
+}
diff --git a/gssm/src/lib/tun.h b/gssm/src/lib/tun.h
new file mode 100644
index 0000000..a7868c4
--- /dev/null
+++ b/gssm/src/lib/tun.h
@@ -0,0 +1,4 @@
+// $Id: tun.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+int mktun(const char *, unsigned char *);
+int write_interface(int, unsigned char *, unsigned int, unsigned char *);
diff --git a/gssm/src/mktun/Makefile.am b/gssm/src/mktun/Makefile.am
new file mode 100644
index 0000000..95dc50a
--- /dev/null
+++ b/gssm/src/mktun/Makefile.am
@@ -0,0 +1,7 @@
+# $Id: Makefile.am,v 1.3 2007-06-01 05:35:59 jl Exp $
+
+#include $(top_srcdir)/Makefile.common
+
+bin_PROGRAMS = mktun
+mktun_SOURCES = mktun.c
+
diff --git a/gssm/src/mktun/mktun.c b/gssm/src/mktun/mktun.c
new file mode 100644
index 0000000..e22d496
--- /dev/null
+++ b/gssm/src/mktun/mktun.c
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <libgen.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if_tun.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <arpa/inet.h>
+
+
+static struct option long_options[] = {
+ { "delete", no_argument, 0, 'd'},
+ { "help", no_argument, 0, 'h'},
+ { 0, 0, 0, 0}
+};
+
+
+void usage(char *prog) {
+
+ fprintf(stderr, "note: you must be root (except perhaps to delete "
+ "the interface)\n");
+ fprintf(stderr, "usage: %s [--help | -h] | [--delete | -d] "
+ "<interface_name>\n", basename(prog));
+ exit(-1);
+}
+
+
+int main(int argc, char **argv) {
+
+ struct ifreq ifr, ifw;
+ char if_name[IFNAMSIZ], *chan_name = "gsm";
+ int option_index = 0, c, delete_if = 0, persist = 1, fd, sd;
+
+ while((c = getopt_long(argc, argv, "dh?", long_options, &option_index))
+ != -1) {
+ switch(c) {
+ case 'd':
+ delete_if = 1;
+ break;
+ case 'h':
+ case '?':
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ if(optind >= argc)
+ usage(argv[0]);
+
+ chan_name = argv[optind];
+
+ if(!delete_if && getuid() && geteuid())
+ usage(argv[0]);
+
+ // construct TUN interface
+ if((fd = open("/dev/net/tun", O_RDWR)) == -1) {
+ perror("open");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", chan_name);
+ if(ioctl(fd, TUNSETIFF, (void *)&ifr) == -1) {
+ perror("TUNSETIFF");
+ close(fd);
+ return -1;
+ }
+
+ // save actual name
+ memcpy(if_name, ifr.ifr_name, IFNAMSIZ);
+
+ if(delete_if)
+ persist = 0;
+
+ if(ioctl(fd, TUNSETPERSIST, (void *)persist) == -1) {
+ perror("TUNSETPERSIST");
+ close(fd);
+ return -1;
+ }
+
+ if(delete_if) {
+ close(fd);
+ return 0;
+ }
+
+ // set interface up
+ if((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+ perror("socket");
+ close(fd);
+ return -1;
+ }
+
+ // get current flags
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
+ if(ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) {
+ perror("SIOCGIFFLAGS");
+ close(sd);
+ close(fd);
+ return -1;
+ }
+
+ // set up
+ memset(&ifw, 0, sizeof(ifw));
+ strncpy(ifw.ifr_name, if_name, IFNAMSIZ - 1);
+ ifw.ifr_flags = ifr.ifr_flags | IFF_UP | IFF_RUNNING;
+ if(ioctl(sd, SIOCSIFFLAGS, &ifw) == -1) {
+ perror("SIOCSIFFLAGS");
+ close(sd);
+ close(fd);
+ return -1;
+ }
+
+ close(sd);
+ close(fd);
+
+ return 0;
+}
diff --git a/gssm/src/python/file_gssm.py b/gssm/src/python/file_gssm.py
new file mode 100755
index 0000000..47013f3
--- /dev/null
+++ b/gssm/src/python/file_gssm.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+
+# $Id: file_gssm.py,v 1.3 2007-07-07 16:31:44 jl Exp $
+
+from gnuradio import gr, usrp, db_dbs_rx, blks
+from gnuradio.blksimpl import gmsk
+import gssm
+import sys
+
+#sps = 1000e3
+
+usrp_rate = 64e6
+decim_rate = 112
+sps = usrp_rate / decim_rate
+
+gsm_rate = 1625000.0 / 6.0
+
+#xcf = 150e3
+#xtw = 50e3
+#xm = -31127.933289
+
+file_name = "signal.data"
+
+
+class gssm_graph(gr.flow_graph):
+ def __init__(self, fname):
+ gr.flow_graph.__init__(self)
+
+ src = gr.file_source(gr.sizeof_gr_complex, fname)
+ gs = gssm.sink()
+ self.connect(src, gs)
+
+def main():
+ fname = file_name
+ if len(sys.argv) == 2:
+ fname = sys.argv[1]
+ try:
+ gg = gssm_graph(fname)
+ gg.run()
+
+ except KeyboardInterrupt:
+ pass
+
+if __name__ == '__main__':
+ main()
diff --git a/gssm/src/python/file_stats.py b/gssm/src/python/file_stats.py
new file mode 100755
index 0000000..cf8a109
--- /dev/null
+++ b/gssm/src/python/file_stats.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+# $Id: file_stats.py,v 1.1 2007-07-07 16:26:33 jl Exp $
+
+from gnuradio import gr, usrp, db_dbs_rx, blks
+from gnuradio.blksimpl import gmsk
+import gssm
+import sys
+
+#sps = 1000e3
+
+usrp_rate = 64e6
+decim_rate = 112
+sps = usrp_rate / decim_rate
+
+gsm_rate = 1625000.0 / 6.0
+
+#xcf = 150e3
+#xtw = 50e3
+#xm = -31127.933289
+
+file_name = "signal.data"
+
+
+class gssm_graph(gr.flow_graph):
+ def __init__(self, fname):
+ gr.flow_graph.__init__(self)
+
+ src = gr.file_source(gr.sizeof_gr_complex, fname)
+ self.gs = gs = gssm.sink(sps)
+ self.connect(src, gs)
+
+def main():
+ fname = file_name
+ if len(sys.argv) == 2:
+ fname = sys.argv[1]
+ try:
+ gg = gssm_graph(fname)
+ gg.run()
+ gg.gs.stats()
+
+ except KeyboardInterrupt:
+ pass
+
+if __name__ == '__main__':
+ main()
diff --git a/gssm/src/python/gssm_stats.py b/gssm/src/python/gssm_stats.py
new file mode 100755
index 0000000..43677d9
--- /dev/null
+++ b/gssm/src/python/gssm_stats.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+
+# $Id: gssm_stats.py,v 1.2 2007-07-07 16:31:44 jl Exp $
+
+from gnuradio import gr, usrp, db_dbs_rx, blks
+from gnuradio.blksimpl import gmsk
+import usrp_dbid
+import gssm
+import sys
+import time
+import thread
+
+# constant
+gsm_rate = 1625000.0 / 6.0
+
+# script constant
+decim = 112
+gain = 32
+
+# bts channel
+c0 = 874e6
+
+# experimental constant
+default_usrp_offset = 4e3
+
+# filter constants
+xcf = 150e3
+xtw = 50e3
+
+def display_stats(gs):
+ while 1:
+ print "%d:\t%d:%d" % \
+ (gs.d_found_fc_count, gs.d_valid_s, gs.d_invalid_s)
+ time.sleep(1)
+
+
+class gssm_flow_graph(gr.flow_graph):
+ def __init__(self, usrp_offset):
+ gr.flow_graph.__init__(self)
+
+ print "decim = %d, gain = %d, offset = %.2f" % \
+ (decim, gain, usrp_offset)
+ print "filter center %.2f, filter width %.2f" % \
+ (xcf, xtw)
+
+ u = usrp.source_c(decim_rate = decim)
+ s = usrp.pick_subdev(u, (usrp_dbid.DBS_RX,))
+ u.set_mux(usrp.determine_rx_mux_value(u, s))
+ subdev = usrp.selected_subdev(u, s)
+
+ if subdev.dbid() != usrp_dbid.DBS_RX:
+ raise Exception('dbs daughterboard not detected!')
+
+ subdev.set_gain(gain)
+
+ sps = u.adc_freq() / u.decim_rate()
+ if sps < 2 * gsm_rate:
+ raise Exception('sample rate too low')
+
+ u.tune(0, subdev, c0 + usrp_offset)
+
+ xt = gr.firdes.low_pass(1.0, sps, xcf, xtw,
+ gr.firdes.WIN_HAMMING)
+ xf = gr.fir_filter_ccf(1, xt)
+
+ self.gs = gs = gssm.sink()
+
+ self.connect(u, xf, gs)
+
+def main():
+ if len(sys.argv) == 2:
+ uo = float(sys.argv[1])
+ else:
+ uo = default_usrp_offset
+ g = gssm_flow_graph(uo)
+ # thread.start_new_thread(display_stats, (g.gs,))
+ # g.run()
+ g.start()
+ time.sleep(10.0)
+ g.stop()
+ g.gs.stats()
+
+if __name__ == '__main__':
+ main()
+
diff --git a/gssm/src/python/gssm_usrp.py b/gssm/src/python/gssm_usrp.py
new file mode 100755
index 0000000..6fe84c5
--- /dev/null
+++ b/gssm/src/python/gssm_usrp.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+# $Id: gssm_usrp.py,v 1.2 2007-07-07 16:31:44 jl Exp $
+
+from gnuradio import gr, usrp, db_dbs_rx, blks
+from gnuradio.blksimpl import gmsk
+from usrpm import usrp_dbid
+import gssm
+import sys
+
+# constant
+gsm_rate = 1625000.0 / 6.0
+
+# script constant
+decim = 112
+gain = 70
+
+# bts channel
+c0 = 875.4e6
+
+# experimental constant
+default_usrp_offset = 12e3
+
+class gssm_flow_graph(gr.flow_graph):
+ def __init__(self, usrp_offset):
+ gr.flow_graph.__init__(self)
+
+ u = usrp.source_c(decim_rate = decim)
+ s = usrp.pick_subdev(u, (usrp_dbid.DBS_RX,))
+ u.set_mux(usrp.determine_rx_mux_value(u, s))
+ subdev = usrp.selected_subdev(u, s)
+
+ if subdev.dbid() != usrp_dbid.DBS_RX:
+ raise Exception('dbs daughterboard not detected!')
+
+ subdev.set_gain(gain)
+
+ sps = u.adc_freq() / u.decim_rate()
+ if sps < 2 * gsm_rate:
+ raise Exception('sample rate too low')
+
+ u.tune(0, subdev, c0 + usrp_offset)
+
+ xcf = 150e3
+ xtw = 50e3
+ xt = gr.firdes.low_pass(1.0, sps, xcf, xtw,
+ gr.firdes.WIN_HAMMING)
+ xf = gr.fir_filter_ccf(1, xt)
+
+ g = gssm.sink()
+
+ self.connect(u, xf, g)
+
+def main():
+ if len(sys.argv) == 2:
+ uo = float(sys.argv[1])
+ else:
+ uo = default_usrp_offset
+ g = gssm_flow_graph(uo)
+ g.run()
+
+if __name__ == '__main__':
+ main()
personal git repositories of Harald Welte. Your mileage may vary