summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/calypso-block.svg707
-rw-r--r--doc/calypso-gsm-notes.txt2
-rw-r--r--doc/calypso-signals.txt184
-rw-r--r--doc/gsmdevboard-block.svg746
-rw-r--r--include/l1ctl_proto.h302
-rw-r--r--include/osmocore/rsl.h24
-rw-r--r--include/osmocore/utils.h17
-rw-r--r--src/Makefile118
-rw-r--r--src/README.building30
-rw-r--r--src/README.development72
-rwxr-xr-xsrc/host/calypso_pll/pll.pl10
-rwxr-xr-xsrc/host/fb_tools/bdf_to_c.py293
-rw-r--r--src/host/gsmmap/.gitignore35
-rw-r--r--src/host/gsmmap/Makefile.am17
-rw-r--r--src/host/gsmmap/configure.ac26
-rw-r--r--src/host/gsmmap/geo.c47
-rw-r--r--src/host/gsmmap/geo.h12
-rwxr-xr-xsrc/host/gsmmap/git-version-gen151
-rw-r--r--src/host/gsmmap/gsmmap.c658
-rw-r--r--src/host/gsmmap/locate.c182
-rw-r--r--src/host/gsmmap/locate.h8
-rw-r--r--src/host/gsmmap/log.c377
-rw-r--r--src/host/gsmmap/log.h80
-rw-r--r--src/host/layer23/.gitignore36
-rw-r--r--src/host/layer23/COPYING (renamed from COPYING)0
-rw-r--r--src/host/layer23/Makefile.am3
-rw-r--r--src/host/layer23/README42
-rw-r--r--src/host/layer23/configure.ac41
-rw-r--r--src/host/layer23/include/Makefile.am2
l---------src/host/layer23/include/l1ctl_proto.h1
-rw-r--r--src/host/layer23/include/osmocom/Makefile.am1
-rw-r--r--src/host/layer23/include/osmocom/bb/Makefile.am1
-rw-r--r--src/host/layer23/include/osmocom/bb/common/Makefile.am2
-rw-r--r--src/host/layer23/include/osmocom/bb/common/gps.h53
-rw-r--r--src/host/layer23/include/osmocom/bb/common/l1ctl.h76
-rw-r--r--src/host/layer23/include/osmocom/bb/common/l1l2_interface.h8
-rw-r--r--src/host/layer23/include/osmocom/bb/common/l23_app.h36
-rw-r--r--src/host/layer23/include/osmocom/bb/common/logging.h29
-rw-r--r--src/host/layer23/include/osmocom/bb/common/networks.h24
-rw-r--r--src/host/layer23/include/osmocom/bb/common/osmocom_data.h131
-rw-r--r--src/host/layer23/include/osmocom/bb/common/sap_interface.h11
-rw-r--r--src/host/layer23/include/osmocom/bb/common/sim.h284
-rw-r--r--src/host/layer23/include/osmocom/bb/common/sysinfo.h162
-rw-r--r--src/host/layer23/include/osmocom/bb/misc/Makefile.am1
-rw-r--r--src/host/layer23/include/osmocom/bb/misc/cell_log.h25
-rw-r--r--src/host/layer23/include/osmocom/bb/misc/layer3.h17
-rw-r--r--src/host/layer23/include/osmocom/bb/misc/rslms.h23
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/Makefile.am3
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/app_mobile.h17
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm322.h255
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm411_sms.h33
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm480_ss.h9
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h18
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h235
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h215
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/mncc.h179
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/mncc_sock.h16
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/settings.h124
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/subscriber.h111
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/support.h122
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/transaction.h76
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/voice.h7
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/vty.h20
-rw-r--r--src/host/layer23/src/Makefile.am1
-rw-r--r--src/host/layer23/src/common/Makefile.am6
-rw-r--r--src/host/layer23/src/common/gps.c402
-rw-r--r--src/host/layer23/src/common/l1ctl.c967
-rw-r--r--src/host/layer23/src/common/l1ctl_lapdm_glue.c62
-rw-r--r--src/host/layer23/src/common/l1l2_interface.c180
-rw-r--r--src/host/layer23/src/common/logging.c137
-rw-r--r--src/host/layer23/src/common/main.c297
-rw-r--r--src/host/layer23/src/common/networks.c1986
-rw-r--r--src/host/layer23/src/common/sap_interface.c190
-rw-r--r--src/host/layer23/src/common/sim.c1253
-rw-r--r--src/host/layer23/src/common/sysinfo.c870
-rw-r--r--src/host/layer23/src/misc/Makefile.am13
-rw-r--r--src/host/layer23/src/misc/app_bcch_scan.c69
-rw-r--r--src/host/layer23/src/misc/app_cbch_sniff.c201
-rw-r--r--src/host/layer23/src/misc/app_ccch_scan.c509
-rw-r--r--src/host/layer23/src/misc/app_cell_log.c195
-rw-r--r--src/host/layer23/src/misc/app_echo_test.c65
-rw-r--r--src/host/layer23/src/misc/bcch_scan.c317
-rw-r--r--src/host/layer23/src/misc/cell_log.c819
-rw-r--r--src/host/layer23/src/misc/rslms.c151
-rw-r--r--src/host/layer23/src/mobile/Makefile.am15
-rw-r--r--src/host/layer23/src/mobile/app_mobile.c407
-rw-r--r--src/host/layer23/src/mobile/gsm322.c5170
-rw-r--r--src/host/layer23/src/mobile/gsm411_sms.c941
-rw-r--r--src/host/layer23/src/mobile/gsm480_ss.c1289
-rw-r--r--src/host/layer23/src/mobile/gsm48_cc.c2223
-rw-r--r--src/host/layer23/src/mobile/gsm48_mm.c4394
-rw-r--r--src/host/layer23/src/mobile/gsm48_rr.c5663
-rw-r--r--src/host/layer23/src/mobile/main.c271
-rw-r--r--src/host/layer23/src/mobile/mncc_sock.c347
-rw-r--r--src/host/layer23/src/mobile/mnccms.c813
-rw-r--r--src/host/layer23/src/mobile/settings.c188
-rw-r--r--src/host/layer23/src/mobile/subscriber.c1255
-rw-r--r--src/host/layer23/src/mobile/support.c182
-rw-r--r--src/host/layer23/src/mobile/transaction.c143
-rw-r--r--src/host/layer23/src/mobile/voice.c78
-rw-r--r--src/host/layer23/src/mobile/vty_interface.c2946
-rw-r--r--src/host/osmocon/.gitignore36
-rw-r--r--src/host/osmocon/COPYING339
-rw-r--r--src/host/osmocon/Makefile.am21
-rw-r--r--src/host/osmocon/configure.ac25
-rwxr-xr-xsrc/host/osmocon/git-version-gen151
-rwxr-xr-xsrc/host/osmocon/memdump_convert.pl29
-rw-r--r--src/host/osmocon/osmocon.c1513
-rw-r--r--src/host/osmocon/osmoload.c1216
-rw-r--r--src/host/osmocon/tpu_debug.c138
-rwxr-xr-xsrc/host/rita_pll/mtk_pll.pl79
-rw-r--r--src/host/rita_pll/mtk_pll.txt4461
-rwxr-xr-xsrc/host/rita_pll/rita_pll.pl115
-rw-r--r--src/host/rita_pll/rita_pll.txt3625
-rw-r--r--src/host/rita_pll/rita_pll_notes.txt19
-rw-r--r--src/shared/.gitignore5
-rw-r--r--src/shared/libosmocore/.gitignore (renamed from .gitignore)0
-rw-r--r--src/shared/libosmocore/COPYING339
-rw-r--r--src/shared/libosmocore/Doxyfile.codec.in (renamed from Doxyfile.codec.in)0
-rw-r--r--src/shared/libosmocore/Doxyfile.core.in (renamed from Doxyfile.core.in)0
-rw-r--r--src/shared/libosmocore/Doxyfile.gsm.in (renamed from Doxyfile.gsm.in)0
-rw-r--r--src/shared/libosmocore/Doxyfile.vty.in (renamed from Doxyfile.vty.in)0
-rw-r--r--src/shared/libosmocore/Makefile.am (renamed from Makefile.am)0
-rw-r--r--src/shared/libosmocore/configure.ac (renamed from configure.ac)0
-rw-r--r--src/shared/libosmocore/debian/changelog (renamed from debian/changelog)0
-rw-r--r--src/shared/libosmocore/debian/compat (renamed from debian/compat)0
-rw-r--r--src/shared/libosmocore/debian/control (renamed from debian/control)0
-rw-r--r--src/shared/libosmocore/debian/copyright (renamed from debian/copyright)0
-rw-r--r--src/shared/libosmocore/debian/docs (renamed from debian/docs)0
-rw-r--r--src/shared/libosmocore/debian/libosmocore-dbg.dirs (renamed from debian/libosmocore-dbg.dirs)0
-rw-r--r--src/shared/libosmocore/debian/libosmocore-dbg.install (renamed from debian/libosmocore-dbg.install)0
-rw-r--r--src/shared/libosmocore/debian/libosmocore-dev.dirs (renamed from debian/libosmocore-dev.dirs)0
-rw-r--r--src/shared/libosmocore/debian/libosmocore-dev.install (renamed from debian/libosmocore-dev.install)0
-rw-r--r--src/shared/libosmocore/debian/libosmocore.dirs (renamed from debian/libosmocore.dirs)0
-rw-r--r--src/shared/libosmocore/debian/libosmocore.install (renamed from debian/libosmocore.install)0
-rw-r--r--src/shared/libosmocore/debian/patches/debian-changes-0.1.17-1 (renamed from debian/patches/debian-changes-0.1.17-1)0
-rw-r--r--src/shared/libosmocore/debian/patches/series (renamed from debian/patches/series)0
-rwxr-xr-xsrc/shared/libosmocore/debian/rules (renamed from debian/rules)0
-rw-r--r--src/shared/libosmocore/debian/source/format (renamed from debian/source/format)0
-rw-r--r--src/shared/libosmocore/doc/.empty (renamed from doc/.empty)0
-rw-r--r--src/shared/libosmocore/doc/vty/example.xml (renamed from doc/vty/example.xml)0
-rw-r--r--src/shared/libosmocore/doc/vty/merge_doc.xsl (renamed from doc/vty/merge_doc.xsl)0
-rw-r--r--src/shared/libosmocore/doc/vty/vtydoc.xsd (renamed from doc/vty/vtydoc.xsd)0
-rwxr-xr-xsrc/shared/libosmocore/git-version-gen (renamed from git-version-gen)0
-rw-r--r--src/shared/libosmocore/include/Makefile.am (renamed from include/Makefile.am)0
-rw-r--r--src/shared/libosmocore/include/osmocom/codec/codec.h (renamed from include/osmocom/codec/codec.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/application.h (renamed from include/osmocom/core/application.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/backtrace.h (renamed from include/osmocom/core/backtrace.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/bits.h (renamed from include/osmocom/core/bits.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/bitvec.h (renamed from include/osmocom/core/bitvec.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/conv.h (renamed from include/osmocom/core/conv.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/crc16.h (renamed from include/osmocom/core/crc16.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/crcXXgen.h.tpl (renamed from include/osmocom/core/crcXXgen.h.tpl)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/crcgen.h (renamed from include/osmocom/core/crcgen.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/gsmtap.h (renamed from include/osmocom/core/gsmtap.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/gsmtap_util.h (renamed from include/osmocom/core/gsmtap_util.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/linuxlist.h (renamed from include/osmocom/core/linuxlist.h)2
-rw-r--r--src/shared/libosmocore/include/osmocom/core/linuxrbtree.h (renamed from include/osmocom/core/linuxrbtree.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/logging.h (renamed from include/osmocom/core/logging.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/msgb.h (renamed from include/osmocom/core/msgb.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/msgfile.h (renamed from include/osmocom/core/msgfile.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/panic.h (renamed from include/osmocom/core/panic.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/plugin.h (renamed from include/osmocom/core/plugin.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/prim.h (renamed from include/osmocom/core/prim.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/process.h (renamed from include/osmocom/core/process.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/rate_ctr.h (renamed from include/osmocom/core/rate_ctr.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/select.h (renamed from include/osmocom/core/select.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/serial.h (renamed from include/osmocom/core/serial.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/signal.h (renamed from include/osmocom/core/signal.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/socket.h (renamed from include/osmocom/core/socket.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/statistics.h (renamed from include/osmocom/core/statistics.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/talloc.h (renamed from include/osmocom/core/talloc.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/timer.h (renamed from include/osmocom/core/timer.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/timer_compat.h (renamed from include/osmocom/core/timer_compat.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/utils.h (renamed from include/osmocom/core/utils.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/core/write_queue.h (renamed from include/osmocom/core/write_queue.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/crypt/auth.h (renamed from include/osmocom/crypt/auth.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/crypt/gprs_cipher.h (renamed from include/osmocom/crypt/gprs_cipher.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gprs/gprs_bssgp.h (renamed from include/osmocom/gprs/gprs_bssgp.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gprs/gprs_bssgp_bss.h (renamed from include/osmocom/gprs/gprs_bssgp_bss.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gprs/gprs_msgb.h (renamed from include/osmocom/gprs/gprs_msgb.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gprs/gprs_ns.h (renamed from include/osmocom/gprs/gprs_ns.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gprs/gprs_ns_frgre.h (renamed from include/osmocom/gprs/gprs_ns_frgre.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gprs/protocol/gsm_08_16.h (renamed from include/osmocom/gprs/protocol/gsm_08_16.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gprs/protocol/gsm_08_18.h (renamed from include/osmocom/gprs/protocol/gsm_08_18.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/a5.h (renamed from include/osmocom/gsm/a5.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/abis_nm.h (renamed from include/osmocom/gsm/abis_nm.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/comp128.h (renamed from include/osmocom/gsm/comp128.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gan.h (renamed from include/osmocom/gsm/gan.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm0411_smc.h (renamed from include/osmocom/gsm/gsm0411_smc.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm0411_smr.h (renamed from include/osmocom/gsm/gsm0411_smr.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm0411_utils.h (renamed from include/osmocom/gsm/gsm0411_utils.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm0480.h (renamed from include/osmocom/gsm/gsm0480.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm0502.h (renamed from include/osmocom/gsm/gsm0502.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm0808.h (renamed from include/osmocom/gsm/gsm0808.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm48.h (renamed from include/osmocom/gsm/gsm48.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h (renamed from include/osmocom/gsm/gsm48_ie.h)2
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm_utils.h (renamed from include/osmocom/gsm/gsm_utils.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/lapd_core.h (renamed from include/osmocom/gsm/lapd_core.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/lapdm.h (renamed from include/osmocom/gsm/lapdm.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/mncc.h (renamed from include/osmocom/gsm/mncc.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/prim.h (renamed from include/osmocom/gsm/prim.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_03_41.h (renamed from include/osmocom/gsm/protocol/gsm_03_41.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h (renamed from include/osmocom/gsm/protocol/gsm_04_08.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_11.h (renamed from include/osmocom/gsm/protocol/gsm_04_11.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_12.h (renamed from include/osmocom/gsm/protocol/gsm_04_12.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_80.h (renamed from include/osmocom/gsm/protocol/gsm_04_80.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_08_08.h (renamed from include/osmocom/gsm/protocol/gsm_08_08.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_08_58.h (renamed from include/osmocom/gsm/protocol/gsm_08_58.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_12_21.h (renamed from include/osmocom/gsm/protocol/gsm_12_21.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_44_318.h (renamed from include/osmocom/gsm/protocol/gsm_44_318.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/ipaccess.h (renamed from include/osmocom/gsm/protocol/ipaccess.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/rsl.h (renamed from include/osmocom/gsm/rsl.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/rxlev_stat.h (renamed from include/osmocom/gsm/rxlev_stat.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/sysinfo.h (renamed from include/osmocom/gsm/sysinfo.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/tlv.h (renamed from include/osmocom/gsm/tlv.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/vty/buffer.h (renamed from include/osmocom/vty/buffer.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/vty/command.h (renamed from include/osmocom/vty/command.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/vty/logging.h (renamed from include/osmocom/vty/logging.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/vty/misc.h (renamed from include/osmocom/vty/misc.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/vty/telnet_interface.h (renamed from include/osmocom/vty/telnet_interface.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/vty/vector.h (renamed from include/osmocom/vty/vector.h)0
-rw-r--r--src/shared/libosmocore/include/osmocom/vty/vty.h (renamed from include/osmocom/vty/vty.h)0
-rw-r--r--src/shared/libosmocore/libosmocodec.pc.in (renamed from libosmocodec.pc.in)0
-rw-r--r--src/shared/libosmocore/libosmocore.pc.in (renamed from libosmocore.pc.in)0
-rw-r--r--src/shared/libosmocore/libosmogb.pc.in (renamed from libosmogb.pc.in)0
-rw-r--r--src/shared/libosmocore/libosmogsm.pc.in (renamed from libosmogsm.pc.in)0
-rw-r--r--src/shared/libosmocore/libosmovty.pc.in (renamed from libosmovty.pc.in)0
-rw-r--r--src/shared/libosmocore/m4/DUMMY (renamed from m4/DUMMY)0
-rw-r--r--src/shared/libosmocore/src/Makefile.am (renamed from src/Makefile.am)0
-rw-r--r--src/shared/libosmocore/src/application.c (renamed from src/application.c)0
-rw-r--r--src/shared/libosmocore/src/backtrace.c (renamed from src/backtrace.c)0
-rw-r--r--src/shared/libosmocore/src/bits.c (renamed from src/bits.c)0
-rw-r--r--src/shared/libosmocore/src/bitvec.c (renamed from src/bitvec.c)0
-rw-r--r--src/shared/libosmocore/src/codec/Makefile.am (renamed from src/codec/Makefile.am)0
-rw-r--r--src/shared/libosmocore/src/codec/gsm610.c (renamed from src/codec/gsm610.c)0
-rw-r--r--src/shared/libosmocore/src/codec/gsm620.c (renamed from src/codec/gsm620.c)0
-rw-r--r--src/shared/libosmocore/src/codec/gsm660.c (renamed from src/codec/gsm660.c)0
-rw-r--r--src/shared/libosmocore/src/codec/gsm690.c (renamed from src/codec/gsm690.c)0
-rw-r--r--src/shared/libosmocore/src/conv.c (renamed from src/conv.c)0
-rw-r--r--src/shared/libosmocore/src/crc16.c (renamed from src/crc16.c)0
-rw-r--r--src/shared/libosmocore/src/crcXXgen.c.tpl (renamed from src/crcXXgen.c.tpl)0
-rw-r--r--src/shared/libosmocore/src/gb/Makefile.am (renamed from src/gb/Makefile.am)0
-rw-r--r--src/shared/libosmocore/src/gb/common_vty.c (renamed from src/gb/common_vty.c)0
-rw-r--r--src/shared/libosmocore/src/gb/common_vty.h (renamed from src/gb/common_vty.h)0
-rw-r--r--src/shared/libosmocore/src/gb/gprs_bssgp.c (renamed from src/gb/gprs_bssgp.c)0
-rw-r--r--src/shared/libosmocore/src/gb/gprs_bssgp_bss.c (renamed from src/gb/gprs_bssgp_bss.c)0
-rw-r--r--src/shared/libosmocore/src/gb/gprs_bssgp_util.c (renamed from src/gb/gprs_bssgp_util.c)0
-rw-r--r--src/shared/libosmocore/src/gb/gprs_bssgp_vty.c (renamed from src/gb/gprs_bssgp_vty.c)0
-rw-r--r--src/shared/libosmocore/src/gb/gprs_ns.c (renamed from src/gb/gprs_ns.c)0
-rw-r--r--src/shared/libosmocore/src/gb/gprs_ns_frgre.c (renamed from src/gb/gprs_ns_frgre.c)0
-rw-r--r--src/shared/libosmocore/src/gb/gprs_ns_vty.c (renamed from src/gb/gprs_ns_vty.c)0
-rw-r--r--src/shared/libosmocore/src/gb/libosmogb.map (renamed from src/gb/libosmogb.map)0
-rw-r--r--src/shared/libosmocore/src/gsm/Makefile.am (renamed from src/gsm/Makefile.am)0
-rw-r--r--src/shared/libosmocore/src/gsm/a5.c (renamed from src/gsm/a5.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/abis_nm.c (renamed from src/gsm/abis_nm.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/auth_comp128v1.c (renamed from src/gsm/auth_comp128v1.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/auth_core.c (renamed from src/gsm/auth_core.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/auth_milenage.c (renamed from src/gsm/auth_milenage.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/comp128.c (renamed from src/gsm/comp128.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gan.c (renamed from src/gsm/gan.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gprs_cipher_core.c (renamed from src/gsm/gprs_cipher_core.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gsm0411_smc.c (renamed from src/gsm/gsm0411_smc.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gsm0411_smr.c (renamed from src/gsm/gsm0411_smr.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gsm0411_utils.c (renamed from src/gsm/gsm0411_utils.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gsm0480.c (renamed from src/gsm/gsm0480.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gsm0502.c (renamed from src/gsm/gsm0502.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gsm0808.c (renamed from src/gsm/gsm0808.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gsm48.c (renamed from src/gsm/gsm48.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gsm48_ie.c (renamed from src/gsm/gsm48_ie.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/gsm_utils.c (renamed from src/gsm/gsm_utils.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/lapd_core.c (renamed from src/gsm/lapd_core.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/lapdm.c (renamed from src/gsm/lapdm.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/libosmogsm.map (renamed from src/gsm/libosmogsm.map)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/aes-encblock.c (renamed from src/gsm/milenage/aes-encblock.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/aes-internal-enc.c (renamed from src/gsm/milenage/aes-internal-enc.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/aes-internal.c (renamed from src/gsm/milenage/aes-internal.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/aes.h (renamed from src/gsm/milenage/aes.h)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/aes_i.h (renamed from src/gsm/milenage/aes_i.h)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/aes_wrap.h (renamed from src/gsm/milenage/aes_wrap.h)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/common.h (renamed from src/gsm/milenage/common.h)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/crypto.h (renamed from src/gsm/milenage/crypto.h)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/includes.h (renamed from src/gsm/milenage/includes.h)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/milenage.c (renamed from src/gsm/milenage/milenage.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/milenage.h (renamed from src/gsm/milenage/milenage.h)0
-rw-r--r--src/shared/libosmocore/src/gsm/rsl.c (renamed from src/gsm/rsl.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/rxlev_stat.c (renamed from src/gsm/rxlev_stat.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/sysinfo.c (renamed from src/gsm/sysinfo.c)0
-rw-r--r--src/shared/libosmocore/src/gsm/tlv_parser.c (renamed from src/gsm/tlv_parser.c)0
-rw-r--r--src/shared/libosmocore/src/gsmtap_util.c (renamed from src/gsmtap_util.c)0
-rw-r--r--src/shared/libosmocore/src/logging.c (renamed from src/logging.c)0
-rw-r--r--src/shared/libosmocore/src/logging_syslog.c (renamed from src/logging_syslog.c)0
-rw-r--r--src/shared/libosmocore/src/msgb.c (renamed from src/msgb.c)0
-rw-r--r--src/shared/libosmocore/src/msgfile.c (renamed from src/msgfile.c)0
-rw-r--r--src/shared/libosmocore/src/panic.c (renamed from src/panic.c)0
-rw-r--r--src/shared/libosmocore/src/plugin.c (renamed from src/plugin.c)0
-rw-r--r--src/shared/libosmocore/src/rate_ctr.c (renamed from src/rate_ctr.c)0
-rw-r--r--src/shared/libosmocore/src/rbtree.c (renamed from src/rbtree.c)0
-rw-r--r--src/shared/libosmocore/src/select.c (renamed from src/select.c)0
-rw-r--r--src/shared/libosmocore/src/serial.c (renamed from src/serial.c)0
-rw-r--r--src/shared/libosmocore/src/signal.c (renamed from src/signal.c)0
-rw-r--r--src/shared/libosmocore/src/socket.c (renamed from src/socket.c)0
-rw-r--r--src/shared/libosmocore/src/statistics.c (renamed from src/statistics.c)0
-rw-r--r--src/shared/libosmocore/src/talloc.c (renamed from src/talloc.c)0
-rw-r--r--src/shared/libosmocore/src/timer.c (renamed from src/timer.c)0
-rw-r--r--src/shared/libosmocore/src/utils.c (renamed from src/utils.c)0
-rw-r--r--src/shared/libosmocore/src/vty/Makefile.am (renamed from src/vty/Makefile.am)0
-rw-r--r--src/shared/libosmocore/src/vty/buffer.c (renamed from src/vty/buffer.c)0
-rw-r--r--src/shared/libosmocore/src/vty/command.c (renamed from src/vty/command.c)0
-rw-r--r--src/shared/libosmocore/src/vty/logging_vty.c (renamed from src/vty/logging_vty.c)0
-rw-r--r--src/shared/libosmocore/src/vty/telnet_interface.c (renamed from src/vty/telnet_interface.c)0
-rw-r--r--src/shared/libosmocore/src/vty/utils.c (renamed from src/vty/utils.c)0
-rw-r--r--src/shared/libosmocore/src/vty/vector.c (renamed from src/vty/vector.c)0
-rw-r--r--src/shared/libosmocore/src/vty/vty.c (renamed from src/vty/vty.c)0
-rw-r--r--src/shared/libosmocore/src/write_queue.c (renamed from src/write_queue.c)0
-rw-r--r--src/shared/libosmocore/tests/Makefile.am (renamed from tests/Makefile.am)0
-rw-r--r--src/shared/libosmocore/tests/a5/a5_test.c (renamed from tests/a5/a5_test.c)0
-rw-r--r--src/shared/libosmocore/tests/a5/a5_test.ok (renamed from tests/a5/a5_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/auth/milenage_test.c (renamed from tests/auth/milenage_test.c)0
-rw-r--r--src/shared/libosmocore/tests/auth/milenage_test.ok (renamed from tests/auth/milenage_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/bits/bitrev_test.c (renamed from tests/bits/bitrev_test.c)0
-rw-r--r--src/shared/libosmocore/tests/bits/bitrev_test.ok (renamed from tests/bits/bitrev_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/conv/conv_test.c (renamed from tests/conv/conv_test.c)0
-rw-r--r--src/shared/libosmocore/tests/conv/conv_test.ok (renamed from tests/conv/conv_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/gb/bssgp_fc_test.c (renamed from tests/gb/bssgp_fc_test.c)0
-rw-r--r--src/shared/libosmocore/tests/gb/bssgp_fc_tests.err (renamed from tests/gb/bssgp_fc_tests.err)0
-rw-r--r--src/shared/libosmocore/tests/gb/bssgp_fc_tests.ok (renamed from tests/gb/bssgp_fc_tests.ok)0
-rwxr-xr-xsrc/shared/libosmocore/tests/gb/bssgp_fc_tests.sh (renamed from tests/gb/bssgp_fc_tests.sh)0
-rw-r--r--src/shared/libosmocore/tests/gsm0408/gsm0408_test.c (renamed from tests/gsm0408/gsm0408_test.c)0
-rw-r--r--src/shared/libosmocore/tests/gsm0408/gsm0408_test.ok (renamed from tests/gsm0408/gsm0408_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/gsm0808/gsm0808_test.c (renamed from tests/gsm0808/gsm0808_test.c)0
-rw-r--r--src/shared/libosmocore/tests/gsm0808/gsm0808_test.ok (renamed from tests/gsm0808/gsm0808_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/lapd/lapd_test.c (renamed from tests/lapd/lapd_test.c)0
-rw-r--r--src/shared/libosmocore/tests/lapd/lapd_test.ok (renamed from tests/lapd/lapd_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/logging/logging_test.c (renamed from tests/logging/logging_test.c)0
-rw-r--r--src/shared/libosmocore/tests/logging/logging_test.err (renamed from tests/logging/logging_test.err)0
-rw-r--r--src/shared/libosmocore/tests/logging/logging_test.ok (renamed from tests/logging/logging_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/msgfile/msgconfig.cfg (renamed from tests/msgfile/msgconfig.cfg)0
-rw-r--r--src/shared/libosmocore/tests/msgfile/msgfile_test.c (renamed from tests/msgfile/msgfile_test.c)0
-rw-r--r--src/shared/libosmocore/tests/msgfile/msgfile_test.ok (renamed from tests/msgfile/msgfile_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/sms/sms_test.c (renamed from tests/sms/sms_test.c)0
-rw-r--r--src/shared/libosmocore/tests/sms/sms_test.ok (renamed from tests/sms/sms_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/smscb/smscb_test.c (renamed from tests/smscb/smscb_test.c)0
-rw-r--r--src/shared/libosmocore/tests/smscb/smscb_test.ok (renamed from tests/smscb/smscb_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/testsuite.at (renamed from tests/testsuite.at)0
-rw-r--r--src/shared/libosmocore/tests/timer/timer_test.c (renamed from tests/timer/timer_test.c)0
-rw-r--r--src/shared/libosmocore/tests/timer/timer_test.ok (renamed from tests/timer/timer_test.ok)0
-rw-r--r--src/shared/libosmocore/tests/ussd/ussd_test.c (renamed from tests/ussd/ussd_test.c)0
-rw-r--r--src/shared/libosmocore/tests/ussd/ussd_test.ok (renamed from tests/ussd/ussd_test.ok)0
-rw-r--r--src/shared/libosmocore/utils/Makefile.am (renamed from utils/Makefile.am)0
-rwxr-xr-xsrc/shared/libosmocore/utils/gen_website_doc_tree.sh (renamed from utils/gen_website_doc_tree.sh)0
-rw-r--r--src/shared/libosmocore/utils/osmo-arfcn.c (renamed from utils/osmo-arfcn.c)0
-rw-r--r--src/shared/libosmocore/utils/osmo-auc-gen.c (renamed from utils/osmo-auc-gen.c)0
-rwxr-xr-xsrc/shared/update-libosmocore.sh3
-rw-r--r--src/target/firmware/.gitignore9
-rw-r--r--src/target/firmware/COPYING339
-rw-r--r--src/target/firmware/Makefile108
-rw-r--r--src/target/firmware/Makefile.inc208
-rw-r--r--src/target/firmware/Makefile.mtk32
-rw-r--r--src/target/firmware/abb/twl3025.c368
-rw-r--r--src/target/firmware/apps/chainload/main.c54
-rw-r--r--src/target/firmware/apps/compal_dsp_dump/main.c85
-rw-r--r--src/target/firmware/apps/hello_world/main.c199
-rw-r--r--src/target/firmware/apps/layer1/main.c173
-rw-r--r--src/target/firmware/apps/loader/main.c445
-rw-r--r--src/target/firmware/apps/loader/protocol.h37
-rw-r--r--src/target/firmware/apps/loader_mtk/main.c366
-rw-r--r--src/target/firmware/apps/rssi/main.c1562
-rwxr-xr-xsrc/target/firmware/apps/simtest/main.c362
-rw-r--r--src/target/firmware/battery/compal_e88.c384
-rw-r--r--src/target/firmware/battery/dummy.c9
-rw-r--r--src/target/firmware/board/common/calypso_pwl.S21
-rw-r--r--src/target/firmware/board/common/calypso_uart.S92
-rw-r--r--src/target/firmware/board/compal/LINKAGE.txt12
-rw-r--r--src/target/firmware/board/compal/exceptions_redirect.S24
-rw-r--r--src/target/firmware/board/compal/exceptions_redirected.S20
-rw-r--r--src/target/firmware/board/compal/handlers.S79
-rw-r--r--src/target/firmware/board/compal/header.S11
-rw-r--r--src/target/firmware/board/compal/highram.lds121
-rw-r--r--src/target/firmware/board/compal/macros.S76
-rw-r--r--src/target/firmware/board/compal/ram.lds123
-rw-r--r--src/target/firmware/board/compal/rf_power.c62
-rw-r--r--src/target/firmware/board/compal/rffe_dualband.c102
-rw-r--r--src/target/firmware/board/compal/start.ram.S26
-rw-r--r--src/target/firmware/board/compal/start.rom.S32
-rw-r--r--src/target/firmware/board/compal_e86/init.c144
-rw-r--r--src/target/firmware/board/compal_e86/rffe_dualband_e86.c106
-rw-r--r--src/target/firmware/board/compal_e88/LINKAGE.txt33
-rw-r--r--src/target/firmware/board/compal_e88/MEMORY_MAP.txt21
-rw-r--r--src/target/firmware/board/compal_e88/flash.lds134
-rwxr-xr-xsrc/target/firmware/board/compal_e88/init.c140
-rw-r--r--src/target/firmware/board/compal_e88/loader.lds147
-rw-r--r--src/target/firmware/board/compal_e99/init.c142
-rw-r--r--src/target/firmware/board/gta0x/init.c133
-rw-r--r--src/target/firmware/board/gta0x/rf_power.c63
-rw-r--r--src/target/firmware/board/gta0x/rffe_gta0x_triband.c131
-rw-r--r--src/target/firmware/board/manifest.c7
-rw-r--r--src/target/firmware/board/mediatek/macros.S76
-rw-r--r--src/target/firmware/board/mediatek/ram.lds112
-rw-r--r--src/target/firmware/board/mediatek/start.ram.S26
-rw-r--r--src/target/firmware/board/mediatek/uart.c424
-rw-r--r--src/target/firmware/board/mt62xx/init.c139
-rw-r--r--src/target/firmware/board/pirelli_dpl10/init.c149
-rw-r--r--src/target/firmware/board/pirelli_dpl10/rf_power.c63
-rw-r--r--src/target/firmware/board/pirelli_dpl10/rffe_dpl10_triband.c136
-rw-r--r--src/target/firmware/board/se_j100/init.c141
-rw-r--r--src/target/firmware/calypso/Makefile4
-rw-r--r--src/target/firmware/calypso/arm.c26
-rw-r--r--src/target/firmware/calypso/backlight.c69
-rw-r--r--src/target/firmware/calypso/buzzer.c86
-rw-r--r--src/target/firmware/calypso/clock.c200
-rw-r--r--src/target/firmware/calypso/dma.c44
-rw-r--r--src/target/firmware/calypso/dsp.c693
-rw-r--r--src/target/firmware/calypso/dsp_bootcode.c9
-rw-r--r--src/target/firmware/calypso/dsp_dumpcode.c45
-rw-r--r--src/target/firmware/calypso/dsp_params.c94
-rw-r--r--src/target/firmware/calypso/du.c51
-rw-r--r--src/target/firmware/calypso/i2c.c123
-rw-r--r--src/target/firmware/calypso/irq.c266
-rw-r--r--src/target/firmware/calypso/keypad.c207
-rw-r--r--src/target/firmware/calypso/misc.c60
-rw-r--r--src/target/firmware/calypso/rtc.c78
-rw-r--r--src/target/firmware/calypso/sim.c741
-rw-r--r--src/target/firmware/calypso/spi.c141
-rw-r--r--src/target/firmware/calypso/timer.c156
-rw-r--r--src/target/firmware/calypso/tpu.c346
-rw-r--r--src/target/firmware/calypso/tsp.c121
-rw-r--r--src/target/firmware/calypso/uart.c440
-rw-r--r--src/target/firmware/calypso/uwire.c136
-rw-r--r--src/target/firmware/comm/Makefile5
-rw-r--r--src/target/firmware/comm/msgb.c79
-rw-r--r--src/target/firmware/comm/sercomm.c297
-rw-r--r--src/target/firmware/comm/sercomm_cons.c140
-rw-r--r--src/target/firmware/comm/timer.c215
-rw-r--r--src/target/firmware/fb/4x6.c731
-rw-r--r--src/target/firmware/fb/5x8.c802
-rw-r--r--src/target/firmware/fb/c64.c1069
-rw-r--r--src/target/firmware/fb/fb_bw8.c311
-rw-r--r--src/target/firmware/fb/fb_dummy.c70
-rw-r--r--src/target/firmware/fb/fb_rgb332.c305
-rw-r--r--src/target/firmware/fb/fb_s6b33b1x.c193
-rw-r--r--src/target/firmware/fb/fb_ssd1783.c204
-rw-r--r--src/target/firmware/fb/fb_ssd1963.c196
-rw-r--r--src/target/firmware/fb/fb_st7558.c132
-rw-r--r--src/target/firmware/fb/fb_td014.c150
-rw-r--r--src/target/firmware/fb/font.c59
-rw-r--r--src/target/firmware/fb/framebuffer.c28
-rw-r--r--src/target/firmware/fb/helvB08.c833
-rw-r--r--src/target/firmware/fb/helvB14.c1195
-rw-r--r--src/target/firmware/fb/helvB24.c1871
-rw-r--r--src/target/firmware/fb/helvR08.c826
-rw-r--r--src/target/firmware/fb/helvR14.c1198
-rw-r--r--src/target/firmware/fb/helvR24.c1870
-rw-r--r--src/target/firmware/fb/symbols.c113
-rw-r--r--src/target/firmware/flash/cfi_flash.c574
-rwxr-xr-xsrc/target/firmware/include/abb/twl3025.h186
-rw-r--r--src/target/firmware/include/arm.h7
-rw-r--r--src/target/firmware/include/arpa/inet.h2
-rw-r--r--src/target/firmware/include/asm/assembler.h113
-rw-r--r--src/target/firmware/include/asm/atomic.h106
-rw-r--r--src/target/firmware/include/asm/bitops.h225
-rw-r--r--src/target/firmware/include/asm/div64.h48
-rw-r--r--src/target/firmware/include/asm/linkage.h18
-rw-r--r--src/target/firmware/include/asm/ptrace.h128
-rw-r--r--src/target/firmware/include/asm/swab.h45
-rw-r--r--src/target/firmware/include/asm/system.h123
-rwxr-xr-xsrc/target/firmware/include/battery/battery.h37
-rw-r--r--src/target/firmware/include/battery/compal_e88.h15
-rw-r--r--src/target/firmware/include/board.h8
-rw-r--r--src/target/firmware/include/byteorder.h79
-rw-r--r--src/target/firmware/include/calypso/backlight.h10
-rw-r--r--src/target/firmware/include/calypso/buzzer.h34
-rw-r--r--src/target/firmware/include/calypso/clock.h67
-rw-r--r--src/target/firmware/include/calypso/dma.h6
-rw-r--r--src/target/firmware/include/calypso/dsp.h41
-rw-r--r--src/target/firmware/include/calypso/dsp_api.h1560
-rw-r--r--src/target/firmware/include/calypso/du.h32
-rw-r--r--src/target/firmware/include/calypso/irq.h49
-rw-r--r--src/target/firmware/include/calypso/l1_environment.h385
-rw-r--r--src/target/firmware/include/calypso/misc.h8
-rw-r--r--src/target/firmware/include/calypso/rtc.h6
-rwxr-xr-xsrc/target/firmware/include/calypso/sim.h179
-rw-r--r--src/target/firmware/include/calypso/timer.h25
-rw-r--r--src/target/firmware/include/calypso/tpu.h122
-rw-r--r--src/target/firmware/include/calypso/tsp.h31
-rw-r--r--src/target/firmware/include/comm/sercomm.h57
-rw-r--r--src/target/firmware/include/comm/sercomm_cons.h10
-rw-r--r--src/target/firmware/include/comm/timer.h77
-rw-r--r--src/target/firmware/include/console.h20
-rw-r--r--src/target/firmware/include/ctors.h16
-rw-r--r--src/target/firmware/include/ctype.h54
-rw-r--r--src/target/firmware/include/debug.h31
-rw-r--r--src/target/firmware/include/defines.h18
-rw-r--r--src/target/firmware/include/delay.h7
-rw-r--r--src/target/firmware/include/fb/fb_bw8.h51
-rw-r--r--src/target/firmware/include/fb/fb_rgb332.h47
-rw-r--r--src/target/firmware/include/fb/font.h82
-rw-r--r--src/target/firmware/include/fb/framebuffer.h128
-rw-r--r--src/target/firmware/include/flash/cfi_flash.h41
-rw-r--r--src/target/firmware/include/i2c.h7
-rw-r--r--src/target/firmware/include/keypad.h66
-rw-r--r--src/target/firmware/include/layer1/afc.h18
-rw-r--r--src/target/firmware/include/layer1/agc.h7
-rw-r--r--src/target/firmware/include/layer1/apc.h10
-rw-r--r--src/target/firmware/include/layer1/async.h62
-rw-r--r--src/target/firmware/include/layer1/avg.h23
-rw-r--r--src/target/firmware/include/layer1/l23_api.h18
-rw-r--r--src/target/firmware/include/layer1/mframe_sched.h68
-rw-r--r--src/target/firmware/include/layer1/prim.h34
-rw-r--r--src/target/firmware/include/layer1/rfch.h9
-rw-r--r--src/target/firmware/include/layer1/sched_gsmtime.h24
-rw-r--r--src/target/firmware/include/layer1/sync.h204
-rw-r--r--src/target/firmware/include/layer1/tdma_sched.h73
-rw-r--r--src/target/firmware/include/layer1/toa.h10
-rw-r--r--src/target/firmware/include/layer1/tpu_window.h24
-rw-r--r--src/target/firmware/include/manifest.h10
-rw-r--r--src/target/firmware/include/memory.h28
-rw-r--r--src/target/firmware/include/mtk/bfe.h107
-rw-r--r--src/target/firmware/include/mtk/bpi.h20
-rw-r--r--src/target/firmware/include/mtk/bsi.h41
-rw-r--r--src/target/firmware/include/mtk/emi.h42
-rw-r--r--src/target/firmware/include/mtk/mt6139.h60
-rw-r--r--src/target/firmware/include/mtk/mt6235.h74
-rw-r--r--src/target/firmware/include/mtk/mt6235_sciphone_g2.h38
-rw-r--r--src/target/firmware/include/mtk/system.h195
-rw-r--r--src/target/firmware/include/mtk/tdma_timer.h60
-rw-r--r--src/target/firmware/include/rf/trf6151.h51
-rw-r--r--src/target/firmware/include/rffe.h35
-rw-r--r--src/target/firmware/include/spi.h7
-rw-r--r--src/target/firmware/include/stdint.h36
-rw-r--r--src/target/firmware/include/stdio.h52
-rw-r--r--src/target/firmware/include/string.h12
-rw-r--r--src/target/firmware/include/swab.h297
-rw-r--r--src/target/firmware/include/uart.h32
-rw-r--r--src/target/firmware/include/uwire.h7
-rw-r--r--src/target/firmware/layer1/Makefile9
-rw-r--r--src/target/firmware/layer1/afc.c130
-rw-r--r--src/target/firmware/layer1/agc.c62
-rw-r--r--src/target/firmware/layer1/apc.c57
-rw-r--r--src/target/firmware/layer1/async.c159
-rw-r--r--src/target/firmware/layer1/avg.c57
-rw-r--r--src/target/firmware/layer1/init.c73
-rw-r--r--src/target/firmware/layer1/l23_api.c690
-rw-r--r--src/target/firmware/layer1/mframe_sched.c494
-rw-r--r--src/target/firmware/layer1/prim_fbsb.c575
-rw-r--r--src/target/firmware/layer1/prim_freq.c113
-rw-r--r--src/target/firmware/layer1/prim_pm.c241
-rw-r--r--src/target/firmware/layer1/prim_rach.c160
-rw-r--r--src/target/firmware/layer1/prim_rx_nb.c217
-rw-r--r--src/target/firmware/layer1/prim_tch.c752
-rw-r--r--src/target/firmware/layer1/prim_tx_nb.c173
-rw-r--r--src/target/firmware/layer1/prim_utils.c74
-rw-r--r--src/target/firmware/layer1/rfch.c152
-rw-r--r--src/target/firmware/layer1/sched_gsmtime.c119
-rw-r--r--src/target/firmware/layer1/sync.c402
-rw-r--r--src/target/firmware/layer1/tdma_sched.c244
-rw-r--r--src/target/firmware/layer1/toa.c80
-rw-r--r--src/target/firmware/layer1/tpu_window.c175
-rw-r--r--src/target/firmware/lib/Makefile7
-rw-r--r--src/target/firmware/lib/bitops.h33
-rw-r--r--src/target/firmware/lib/changebit.S21
-rw-r--r--src/target/firmware/lib/clearbit.S22
-rw-r--r--src/target/firmware/lib/console.c190
-rw-r--r--src/target/firmware/lib/copy_template.S255
-rw-r--r--src/target/firmware/lib/ctors.c15
-rw-r--r--src/target/firmware/lib/ctype.c34
-rw-r--r--src/target/firmware/lib/delay.c16
-rw-r--r--src/target/firmware/lib/div64.S200
-rw-r--r--src/target/firmware/lib/lib1funcs.S334
-rw-r--r--src/target/firmware/lib/memcpy.S59
-rw-r--r--src/target/firmware/lib/memset.S80
-rw-r--r--src/target/firmware/lib/printf.c19
-rw-r--r--src/target/firmware/lib/setbit.S22
-rw-r--r--src/target/firmware/lib/string.c50
-rw-r--r--src/target/firmware/lib/testchangebit.S18
-rw-r--r--src/target/firmware/lib/testclearbit.S18
-rw-r--r--src/target/firmware/lib/testsetbit.S18
-rw-r--r--src/target/firmware/lib/vsprintf.c847
-rw-r--r--src/target/firmware/rf/mt6139.c205
-rw-r--r--src/target/firmware/rf/trf6151.c605
-rw-r--r--src/target/ui-experiment/README11
-rw-r--r--src/target/ui-experiment/display.h46
-rw-r--r--src/target/ui-experiment/font.hbin0 -> 61204 bytes
-rw-r--r--src/target/ui-experiment/image.h166
-rw-r--r--src/target/ui-experiment/menu.h18
-rw-r--r--src/target/ui-experiment/pixel.h113
-rw-r--r--src/target/ui-experiment/png2tiny.c51
-rw-r--r--src/target/ui-experiment/screen.h21
-rw-r--r--src/target/ui-experiment/sdl.c250
-rw-r--r--src/target/ui-experiment/sdl.h9
-rw-r--r--src/target/ui-experiment/ui.h81
-rw-r--r--src/target_dsp/.gitignore4
-rw-r--r--src/target_dsp/calypso/Makefile15
-rwxr-xr-xsrc/target_dsp/calypso/bin2cfile.py57
-rw-r--r--src/target_dsp/calypso/bl_stage3.S142
-rw-r--r--src/target_dsp/calypso/dsp_dump.lds22
-rwxr-xr-xsrc/target_dsp/calypso/dump2coff.py260
-rw-r--r--src/target_dsp/calypso/ida/README.txt73
-rw-r--r--src/target_dsp/calypso/ida/ndb.h294
-rw-r--r--src/target_dsp/calypso/ida/tms320c54.cfg136
-rw-r--r--src/wireshark/gsmtap.patch445
-rw-r--r--src/wireshark/smscb.patch743
602 files changed, 96716 insertions, 2 deletions
diff --git a/doc/calypso-block.svg b/doc/calypso-block.svg
new file mode 100644
index 00000000..6f872676
--- /dev/null
+++ b/doc/calypso-block.svg
@@ -0,0 +1,707 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="297mm"
+ height="210mm"
+ id="svg2383"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="calypso-block.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/laforge/calypso-block.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs2385">
+ <marker
+ inkscape:stockid="CurveIn"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="CurveIn"
+ style="overflow:visible">
+ <path
+ id="path3349"
+ d="M 4.6254930,-5.0456926 C 1.8654930,-5.0456926 -0.37450702,-2.8056926 -0.37450702,-0.045692580 C -0.37450702,2.7143074 1.8654930,4.9543074 4.6254930,4.9543074"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none;fill:none"
+ transform="scale(0.6)" />
+ </marker>
+ <marker
+ inkscape:stockid="DotM"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="DotM"
+ style="overflow:visible">
+ <path
+ id="path3229"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.4) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mstart"
+ style="overflow:visible">
+ <path
+ id="path7719"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path3191"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path3179"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path3173"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path3307"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ id="path3185"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(1,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lend"
+ style="overflow:visible;">
+ <path
+ id="path3188"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 372.04724 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="1052.3622 : 372.04724 : 1"
+ inkscape:persp3d-origin="526.18109 : 248.03149 : 1"
+ id="perspective2392" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:document-units="mm"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.96166971"
+ inkscape:cx="576.3753"
+ inkscape:cy="495.79724"
+ inkscape:current-layer="layer1"
+ id="namedview2387"
+ showgrid="true"
+ inkscape:snap-global="true"
+ inkscape:window-width="1022"
+ inkscape:window-height="731"
+ inkscape:window-x="1024"
+ inkscape:window-y="0"
+ inkscape:snap-guide="true"
+ inkscape:object-paths="false"
+ inkscape:object-nodes="false"
+ objecttolerance="3"
+ gridtolerance="10000">
+ <inkscape:grid
+ type="xygrid"
+ id="grid2400"
+ visible="true"
+ enabled="true"
+ units="mm"
+ spacingx="5mm"
+ spacingy="5mm"
+ empspacing="2" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata2389">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#CurveIn);stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 992.12598,230.31495 L 1045.2756,230.31495 L 1045.2756,159.44881 L 1045.2756,159.44881"
+ id="path22123" />
+ <g
+ id="g12239">
+ <rect
+ y="35.433064"
+ x="70.866142"
+ height="265.74802"
+ width="177.16536"
+ id="rect7161"
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.77165353000000003;stroke-miterlimit:4;stroke-dasharray:none" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text7163"
+ y="53.149601"
+ x="72.866142"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="53.149601"
+ x="72.866142"
+ id="tspan7165"
+ sodipodi:role="line">CALYPSO</tspan></text>
+ </g>
+ <g
+ id="g20347">
+ <rect
+ y="70.77356"
+ x="389.63159"
+ height="230.24446"
+ width="106.56361"
+ id="rect2406"
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.50725651;stroke-miterlimit:4;stroke-dasharray:none" />
+ <text
+ transform="scale(1.0221827,0.9782987)"
+ sodipodi:linespacing="100%"
+ id="text7157"
+ y="92.63372"
+ x="381.30542"
+ style="font-size:21.45465279px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="92.63372"
+ x="381.30542"
+ id="tspan7159"
+ sodipodi:role="line">TWL3025</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text12244"
+ y="216.1601"
+ x="394.66666"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="216.1601"
+ x="394.66666"
+ id="tspan12246"
+ sodipodi:role="line">BSP</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text12248"
+ y="252.99342"
+ x="395.16666"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="252.99342"
+ x="395.16666"
+ id="tspan12250"
+ sodipodi:role="line">USP</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text12252"
+ y="286.42783"
+ x="396.16666"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="286.42783"
+ x="396.16666"
+ id="tspan12254"
+ sodipodi:role="line">TSP</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text20330"
+ y="163.44881"
+ x="464.62991"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="163.44881"
+ x="464.62991"
+ id="tspan20332"
+ sodipodi:role="line">BUL</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text20334"
+ y="146.96971"
+ x="463.70053"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="146.96971"
+ x="463.70053"
+ id="tspan20336"
+ sodipodi:role="line">BDL</tspan></text>
+ </g>
+ <g
+ id="g13450">
+ <rect
+ y="177.16687"
+ x="885.82831"
+ height="88.888702"
+ width="106.29617"
+ id="rect12310"
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.77468574;stroke-miterlimit:4;stroke-dasharray:none" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text13440"
+ y="230.31496"
+ x="903.54333"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="230.31496"
+ x="903.54333"
+ id="tspan13442"
+ sodipodi:role="line">Antenna</tspan><tspan
+ id="tspan13444"
+ y="242.31496"
+ x="903.54333"
+ sodipodi:role="line">Switch</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text13446"
+ y="194.88188"
+ x="887.82678"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="194.88188"
+ x="887.82678"
+ id="tspan13448"
+ sodipodi:role="line">ASM4532</tspan></text>
+ </g>
+ <rect
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.61511528;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect11596"
+ width="142.16623"
+ height="88.074844"
+ x="885.74847"
+ y="35.354794" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#550000;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)"
+ d="M 496.06299,283.46456 L 850.3937,283.46456 L 850.3937,106.29921 L 885.82677,106.29921"
+ id="path21554" />
+ <path
+ style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:3.54330707;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow2Mstart);marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 248.0315,212.59842 L 389.76378,212.59842 L 389.76378,212.59842"
+ id="path7167" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.54330708999999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)"
+ d="M 248.0315,283.46456 L 389.76378,283.46456"
+ id="path7171" />
+ <path
+ style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:3.54330707;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow2Mstart);marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 248.03149,248.03149 L 389.76378,248.03149 L 389.76378,248.03149"
+ id="path9925" />
+ <g
+ id="g12217">
+ <rect
+ y="35.433064"
+ x="637.79529"
+ height="212.59842"
+ width="141.73228"
+ id="rect2408"
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.77165354;stroke-miterlimit:4;stroke-dasharray:none" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text7153"
+ y="53.149601"
+ x="637.79529"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan11602"
+ y="78.149597"
+ x="637.79529"
+ sodipodi:role="line">TRF6151</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text12175"
+ y="88.582672"
+ x="655.51184"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="88.582672"
+ x="655.51184"
+ id="tspan12177"
+ sodipodi:role="line">Transceiver</tspan><tspan
+ id="tspan12179"
+ y="104.58267"
+ x="655.51184"
+ sodipodi:role="line">Mixers</tspan><tspan
+ id="tspan12183"
+ y="120.58267"
+ x="655.51184"
+ sodipodi:role="line">VCO</tspan><tspan
+ id="tspan12181"
+ y="136.58267"
+ x="655.51184"
+ sodipodi:role="line">PLL</tspan></text>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="885.82678"
+ y="53.149601"
+ id="text11598"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan11600"
+ x="885.82678"
+ y="53.149601">RF3166</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="903.54333"
+ y="88.582672"
+ id="text12185"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ x="903.54333"
+ y="88.582672"
+ id="tspan12193">RF PA</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="218.59842"
+ y="287.46457"
+ id="text12256"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan12258"
+ x="218.59842"
+ y="287.46457">TSP</tspan></text>
+ <g
+ id="g12268">
+ <path
+ id="path11606"
+ d="M 779.52756,53.149601 L 885.82677,53.149601 L 885.82677,53.149601"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12260"
+ y="51.149601"
+ x="814.96063"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="51.149601"
+ x="814.96063"
+ id="tspan12262"
+ sodipodi:role="line">GSM</tspan></text>
+ </g>
+ <g
+ id="g12273">
+ <path
+ id="path12195"
+ d="M 779.52756,70.866136 L 885.82677,70.866136 L 885.82677,70.866136"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12264"
+ y="68.866135"
+ x="814.96063"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="68.866135"
+ x="814.96063"
+ id="tspan12266"
+ sodipodi:role="line">DCS/PCS</tspan></text>
+ </g>
+ <g
+ id="g12290">
+ <path
+ id="path12197"
+ d="M 885.82677,194.88188 L 779.52756,194.88188 L 779.52756,194.88188"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12278"
+ y="192.88188"
+ x="814.96063"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="192.88188"
+ x="814.96063"
+ id="tspan12280"
+ sodipodi:role="line">GSM</tspan></text>
+ </g>
+ <g
+ id="g12295">
+ <path
+ id="path12165"
+ d="M 885.82677,212.59841 L 779.52756,212.59841 L 779.52756,212.59841"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12282"
+ y="210.59842"
+ x="814.96063"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="210.59842"
+ x="814.96063"
+ id="tspan12284"
+ sodipodi:role="line">DCS</tspan></text>
+ </g>
+ <g
+ id="g12300">
+ <path
+ id="path12199"
+ d="M 885.82677,230.31495 L 779.52756,230.31495 L 779.52756,230.31495"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12286"
+ y="228.31496"
+ x="814.96063"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="228.31496"
+ x="814.96063"
+ id="tspan12288"
+ sodipodi:role="line">PCS</tspan></text>
+ </g>
+ <g
+ id="g18005">
+ <text
+ sodipodi:linespacing="100%"
+ id="text14594"
+ y="49.149601"
+ x="425.21259"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan14598"
+ y="49.149601"
+ x="425.21259"
+ sodipodi:role="line">RFCLK</tspan></text>
+ <path
+ id="path14605"
+ d="M 637.79528,53.149601 L 248.0315,53.149601 L 248.0315,53.149601"
+ style="fill:none;fill-rule:evenodd;stroke:#ffff00;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)" />
+ </g>
+ <g
+ id="g18583">
+ <path
+ inkscape:label="#path2410"
+ id="path241011111"
+ d="M 496.06299,141.73228 L 637.79528,141.73228 L 637.79528,141.73228 L 637.79528,141.73228"
+ style="fill:#00ff00;fill-rule:evenodd;stroke:#00ff00;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow2Mstart);marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12167"
+ y="137.73228"
+ x="539.21259"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="137.73228"
+ x="539.21259"
+ id="tspan12169"
+ sodipodi:role="line">I/Q Analog</tspan></text>
+ <path
+ id="path15170"
+ d="M 531.49606,141.73228 L 531.49606,159.44881 L 496.06299,159.44881 L 496.06299,159.44881"
+ style="fill:none;fill-rule:evenodd;stroke:#00ff00;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow2Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g18000">
+ <path
+ id="path17431"
+ d="M 248.0315,88.582671 L 389.76378,88.582671"
+ style="fill:none;fill-rule:evenodd;stroke:#ffff00;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text17996"
+ y="84.582672"
+ x="295.18109"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="84.582672"
+ x="295.18109"
+ id="tspan17998"
+ sodipodi:role="line">CLK13M</tspan></text>
+ </g>
+ <g
+ id="g18593">
+ <path
+ id="path18010"
+ d="M 496.06299,194.88188 L 637.79528,194.88188"
+ style="fill:none;fill-rule:evenodd;stroke:#550000;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text18589"
+ y="188.88188"
+ x="537.49603"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="188.88188"
+ x="537.49603"
+ id="tspan18591"
+ sodipodi:role="line">AFC Analog</tspan></text>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)"
+ d="M 212.59843,301.1811 L 212.59843,372.04724 L 921.25984,372.04724 L 921.25984,265.74803"
+ id="path19726" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="354.33072"
+ y="368.04724"
+ id="text20291"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan20293"
+ x="354.33072"
+ y="368.04724">TSP Parallel</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="356.33072"
+ y="330.89764"
+ id="text20295"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan20297"
+ x="356.33072"
+ y="330.89764">TSP Serial</tspan></text>
+ <g
+ id="g20314"
+ transform="translate(-4.7244095e-7,-17.716533)">
+ <path
+ id="path20301"
+ d="M 248.0315,124.01574 L 389.76378,124.01574"
+ style="fill:none;fill-rule:evenodd;stroke:#ffff00;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text20303"
+ y="120.01574"
+ x="295.18109"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan20310"
+ y="120.01574"
+ x="295.18109"
+ sodipodi:role="line">CLK32K</tspan></text>
+ </g>
+ <g
+ id="g20421">
+ <path
+ id="path12871"
+ d="M 956.69291,124.01574 L 956.69291,177.16535"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ transform="matrix(0,-1,1,0,0,0)"
+ sodipodi:linespacing="100%"
+ id="text20402"
+ y="952.69293"
+ x="-159.44881"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="952.69293"
+ x="-159.44881"
+ id="tspan20404"
+ sodipodi:role="line">GSM</tspan></text>
+ </g>
+ <g
+ id="g20415">
+ <g
+ id="g20410">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 921.25984,124.01574 L 921.25984,177.16535"
+ id="path12312" />
+ <text
+ xml:space="preserve"
+ style="font-size:11.36807537px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="-184.69075"
+ y="867.06183"
+ id="text20406"
+ sodipodi:linespacing="100%"
+ transform="matrix(0,-0.9473396,1.0555877,0,0,0)"><tspan
+ sodipodi:role="line"
+ id="tspan20408"
+ x="-184.69075"
+ y="867.06183">DCS/PCS</tspan></text>
+ </g>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-start:url(#DotM);marker-end:url(#Arrow2Mend)"
+ d="M 921.25984,372.04724 L 1009.8425,372.04724 L 1009.8425,124.01574 L 1009.8425,124.01574"
+ id="path20426" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="539.21259"
+ y="279.46457"
+ id="text22119"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan22121"
+ x="539.21259"
+ y="279.46457">APC Analog</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM);marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 318.89764,283.46456 L 318.89764,336.61417 L 673.22835,336.61417 L 673.22835,248.03149"
+ id="path18598" />
+ </g>
+</svg>
diff --git a/doc/calypso-gsm-notes.txt b/doc/calypso-gsm-notes.txt
new file mode 100644
index 00000000..4377ceb4
--- /dev/null
+++ b/doc/calypso-gsm-notes.txt
@@ -0,0 +1,2 @@
+GSM burst duration: 577uS
+RITA synthesizer retuning max: 170uS
diff --git a/doc/calypso-signals.txt b/doc/calypso-signals.txt
new file mode 100644
index 00000000..be49cf03
--- /dev/null
+++ b/doc/calypso-signals.txt
@@ -0,0 +1,184 @@
+CALYPSO PAD AND NAME I/O CONNECTS TO TO BFIN?
+========================================================================================================
+C12 CLK32K_OUT O TWL3025:CLK32K (32kHz clock input) M
+F12 CLK13M_OUT_START_BIT O TWL3025:CLK13M (master clock input) M
+D12 nRESPWON I TWL3025:RESPWONz (dbb power-on reset @ batt insert) O
+P1 EXT-FIQ I TWL3025:INT1 O
+M3 EXT-IRQ I TWL3025:INT2 M
+A12 TCXOEN O TRF6151:XSEL,XEN (enable 26MHz oscillator) M
+F10 ON_OFF I TWL3025:ON_nOFF (dbb reset @ each switch on) O
+B14 IT_WAKEUP O TWL3025:ITWAKEUP (real-time wake-up irq) O
+B11 NEMU0 NC
+E10 NEMU1 NC
+D11 NBSCAN NC
+D10 TDI I
+C10 TDO O
+B10 TCK I
+E9 TMS I
+L11 BFSR I TWL3025:BFSX (bb-serial tx frame sync) M
+K10 BDR I TWL3025:BDX (bb-serial tx data) M
+P12 BFSX O TWL3025:BFSR (bb-serial rx frame sync) M
+M11 BDX O TWL3025:BDR (bb-serial rx data) M
+N11 BCLKX-IO6 NC
+P11 BCLKR-ARMCLK GND
+P14 VDX O TWL3025:VDR (vb-serial rx data)
+N13 VDR I TWL3025:VDX (vb-serial tx data)
+M13 VFSRX I TWL3025:VFS (vb-serial frame sync)
+N12 VCLKRX I TWL3025:VCK (vb-serial clock)
+N7 MCUDI I TWL3025:UDX (spi output) M
+M7 MCUDO O TWL3025:UDR (spi input) M
+M8 MCUEN0 O TWL3025:UEN (spi enable) M
+P8 MCUEN1-IO9 NC
+L8 MCUEN2-IO13 NC
+G13 SIM_IO IO TWL3025:DBBSIO (sim card shifter data) L
+F13 SIM_CLK O TWL3025:DBBSCK (sim card shifter clock) L
+G10 SIM_RST O TWL3025:DBBSRST (sim card shifter reset inp) L
+G11 SIM_CD-MAS0 V_IO
+F14 SIM_PWRCTRL-IO5 O TWL3025:DBBSIO (via 10k) L
+B13 OSC32K_OUT O XTAL
+C13 OSC32K_IN I XTAL
+A14 VSSO GND
+E13 CLKTCXO I TRF6151C:RFCLK (TCXO clock output) M
+M2 IDDQ GND
+N1 NI BOOT GND (via 100k)
+N2 nRESET_OUT O NC
+M4 IO3-SIM_RNW NC
+L4 IO2-IRQ4 NC
+P3 IO1-TPU_IDLE O S3C2410
+N3 IO0-TPU_WAIT NC
+L7 LT-PWL NC
+K7 BU-PWT NC
+L6 KBR4-XDIO7 NC
+N6 KBR3-XDIO6 NC
+P6 KBR2-XDIO5 NC
+M6 KBR1-XDIO4 NC
+K6 KBR0-XDIO3 NC
+M5 KBC4-XDIO2 NC
+P5 KBC3-XDIO1 NC
+L5 KBC2-XDIO0 NC
+K5 KBC1-nIRQ NC
+N4 KBC0-nFIQ NC
+K9 MCSI_FSYNCH-IO12 NC
+N10 MCSI_CLI-IO11 NC
+M10 MCSI_RXD-IO10 NC
+L10 MCSI_TXD-IO9 NC
+C9 CTS_MODEM-X_F S3C24xx
+D9 DSR_MODEM-LPG S3c24xx
+E8 RTS_MODEM-TOUT S3c24xx
+A9 RX_MODEM I S3c24xx
+B9 TX_MODEM O S3c24xx
+B8 SD_IRDA-CLKOUT_DSP NC
+A8 RXIR_IRDA-X_A1 NC
+C7 TXIR_IRDA-X_A4 NC
+D8 RX_IRDA I socket
+C8 TX_IRDA O socket
+N9 NSCS(1)-X_A32 NC
+L9 NSCS0-SCL NC
+M9 SDI-SDA I V-IO
+K8 SDO-nINT10 I NC
+P9 SCLK-nINT1 I INT0
+I14 TSPCLKX O TRF6151:CLK (serial clock) M
+H11 TSPDO O TWL3025:TDR,TRF6151:DATA (serial data) M
+H10 DSPDI-IO4 I NC
+H13 TSPEN0 O TWL3025:TEN (TSP enable) M
+H12 TSPEN1 NC
+H14 TSPEN2 TRF6151:STROBE (serial strobe) M
+G12 TSPEN3-nSCS2 NC
+M12 TSPACT0 O TRF6151:RESETz (serial interface reset) M
+M14 TSPACT1 O ASM4532:VC2 M
+L12 TSPACT2 O ASM4532:VC1 M
+L13 TSPACT3 O RF3166:BAND_SELECT M
+I10 TSPACT4-nRDYMEM O ASM4532:VC3 M
+K11 TSPACT5-DPLLCLK NC
+K13 TSPACT6-nCS6 NC
+K12 TSPACT7-CLKX_SPI NC
+K14 TSPACT8-nMREQ NC
+I11 TSPACT9-MAS1 RF3166:TX_ENABLE (PA TX) M
+I12 TSPACT10-nWAIT NC
+I13 TSPACT11-MCLK NC
+B7 DATA0 RAM/FLASH
+D7 DATA1 RAM/FLASH
+E7 DATA2 RAM/FLASH
+D6 DATA3 RAM/FLASH
+A6 DATA4 RAM/FLASH
+C6 DATA5 RAM/FLASH
+E6 DATA6 RAM/FLASH
+C6 DATA7 RAM/FLASH
+B5 DATA8 RAM/FLASH
+D5 DATA9 RAM/FLASH
+E5 DATA10 RAM/FLASH
+B4 DATA11 RAM/FLASH
+C4 DATA12 RAM/FLASH
+D4 DATA13 RAM/FLASH
+A3 DATA14 RAM/FLASH
+B3 DATA15 RAM/FLASH
+F3 ADD0 RAM/FLASH
+F2 ADD1 RAM/FLASH
+G5 ADD2 RAM/FLASH
+G4 ADD3 RAM/FLASH
+G2 ADD4 RAM/FLASH
+G3 ADD5 RAM/FLASH
+H1 ADD6 RAM/FLASH
+H3 ADD7 RAM/FLASH
+H2 ADD8 RAM/FLASH
+H4 ADD9 RAM/FLASH
+H5 ADD10 RAM/FLASH
+I1 ADD11 RAM/FLASH
+I2 ADD12 RAM/FLASH
+I3 ADD13 RAM/FLASH
+K3 ADD15 RAM/FLASH
+K2 ADD16 RAM/FLASH
+K4 ADD17 RAM/FLASH
+I5 ADD18 RAM/FLASH
+L1 ADD19 RAM/FLASH
+L2 ADD20 RAM/FLASH
+L3 ADD21-CLK16X_IRDA RAM/FLASH
+B2 RNW RAM/FLASH
+E3 nFEW-X_A0 NC
+E2 nFOE-X_A3 RAM/FLASH
+F4 FDP-nIACK RAM/FLASH
+E4 nBLE-IO15 RAM/FLASH
+F5 nBHE-IO14 RAM/FLASH
+C2 nCS0
+C3 nCS1 RAM/FLASH
+C1 nCS2 NC
+D3 nCS3-nINT4 NC
+D2 CS4-ADD22 RAM/FLASH
+C11 nCS4-CO35 RAM/FLASH
+A4 VDDS-MF1 V-FLASH
+B6 VDDS-MF2 V-FLASH
+G1 VDDS-MF3 V-FLASH
+D1 VDDS-MF4 V-FLASH
+A11 VDDS_2 V-IO
+L14 VDDS_1 V-IO
+N5 VDDS_1 V-IO
+A5 VDD1 V-DBB
+B12 VDD2 V-DBB
+N14 VDD3 V-DBB
+P7 VDD4 V-DBB
+M1 VDD5 V-DBB
+E1 VDD6 V-DBB
+F1 VSS1 GND
+N8 VSS2 GND
+K1 VSS3 GND
+P2 VSS4 GND
+P4 VSS5 GND
+P10 VSS6 GND
+P13 VSS7 GND
+G14 BSS8 GND
+A10 VSS9 GND
+A7 VSS10 GND
+A2 VSS11 GND
+B1 VSS12 GND
+D13 VDDS_RTC V-RTC
+D14 VDD_RTC V-RTC
+C14 VSS_RTC GND
+E11 VDD_ANG V-IO
+E12 VSS_ANG GND
+F11 VDD_PLL V-DBB
+E14 VSS_PLL GND
+
+Other signals
+
+MODEM_ON
+MODEM_RST
diff --git a/doc/gsmdevboard-block.svg b/doc/gsmdevboard-block.svg
new file mode 100644
index 00000000..cb19bc0a
--- /dev/null
+++ b/doc/gsmdevboard-block.svg
@@ -0,0 +1,746 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="297mm"
+ height="210mm"
+ id="svg2383"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="gsmdevboard-block.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/sunbeam/home/laforge/gsmdevboard-block.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs2385">
+ <marker
+ inkscape:stockid="CurveIn"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="CurveIn"
+ style="overflow:visible">
+ <path
+ id="path3349"
+ d="M 4.6254930,-5.0456926 C 1.8654930,-5.0456926 -0.37450702,-2.8056926 -0.37450702,-0.045692580 C -0.37450702,2.7143074 1.8654930,4.9543074 4.6254930,4.9543074"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none;fill:none"
+ transform="scale(0.6)" />
+ </marker>
+ <marker
+ inkscape:stockid="DotM"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="DotM"
+ style="overflow:visible">
+ <path
+ id="path3229"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.4) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mstart"
+ style="overflow:visible">
+ <path
+ id="path7719"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path3191"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path3179"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path3173"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path3307"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ id="path3185"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(1,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lend"
+ style="overflow:visible;">
+ <path
+ id="path3188"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 372.04724 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="1052.3622 : 372.04724 : 1"
+ inkscape:persp3d-origin="526.18109 : 248.03149 : 1"
+ id="perspective2392" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:document-units="mm"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.96166971"
+ inkscape:cx="386.08127"
+ inkscape:cy="495.79724"
+ inkscape:current-layer="layer1"
+ id="namedview2387"
+ showgrid="true"
+ inkscape:snap-global="true"
+ inkscape:window-width="1598"
+ inkscape:window-height="1163"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:snap-guide="true"
+ inkscape:object-paths="false"
+ inkscape:object-nodes="false"
+ objecttolerance="3"
+ gridtolerance="10000">
+ <inkscape:grid
+ type="xygrid"
+ id="grid2400"
+ visible="true"
+ enabled="true"
+ units="mm"
+ spacingx="5mm"
+ spacingy="5mm"
+ empspacing="2" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata2389">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#CurveIn);stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 992.12598,230.31495 L 1045.2756,230.31495 L 1045.2756,159.44881 L 1045.2756,159.44881"
+ id="path22123" />
+ <g
+ id="g20347">
+ <rect
+ y="70.77356"
+ x="389.63159"
+ height="230.24446"
+ width="106.56361"
+ id="rect2406"
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.50725651;stroke-miterlimit:4;stroke-dasharray:none" />
+ <text
+ transform="scale(1.0221827,0.9782987)"
+ sodipodi:linespacing="100%"
+ id="text7157"
+ y="92.63372"
+ x="381.30542"
+ style="font-size:21.45465279px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="92.63372"
+ x="381.30542"
+ id="tspan7159"
+ sodipodi:role="line">TWL3025</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text12244"
+ y="216.1601"
+ x="394.66666"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="216.1601"
+ x="394.66666"
+ id="tspan12246"
+ sodipodi:role="line">BSP</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text12248"
+ y="252.99342"
+ x="395.16666"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="252.99342"
+ x="395.16666"
+ id="tspan12250"
+ sodipodi:role="line">USP</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text12252"
+ y="286.42783"
+ x="396.16666"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="286.42783"
+ x="396.16666"
+ id="tspan12254"
+ sodipodi:role="line">TSP</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text20330"
+ y="163.44881"
+ x="464.62991"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="163.44881"
+ x="464.62991"
+ id="tspan20332"
+ sodipodi:role="line">BUL</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text20334"
+ y="146.96971"
+ x="463.70053"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="146.96971"
+ x="463.70053"
+ id="tspan20336"
+ sodipodi:role="line">BDL</tspan></text>
+ </g>
+ <g
+ id="g13450">
+ <rect
+ y="177.16687"
+ x="885.82831"
+ height="88.888702"
+ width="106.29617"
+ id="rect12310"
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.77468574;stroke-miterlimit:4;stroke-dasharray:none" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text13440"
+ y="230.31496"
+ x="903.54333"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="230.31496"
+ x="903.54333"
+ id="tspan13442"
+ sodipodi:role="line">Antenna</tspan><tspan
+ id="tspan13444"
+ y="242.31496"
+ x="903.54333"
+ sodipodi:role="line">Switch</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text13446"
+ y="194.88188"
+ x="887.82678"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="194.88188"
+ x="887.82678"
+ id="tspan13448"
+ sodipodi:role="line">ASM4532</tspan></text>
+ </g>
+ <rect
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.61511528;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect11596"
+ width="142.16623"
+ height="88.074844"
+ x="885.74847"
+ y="35.354794" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#550000;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)"
+ d="M 496.06299,283.46456 L 850.3937,283.46456 L 850.3937,106.29921 L 885.82677,106.29921"
+ id="path21554" />
+ <path
+ style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:3.54330707;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow2Mstart);marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 248.0315,212.59842 L 389.76378,212.59842 L 389.76378,212.59842"
+ id="path7167" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.54330708999999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)"
+ d="M 248.0315,283.46456 L 389.76378,283.46456"
+ id="path7171" />
+ <path
+ style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:3.54330707;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow2Mstart);marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 248.03149,248.03149 L 389.76378,248.03149 L 389.76378,248.03149"
+ id="path9925" />
+ <g
+ id="g12217">
+ <rect
+ y="35.433064"
+ x="637.79529"
+ height="212.59842"
+ width="141.73228"
+ id="rect2408"
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.77165354;stroke-miterlimit:4;stroke-dasharray:none" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text7153"
+ y="53.149601"
+ x="637.79529"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan11602"
+ y="78.149597"
+ x="637.79529"
+ sodipodi:role="line">TRF6151</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text12175"
+ y="88.582672"
+ x="655.51184"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="88.582672"
+ x="655.51184"
+ id="tspan12177"
+ sodipodi:role="line">Transceiver</tspan><tspan
+ id="tspan12179"
+ y="104.58267"
+ x="655.51184"
+ sodipodi:role="line">Mixers</tspan><tspan
+ id="tspan12183"
+ y="120.58267"
+ x="655.51184"
+ sodipodi:role="line">VCO</tspan><tspan
+ id="tspan12181"
+ y="136.58267"
+ x="655.51184"
+ sodipodi:role="line">PLL</tspan></text>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="885.82678"
+ y="53.149601"
+ id="text11598"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan11600"
+ x="885.82678"
+ y="53.149601">RF3166</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="903.54333"
+ y="88.582672"
+ id="text12185"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ x="903.54333"
+ y="88.582672"
+ id="tspan12193">RF PA</tspan></text>
+ <g
+ id="g12268">
+ <path
+ id="path11606"
+ d="M 779.52756,53.149601 L 885.82677,53.149601 L 885.82677,53.149601"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12260"
+ y="51.149601"
+ x="814.96063"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="51.149601"
+ x="814.96063"
+ id="tspan12262"
+ sodipodi:role="line">GSM</tspan></text>
+ </g>
+ <g
+ id="g12273">
+ <path
+ id="path12195"
+ d="M 779.52756,70.866136 L 885.82677,70.866136 L 885.82677,70.866136"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12264"
+ y="68.866135"
+ x="814.96063"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="68.866135"
+ x="814.96063"
+ id="tspan12266"
+ sodipodi:role="line">DCS/PCS</tspan></text>
+ </g>
+ <g
+ id="g12290">
+ <path
+ id="path12197"
+ d="M 885.82677,194.88188 L 779.52756,194.88188 L 779.52756,194.88188"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12278"
+ y="192.88188"
+ x="814.96063"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="192.88188"
+ x="814.96063"
+ id="tspan12280"
+ sodipodi:role="line">GSM</tspan></text>
+ </g>
+ <g
+ id="g12295">
+ <path
+ id="path12165"
+ d="M 885.82677,212.59841 L 779.52756,212.59841 L 779.52756,212.59841"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12282"
+ y="210.59842"
+ x="814.96063"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="210.59842"
+ x="814.96063"
+ id="tspan12284"
+ sodipodi:role="line">DCS</tspan></text>
+ </g>
+ <g
+ id="g12300">
+ <path
+ id="path12199"
+ d="M 885.82677,230.31495 L 779.52756,230.31495 L 779.52756,230.31495"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12286"
+ y="228.31496"
+ x="814.96063"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="228.31496"
+ x="814.96063"
+ id="tspan12288"
+ sodipodi:role="line">PCS</tspan></text>
+ </g>
+ <g
+ id="g18005">
+ <text
+ sodipodi:linespacing="100%"
+ id="text14594"
+ y="49.149601"
+ x="425.21259"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan14598"
+ y="49.149601"
+ x="425.21259"
+ sodipodi:role="line">RFCLK</tspan></text>
+ <path
+ id="path14605"
+ d="M 637.79528,53.149601 L 248.0315,53.149601 L 248.0315,53.149601"
+ style="fill:none;fill-rule:evenodd;stroke:#ffff00;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)" />
+ </g>
+ <g
+ id="g18583">
+ <path
+ inkscape:label="#path2410"
+ id="path241011111"
+ d="M 496.06299,141.73228 L 637.79528,141.73228 L 637.79528,141.73228 L 637.79528,141.73228"
+ style="fill:#00ff00;fill-rule:evenodd;stroke:#00ff00;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow2Mstart);marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text12167"
+ y="137.73228"
+ x="539.21259"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="137.73228"
+ x="539.21259"
+ id="tspan12169"
+ sodipodi:role="line">I/Q Analog</tspan></text>
+ <path
+ id="path15170"
+ d="M 531.49606,141.73228 L 531.49606,159.44881 L 496.06299,159.44881 L 496.06299,159.44881"
+ style="fill:none;fill-rule:evenodd;stroke:#00ff00;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow2Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g18000">
+ <path
+ id="path17431"
+ d="M 248.0315,88.582671 L 389.76378,88.582671"
+ style="fill:none;fill-rule:evenodd;stroke:#ffff00;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text17996"
+ y="84.582672"
+ x="295.18109"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="84.582672"
+ x="295.18109"
+ id="tspan17998"
+ sodipodi:role="line">CLK13M</tspan></text>
+ </g>
+ <g
+ id="g18593">
+ <path
+ id="path18010"
+ d="M 496.06299,194.88188 L 637.79528,194.88188"
+ style="fill:none;fill-rule:evenodd;stroke:#550000;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text18589"
+ y="188.88188"
+ x="537.49603"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="188.88188"
+ x="537.49603"
+ id="tspan18591"
+ sodipodi:role="line">AFC Analog</tspan></text>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)"
+ d="M 212.59843,301.1811 L 212.59843,372.04724 L 921.25984,372.04724 L 921.25984,265.74803"
+ id="path19726" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="354.33072"
+ y="368.04724"
+ id="text20291"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan20293"
+ x="354.33072"
+ y="368.04724">TSP Parallel</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="356.33072"
+ y="330.89764"
+ id="text20295"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan20297"
+ x="356.33072"
+ y="330.89764">TSP Serial</tspan></text>
+ <g
+ id="g20314"
+ transform="translate(-4.7244095e-7,-17.716533)">
+ <path
+ id="path20301"
+ d="M 248.0315,124.01574 L 389.76378,124.01574"
+ style="fill:none;fill-rule:evenodd;stroke:#ffff00;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text20303"
+ y="120.01574"
+ x="295.18109"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan20310"
+ y="120.01574"
+ x="295.18109"
+ sodipodi:role="line">CLK32K</tspan></text>
+ </g>
+ <g
+ id="g20421">
+ <path
+ id="path12871"
+ d="M 956.69291,124.01574 L 956.69291,177.16535"
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464575;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ transform="matrix(0,-1,1,0,0,0)"
+ sodipodi:linespacing="100%"
+ id="text20402"
+ y="952.69293"
+ x="-159.44881"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="952.69293"
+ x="-159.44881"
+ id="tspan20404"
+ sodipodi:role="line">GSM</tspan></text>
+ </g>
+ <g
+ id="g20415">
+ <g
+ id="g20410">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#ff00ff;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 921.25984,124.01574 L 921.25984,177.16535"
+ id="path12312" />
+ <text
+ xml:space="preserve"
+ style="font-size:11.36807537px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="-184.69075"
+ y="867.06183"
+ id="text20406"
+ sodipodi:linespacing="100%"
+ transform="matrix(0,-0.9473396,1.0555877,0,0,0)"><tspan
+ sodipodi:role="line"
+ id="tspan20408"
+ x="-184.69075"
+ y="867.06183">DCS/PCS</tspan></text>
+ </g>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-start:url(#DotM);marker-end:url(#Arrow2Mend)"
+ d="M 921.25984,372.04724 L 1009.8425,372.04724 L 1009.8425,124.01574 L 1009.8425,124.01574"
+ id="path20426" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="539.21259"
+ y="279.46457"
+ id="text22119"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan22121"
+ x="539.21259"
+ y="279.46457">APC Analog</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2.83464567;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM);marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 318.89764,283.46456 L 318.89764,336.61417 L 673.22835,336.61417 L 673.22835,248.03149"
+ id="path18598" />
+ <g
+ id="g3366">
+ <rect
+ y="35.433064"
+ x="70.866142"
+ height="265.74802"
+ width="177.16536"
+ id="rect7161"
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.77165353;stroke-miterlimit:4;stroke-dasharray:none" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text7163"
+ y="53.149601"
+ x="72.866142"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3352"
+ y="53.149601"
+ x="72.866142"
+ sodipodi:role="line">BF537</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text12256"
+ y="287.46457"
+ x="218.59842"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="287.46457"
+ x="218.59842"
+ id="tspan12258"
+ sodipodi:role="line">TSP</tspan></text>
+ <path
+ d="M 158.52718,76.505608 A 0.46875,0.46875 0 1 1 157.58968,76.505608 A 0.46875,0.46875 0 1 1 158.52718,76.505608 z"
+ sodipodi:ry="0.46875"
+ sodipodi:rx="0.46875"
+ sodipodi:cy="76.505608"
+ sodipodi:cx="158.05843"
+ style="fill:#000000;stroke:none"
+ id="path2520"
+ sodipodi:type="arc" />
+ <path
+ id="path2522"
+ d="M 159.44882,35.327311 L 159.44882,301.07535 L 159.44882,301.07535 L 159.44882,301.07535 L 159.44882,301.07535"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.47677553;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text3348"
+ y="53.149601"
+ x="159.44882"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3358"
+ y="53.149601"
+ x="159.44882"
+ sodipodi:role="line">Spartan</tspan><tspan
+ id="tspan3356"
+ y="73.149597"
+ x="159.44882"
+ sodipodi:role="line">3E</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text3362"
+ y="290.92511"
+ x="89.994156"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="290.92511"
+ x="89.994156"
+ id="tspan3364"
+ sodipodi:role="line">Ethernet</tspan></text>
+ </g>
+ </g>
+</svg>
diff --git a/include/l1ctl_proto.h b/include/l1ctl_proto.h
new file mode 100644
index 00000000..4b9540e9
--- /dev/null
+++ b/include/l1ctl_proto.h
@@ -0,0 +1,302 @@
+/* Messages to be sent between the different layers */
+
+/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by Holger Hans Peter Freyther
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef __L1CTL_PROTO_H__
+#define __L1CTL_PROTO_H__
+
+enum {
+ _L1CTL_NONE = 0,
+ L1CTL_FBSB_REQ,
+ L1CTL_FBSB_CONF,
+ L1CTL_DATA_IND,
+ L1CTL_RACH_REQ,
+ L1CTL_DM_EST_REQ,
+ L1CTL_DATA_REQ,
+ L1CTL_RESET_IND,
+ L1CTL_PM_REQ, /* power measurement */
+ L1CTL_PM_CONF, /* power measurement */
+ L1CTL_ECHO_REQ,
+ L1CTL_ECHO_CONF,
+ L1CTL_RACH_CONF,
+ L1CTL_RESET_REQ,
+ L1CTL_RESET_CONF,
+ L1CTL_DATA_CONF,
+ L1CTL_CCCH_MODE_REQ,
+ L1CTL_CCCH_MODE_CONF,
+ L1CTL_DM_REL_REQ,
+ L1CTL_PARAM_REQ,
+ L1CTL_DM_FREQ_REQ,
+ L1CTL_CRYPTO_REQ,
+ L1CTL_SIM_REQ,
+ L1CTL_SIM_CONF,
+ L1CTL_TCH_MODE_REQ,
+ L1CTL_TCH_MODE_CONF,
+ L1CTL_NEIGH_PM_REQ,
+ L1CTL_NEIGH_PM_IND,
+ L1CTL_TRAFFIC_REQ,
+ L1CTL_TRAFFIC_CONF,
+ L1CTL_TRAFFIC_IND,
+};
+
+enum ccch_mode {
+ CCCH_MODE_NONE = 0,
+ CCCH_MODE_NON_COMBINED,
+ CCCH_MODE_COMBINED,
+};
+
+enum neigh_mode {
+ NEIGH_MODE_NONE = 0,
+ NEIGH_MODE_PM,
+ NEIGH_MODE_SB,
+};
+
+#define TRAFFIC_DATA_LEN 40
+
+/*
+ * NOTE: struct size. We do add manual padding out of the believe
+ * that it will avoid some unaligned access.
+ */
+
+/* there are no more messages in a sequence */
+#define L1CTL_F_DONE 0x01
+
+struct l1ctl_hdr {
+ uint8_t msg_type;
+ uint8_t flags;
+ uint8_t padding[2];
+ uint8_t data[0];
+} __attribute__((packed));
+
+/*
+ * downlink info ... down from the BTS..
+ */
+struct l1ctl_info_dl {
+ /* GSM 08.58 channel number (9.3.1) */
+ uint8_t chan_nr;
+ /* GSM 08.58 link identifier (9.3.2) */
+ uint8_t link_id;
+ /* the ARFCN and the band. FIXME: what about MAIO? */
+ uint16_t band_arfcn;
+
+ uint32_t frame_nr;
+
+ uint8_t rx_level; /* 0 .. 63 in typical GSM notation (dBm+110) */
+ uint8_t snr; /* Signal/Noise Ration (dB) */
+ uint8_t num_biterr;
+ uint8_t fire_crc;
+
+ uint8_t payload[0];
+} __attribute__((packed));
+
+/* new CCCH was found. This is following the header */
+struct l1ctl_fbsb_conf {
+ int16_t initial_freq_err;
+ uint8_t result;
+ uint8_t bsic;
+ /* FIXME: contents of cell_info ? */
+} __attribute__((packed));
+
+/* CCCH mode was changed */
+struct l1ctl_ccch_mode_conf {
+ uint8_t ccch_mode; /* enum ccch_mode */
+ uint8_t padding[3];
+} __attribute__((packed));
+
+/* TCH mode was changed */
+struct l1ctl_tch_mode_conf {
+ uint8_t tch_mode; /* enum tch_mode */
+ uint8_t audio_mode;
+ uint8_t padding[2];
+} __attribute__((packed));
+
+/* data on the CCCH was found. This is following the header */
+struct l1ctl_data_ind {
+ uint8_t data[23];
+} __attribute__((packed));
+
+/* traffic from the network */
+struct l1ctl_traffic_ind {
+ uint8_t data[TRAFFIC_DATA_LEN];
+} __attribute__((packed));
+
+/*
+ * uplink info
+ */
+struct l1ctl_info_ul {
+ /* GSM 08.58 channel number (9.3.1) */
+ uint8_t chan_nr;
+ /* GSM 08.58 link identifier (9.3.2) */
+ uint8_t link_id;
+ uint8_t padding[2];
+
+ uint8_t payload[0];
+} __attribute__((packed));
+
+/*
+ * msg for FBSB_REQ
+ * the l1_info_ul header is in front
+ */
+struct l1ctl_fbsb_req {
+ uint16_t band_arfcn;
+ uint16_t timeout; /* in TDMA frames */
+
+ uint16_t freq_err_thresh1;
+ uint16_t freq_err_thresh2;
+
+ uint8_t num_freqerr_avg;
+ uint8_t flags; /* L1CTL_FBSB_F_* */
+ uint8_t sync_info_idx;
+ uint8_t ccch_mode; /* enum ccch_mode */
+} __attribute__((packed));
+
+#define L1CTL_FBSB_F_FB0 (1 << 0)
+#define L1CTL_FBSB_F_FB1 (1 << 1)
+#define L1CTL_FBSB_F_SB (1 << 2)
+#define L1CTL_FBSB_F_FB01SB (L1CTL_FBSB_F_FB0|L1CTL_FBSB_F_FB1|L1CTL_FBSB_F_SB)
+
+/*
+ * msg for CCCH_MODE_REQ
+ * the l1_info_ul header is in front
+ */
+struct l1ctl_ccch_mode_req {
+ uint8_t ccch_mode; /* enum ccch_mode */
+ uint8_t padding[3];
+} __attribute__((packed));
+
+/*
+ * msg for TCH_MODE_REQ
+ * the l1_info_ul header is in front
+ */
+struct l1ctl_tch_mode_req {
+ uint8_t tch_mode; /* enum gsm48_chan_mode */
+#define AUDIO_TX_MICROPHONE (1<<0)
+#define AUDIO_TX_TRAFFIC_REQ (1<<1)
+#define AUDIO_RX_SPEAKER (1<<2)
+#define AUDIO_RX_TRAFFIC_IND (1<<3)
+ uint8_t audio_mode;
+ uint8_t padding[2];
+} __attribute__((packed));
+
+/* the l1_info_ul header is in front */
+struct l1ctl_rach_req {
+ uint8_t ra;
+ uint8_t combined;
+ uint16_t offset;
+} __attribute__((packed));
+
+/* the l1_info_ul header is in front */
+struct l1ctl_par_req {
+ int8_t ta;
+ uint8_t tx_power;
+ uint8_t padding[2];
+} __attribute__((packed));
+
+struct l1ctl_h0 {
+ uint16_t band_arfcn;
+} __attribute__((packed));
+
+struct l1ctl_h1 {
+ uint8_t hsn;
+ uint8_t maio;
+ uint8_t n;
+ uint8_t _padding[1];
+ uint16_t ma[64];
+} __attribute__((packed));
+
+struct l1ctl_dm_est_req {
+ uint8_t tsc;
+ uint8_t h;
+ union {
+ struct l1ctl_h0 h0;
+ struct l1ctl_h1 h1;
+ };
+ uint8_t tch_mode;
+ uint8_t audio_mode;
+} __attribute__((packed));
+
+struct l1ctl_dm_freq_req {
+ uint16_t fn;
+ uint8_t tsc;
+ uint8_t h;
+ union {
+ struct l1ctl_h0 h0;
+ struct l1ctl_h1 h1;
+ };
+} __attribute__((packed));
+
+struct l1ctl_crypto_req {
+ uint8_t algo;
+ uint8_t key[0];
+} __attribute__((packed));
+
+struct l1ctl_pm_req {
+ uint8_t type;
+ uint8_t padding[3];
+
+ union {
+ struct {
+ uint16_t band_arfcn_from;
+ uint16_t band_arfcn_to;
+ } range;
+ };
+} __attribute__((packed));
+
+/* a single L1CTL_PM response */
+struct l1ctl_pm_conf {
+ uint16_t band_arfcn;
+ uint8_t pm[2];
+} __attribute__((packed));
+
+enum l1ctl_reset_type {
+ L1CTL_RES_T_BOOT, /* only _IND */
+ L1CTL_RES_T_FULL,
+ L1CTL_RES_T_SCHED,
+};
+
+/* argument to L1CTL_RESET_REQ and L1CTL_RESET_IND */
+struct l1ctl_reset {
+ uint8_t type;
+ uint8_t pad[3];
+} __attribute__((packed));
+
+struct l1ctl_neigh_pm_req {
+ uint8_t n;
+ uint8_t padding[1];
+ uint16_t band_arfcn[64];
+ uint8_t tn[64];
+} __attribute__((packed));
+
+/* neighbour cell measurement results */
+struct l1ctl_neigh_pm_ind {
+ uint16_t band_arfcn;
+ uint8_t pm[2];
+ uint8_t tn;
+ uint8_t padding;
+} __attribute__((packed));
+
+/* traffic data to network */
+struct l1ctl_traffic_req {
+ uint8_t data[TRAFFIC_DATA_LEN];
+} __attribute__((packed));
+
+#endif /* __L1CTL_PROTO_H__ */
diff --git a/include/osmocore/rsl.h b/include/osmocore/rsl.h
new file mode 100644
index 00000000..c9375a7c
--- /dev/null
+++ b/include/osmocore/rsl.h
@@ -0,0 +1,24 @@
+#ifndef _OSMOCORE_RSL_H
+#define _OSMOCORE_RSL_H
+
+#include <stdint.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/protocol/gsm_08_58.h>
+
+void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type);
+
+extern const struct tlv_definition rsl_att_tlvdef;
+#define rsl_tlv_parse(dec, buf, len) \
+ tlv_parse(dec, &rsl_att_tlvdef, buf, len, 0, 0)
+
+/* encode channel number as per Section 9.3.1 */
+uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot);
+
+const struct value_string rsl_rlm_cause_strs[];
+
+const char *rsl_err_name(uint8_t err);
+
+/* Section 3.3.2.3 TS 05.02. I think this looks like a table */
+int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
+
+#endif /* _OSMOCORE_RSL_H */
diff --git a/include/osmocore/utils.h b/include/osmocore/utils.h
new file mode 100644
index 00000000..cf3b4607
--- /dev/null
+++ b/include/osmocore/utils.h
@@ -0,0 +1,17 @@
+#ifndef OSMOCORE_UTIL_H
+#define OSMOCORE_UTIL_H
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#include <stdint.h>
+
+struct value_string {
+ unsigned int value;
+ const char *str;
+};
+
+const char *get_value_string(const struct value_string *vs, uint32_t val);
+int get_string_value(const struct value_string *vs, const char *str);
+
+
+#endif
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 00000000..cda880f1
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,118 @@
+
+# this is not really used as we don't do 'make install'. You can still specify
+# it in case you _want_ to manually 'make install' the target libosmocore.
+CROSS_INST_PREFIX ?= /usr/local/stow/osmocom-bb/arm-2010.09
+
+# this is the host tuple of your cross-toolchain
+CROSS_HOST ?= $(shell which arm-elf-gcc >/dev/null 2>&1 && echo arm-elf || echo arm-none-eabi)
+
+# this is the prefix of your cross-toolchain programs
+CROSS_TOOL_PREFIX=$(CROSS_HOST)-
+
+TOPDIR=$(shell pwd)
+OSMOCORE_CONFIGURE_ENV= LIBOSMOCORE_LIBS=$(TOPDIR)/shared/libosmocore/build-host/src/.libs/libosmocore.a \
+ LIBOSMOVTY_LIBS=$(TOPDIR)/shared/libosmocore/build-host/src/vty/.libs/libosmovty.a \
+ LIBOSMOGSM_LIBS=$(TOPDIR)/shared/libosmocore/build-host/src/gsm/.libs/libosmogsm.a \
+ LIBOSMOCODEC_LIBS=$(TOPDIR)/shared/libosmocore/build-host/src/codec/.libs/libosmocodec.a \
+ LIBOSMOCORE_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include \
+ LIBOSMOVTY_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include \
+ LIBOSMOGSM_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include \
+ LIBOSMOCODEC_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include
+
+all: libosmocore-target nofirmware firmware mtk-firmware
+nofirmware: libosmocore-host layer23 osmocon gsmmap
+
+libosmocore-host: shared/libosmocore/build-host/src/.libs/libosmocore.la
+
+shared/libosmocore/build-host:
+ mkdir $@
+
+shared/libosmocore/configure: shared/libosmocore/configure.ac
+ cd shared/libosmocore && autoreconf -i
+
+shared/libosmocore/build-host/Makefile: shared/libosmocore/configure shared/libosmocore/build-host
+ cd shared/libosmocore/build-host && ../configure $(HOST_CONFARGS)
+
+shared/libosmocore/build-host/src/.libs/libosmocore.la: shared/libosmocore/build-host/Makefile
+ cd shared/libosmocore/build-host && make
+
+
+libosmocore-target: shared/libosmocore/build-target/src/.libs/libosmocore.a
+
+shared/libosmocore/build-target:
+ mkdir $@
+
+shared/libosmocore/build-target/Makefile: shared/libosmocore/configure shared/libosmocore/build-target
+ cd shared/libosmocore/build-target && ../configure \
+ --host=$(CROSS_HOST) --enable-embedded --disable-shared \
+ --disable-tests ac_cv_header_sys_select_h=no \
+ --disable-tests ac_cv_header_sys_socket_h=no \
+ CFLAGS="-Os -ffunction-sections -I$(TOPDIR)/target/firmware/include -nostartfiles -nodefaultlibs"
+
+shared/libosmocore/build-target/src/.libs/libosmocore.a: shared/libosmocore/build-target/Makefile
+ cd shared/libosmocore/build-target && make
+
+
+.PHONY: osmocon
+osmocon: host/osmocon/osmocon
+
+host/osmocon/configure: host/osmocon/configure.ac
+ cd host/osmocon && autoreconf -i
+
+host/osmocon/Makefile: host/osmocon/configure
+ cd host/osmocon && $(OSMOCORE_CONFIGURE_ENV) ./configure $(HOST_CONFARGS)
+
+host/osmocon/osmocon: host/osmocon/Makefile libosmocore-host
+ make -C host/osmocon
+
+
+.PHONY: gsmmap
+gsmmap: host/gsmmap/gsmmap
+
+host/gsmmap/configure: host/gsmmap/configure.ac
+ cd host/gsmmap && autoreconf -i
+
+host/gsmmap/Makefile: host/gsmmap/configure
+ cd host/gsmmap && $(OSMOCORE_CONFIGURE_ENV) ./configure $(HOST_CONFARGS)
+
+host/gsmmap/gsmmap: host/gsmmap/Makefile libosmocore-host
+ make -C host/gsmmap
+
+
+.PHONY: layer23
+layer23: host/layer23/layer23
+
+host/layer23/configure: host/layer23/configure.ac
+ cd host/layer23 && autoreconf -i
+
+host/layer23/Makefile: host/layer23/configure
+ cd host/layer23 && $(OSMOCORE_CONFIGURE_ENV) ./configure $(HOST_CONFARGS)
+
+host/layer23/layer23: host/layer23/Makefile libosmocore-host
+ make -C host/layer23
+
+
+.PHONY: firmware
+firmware: libosmocore-target
+ make -C target/firmware CROSS_COMPILE=$(CROSS_TOOL_PREFIX)
+
+.PHONY: mtk-firmware
+mtk-firmware: libosmocore-target
+ make -C target/firmware -f Makefile.mtk CROSS_COMPILE=$(CROSS_TOOL_PREFIX)
+
+
+clean:
+ make -C shared/libosmocore/build-host $@
+ make -C shared/libosmocore/build-target $@
+ make -C host/layer23 $@
+ make -C host/osmocon $@
+ make -C target/firmware $@
+ make -C target/firmware -f Makefile.mtk $@
+
+distclean:
+ rm -rf shared/libosmocore/build-host
+ rm -rf shared/libosmocore/build-target
+ make -C host/layer23 $@
+ make -C host/osmocon $@
+# 'firmware' also handles 'mtk-firmware'
+ make -C target/firmware $@
diff --git a/src/README.building b/src/README.building
new file mode 100644
index 00000000..328c9ed7
--- /dev/null
+++ b/src/README.building
@@ -0,0 +1,30 @@
+== How to build OsmocomBB? ==
+
+=== Prerequisites ===
+
+We assume you are building on a GNU/Linux host system such as Debian
+GNU/Linux. Successful builds have also been reported using MacOS X
+and the Cygwin environment for MS Windows, but we do not officially support
+this.
+
+ # Get a GNU toolchain (gcc/binutils) for ARM (e.g. from http://gnuarm.com/)
+ # Set your path to include the arm-elf-* executables of your toolchain
+ # call 'make' in this (the src) subdirectory
+
+=== Details ===
+
+The master Makefile will build:
+
+ * libosmocore for the host (x86 or whatever you use)
+ * libosmocore for the target (ARM)
+ * osmocon and layer23 executables for the host (linking libosmocore)
+ * the actual target firmware images (in src/target/firmware/board/*/*.bin)
+
+== Transmitting ==
+
+For safety reasons, all code that can enable the transmitter on the phone is
+disabled in the default builds. Plese check the src/target/firmware/Makefile
+for the "#CFLAGS += -DCONFIG_TX_ENABLE" line.
+
+Please notice that GSM operates in licensed spectrum and in most jurisdictions
+you will need a license from a regulatory authority to transmit.
diff --git a/src/README.development b/src/README.development
new file mode 100644
index 00000000..1963b5a4
--- /dev/null
+++ b/src/README.development
@@ -0,0 +1,72 @@
+= Contributing to OsmocomBB development =
+
+Feel free to help us by extending the code. Always make sure to
+send back all your patches to the baseband-devel@lists.osmocom.org
+mailing list - Free Software is all about sharing.
+
+== Coding Style ==
+
+Like all C language Osmocom projects, we use the Linux Kernel coding
+style, you can find it in the Documentation/CodingStyle subdirectory
+of any Linux Kernel source.
+
+== More Information ==
+
+Please consult the http://bb.osmocom.org/ web page / wiki.
+
+If you have any technical questions regarding the code, don't hesitate
+to ask the baseband-devel@lists.osmocom.org mailing list.
+
+== subdirectories containing libraries and code ==
+
+=== src/shared/libosmocore ===
+
+This is a library of various utility routines, including linked lists,
+message buffers, bit-vectors, memory allocator, signals, select loop
+handling, timers - as well as some more specifically GSM related things
+like a TLV parser, a Comp128V1 implementation and utility functions for
+RSL (TS 08.58) and CC/MM/RR (TS 04.08).
+
+libosmocore is maintained in git://git.osmocom.org/libosmocore.git, so
+
+ DO NOT DIRECTLY COMMIT TO libosmocore IN THIS REPOSITORY!
+
+We simply maintain a copy (synchronized by git-subtree) in this
+repository for the ease of building and to make sure everyone is using
+the proper/compatible version of libosmocore
+
+Please note, whatever you add to libosmocore will need to build as a
+Linux userspace program (using glibc) just as well as on the OsmocomBB
+embedded target without OS. So please refrain from using fancy
+functions.
+
+
+=== src/target/firmware ===
+
+The firmware is what we build for the actual target (phone). It was
+written with some idea of modularity in mind, i.e. we have
+
+ * Ti Calypso specific code in calypso/
+ * Analog Baseband code in abb/
+ * RF Mixer code in rf/
+ * Layer1 code in layer1/
+ * NOR flash handling in flash/
+ * LCD display handling in display/
+ * minimal C-Library code in lib/
+ * communications utility routines in comm/
+ * Board (phone model/family) specific code in board/
+ * board/compal_e88 is the Motorola C115-C124 family
+ * board/compal_e99 is the Motorola C155 family
+ * Applications (each app builds one firmware image) in apps/
+
+
+=== src/target_dsp/calypso ===
+
+This is where we keep some (assembly) code that we wrote for
+the DSP that is part of the Calypso DBB.
+
+=== src/host/layer23 ===
+
+The Layer2 (LAPDm / TS 04.06) and Layer3 (CC/MM/RR / TS 04.08)
+implementations, as they are growing.
+
diff --git a/src/host/calypso_pll/pll.pl b/src/host/calypso_pll/pll.pl
new file mode 100755
index 00000000..52c91319
--- /dev/null
+++ b/src/host/calypso_pll/pll.pl
@@ -0,0 +1,10 @@
+#!/usr/bin/perl
+
+my $f_in = 26*1000*1000;
+
+for (my $mult = 1; $mult < 31; $mult++) {
+ for (my $div = 0; $div < 3; $div++) {
+ my $fout = $f_in * ($mult / ($div+1));
+ printf("%03.1f MHz (mult=%2u, div=%1u)\n", $fout/(1000*1000), $mult, $div);
+ }
+}
diff --git a/src/host/fb_tools/bdf_to_c.py b/src/host/fb_tools/bdf_to_c.py
new file mode 100755
index 00000000..86be6a6b
--- /dev/null
+++ b/src/host/fb_tools/bdf_to_c.py
@@ -0,0 +1,293 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+'''
+This script converts a bdf-font to a c-source-file containing
+selected glyphs in the format defined by the <fb/font.h> header.
+'''
+
+# (C) 2010 by Christian Vogel <vogelchr@vogel.cx>
+#
+# All Rights Reserved
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from optparse import OptionParser
+import sys
+import os
+
+def unique_name(thisname,existingnames) :
+ # return first of thisname, thisname_1, thisname_2, ...
+ # that does not yet exist in existingnames. This is used
+ # because somethings glyphs with non-unique names exist
+ # in fonts!
+ retname=thisname
+ N=1
+ while retname in existingnames :
+ N=N+1
+ retname='%s_%d'%(thisname,N)
+ return retname
+
+
+# return number N (for a character), optionally including
+# the ascii character
+def ascii_charnum(n) :
+ if n >= 32 and n < 127 :
+ if n != 34 : # """ looks stupid
+ return '(%d, ASCII "%s")'%(n,chr(n))
+ else :
+ return '(%d, ASCII \'%s\')'%(n,chr(n))
+ return '(%d)'%(n)
+
+def is_zeroes(s) :
+ # check if list s consists entirely of "00" strings
+ # (used to detect empty lines in fonts)
+ for x in s :
+ if s != '00' :
+ return False
+ return True
+
+def byte_to_bits(x) :
+ # convert byte x to a string representing the bits #=1, .=0
+ # used for drawing pretty pictures in the comments of the
+ # generated C-file
+ ret = ''
+ for i in range(8) :
+ if x & 1<<(7-i) :
+ ret = ret + '#'
+ else :
+ ret = ret + '.'
+ return ret
+
+class BDF_Font(object) :
+ # this class stores a read-in bdf font
+ def __init__(self,filename) :
+ self.filename = filename
+ self.glyphs = dict()
+ self.enc = dict()
+ self.height = None
+ self.registry = None
+ self.encoding = None
+ self.ascent = 0
+ self.descent = 0
+ self.read_font(filename)
+
+ def add_header(self,data) :
+ #print 'Header data: ',data
+ self.registry = data.get('charset_registry','none')
+ self.encoding = data.get('charset_encoding','unknown')
+ self.ascent = int(data['font_ascent'])
+ self.descent = int(data['font_descent'])
+ bbx = data['fontboundingbox'].split(None,3)
+ self.height = int(bbx[1])
+
+ def add_glyph(self,charname,data,bitmap) :
+ chnum = int(data['encoding'])
+# print 'add_glyph(%s) -> %s'%(charname,ascii_charnum(chnum))
+ self.enc[chnum] = charname
+ self.glyphs[charname] = data
+ self.glyphs[charname]['bitmap']=bitmap
+
+ def read_font(self,filename) :
+ f = file(filename)
+
+ hdr_data = dict()
+ # read in header
+ for l in f :
+ l = l.strip()
+ if l == '' :
+ continue
+ arr = l.split(None,1)
+ if len(arr) > 1 :
+ hdr_data[ arr[0].lower() ] = arr[1]
+ if arr[0].lower() == 'chars' :
+ break
+
+ self.add_header(hdr_data)
+
+ # now read in characters
+ inchar = None
+ data = dict() # store glyph data
+ bitmap = None
+ for l in f :
+ l = l.strip()
+ if l == '' :
+ continue
+
+ # waiting for next glyph
+ if inchar == None :
+ if l.lower() == 'endfont' :
+ break # end of font :-)
+ arr = l.split(None,1)
+ if len(arr) < 2 and \
+ arr[0].lower() != 'STARTCHAR' :
+ print >>sys.stderr,'Not start of glyph: %s'%(l)
+ continue
+ inchar = unique_name(arr[1],self.glyphs)
+ continue
+
+ # ENDCHAR always ends the glyph
+ if l.lower() == 'endchar' :
+ self.add_glyph(inchar,data,bitmap)
+ inchar = None
+ bitmap = None
+ data = dict()
+ continue
+
+ # in bitmap
+ if bitmap != None :
+ bitmap.append(l)
+ continue
+
+ # else: metadata for this glyph
+ arr = l.split(None,1)
+
+ if arr[0].lower() == 'bitmap' :
+ bitmap = list() # start collecting pixels
+ continue
+
+ if len(arr) < 2 :
+ print >>sys.stderr,'Bad line in font: %s'%(l)
+ continue
+ data[arr[0].lower()] = arr[1]
+
+if __name__ == '__main__' :
+ P = OptionParser(usage='%prog [options] bdf-file')
+ P.add_option('-o','--out',action='store', dest='out', default=None,
+ metavar='FILE',help='write .c-code representing font to FILE')
+ P.add_option('-b','--base',action='store',dest='base',default=None,
+ metavar='base_symbol',help='prefix for all generated symbols')
+ P.add_option('-f','--firstchar',action='store',dest='firstchar',type="int",
+ metavar='N',default=None,help='numeric value of first char')
+ P.add_option('-l','--lastchar',action='store',dest='lastchar',type="int",
+ metavar='N',default=None,help='numeric value of last char')
+
+ opts,args = P.parse_args()
+
+ if len(args) != 1 :
+ P.error('Please specify (exactly one) bdf input file.')
+
+ font = BDF_Font(args[0])
+
+ if opts.firstchar == None :
+ opts.firstchar = min(font.enc)
+ print 'First character in font: %d, %s'%(opts.firstchar,
+ font.enc[opts.firstchar])
+
+ if opts.lastchar == None :
+ opts.lastchar = max(font.enc)
+ print 'Last character in font: %d, %s'%(opts.lastchar,
+ font.enc[opts.lastchar])
+
+ if opts.base == None :
+ opts.base = 'font_'+os.path.basename(args[0])
+ if opts.base[-4:] == '.bdf' :
+ opts.base = opts.base[:-4]
+ print >>sys.stderr,'Guessing symbol prefix to be %s.'%(opts.base)
+
+ if opts.out == None :
+ opts.out = os.path.basename(args[0])
+ if opts.out[-4:] == '.bdf' :
+ opts.out = opts.out[:-4]
+ opts.out = opts.out + '.c'
+ print >>sys.stderr,'Guessing output filename to be %s.'%(opts.out)
+
+ if os.path.exists(opts.out) :
+ print >>sys.stderr,'Will *NOT* overwrite existing file when guessing output!'
+ sys.exit(1)
+
+ of = file(opts.out,'w')
+
+ print >>of,'#include <fb/font.h>'
+ print >>of,'/* file autogenerated by %s */'%(sys.argv[0])
+
+ offsets = list()
+ glyphnames = list()
+
+ print >>of,'static const uint8_t %s_data[] = {'%(opts.base)
+
+ pos = 0
+
+ # output font data, build up per-character information
+
+ for i in range(opts.firstchar,opts.lastchar+1) :
+ if not i in font.enc :
+ offsets.append(0xffff)
+ glyphnames.append('(no glyph)')
+ continue
+
+ charname = font.enc[i]
+ glyphnames.append('%s %s'%(charname,ascii_charnum(i)))
+ offsets.append(pos)
+ glyph = font.glyphs[charname]
+ bbx = map(int,glyph['bbx'].split(None,3))
+ bitmap = glyph['bitmap']
+
+ if bbx[1] != len(bitmap) :
+ print >>sys.stderr,'ERROR: glyph',charname,'has wrong number of lines of data!'
+ print >>sys.stderr,' want: ',bbx[1],'but have',len(bitmap)
+ sys.exit(1)
+
+ removedrows = 0
+
+ while len(bitmap) > 1 and is_zeroes(bitmap[0]) :
+ removedrows = removedrows + 1
+ bbx[1] = bbx[1] - 1 # decrease height
+ bitmap = bitmap[1:]
+
+ while len(bitmap) > 1 and is_zeroes(bitmap[-1]) :
+ removedrows = removedrows + 1
+ bbx[1] = bbx[1] - 1 # decrease height
+ bbx[3] = bbx[3] + 1 # increase y0
+ bitmap = bitmap[:-1]
+
+ if removedrows > 0 :
+ print "Glyph %s: removed %d rows."%(charname,removedrows)
+
+ w = int(glyph['dwidth'].split(None,1)[0])
+
+ print >>of,'/* --- new character %s %s starting at offset 0x%04x --- */'%(
+ charname,ascii_charnum(i),pos)
+ print >>of,'\t/*%04x:*/\t%d, %d, %d, %d, %d, /* width and bbox (w,h,x,y) */'%(
+ pos,w,bbx[0],bbx[1],bbx[2],bbx[3])
+
+ pos += 5
+
+ for k,l in enumerate(bitmap) :
+ bytes = [ int(l[i:i+2],16) for i in range(0,len(l),2) ]
+ if len(bytes) != (bbx[0]+7)/8 :
+ print >>sys.stderr,'ERROR: glyph',charname,'has wrong # of bytes'
+ print >>sys.stderr,' per line. Want',(bbx[0]+7)/8,'have',len(bytes)
+ sys.exit(1)
+ cdata = ','.join([ '0x%02x'%v for v in bytes ])
+ comment = ''.join([ byte_to_bits(b) for b in bytes ])
+ print >>of,'\t/*%04x:*/\t'%(pos)+cdata+', /* '+comment+' */'
+ pos += len(bytes)
+
+ print >>of,"};"
+
+ x = ',\n\t'.join(['0x%04x /* %s */'%(w,n) for w,n in zip(offsets,glyphnames)])
+ print >>of,'static const uint16_t %s_offsets[] = {\n\t%s\n};'%(opts.base,x)
+
+ height = font.ascent + font.descent
+
+ print >>of,'const struct fb_font %s = {'%(opts.base)
+ print >>of,'\t.height = %d,'%(height)
+ print >>of,'\t.ascent = %d,'%(font.ascent)
+ print >>of,'\t.firstchar = %d, /* %s */'%(opts.firstchar,font.enc.get(opts.firstchar,"?"))
+ print >>of,'\t.lastchar = %d, /* %s */'%(opts.lastchar,font.enc.get(opts.lastchar,"?"))
+ print >>of,'\t.chardata = %s_data,'%(opts.base)
+ print >>of,'\t.charoffs = %s_offsets,'%(opts.base)
+ print >>of,'};'
diff --git a/src/host/gsmmap/.gitignore b/src/host/gsmmap/.gitignore
new file mode 100644
index 00000000..661fd133
--- /dev/null
+++ b/src/host/gsmmap/.gitignore
@@ -0,0 +1,35 @@
+# autoreconf by-products
+*.in
+
+aclocal.m4
+autom4te.cache/
+configure
+depcomp
+install-sh
+missing
+
+# configure by-products
+.deps/
+Makefile
+
+config.status
+version.h
+
+# build by-products
+*.o
+
+gsmmap
+
+# various
+.version
+.tarball-version
+
+# IDA file
+*.id*
+*.nam
+*.til
+
+# Other test files
+*.dump
+*.bin
+*.log
diff --git a/src/host/gsmmap/Makefile.am b/src/host/gsmmap/Makefile.am
new file mode 100644
index 00000000..29be15c5
--- /dev/null
+++ b/src/host/gsmmap/Makefile.am
@@ -0,0 +1,17 @@
+AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
+
+# versioning magic
+BUILT_SOURCES = $(top_srcdir)/.version
+$(top_srcdir)/.version:
+ echo $(VERSION) > $@-t && mv $@-t $@
+dist-hook:
+ echo $(VERSION) > $(distdir)/.tarball-version
+
+INCLUDES = $(all_includes) -I../layer23/include -DHOST_BUILD
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS)
+
+sbin_PROGRAMS = gsmmap
+
+gsmmap_SOURCES = gsmmap.c geo.c locate.c log.c ../layer23/src/common/sysinfo.c ../layer23/src/common/networks.c ../layer23/src/common/logging.c
+gsmmap_LDADD = $(LIBOSMOGSM_LIBS) $(LIBOSMOCORE_LIBS) -lm
+
diff --git a/src/host/gsmmap/configure.ac b/src/host/gsmmap/configure.ac
new file mode 100644
index 00000000..3a42d4c3
--- /dev/null
+++ b/src/host/gsmmap/configure.ac
@@ -0,0 +1,26 @@
+dnl Process this file with autoconf to produce a configure script
+AC_INIT([gsmmap],
+ m4_esyscmd([./git-version-gen .tarball-version]),
+ [baseband-devel@lists.osmocom.org])
+
+AM_INIT_AUTOMAKE([dist-bzip2])
+
+dnl kernel style compile messages
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+dnl checks for programs
+AC_PROG_MAKE_SET
+AC_PROG_CC
+AC_PROG_INSTALL
+
+dnl checks for libraries
+PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore)
+PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm)
+
+dnl checks for header files
+AC_HEADER_STDC
+
+dnl Checks for typedefs, structures and compiler characteristics
+
+AC_OUTPUT(
+ Makefile)
diff --git a/src/host/gsmmap/geo.c b/src/host/gsmmap/geo.c
new file mode 100644
index 00000000..65633d2c
--- /dev/null
+++ b/src/host/gsmmap/geo.c
@@ -0,0 +1,47 @@
+#include <math.h>
+#include "geo.h"
+
+void geo2space(double *x, double *y, double *z, double lon, double lat)
+{
+ *z = sin(lat / 180.0 * PI) * POLE_RADIUS;
+ *x = sin(lon / 180.0 * PI) * cos(lat / 180.0 * PI) * EQUATOR_RADIUS;
+ *y = -cos(lon / 180.0 * PI) * cos(lat / 180.0 * PI) * EQUATOR_RADIUS;
+}
+
+void space2geo(double *lon, double *lat, double x, double y, double z)
+{
+ double r;
+
+ /* bring geoid to 1m radius */
+ z = z / POLE_RADIUS;
+ x = x / EQUATOR_RADIUS;
+ y = y / EQUATOR_RADIUS;
+
+ /* normalize */
+ r = sqrt(x * x + y * y + z * z);
+ z = z / r;
+ x = x / r;
+ y = y / r;
+
+ *lat = asin(z) / PI * 180;
+ *lon = atan2(x, -y) / PI * 180;
+}
+
+double distinspace(double x1, double y1, double z1, double x2, double y2,
+ double z2)
+{
+ double x = x1 - x2;
+ double y = y1 - y2;
+ double z = z1 - z2;
+
+ return sqrt(x * x + y * y + z * z);
+}
+
+double distonplane(double x1, double y1, double x2, double y2)
+{
+ double x = x1 - x2;
+ double y = y1 - y2;
+
+ return sqrt(x * x + y * y);
+}
+
diff --git a/src/host/gsmmap/geo.h b/src/host/gsmmap/geo.h
new file mode 100644
index 00000000..25e26cba
--- /dev/null
+++ b/src/host/gsmmap/geo.h
@@ -0,0 +1,12 @@
+/* WGS 84 */
+#define EQUATOR_RADIUS 6378137.0
+#define POLE_RADIUS 6356752.314
+
+#define PI 3.1415926536
+
+void geo2space(double *x, double *y, double *z, double lat, double lon);
+void space2geo(double *lat, double *lon, double x, double y, double z);
+double distinspace(double x1, double y1, double z1, double x2, double y2,
+ double z2);
+double distonplane(double x1, double y1, double x2, double y2);
+
diff --git a/src/host/gsmmap/git-version-gen b/src/host/gsmmap/git-version-gen
new file mode 100755
index 00000000..652fac68
--- /dev/null
+++ b/src/host/gsmmap/git-version-gen
@@ -0,0 +1,151 @@
+#!/bin/sh
+# Print a version string.
+scriptversion=2010-01-28.01
+
+# Copyright (C) 2007-2010 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
+# It may be run two ways:
+# - from a git repository in which the "git describe" command below
+# produces useful output (thus requiring at least one signed tag)
+# - from a non-git-repo directory containing a .tarball-version file, which
+# presumes this script is invoked like "./git-version-gen .tarball-version".
+
+# In order to use intra-version strings in your project, you will need two
+# separate generated version string files:
+#
+# .tarball-version - present only in a distribution tarball, and not in
+# a checked-out repository. Created with contents that were learned at
+# the last time autoconf was run, and used by git-version-gen. Must not
+# be present in either $(srcdir) or $(builddir) for git-version-gen to
+# give accurate answers during normal development with a checked out tree,
+# but must be present in a tarball when there is no version control system.
+# Therefore, it cannot be used in any dependencies. GNUmakefile has
+# hooks to force a reconfigure at distribution time to get the value
+# correct, without penalizing normal development with extra reconfigures.
+#
+# .version - present in a checked-out repository and in a distribution
+# tarball. Usable in dependencies, particularly for files that don't
+# want to depend on config.h but do want to track version changes.
+# Delete this file prior to any autoconf run where you want to rebuild
+# files to pick up a version string change; and leave it stale to
+# minimize rebuild time after unrelated changes to configure sources.
+#
+# It is probably wise to add these two files to .gitignore, so that you
+# don't accidentally commit either generated file.
+#
+# Use the following line in your configure.ac, so that $(VERSION) will
+# automatically be up-to-date each time configure is run (and note that
+# since configure.ac no longer includes a version string, Makefile rules
+# should not depend on configure.ac for version updates).
+#
+# AC_INIT([GNU project],
+# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
+# [bug-project@example])
+#
+# Then use the following lines in your Makefile.am, so that .version
+# will be present for dependencies, and so that .tarball-version will
+# exist in distribution tarballs.
+#
+# BUILT_SOURCES = $(top_srcdir)/.version
+# $(top_srcdir)/.version:
+# echo $(VERSION) > $@-t && mv $@-t $@
+# dist-hook:
+# echo $(VERSION) > $(distdir)/.tarball-version
+
+case $# in
+ 1) ;;
+ *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
+esac
+
+tarball_version_file=$1
+nl='
+'
+
+# First see if there is a tarball-only version file.
+# then try "git describe", then default.
+if test -f $tarball_version_file
+then
+ v=`cat $tarball_version_file` || exit 1
+ case $v in
+ *$nl*) v= ;; # reject multi-line output
+ [0-9]*) ;;
+ *) v= ;;
+ esac
+ test -z "$v" \
+ && echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
+fi
+
+if test -n "$v"
+then
+ : # use $v
+elif
+ v=`git describe --abbrev=4 --match='osmocon_v*' HEAD 2>/dev/null \
+ || git describe --abbrev=4 HEAD 2>/dev/null` \
+ && case $v in
+ osmocon_[0-9]*) ;;
+ osmocon_v[0-9]*) ;;
+ *) (exit 1) ;;
+ esac
+then
+ # Is this a new git that lists number of commits since the last
+ # tag or the previous older version that did not?
+ # Newer: v6.10-77-g0f8faeb
+ # Older: v6.10-g0f8faeb
+ case $v in
+ *-*-*) : git describe is okay three part flavor ;;
+ *-*)
+ : git describe is older two part flavor
+ # Recreate the number of commits and rewrite such that the
+ # result is the same as if we were using the newer version
+ # of git describe.
+ vtag=`echo "$v" | sed 's/-.*//'`
+ numcommits=`git rev-list "$vtag"..HEAD | wc -l`
+ v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
+ ;;
+ esac
+
+ # Change the first '-' to a '.', so version-comparing tools work properly.
+ # Remove the "g" in git describe's output string, to save a byte.
+ v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/;s/^osmocon_//'`;
+else
+ v="UNKNOWN"
+fi
+
+v=`echo "$v" |sed 's/^v//'`
+
+# Don't declare a version "dirty" merely because a time stamp has changed.
+git status > /dev/null 2>&1
+
+dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
+case "$dirty" in
+ '') ;;
+ *) # Append the suffix only if there isn't one already.
+ case $v in
+ *-dirty) ;;
+ *) v="$v-dirty" ;;
+ esac ;;
+esac
+
+# Omit the trailing newline, so that m4_esyscmd can use the result directly.
+echo "$v" | tr -d '\012'
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/src/host/gsmmap/gsmmap.c b/src/host/gsmmap/gsmmap.c
new file mode 100644
index 00000000..83f0d01c
--- /dev/null
+++ b/src/host/gsmmap/gsmmap.c
@@ -0,0 +1,658 @@
+/* Conversion of logged cells to KML file */
+
+/* (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#warning todo bsic
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <math.h>
+#include <time.h>
+
+#define GSM_TA_M 553.85
+#define PI 3.1415926536
+
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/networks.h>
+#include <osmocom/bb/common/logging.h>
+
+#include "log.h"
+#include "geo.h"
+#include "locate.h"
+
+/*
+ * structure of power and cell infos
+ */
+
+struct power power;
+struct sysinfo sysinfo;
+static struct node_power *node_power_first = NULL;
+static struct node_power **node_power_last_p = &node_power_first;
+struct node_mcc *node_mcc_first = NULL;
+int log_lines = 0, log_debug = 0;
+
+
+static void nomem(void)
+{
+ fprintf(stderr, "No mem!\n");
+ exit(-ENOMEM);
+}
+
+static void add_power()
+{
+ struct node_power *node_power;
+
+// printf("New Power\n");
+ /* append or insert to list */
+ node_power = calloc(1, sizeof(struct node_power));
+ if (!node_power)
+ nomem();
+ *node_power_last_p = node_power;
+ node_power_last_p = &node_power->next;
+ memcpy(&node_power->power, &power, sizeof(power));
+}
+
+static void print_si(void *priv, const char *fmt, ...)
+{
+ char buffer[1000];
+ FILE *outfp = (FILE *)priv;
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
+ buffer[sizeof(buffer) - 1] = '\0';
+ va_end(args);
+
+ if (buffer[0])
+ fprintf(outfp, "%s", buffer);
+}
+
+static void add_sysinfo()
+{
+ struct gsm48_sysinfo s;
+ struct node_mcc *mcc;
+ struct node_mnc *mnc;
+ struct node_lac *lac;
+ struct node_cell *cell;
+ struct node_meas *meas;
+
+ memset(&s, 0, sizeof(s));
+
+ /* decode sysinfo */
+ if (sysinfo.si1[2])
+ gsm48_decode_sysinfo1(&s,
+ (struct gsm48_system_information_type_1 *) sysinfo.si1,
+ 23);
+ if (sysinfo.si2[2])
+ gsm48_decode_sysinfo2(&s,
+ (struct gsm48_system_information_type_2 *) sysinfo.si2,
+ 23);
+ if (sysinfo.si2bis[2])
+ gsm48_decode_sysinfo2bis(&s,
+ (struct gsm48_system_information_type_2bis *)
+ sysinfo.si2bis,
+ 23);
+ if (sysinfo.si2ter[2])
+ gsm48_decode_sysinfo2ter(&s,
+ (struct gsm48_system_information_type_2ter *)
+ sysinfo.si2ter,
+ 23);
+ if (sysinfo.si3[2])
+ gsm48_decode_sysinfo3(&s,
+ (struct gsm48_system_information_type_3 *) sysinfo.si3,
+ 23);
+ if (sysinfo.si4[2])
+ gsm48_decode_sysinfo4(&s,
+ (struct gsm48_system_information_type_4 *) sysinfo.si4,
+ 23);
+ printf("--------------------------------------------------------------------------\n");
+ gsm48_sysinfo_dump(&s, sysinfo.arfcn, print_si, stdout, NULL);
+ mcc = get_node_mcc(s.mcc);
+ if (!mcc)
+ nomem();
+ mnc = get_node_mnc(mcc, s.mnc);
+ if (!mnc)
+ nomem();
+ lac = get_node_lac(mnc, s.lac);
+ if (!lac)
+ nomem();
+ cell = get_node_cell(lac, s.cell_id);
+ if (!cell)
+ nomem();
+ meas = add_node_meas(cell);
+ if (!meas)
+ nomem();
+ if (!cell->content) {
+ cell->content = 1;
+ memcpy(&cell->sysinfo, &sysinfo, sizeof(sysinfo));
+ memcpy(&cell->s, &s, sizeof(s));
+ } else {
+ if (memcmp(&cell->sysinfo.si1, sysinfo.si1,
+ sizeof(sysinfo.si1))) {
+new_sysinfo:
+ fprintf(stderr, "FIXME: the cell changed sysinfo\n");
+ return;
+ }
+ if (memcmp(&cell->sysinfo.si2, sysinfo.si2,
+ sizeof(sysinfo.si2)))
+ goto new_sysinfo;
+ if (memcmp(&cell->sysinfo.si2bis, sysinfo.si2bis,
+ sizeof(sysinfo.si2bis)))
+ goto new_sysinfo;
+ if (memcmp(&cell->sysinfo.si2ter, sysinfo.si2ter,
+ sizeof(sysinfo.si2ter)))
+ goto new_sysinfo;
+ if (memcmp(&cell->sysinfo.si3, sysinfo.si3,
+ sizeof(sysinfo.si3)))
+ goto new_sysinfo;
+ if (memcmp(&cell->sysinfo.si4, sysinfo.si4,
+ sizeof(sysinfo.si4)))
+ goto new_sysinfo;
+ }
+}
+
+void kml_header(FILE *outfp, char *name)
+{
+ /* XML header */
+ fprintf(outfp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+
+ /* KML open tag */
+ fprintf(outfp, "<kml xmlns=\"http://www.opengis.net/kml/2.2\" "
+ "xmlns:gx=\"http://www.google.com/kml/ext/2.2\" "
+ "xmlns:kml=\"http://www.opengis.net/kml/2.2\" "
+ "xmlns:atom=\"http://www.w3.org/2005/Atom\">\n");
+
+ /* document open tag */
+ fprintf(outfp, "<Document>\n");
+
+ /* pushpin */
+ fprintf(outfp, "\t<Style id=\"sn_placemark_red_pushpin\">\n");
+ fprintf(outfp, "\t\t<IconStyle>\n");
+ fprintf(outfp, "\t\t\t<scale>1.1</scale>\n");
+ fprintf(outfp, "\t\t\t<Icon>\n");
+ fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
+ "pushpin/red-pushpin.png</href>\n");
+ fprintf(outfp, "\t\t\t</Icon>\n");
+ fprintf(outfp, "\t\t</IconStyle>\n");
+ fprintf(outfp, "\t\t<ListStyle>\n");
+ fprintf(outfp, "\t\t</ListStyle>\n");
+ fprintf(outfp, "\t</Style>\n");
+ fprintf(outfp, "\t<Style id=\"sh_placemark_red_pushpin_highlight\">\n");
+ fprintf(outfp, "\t\t<IconStyle>\n");
+ fprintf(outfp, "\t\t\t<scale>1.3</scale>\n");
+ fprintf(outfp, "\t\t\t<Icon>\n");
+ fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
+ "pushpin/red-pushpin.png</href>\n");
+ fprintf(outfp, "\t\t\t</Icon>\n");
+ fprintf(outfp, "\t\t</IconStyle>\n");
+ fprintf(outfp, "\t\t<ListStyle>\n");
+ fprintf(outfp, "\t\t</ListStyle>\n");
+ fprintf(outfp, "\t</Style>\n");
+ fprintf(outfp, "\t<StyleMap id=\"msn_placemark_red_pushpin\">\n");
+ fprintf(outfp, "\t\t<Pair>\n");
+ fprintf(outfp, "\t\t\t<key>normal</key>\n");
+ fprintf(outfp, "\t\t\t<styleUrl>#sn_placemark_red_pushpin"
+ "</styleUrl>\n");
+ fprintf(outfp, "\t\t</Pair>\n");
+ fprintf(outfp, "\t\t<Pair>\n");
+ fprintf(outfp, "\t\t\t<key>highlight</key>\n");
+ fprintf(outfp, "\t\t\t<styleUrl>#sh_placemark_red_pushpin_highlight"
+ "</styleUrl>\n");
+ fprintf(outfp, "\t\t</Pair>\n");
+ fprintf(outfp, "\t</StyleMap>\n");
+
+ fprintf(outfp, "\t<Style id=\"sn_placemark_grn_pushpin\">\n");
+ fprintf(outfp, "\t\t<IconStyle>\n");
+ fprintf(outfp, "\t\t\t<scale>1.1</scale>\n");
+ fprintf(outfp, "\t\t\t<Icon>\n");
+ fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
+ "pushpin/grn-pushpin.png</href>\n");
+ fprintf(outfp, "\t\t\t</Icon>\n");
+ fprintf(outfp, "\t\t</IconStyle>\n");
+ fprintf(outfp, "\t\t<ListStyle>\n");
+ fprintf(outfp, "\t\t</ListStyle>\n");
+ fprintf(outfp, "\t</Style>\n");
+ fprintf(outfp, "\t<Style id=\"sh_placemark_grn_pushpin_highlight\">\n");
+ fprintf(outfp, "\t\t<IconStyle>\n");
+ fprintf(outfp, "\t\t\t<scale>1.3</scale>\n");
+ fprintf(outfp, "\t\t\t<Icon>\n");
+ fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
+ "pushpin/grn-pushpin.png</href>\n");
+ fprintf(outfp, "\t\t\t</Icon>\n");
+ fprintf(outfp, "\t\t</IconStyle>\n");
+ fprintf(outfp, "\t\t<ListStyle>\n");
+ fprintf(outfp, "\t\t</ListStyle>\n");
+ fprintf(outfp, "\t</Style>\n");
+ fprintf(outfp, "\t<StyleMap id=\"msn_placemark_grn_pushpin\">\n");
+ fprintf(outfp, "\t\t<Pair>\n");
+ fprintf(outfp, "\t\t\t<key>normal</key>\n");
+ fprintf(outfp, "\t\t\t<styleUrl>#sn_placemark_grn_pushpin"
+ "</styleUrl>\n");
+ fprintf(outfp, "\t\t</Pair>\n");
+ fprintf(outfp, "\t\t<Pair>\n");
+ fprintf(outfp, "\t\t\t<key>highlight</key>\n");
+ fprintf(outfp, "\t\t\t<styleUrl>#sh_placemark_grn_pushpin_highlight"
+ "</styleUrl>\n");
+ fprintf(outfp, "\t\t</Pair>\n");
+ fprintf(outfp, "\t</StyleMap>\n");
+
+ /* circle */
+ fprintf(outfp, "\t<Style id=\"sn_placemark_circle\">\n");
+ fprintf(outfp, "\t\t<IconStyle>\n");
+ fprintf(outfp, "\t\t\t<scale>1.0</scale>\n");
+ fprintf(outfp, "\t\t\t<Icon>\n");
+ fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
+ "shapes/placemark_circle.png</href>\n");
+ fprintf(outfp, "\t\t\t</Icon>\n");
+ fprintf(outfp, "\t\t</IconStyle>\n");
+ fprintf(outfp, "\t\t<ListStyle>\n");
+ fprintf(outfp, "\t\t</ListStyle>\n");
+ fprintf(outfp, "\t</Style>\n");
+ fprintf(outfp, "\t<Style id=\"sh_placemark_circle_highlight\">\n");
+ fprintf(outfp, "\t\t<IconStyle>\n");
+ fprintf(outfp, "\t\t\t<scale>1.2</scale>\n");
+ fprintf(outfp, "\t\t\t<Icon>\n");
+ fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
+ "shapes/placemark_circle_highlight.png</href>\n");
+ fprintf(outfp, "\t\t\t</Icon>\n");
+ fprintf(outfp, "\t\t</IconStyle>\n");
+ fprintf(outfp, "\t\t<ListStyle>\n");
+ fprintf(outfp, "\t\t</ListStyle>\n");
+ fprintf(outfp, "\t</Style>\n");
+ fprintf(outfp, "\t<StyleMap id=\"msn_placemark_circle\">\n");
+ fprintf(outfp, "\t\t<Pair>\n");
+ fprintf(outfp, "\t\t\t<key>normal</key>\n");
+ fprintf(outfp, "\t\t\t<styleUrl>#sn_placemark_circle</styleUrl>\n");
+ fprintf(outfp, "\t\t</Pair>\n");
+ fprintf(outfp, "\t\t<Pair>\n");
+ fprintf(outfp, "\t\t\t<key>highlight</key>\n");
+ fprintf(outfp, "\t\t\t<styleUrl>#sh_placemark_circle_highlight"
+ "</styleUrl>\n");
+ fprintf(outfp, "\t\t</Pair>\n");
+ fprintf(outfp, "\t</StyleMap>\n");
+}
+
+void kml_footer(FILE *outfp)
+{
+ /* document close tag */
+ fprintf(outfp, "</Document>\n");
+
+ /* KML close tag */
+ fprintf(outfp, "</kml>\n");
+
+}
+
+void kml_meas(FILE *outfp, struct node_meas *meas, int n, uint16_t mcc,
+ uint16_t mnc, uint16_t lac, uint16_t cellid)
+{
+ struct tm *tm = localtime(&meas->gmt);
+
+ fprintf(outfp, "\t\t\t\t\t<Placemark>\n");
+ fprintf(outfp, "\t\t\t\t\t\t<name>%d: %d</name>\n", n, meas->rxlev);
+ fprintf(outfp, "\t\t\t\t\t\t<description>\n");
+ fprintf(outfp, "MCC=%s MNC=%s\nLAC=%04x CELL-ID=%04x\n(%s %s)\n",
+ gsm_print_mcc(mcc), gsm_print_mnc(mnc), lac, cellid,
+ gsm_get_mcc(mcc), gsm_get_mnc(mcc, mnc));
+ fprintf(outfp, "\n%s", asctime(tm));
+ fprintf(outfp, "RX-LEV %d dBm\n", meas->rxlev);
+ if (meas->ta_valid)
+ fprintf(outfp, "TA=%d (%d-%d meter)\n", meas->ta,
+ (int)(GSM_TA_M * meas->ta),
+ (int)(GSM_TA_M * (meas->ta + 1)));
+ fprintf(outfp, "\t\t\t\t\t\t</description>\n");
+ fprintf(outfp, "\t\t\t\t\t\t<LookAt>\n");
+ fprintf(outfp, "\t\t\t\t\t\t\t<longitude>%.8f</longitude>\n",
+ meas->longitude);
+ fprintf(outfp, "\t\t\t\t\t\t\t<latitude>%.8f</latitude>\n",
+ meas->latitude);
+ fprintf(outfp, "\t\t\t\t\t\t\t<altitude>0</altitude>\n");
+ fprintf(outfp, "\t\t\t\t\t\t\t<tilt>0</tilt>\n");
+ fprintf(outfp, "\t\t\t\t\t\t\t<altitudeMode>relativeToGround"
+ "</altitudeMode>\n");
+ fprintf(outfp, "\t\t\t\t\t\t\t<gx:altitudeMode>relativeToSeaFloor"
+ "</gx:altitudeMode>\n");
+ fprintf(outfp, "\t\t\t\t\t\t</LookAt>\n");
+ fprintf(outfp, "\t\t\t\t\t\t<styleUrl>#msn_placemark_circle"
+ "</styleUrl>\n");
+ fprintf(outfp, "\t\t\t\t\t\t<Point>\n");
+ fprintf(outfp, "\t\t\t\t\t\t\t<coordinates>%.8f,%.8f</coordinates>\n",
+ meas->longitude, meas->latitude);
+ fprintf(outfp, "\t\t\t\t\t\t</Point>\n");
+ fprintf(outfp, "\t\t\t\t\t</Placemark>\n");
+}
+
+double debug_long, debug_lat, debug_x_scale;
+FILE *debug_fp;
+
+void kml_cell(FILE *outfp, struct node_cell *cell)
+{
+ struct node_meas *meas;
+ double x, y, z, sum_x = 0, sum_y = 0, sum_z = 0, longitude, latitude;
+ int n, known = 0;
+
+ meas = cell->meas;
+ n = 0;
+ while (meas) {
+ if (meas->gps_valid && meas->ta_valid) {
+ geo2space(&x, &y, &z, meas->longitude, meas->latitude);
+ sum_x += x;
+ sum_y += y;
+ sum_z += z;
+ n++;
+ }
+ meas = meas->next;
+ }
+ if (!n)
+ return;
+ if (n < 3) {
+ x = sum_x / n;
+ y = sum_y / n;
+ z = sum_z / n;
+ space2geo(&longitude, &latitude, x, y, z);
+ } else {
+ struct probe *probe_first = NULL, *probe,
+ **probe_last_p = &probe_first;
+ double x_scale;
+
+ /* translate to flat surface */
+ meas = cell->meas;
+ x_scale = 1.0 / cos(meas->latitude / 180.0 * PI);
+ longitude = meas->longitude;
+ latitude = meas->latitude;
+ debug_x_scale = x_scale;
+ debug_long = longitude;
+ debug_lat = latitude;
+ debug_fp = outfp;
+ while (meas) {
+ if (meas->gps_valid && meas->ta_valid) {
+ probe = calloc(1, sizeof(struct probe));
+ if (!probe)
+ nomem();
+ probe->x = (meas->longitude - longitude) /
+ x_scale;
+ if (x < -180)
+ x += 360;
+ else if (x > 180)
+ x -= 360;
+ probe->y = meas->latitude - latitude;
+ probe->dist = GSM_TA_M * (0.5 +
+ (double)meas->ta) /
+ (EQUATOR_RADIUS * PI / 180.0);
+ *probe_last_p = probe;
+ probe_last_p = &probe->next;
+ }
+ meas = meas->next;
+ }
+
+ /* locate */
+ locate_cell(probe_first, &x, &y);
+
+ /* translate from flat surface */
+ longitude += x * x_scale;
+ if (longitude < 0)
+ longitude += 360;
+ else if (longitude >= 360)
+ longitude -= 360;
+ latitude += y;
+
+ /* remove probes */
+ while (probe_first) {
+ probe = probe_first;
+ probe_first = probe->next;
+ free(probe);
+ }
+
+ known = 1;
+ }
+
+ if (!known)
+ return;
+
+ fprintf(outfp, "\t\t\t\t\t<Placemark>\n");
+ fprintf(outfp, "\t\t\t\t\t\t<name>MCC=%s MNC=%s\nLAC=%04x "
+ "CELL-ID=%04x\n(%s %s)</name>\n", gsm_print_mcc(cell->s.mcc),
+ gsm_print_mnc(cell->s.mnc), cell->s.lac, cell->s.cell_id,
+ gsm_get_mcc(cell->s.mcc),
+ gsm_get_mnc(cell->s.mcc, cell->s.mnc));
+ fprintf(outfp, "\t\t\t\t\t\t<description>\n");
+ gsm48_sysinfo_dump(&cell->s, cell->sysinfo.arfcn, print_si, outfp,
+ NULL);
+ fprintf(outfp, "\t\t\t\t\t\t</description>\n");
+ fprintf(outfp, "\t\t\t\t\t\t<LookAt>\n");
+ fprintf(outfp, "\t\t\t\t\t\t\t<longitude>%.8f</longitude>\n",
+ longitude);
+ fprintf(outfp, "\t\t\t\t\t\t\t<latitude>%.8f</latitude>\n", latitude);
+ fprintf(outfp, "\t\t\t\t\t\t\t<altitude>0</altitude>\n");
+ fprintf(outfp, "\t\t\t\t\t\t\t<tilt>0</tilt>\n");
+ fprintf(outfp, "\t\t\t\t\t\t\t<altitudeMode>relativeToGround"
+ "</altitudeMode>\n");
+ fprintf(outfp, "\t\t\t\t\t\t\t<gx:altitudeMode>relativeToSeaFloor"
+ "</gx:altitudeMode>\n");
+ fprintf(outfp, "\t\t\t\t\t\t</LookAt>\n");
+ if (known)
+ fprintf(outfp, "\t\t\t\t\t\t<styleUrl>#msn_placemark_grn_"
+ "pushpin</styleUrl>\n");
+ else
+ fprintf(outfp, "\t\t\t\t\t\t<styleUrl>#msn_placemark_red_"
+ "pushpin</styleUrl>\n");
+ fprintf(outfp, "\t\t\t\t\t\t<Point>\n");
+ fprintf(outfp, "\t\t\t\t\t\t\t<coordinates>%.8f,%.8f</coordinates>\n",
+ longitude, latitude);
+ fprintf(outfp, "\t\t\t\t\t\t</Point>\n");
+ fprintf(outfp, "\t\t\t\t\t</Placemark>\n");
+
+ if (!log_lines)
+ return;
+
+ fprintf(outfp, "\t<Folder>\n");
+ fprintf(outfp, "\t\t<name>Lines</name>\n");
+ fprintf(outfp, "\t\t<open>0</open>\n");
+ fprintf(outfp, "\t\t<visibility>0</visibility>\n");
+
+ geo2space(&x, &y, &z, longitude, latitude);
+ meas = cell->meas;
+ n = 0;
+ while (meas) {
+ if (meas->gps_valid) {
+ double mx, my, mz, dist;
+
+ geo2space(&mx, &my, &mz, meas->longitude,
+ meas->latitude);
+ dist = distinspace(x, y, z, mx, my, mz);
+ fprintf(outfp, "\t\t<Placemark>\n");
+ fprintf(outfp, "\t\t\t<name>Range</name>\n");
+ fprintf(outfp, "\t\t\t<description>\n");
+ fprintf(outfp, "Distance: %d\n", (int)dist);
+ fprintf(outfp, "TA=%d (%d-%d meter)\n", meas->ta,
+ (int)(GSM_TA_M * meas->ta),
+ (int)(GSM_TA_M * (meas->ta + 1)));
+ fprintf(outfp, "\t\t\t</description>\n");
+ fprintf(outfp, "\t\t\t<visibility>0</visibility>\n");
+ fprintf(outfp, "\t\t\t<LineString>\n");
+ fprintf(outfp, "\t\t\t\t<tessellate>1</tessellate>\n");
+ fprintf(outfp, "\t\t\t\t<coordinates>\n");
+ fprintf(outfp, "%.8f,%.8f\n", longitude, latitude);
+ fprintf(outfp, "%.8f,%.8f\n", meas->longitude,
+ meas->latitude);
+ fprintf(outfp, "\t\t\t\t</coordinates>\n");
+ fprintf(outfp, "\t\t\t</LineString>\n");
+ fprintf(outfp, "\t\t</Placemark>\n");
+ }
+ meas = meas->next;
+ }
+ fprintf(outfp, "\t</Folder>\n");
+}
+
+struct log_target *stderr_target;
+
+int main(int argc, char *argv[])
+{
+ FILE *infp, *outfp;
+ int type, n, i;
+ char *p;
+ struct node_mcc *mcc;
+ struct node_mnc *mnc;
+ struct node_lac *lac;
+ struct node_cell *cell;
+ struct node_meas *meas;
+
+ log_init(&log_info, NULL);
+ stderr_target = log_target_create_stderr();
+ log_add_target(stderr_target);
+ log_set_all_filter(stderr_target, 1);
+ log_parse_category_mask(stderr_target, "Dxxx");
+ log_set_log_level(stderr_target, LOGL_INFO);
+
+ if (argc <= 2) {
+usage:
+ fprintf(stderr, "Usage: %s <file.log> <file.kml> "
+ "[lines] [debug]\n", argv[0]);
+ fprintf(stderr, "lines: Add lines between cell and "
+ "Measurement point\n");
+ fprintf(stderr, "debug: Add debugging of location algorithm.\n"
+ );
+ return 0;
+ }
+
+ for (i = 3; i < argc; i++) {
+ if (!strcmp(argv[i], "lines"))
+ log_lines = 1;
+ else if (!strcmp(argv[i], "debug"))
+ log_debug = 1;
+ else goto usage;
+ }
+
+ infp = fopen(argv[1], "r");
+ if (!infp) {
+ fprintf(stderr, "Failed to open '%s' for reading\n", argv[1]);
+ return -EIO;
+ }
+
+ while ((type = read_log(infp))) {
+ switch (type) {
+ case LOG_TYPE_SYSINFO:
+ add_sysinfo();
+ break;
+ case LOG_TYPE_POWER:
+ add_power();
+ break;
+ }
+ }
+
+ fclose(infp);
+
+ if (!strcmp(argv[2], "-"))
+ outfp = stdout;
+ else
+ outfp = fopen(argv[2], "w");
+ if (!outfp) {
+ fprintf(stderr, "Failed to open '%s' for writing\n", argv[2]);
+ return -EIO;
+ }
+
+ /* document name */
+ p = argv[2];
+ while (strchr(p, '/'))
+ p = strchr(p, '/') + 1;
+
+ kml_header(outfp, p);
+ mcc = node_mcc_first;
+ while (mcc) {
+ printf("MCC: %02x\n", mcc->mcc);
+ /* folder open */
+ fprintf(outfp, "\t<Folder>\n");
+ fprintf(outfp, "\t\t<name>MCC %s (%s)</name>\n",
+ gsm_print_mcc(mcc->mcc), gsm_get_mcc(mcc->mcc));
+ fprintf(outfp, "\t\t<open>0</open>\n");
+ mnc = mcc->mnc;
+ while (mnc) {
+ printf(" MNC: %02x\n", mnc->mnc);
+ /* folder open */
+ fprintf(outfp, "\t\t<Folder>\n");
+ fprintf(outfp, "\t\t\t<name>MNC %s (%s)</name>\n",
+ gsm_print_mnc(mnc->mnc), gsm_get_mnc(mcc->mcc, mnc->mnc));
+ fprintf(outfp, "\t\t\t<open>0</open>\n");
+ lac = mnc->lac;
+ while (lac) {
+ printf(" LAC: %04x\n", lac->lac);
+ /* folder open */
+ fprintf(outfp, "\t\t\t<Folder>\n");
+ fprintf(outfp, "\t\t\t\t<name>LAC %04x</name>\n", lac->lac);
+ fprintf(outfp, "\t\t\t\t<open>0</open>\n");
+ cell = lac->cell;
+ while (cell) {
+ printf(" CELL: %04x\n", cell->cellid);
+ fprintf(outfp, "\t\t\t\t<Folder>\n");
+ fprintf(outfp, "\t\t\t\t\t<name>CELL-ID %04x</name>\n", cell->cellid);
+ fprintf(outfp, "\t\t\t\t\t<open>0</open>\n");
+ meas = cell->meas;
+ n = 0;
+ while (meas) {
+ if (meas->ta_valid)
+ printf(" TA: %d\n", meas->ta);
+ if (meas->gps_valid)
+ kml_meas(outfp, meas, ++n, mcc->mcc, mnc->mnc,
+ lac->lac, cell->cellid);
+ meas = meas->next;
+ }
+ kml_cell(outfp, cell);
+ /* folder close */
+ fprintf(outfp, "\t\t\t\t</Folder>\n");
+ cell = cell->next;
+ }
+ /* folder close */
+ fprintf(outfp, "\t\t\t</Folder>\n");
+ lac = lac->next;
+ }
+ /* folder close */
+ fprintf(outfp, "\t\t</Folder>\n");
+ mnc = mnc->next;
+ }
+ /* folder close */
+ fprintf(outfp, "\t</Folder>\n");
+ mcc = mcc->next;
+ }
+#if 0
+ FIXME: power
+ /* folder open */
+ fprintf(outfp, "\t<Folder>\n");
+ fprintf(outfp, "\t\t<name>Power</name>\n");
+ fprintf(outfp, "\t\t<open>0</open>\n");
+ power = node_power_first;
+ n = 0;
+ while (power) {
+ /* folder open */
+ fprintf(outfp, "\t\t<Folder>\n");
+ fprintf(outfp, "\t\t\t<name>Power %d</name>\n", ++n);
+ fprintf(outfp, "\t\t\t<open>0</open>\n");
+ /* folder close */
+ fprintf(outfp, "\t\t</Folder>\n");
+ power = power->next;
+ }
+ /* folder close */
+ fprintf(outfp, "\t</Folder>\n");
+#endif
+ kml_footer(outfp);
+
+ fclose(outfp);
+
+ return 0;
+}
diff --git a/src/host/gsmmap/locate.c b/src/host/gsmmap/locate.c
new file mode 100644
index 00000000..ed0ac931
--- /dev/null
+++ b/src/host/gsmmap/locate.c
@@ -0,0 +1,182 @@
+/* Algorithm to locate a destination by distance measurement:
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <math.h>
+
+#include "geo.h"
+#include "locate.h"
+
+#define CIRCLE_PROBE 30.0
+#define FINETUNE_RADIUS 5.0
+
+extern double debug_long, debug_lat, debug_x_scale;
+extern FILE *debug_fp;
+extern int log_debug;
+
+static double finetune_x[6], finetune_y[6], finetune_dist[6];
+
+int locate_cell(struct probe *probe_first, double *min_x, double *min_y)
+{
+ struct probe *probe, *min_probe;
+ int i, test_steps, optimized;
+ double min_dist, dist, x, y, rad, temp;
+ double circle_probe, finetune_radius;
+
+ /* convert meters into degrees */
+ circle_probe = CIRCLE_PROBE / (EQUATOR_RADIUS * PI / 180.0);
+ finetune_radius = FINETUNE_RADIUS / (EQUATOR_RADIUS * PI / 180.0);
+
+ if (log_debug) {
+ fprintf(debug_fp, "<Folder>\n");
+ fprintf(debug_fp, "\t<name>Debug Locator</name>\n");
+ fprintf(debug_fp, "\t<open>0</open>\n");
+ fprintf(debug_fp, "\t<visibility>0</visibility>\n");
+ }
+
+ /* get probe of minimum distance */
+ min_probe = NULL;
+ probe = probe_first;
+ min_dist = 42;
+ i = 0;
+ while (probe) {
+ if (log_debug) {
+ fprintf(debug_fp, "\t<Placemark>\n");
+ fprintf(debug_fp, "\t\t<name>MEAS</name>\n");
+ fprintf(debug_fp, "\t\t<visibility>0</visibility>\n");
+ fprintf(debug_fp, "\t\t<LineString>\n");
+ fprintf(debug_fp, "\t\t\t<tessellate>1</tessellate>\n");
+ fprintf(debug_fp, "\t\t\t<coordinates>\n");
+ rad = 2.0 * 3.1415927 / 35;
+ for (i = 0; i < 35; i++) {
+ x = probe->x + probe->dist * sin(rad * i);
+ y = probe->y + probe->dist * cos(rad * i);
+ fprintf(debug_fp, "%.8f,%.8f\n", debug_long +
+ x * debug_x_scale, debug_lat + y);
+ }
+ fprintf(debug_fp, "\t\t\t</coordinates>\n");
+ fprintf(debug_fp, "\t\t</LineString>\n");
+ fprintf(debug_fp, "\t</Placemark>\n");
+ }
+
+ if (!min_probe || probe->dist < min_dist) {
+ min_probe = probe;
+ min_dist = probe->dist;
+ }
+ probe = probe->next;
+ i++;
+ }
+
+ if (i < 3) {
+ fprintf(stderr, "Need at least 3 points\n");
+ return -EINVAL;
+ }
+
+ /* calculate the number of steps to search for destination point */
+ test_steps = 2.0 * 3.1415927 * min_probe->dist / circle_probe;
+ rad = 2.0 * 3.1415927 / test_steps;
+
+ if (log_debug) {
+ fprintf(debug_fp, "\t<Placemark>\n");
+ fprintf(debug_fp, "\t\t<name>Smallest MEAS</name>\n");
+ fprintf(debug_fp, "\t\t<visibility>0</visibility>\n");
+ fprintf(debug_fp, "\t\t<LineString>\n");
+ fprintf(debug_fp, "\t\t\t<tessellate>1</tessellate>\n");
+ fprintf(debug_fp, "\t\t\t<coordinates>\n");
+ }
+
+ /* search on a circle for the location of the lowest distance
+ * to the radius with the greatest distance */
+ min_dist = 42;
+ *min_x = *min_y = 42;
+ for (i = 0; i < test_steps; i++) {
+ x = min_probe->x + min_probe->dist * sin(rad * i);
+ y = min_probe->y + min_probe->dist * cos(rad * i);
+ if (log_debug)
+ fprintf(debug_fp, "%.8f,%.8f\n", debug_long +
+ x * debug_x_scale, debug_lat + y);
+ /* look for greatest distance */
+ dist = 0;
+ probe = probe_first;
+ while (probe) {
+ if (probe != min_probe) {
+ /* distance to the radius */
+ temp = distonplane(probe->x, probe->y, x, y);
+ temp -= probe->dist;
+ if (temp < 0)
+ temp = -temp;
+ if (temp > dist)
+ dist = temp;
+ }
+ probe = probe->next;
+ }
+ if (i == 0 || dist < min_dist) {
+ min_dist = dist;
+ *min_x = x;
+ *min_y = y;
+ }
+ }
+
+ if (log_debug) {
+ fprintf(debug_fp, "\t\t\t</coordinates>\n");
+ fprintf(debug_fp, "\t\t</LineString>\n");
+ fprintf(debug_fp, "\t</Placemark>\n");
+
+ fprintf(debug_fp, "\t<Placemark>\n");
+ fprintf(debug_fp, "\t\t<name>Finetune</name>\n");
+ fprintf(debug_fp, "\t\t<visibility>0</visibility>\n");
+ fprintf(debug_fp, "\t\t<LineString>\n");
+ fprintf(debug_fp, "\t\t\t<tessellate>1</tessellate>\n");
+ fprintf(debug_fp, "\t\t\t<coordinates>\n");
+ }
+
+ min_dist = 9999999999.0;
+tune_again:
+ if (log_debug)
+ fprintf(debug_fp, "%.8f,%.8f\n", debug_long +
+ *min_x * debug_x_scale, debug_lat + *min_y);
+
+ /* finetune the point */
+ rad = 2.0 * 3.1415927 / 6;
+ for (i = 0; i < 6; i++) {
+ x = *min_x + finetune_radius * sin(rad * i);
+ y = *min_y + finetune_radius * cos(rad * i);
+ /* search for the point with the lowest sum of distances */
+ dist = 0;
+ probe = probe_first;
+ while (probe) {
+ /* distance to the radius */
+ temp = distonplane(probe->x, probe->y, x, y);
+ temp -= probe->dist;
+ if (temp < 0)
+ temp = -temp;
+ dist += temp;
+ probe = probe->next;
+ }
+ finetune_dist[i] = dist;
+ finetune_x[i] = x;
+ finetune_y[i] = y;
+ }
+
+ optimized = 0;
+ for (i = 0; i < 6; i++) {
+ if (finetune_dist[i] < min_dist) {
+ min_dist = finetune_dist[i];
+ *min_x = finetune_x[i];
+ *min_y = finetune_y[i];
+ optimized = 1;
+ }
+ }
+ if (optimized)
+ goto tune_again;
+
+ if (log_debug) {
+ fprintf(debug_fp, "\t\t\t</coordinates>\n");
+ fprintf(debug_fp, "\t\t</LineString>\n");
+ fprintf(debug_fp, "\t</Placemark>\n");
+ fprintf(debug_fp, "</Folder>\n");
+ }
+
+ return 0;
+}
diff --git a/src/host/gsmmap/locate.h b/src/host/gsmmap/locate.h
new file mode 100644
index 00000000..26133452
--- /dev/null
+++ b/src/host/gsmmap/locate.h
@@ -0,0 +1,8 @@
+
+struct probe {
+ struct probe *next;
+ double x, y, dist;
+};
+
+int locate_cell(struct probe *probe_first, double *min_x, double *min_y);
+
diff --git a/src/host/gsmmap/log.c b/src/host/gsmmap/log.c
new file mode 100644
index 00000000..c2db801e
--- /dev/null
+++ b/src/host/gsmmap/log.c
@@ -0,0 +1,377 @@
+/* Conversion of logged cells to KML file */
+
+/* (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <osmocom/bb/common/osmocom_data.h>
+
+#include "log.h"
+
+extern struct power power;
+extern struct sysinfo sysinfo;
+extern struct node_power *node_power_first;
+extern struct node_power **node_power_last_p;
+extern struct node_mcc *node_mcc_first;
+
+struct node_mcc *get_node_mcc(uint16_t mcc)
+{
+ struct node_mcc *node_mcc;
+ struct node_mcc **node_mcc_p = &node_mcc_first;
+
+//printf("add mcc %d\n", mcc);
+ while (*node_mcc_p) {
+ /* found in list */
+ if ((*node_mcc_p)->mcc == mcc)
+ return *node_mcc_p;
+ /* insert into list */
+ if ((*node_mcc_p)->mcc > mcc)
+ break;
+ node_mcc_p = &((*node_mcc_p)->next);
+ }
+
+//printf("new mcc %d\n", mcc);
+ /* append or insert to list */
+ node_mcc = calloc(1, sizeof(struct node_mcc));
+ if (!node_mcc)
+ return NULL;
+ node_mcc->mcc = mcc;
+ node_mcc->next = *node_mcc_p;
+ *node_mcc_p = node_mcc;
+ return node_mcc;
+}
+
+struct node_mnc *get_node_mnc(struct node_mcc *mcc, uint16_t mnc)
+{
+ struct node_mnc *node_mnc;
+ struct node_mnc **node_mnc_p = &mcc->mnc;
+
+ while (*node_mnc_p) {
+ /* found in list */
+ if ((*node_mnc_p)->mnc == mnc)
+ return *node_mnc_p;
+ /* insert into list */
+ if ((*node_mnc_p)->mnc > mnc)
+ break;
+ node_mnc_p = &((*node_mnc_p)->next);
+ }
+
+ /* append or insert to list */
+ node_mnc = calloc(1, sizeof(struct node_mnc));
+ if (!node_mnc)
+ return NULL;
+ node_mnc->mnc = mnc;
+ node_mnc->next = *node_mnc_p;
+ *node_mnc_p = node_mnc;
+ return node_mnc;
+}
+
+struct node_lac *get_node_lac(struct node_mnc *mnc, uint16_t lac)
+{
+ struct node_lac *node_lac;
+ struct node_lac **node_lac_p = &mnc->lac;
+
+ while (*node_lac_p) {
+ /* found in list */
+ if ((*node_lac_p)->lac == lac)
+ return *node_lac_p;
+ /* insert into list */
+ if ((*node_lac_p)->lac > lac)
+ break;
+ node_lac_p = &((*node_lac_p)->next);
+ }
+
+ /* append or insert to list */
+ node_lac = calloc(1, sizeof(struct node_lac));
+ if (!node_lac)
+ return NULL;
+ node_lac->lac = lac;
+ node_lac->next = *node_lac_p;
+ *node_lac_p = node_lac;
+ return node_lac;
+}
+
+struct node_cell *get_node_cell(struct node_lac *lac, uint16_t cellid)
+{
+ struct node_cell *node_cell;
+ struct node_cell **node_cell_p = &lac->cell;
+
+ while (*node_cell_p) {
+ /* found in list */
+ if ((*node_cell_p)->cellid == cellid)
+ return *node_cell_p;
+ /* insert into list */
+ if ((*node_cell_p)->cellid > cellid)
+ break;
+ node_cell_p = &((*node_cell_p)->next);
+ }
+
+ /* append or insert to list */
+ node_cell = calloc(1, sizeof(struct node_cell));
+ if (!node_cell)
+ return NULL;
+ node_cell->meas_last_p = &node_cell->meas;
+ node_cell->cellid = cellid;
+ node_cell->next = *node_cell_p;
+ *node_cell_p = node_cell;
+ return node_cell;
+}
+
+struct node_meas *add_node_meas(struct node_cell *cell)
+{
+ struct node_meas *node_meas;
+
+ /* append to list */
+ node_meas = calloc(1, sizeof(struct node_meas));
+ if (!node_meas)
+ return NULL;
+ node_meas->gmt = sysinfo.gmt;
+ node_meas->rxlev = sysinfo.rxlev;
+ if (sysinfo.ta_valid) {
+ node_meas->ta_valid = 1;
+ node_meas->ta = sysinfo.ta;
+ }
+ if (sysinfo.gps_valid) {
+ node_meas->gps_valid = 1;
+ node_meas->longitude = sysinfo.longitude;
+ node_meas->latitude = sysinfo.latitude;
+ }
+ *cell->meas_last_p = node_meas;
+ cell->meas_last_p = &node_meas->next;
+ return node_meas;
+}
+
+/* read "<ncc>,<bcc>" */
+static void read_log_bsic(char *buffer)
+{
+ char *p;
+ uint8_t bsic;
+
+ /* skip first spaces */
+ while (*buffer == ' ')
+ buffer++;
+
+ /* read ncc */
+ p = buffer;
+ while (*p > ' ' && *p != ',')
+ p++;
+ if (*p == '\0')
+ return; /* no value */
+ *p++ = '\0';
+ bsic = atoi(buffer) << 3;
+ buffer = p;
+
+ /* read latitude */
+ bsic |= atoi(buffer);
+
+ sysinfo.bsic = bsic;
+}
+
+/* read "<longitude> <latitude>" */
+static void read_log_pos(char *buffer, double *longitude, double *latitude,
+ uint8_t *valid)
+{
+ char *p;
+
+ /* skip first spaces */
+ while (*buffer == ' ')
+ buffer++;
+
+ /* read longitude */
+ p = buffer;
+ while (*p > ' ')
+ p++;
+ if (*p == '\0')
+ return; /* no value after longitude */
+ *p++ = '\0';
+ *longitude = atof(buffer);
+ buffer = p;
+
+ /* skip second spaces */
+ while (*buffer == ' ')
+ buffer++;
+
+ /* read latitude */
+ *latitude = atof(buffer);
+
+ *valid = 1;
+}
+
+/* read "<arfcn> <value> <next value> ...." */
+static void read_log_power(char *buffer)
+{
+ char *p;
+ int arfcn;
+
+ /* skip first spaces */
+ while (*buffer == ' ')
+ buffer++;
+
+ /* read arfcn */
+ p = buffer;
+ while (*p > ' ')
+ p++;
+ if (*p == '\0')
+ return; /* no value after arfcn */
+ *p++ = '\0';
+ arfcn = atoi(buffer);
+ buffer = p;
+
+ while (*buffer) {
+ /* wrong arfcn */
+ if (arfcn < 0 || arfcn > 1023)
+ break;
+ /* skip spaces */
+ while (*buffer == ' ')
+ buffer++;
+ /* get value */
+ p = buffer;
+ while (*p > ' ')
+ p++;
+ /* last value */
+ if (*p == '\0') {
+ power.rxlev[arfcn] = atoi(buffer);
+ break;
+ }
+ *p++ = '\0';
+ power.rxlev[arfcn] = atoi(buffer);
+ arfcn++;
+ buffer = p;
+ }
+}
+
+/* read "xx xx xx xx xx...." */
+static void read_log_si(char *buffer, uint8_t *data)
+{
+ uint8_t si[23];
+ int i;
+
+// printf("%s ", buffer);
+ for (i = 0; i < 23; i++) {
+ while (*buffer == ' ')
+ buffer++;
+ if (*buffer >= '0' && *buffer <= '9')
+ si[i] = (*buffer - '0') << 4;
+ else if (*buffer >= 'a' && *buffer <= 'f')
+ si[i] = (*buffer - 'a' + 10) << 4;
+ else if (*buffer >= 'A' && *buffer <= 'F')
+ si[i] = (*buffer - 'A' + 10) << 4;
+ else
+ break;
+ buffer++;
+ if (*buffer >= '0' && *buffer <= '9')
+ si[i] += *buffer - '0';
+ else if (*buffer >= 'a' && *buffer <= 'f')
+ si[i] += *buffer - 'a' + 10;
+ else if (*buffer >= 'A' && *buffer <= 'F')
+ si[i] += *buffer - 'A' + 10;
+ else
+ break;
+ buffer++;
+// printf("%02x ", si[i]);
+ }
+// printf("\n");
+
+ if (i == 23)
+ memcpy(data, si, 23);
+}
+
+/* read next record from log file */
+int read_log(FILE *infp)
+{
+ static int type = LOG_TYPE_NONE, ret;
+ char buffer[256];
+
+ memset(&sysinfo, 0, sizeof(sysinfo));
+ memset(&power, 0, sizeof(power));
+ memset(&power.rxlev, -128, sizeof(power.rxlev));
+
+ if (feof(infp))
+ return LOG_TYPE_NONE;
+
+ while (fgets(buffer, sizeof(buffer), infp)) {
+ buffer[sizeof(buffer) - 1] = 0;
+ if (buffer[0])
+ buffer[strlen(buffer) - 1] = '\0';
+ if (buffer[0] == '[') {
+ if (!strcmp(buffer, "[sysinfo]")) {
+ ret = type;
+ type = LOG_TYPE_SYSINFO;
+ if (ret != LOG_TYPE_NONE)
+ return ret;
+ } else
+ if (!strcmp(buffer, "[power]")) {
+ ret = type;
+ type = LOG_TYPE_POWER;
+ if (ret != LOG_TYPE_NONE)
+ return ret;
+ } else {
+ type = LOG_TYPE_NONE;
+ }
+ continue;
+ }
+ switch (type) {
+ case LOG_TYPE_SYSINFO:
+ if (!strncmp(buffer, "arfcn ", 6))
+ sysinfo.arfcn = atoi(buffer + 6);
+ else if (!strncmp(buffer, "si1 ", 4))
+ read_log_si(buffer + 4, sysinfo.si1);
+ else if (!strncmp(buffer, "si2 ", 4))
+ read_log_si(buffer + 4, sysinfo.si2);
+ else if (!strncmp(buffer, "si2bis ", 7))
+ read_log_si(buffer + 7, sysinfo.si2bis);
+ else if (!strncmp(buffer, "si2ter ", 7))
+ read_log_si(buffer + 7, sysinfo.si2ter);
+ else if (!strncmp(buffer, "si3 ", 4))
+ read_log_si(buffer + 4, sysinfo.si3);
+ else if (!strncmp(buffer, "si4 ", 4))
+ read_log_si(buffer + 4, sysinfo.si4);
+ else if (!strncmp(buffer, "time ", 5))
+ sysinfo.gmt = strtoul(buffer + 5, NULL, 0);
+ else if (!strncmp(buffer, "position ", 9))
+ read_log_pos(buffer + 9, &sysinfo.longitude,
+ &sysinfo.latitude, &sysinfo.gps_valid);
+ else if (!strncmp(buffer, "rxlev ", 5))
+ sysinfo.rxlev =
+ strtoul(buffer + 5, NULL, 0);
+ else if (!strncmp(buffer, "bsic ", 5))
+ read_log_bsic(buffer + 5);
+ else if (!strncmp(buffer, "ta ", 3)) {
+ sysinfo.ta_valid = 1;
+ sysinfo.ta = atoi(buffer + 3);
+ }
+ break;
+ case LOG_TYPE_POWER:
+ if (!strncmp(buffer, "arfcn ", 6))
+ read_log_power(buffer + 6);
+ else if (!strncmp(buffer, "time ", 5))
+ power.gmt = strtoul(buffer + 5, NULL, 0);
+ else if (!strncmp(buffer, "position ", 9))
+ read_log_pos(buffer + 9, &power.longitude,
+ &power.latitude, &sysinfo.gps_valid);
+ break;
+ }
+ }
+
+ return type;
+}
+
diff --git a/src/host/gsmmap/log.h b/src/host/gsmmap/log.h
new file mode 100644
index 00000000..d1520101
--- /dev/null
+++ b/src/host/gsmmap/log.h
@@ -0,0 +1,80 @@
+
+enum {
+ LOG_TYPE_NONE = 0,
+ LOG_TYPE_SYSINFO,
+ LOG_TYPE_POWER,
+};
+
+struct power {
+ uint8_t gps_valid;
+ double longitude, latitude;
+ time_t gmt;
+ int8_t rxlev[1024];
+};
+
+struct node_power {
+ struct node_power *next;
+ struct power power;
+};
+
+struct node_mcc {
+ struct node_mcc *next;
+ uint16_t mcc;
+ struct node_mnc *mnc;
+};
+
+struct node_mnc {
+ struct node_mnc *next;
+ uint16_t mnc;
+ struct node_lac *lac;
+};
+
+struct node_lac {
+ struct node_lac *next;
+ uint16_t lac;
+ struct node_cell *cell;
+};
+
+struct sysinfo {
+ uint16_t arfcn;
+ int8_t rxlev;
+ uint8_t bsic;
+ uint8_t gps_valid;
+ double longitude, latitude;
+ time_t gmt;
+ uint8_t si1[23];
+ uint8_t si2[23];
+ uint8_t si2bis[23];
+ uint8_t si2ter[23];
+ uint8_t si3[23];
+ uint8_t si4[23];
+ uint8_t ta_valid;
+ uint8_t ta;
+};
+
+struct node_cell {
+ struct node_cell *next;
+ uint16_t cellid;
+ uint8_t content; /* indicates, if sysinfo is already applied */
+ struct node_meas *meas, **meas_last_p;
+ struct sysinfo sysinfo;
+ struct gsm48_sysinfo s;
+};
+
+struct node_meas {
+ struct node_meas *next;
+ time_t gmt;
+ int8_t rxlev;
+ uint8_t gps_valid;
+ double longitude, latitude;
+ uint8_t ta_valid;
+ uint8_t ta;
+};
+
+struct node_mcc *get_node_mcc(uint16_t mcc);
+struct node_mnc *get_node_mnc(struct node_mcc *mcc, uint16_t mnc);
+struct node_lac *get_node_lac(struct node_mnc *mnc, uint16_t lac);
+struct node_cell *get_node_cell(struct node_lac *lac, uint16_t cellid);
+struct node_meas *add_node_meas(struct node_cell *cell);
+int read_log(FILE *infp);
+
diff --git a/src/host/layer23/.gitignore b/src/host/layer23/.gitignore
new file mode 100644
index 00000000..8fb93f73
--- /dev/null
+++ b/src/host/layer23/.gitignore
@@ -0,0 +1,36 @@
+# autoreconf by-products
+*.in
+
+aclocal.m4
+autom4te.cache/
+config.h.in
+configure
+depcomp
+install-sh
+missing
+
+# configure by-products
+.deps
+Makefile
+
+config.h
+config.log
+config.status
+
+# build by-products
+*.o
+*.a
+
+# various
+*.sw?
+*.deps
+
+# final executables
+src/misc/bcch_scan
+src/misc/cbch_sniff
+src/misc/cell_log
+src/misc/echo_test
+src/misc/cbch_sniff
+src/misc/ccch_scan
+src/misc/layer23
+src/mobile/mobile
diff --git a/COPYING b/src/host/layer23/COPYING
index d511905c..d511905c 100644
--- a/COPYING
+++ b/src/host/layer23/COPYING
diff --git a/src/host/layer23/Makefile.am b/src/host/layer23/Makefile.am
new file mode 100644
index 00000000..bc3910fa
--- /dev/null
+++ b/src/host/layer23/Makefile.am
@@ -0,0 +1,3 @@
+AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
+
+SUBDIRS = include src
diff --git a/src/host/layer23/README b/src/host/layer23/README
new file mode 100644
index 00000000..dd598234
--- /dev/null
+++ b/src/host/layer23/README
@@ -0,0 +1,42 @@
+= OsmocomBB layer23 architecture =
+
+layer23 is an (incomplete) MS-side implementation of the L2 and L3 GSM
+protocols as described in GSM TS 04.06, 04.08 and others.
+
+== Interfaces ==
+
+L1 (on the phone) uses the L1CTL protocol to talk with layer23 (on the PC).
+
+L2 (inside layer23) uses the RSLms protocol to talk with the L3 (inside layer23)
+
+
+=== RSLms ===
+
+RSLms is modeled after the GSM TS 08.58 Radio Subsystem Link protocol. Despite
+being designed for the network side, RSL seems a good match for the L2/L3
+interface inside a MS, too.
+
+At least the RLL (Radio Link Layer) part of RSL is 100% as applicable to the MS
+side as it is for the ntwork side.
+
+==== Lower interface (L2 to RSLms) ====
+
+Layer2 calls rslms_sendmsg() with a msgb that has the msgb->l2h pointing to a
+RSL header (struct abis_rsl_common_hdr).
+
+==== Upper interface (L3 to RSLms) ====
+
+Layer3 calls rslms_recvmsg() with a msgb that has the msgb->l2h pointing to a
+RSL header (struct abis_rsl_common_hdr).
+
+There are utility functions like rslms_tx_rll_req() and rslms_tx_rsll_req_l3()
+for creating msgb's with the apropriate RSL/RLL headers.
+
+
+=== LAPDm ===
+
+LAPDm is the GSM TS 04.06 protocol
+
+The lower interface (to L1) is using L1CTL
+
+The upper interface (to L3) is using RSLms
diff --git a/src/host/layer23/configure.ac b/src/host/layer23/configure.ac
new file mode 100644
index 00000000..9335e66e
--- /dev/null
+++ b/src/host/layer23/configure.ac
@@ -0,0 +1,41 @@
+dnl Process this file with autoconf to produce a configure script
+AC_INIT
+
+AM_INIT_AUTOMAKE(layer23, 0.0.0)
+
+dnl kernel style compile messages
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+dnl checks for programs
+AC_PROG_MAKE_SET
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+
+dnl checks for libraries
+PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore)
+PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty)
+PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm)
+PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec)
+AC_CHECK_LIB(gps, gps_waiting, LIBGPS_CFLAGS=" -D_HAVE_GPSD" LIBGPS_LIBS=" -lgps ",,)
+AC_SUBST([LIBGPS_CFLAGS])
+AC_SUBST([LIBGPS_LIBS])
+
+
+dnl checks for header files
+AC_HEADER_STDC
+
+dnl Checks for typedefs, structures and compiler characteristics
+
+AC_OUTPUT(
+ src/Makefile
+ src/common/Makefile
+ src/misc/Makefile
+ src/mobile/Makefile
+ include/Makefile
+ include/osmocom/Makefile
+ include/osmocom/bb/Makefile
+ include/osmocom/bb/common/Makefile
+ include/osmocom/bb/misc/Makefile
+ include/osmocom/bb/mobile/Makefile
+ Makefile)
diff --git a/src/host/layer23/include/Makefile.am b/src/host/layer23/include/Makefile.am
new file mode 100644
index 00000000..297ece97
--- /dev/null
+++ b/src/host/layer23/include/Makefile.am
@@ -0,0 +1,2 @@
+noinst_HEADERS = l1ctl_proto.h
+SUBDIRS = osmocom
diff --git a/src/host/layer23/include/l1ctl_proto.h b/src/host/layer23/include/l1ctl_proto.h
new file mode 120000
index 00000000..f12ba71e
--- /dev/null
+++ b/src/host/layer23/include/l1ctl_proto.h
@@ -0,0 +1 @@
+../../../../include/l1ctl_proto.h \ No newline at end of file
diff --git a/src/host/layer23/include/osmocom/Makefile.am b/src/host/layer23/include/osmocom/Makefile.am
new file mode 100644
index 00000000..5adf9df5
--- /dev/null
+++ b/src/host/layer23/include/osmocom/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = bb
diff --git a/src/host/layer23/include/osmocom/bb/Makefile.am b/src/host/layer23/include/osmocom/bb/Makefile.am
new file mode 100644
index 00000000..58a5f7fb
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = common misc mobile
diff --git a/src/host/layer23/include/osmocom/bb/common/Makefile.am b/src/host/layer23/include/osmocom/bb/common/Makefile.am
new file mode 100644
index 00000000..945c73db
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/Makefile.am
@@ -0,0 +1,2 @@
+noinst_HEADERS = l1ctl.h l1l2_interface.h l23_app.h logging.h \
+ networks.h gps.h sysinfo.h osmocom_data.h
diff --git a/src/host/layer23/include/osmocom/bb/common/gps.h b/src/host/layer23/include/osmocom/bb/common/gps.h
new file mode 100644
index 00000000..58c0c536
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/gps.h
@@ -0,0 +1,53 @@
+/*
+ * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+enum {
+ GPS_TYPE_UNDEF,
+ GPS_TYPE_GPSD,
+ GPS_TYPE_SERIAL
+};
+
+struct osmo_gps {
+ /* GPS device */
+ uint8_t enable;
+ uint8_t gps_type;
+
+#ifdef _HAVE_GPSD
+ char gpsd_host[32];
+ char gpsd_port[6];
+#endif
+
+ char device[32];
+ uint32_t baud;
+
+ /* current data */
+ uint8_t valid; /* we have a fix */
+ time_t gmt; /* GMT time when position was received */
+ double latitude, longitude;
+};
+
+extern struct osmo_gps g;
+
+int osmo_gps_open(void);
+void osmo_gps_close(void);
+void osmo_gps_init(void);
+
+
diff --git a/src/host/layer23/include/osmocom/bb/common/l1ctl.h b/src/host/layer23/include/osmocom/bb/common/l1ctl.h
new file mode 100644
index 00000000..5ebea96c
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/l1ctl.h
@@ -0,0 +1,76 @@
+#ifndef osmocom_l1ctl_h
+#define osmocom_l1ctl_h
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/bb/common/osmocom_data.h>
+
+struct osmocom_ms;
+
+/* Receive incoming data from L1 using L1CTL format */
+int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg);
+
+/* Transmit L1CTL_DATA_REQ */
+int l1ctl_tx_data_req(struct osmocom_ms *ms, struct msgb *msg, uint8_t chan_nr,
+ uint8_t link_id);
+
+/* Transmit L1CTL_PARAM_REQ */
+int l1ctl_tx_param_req(struct osmocom_ms *ms, uint8_t ta, uint8_t tx_power);
+
+int l1ctl_tx_crypto_req(struct osmocom_ms *ms, uint8_t algo, uint8_t *key,
+ uint8_t len);
+
+/* Transmit L1CTL_RACH_REQ */
+int l1ctl_tx_rach_req(struct osmocom_ms *ms, uint8_t ra, uint16_t offset,
+ uint8_t combined);
+
+/* Transmit L1CTL_DM_EST_REQ */
+int l1ctl_tx_dm_est_req_h0(struct osmocom_ms *ms, uint16_t band_arfcn,
+ uint8_t chan_nr, uint8_t tsc, uint8_t tch_mode, uint8_t audio_mode);
+int l1ctl_tx_dm_est_req_h1(struct osmocom_ms *ms, uint8_t maio, uint8_t hsn,
+ uint16_t *ma, uint8_t ma_len, uint8_t chan_nr, uint8_t tsc,
+ uint8_t tch_mode, uint8_t audio_mode);
+
+/* Transmit L1CTL_DM_FREQ_REQ */
+int l1ctl_tx_dm_freq_req_h0(struct osmocom_ms *ms, uint16_t band_arfcn,
+ uint8_t tsc, uint16_t fn);
+int l1ctl_tx_dm_freq_req_h1(struct osmocom_ms *ms, uint8_t maio, uint8_t hsn,
+ uint16_t *ma, uint8_t ma_len, uint8_t tsc, uint16_t fn);
+
+/* Transmit L1CTL_DM_REL_REQ */
+int l1ctl_tx_dm_rel_req(struct osmocom_ms *ms);
+
+/* Transmit FBSB_REQ */
+int l1ctl_tx_fbsb_req(struct osmocom_ms *ms, uint16_t arfcn,
+ uint8_t flags, uint16_t timeout, uint8_t sync_info_idx,
+ uint8_t ccch_mode);
+
+/* Transmit CCCH_MODE_REQ */
+int l1ctl_tx_ccch_mode_req(struct osmocom_ms *ms, uint8_t ccch_mode);
+
+/* Transmit TCH_MODE_REQ */
+int l1ctl_tx_tch_mode_req(struct osmocom_ms *ms, uint8_t tch_mode,
+ uint8_t audio_mode);
+
+/* Transmit ECHO_REQ */
+int l1ctl_tx_echo_req(struct osmocom_ms *ms, unsigned int len);
+
+/* Transmit L1CTL_RESET_REQ */
+int l1ctl_tx_reset_req(struct osmocom_ms *ms, uint8_t type);
+
+/* Transmit L1CTL_PM_REQ */
+int l1ctl_tx_pm_req_range(struct osmocom_ms *ms, uint16_t arfcn_from,
+ uint16_t arfcm_to);
+
+int l1ctl_tx_sim_req(struct osmocom_ms *ms, uint8_t *data, uint16_t length);
+
+/* Transmit L1CTL_VOICE_REQ */
+int l1ctl_tx_traffic_req(struct osmocom_ms *ms, struct msgb *msg,
+ uint8_t chan_nr, uint8_t link_id);
+
+/* LAPDm wants to send a PH-* primitive to the physical layer (L1) */
+int l1ctl_ph_prim_cb(struct osmo_prim_hdr *oph, void *ctx);
+
+/* Transmit L1CTL_NEIGH_PM_REQ */
+int l1ctl_tx_neigh_pm_req(struct osmocom_ms *ms, int num, uint16_t *arfcn);
+
+#endif
diff --git a/src/host/layer23/include/osmocom/bb/common/l1l2_interface.h b/src/host/layer23/include/osmocom/bb/common/l1l2_interface.h
new file mode 100644
index 00000000..41403d87
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/l1l2_interface.h
@@ -0,0 +1,8 @@
+#ifndef _L1L2_INTERFACE_H
+#define _L1L2_INTERFACE_H
+
+int layer2_open(struct osmocom_ms *ms, const char *socket_path);
+int layer2_close(struct osmocom_ms *ms);
+int osmo_send_l1(struct osmocom_ms *ms, struct msgb *msg);
+
+#endif /* _L1L2_INTERFACE_H */
diff --git a/src/host/layer23/include/osmocom/bb/common/l23_app.h b/src/host/layer23/include/osmocom/bb/common/l23_app.h
new file mode 100644
index 00000000..0b9994c3
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/l23_app.h
@@ -0,0 +1,36 @@
+#ifndef _L23_APP_H
+#define _L23_APP_H
+
+struct option;
+
+/* Options supported by the l23 app */
+enum {
+ L23_OPT_SAP = 1,
+ L23_OPT_ARFCN = 2,
+ L23_OPT_TAP = 4,
+ L23_OPT_VTY = 8,
+ L23_OPT_DBG = 16,
+ L23_OPT_VTYIP = 32,
+};
+
+/* initialization, called once when starting the app, before entering
+ * select loop */
+extern int l23_app_init(struct osmocom_ms *ms);
+extern int (*l23_app_work) (struct osmocom_ms *ms);
+extern int (*l23_app_exit) (struct osmocom_ms *ms);
+
+/* configuration options */
+struct l23_app_info {
+ const char *copyright;
+ const char *contribution;
+
+ char *getopt_string;
+ int (*cfg_supported)();
+ int (*cfg_print_help)();
+ int (*cfg_getopt_opt)(struct option **options);
+ int (*cfg_handle_opt)(int c,const char *optarg);
+};
+
+extern struct l23_app_info *l23_app_info();
+
+#endif /* _L23_APP_H */
diff --git a/src/host/layer23/include/osmocom/bb/common/logging.h b/src/host/layer23/include/osmocom/bb/common/logging.h
new file mode 100644
index 00000000..3efa57a5
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/logging.h
@@ -0,0 +1,29 @@
+#ifndef _LOGGING_H
+#define _LOGGING_H
+
+#define DEBUG
+#include <osmocom/core/logging.h>
+
+enum {
+ DRSL,
+ DRR,
+ DPLMN,
+ DCS,
+ DNB,
+ DMM,
+ DCC,
+ DSS,
+ DSMS,
+ DMNCC,
+ DMEAS,
+ DPAG,
+ DL1C,
+ DSAP,
+ DSUM,
+ DSIM,
+ DGPS,
+};
+
+extern const struct log_info log_info;
+
+#endif /* _LOGGING_H */
diff --git a/src/host/layer23/include/osmocom/bb/common/networks.h b/src/host/layer23/include/osmocom/bb/common/networks.h
new file mode 100644
index 00000000..d34f3162
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/networks.h
@@ -0,0 +1,24 @@
+#ifndef _NETWORKS_H
+#define _NETWORKS_H
+
+#define GSM_INPUT_INVALID 0xffff
+
+struct gsm_networks {
+ uint16_t mcc;
+ int16_t mnc;
+ const char *name;
+};
+
+int gsm_match_mcc(uint16_t mcc, char *imsi);
+int gsm_match_mnc(uint16_t mcc, uint16_t mnc, char *imsi);
+const char *gsm_print_mcc(uint16_t mcc);
+const char *gsm_print_mnc(uint16_t mcc);
+const char *gsm_get_mcc(uint16_t mcc);
+const char *gsm_get_mnc(uint16_t mcc, uint16_t mnc);
+const char *gsm_imsi_mcc(char *imsi);
+const char *gsm_imsi_mnc(char *imsi);
+const uint16_t gsm_input_mcc(char *string);
+const uint16_t gsm_input_mnc(char *string);
+
+#endif /* _NETWORKS_H */
+
diff --git a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
new file mode 100644
index 00000000..ab7c2502
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
@@ -0,0 +1,131 @@
+#ifndef osmocom_data_h
+#define osmocom_data_h
+
+#include <osmocom/core/select.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/core/write_queue.h>
+
+struct osmocom_ms;
+
+ /* FIXME no 'mobile' specific stuff should be here */
+#include <osmocom/bb/mobile/support.h>
+#include <osmocom/bb/mobile/settings.h>
+#include <osmocom/bb/mobile/subscriber.h>
+#include <osmocom/gsm/lapdm.h>
+#include <osmocom/bb/common/sap_interface.h>
+#include <osmocom/bb/mobile/gsm48_rr.h>
+#include <osmocom/bb/common/sysinfo.h>
+#include <osmocom/bb/mobile/gsm322.h>
+#include <osmocom/bb/mobile/gsm48_mm.h>
+#include <osmocom/bb/mobile/gsm48_cc.h>
+#include <osmocom/bb/mobile/mncc_sock.h>
+#include <osmocom/bb/common/sim.h>
+#include <osmocom/bb/common/l1ctl.h>
+
+struct osmosap_entity {
+ osmosap_cb_t msg_handler;
+};
+
+struct osmol1_entity {
+ int (*l1_traffic_ind)(struct osmocom_ms *ms, struct msgb *msg);
+};
+
+struct osmomncc_entity {
+ int (*mncc_recv)(struct osmocom_ms *ms, int msg_type, void *arg);
+ struct mncc_sock_state *sock_state;
+ uint32_t ref;
+};
+
+
+/* RX measurement statistics */
+struct rx_meas_stat {
+ uint32_t last_fn;
+
+ /* cumulated values of current cell from SACCH dl */
+ uint32_t frames;
+ uint32_t snr;
+ uint32_t berr;
+ uint32_t rxlev;
+
+ /* counters loss criterion */
+ int16_t dsc, ds_fail;
+ int16_t s, rl_fail;
+};
+
+/* One Mobilestation for osmocom */
+struct osmocom_ms {
+ struct llist_head entity;
+ char name[32];
+ struct osmo_wqueue l2_wq, sap_wq;
+ uint16_t test_arfcn;
+ struct osmol1_entity l1_entity;
+
+ uint8_t deleting, shutdown, started;
+ struct gsm_support support;
+ struct gsm_settings settings;
+ struct gsm_subscriber subscr;
+ struct gsm_sim sim;
+ struct lapdm_channel lapdm_channel;
+ struct osmosap_entity sap_entity;
+ struct rx_meas_stat meas;
+ struct gsm48_rrlayer rrlayer;
+ struct gsm322_plmn plmn;
+ struct gsm322_cellsel cellsel;
+ struct gsm48_mmlayer mmlayer;
+ struct gsm48_cclayer cclayer;
+ struct osmomncc_entity mncc_entity;
+ struct llist_head trans_list;
+};
+
+enum osmobb_sig_subsys {
+ SS_L1CTL,
+ SS_GLOBAL,
+};
+
+enum osmobb_l1ctl_sig {
+ S_L1CTL_FBSB_ERR,
+ S_L1CTL_FBSB_RESP,
+ S_L1CTL_RESET,
+ S_L1CTL_PM_RES,
+ S_L1CTL_PM_DONE,
+ S_L1CTL_CCCH_MODE_CONF,
+ S_L1CTL_TCH_MODE_CONF,
+ S_L1CTL_LOSS_IND,
+ S_L1CTL_NEIGH_PM_IND,
+};
+
+enum osmobb_global_sig {
+ S_GLOBAL_SHUTDOWN,
+};
+
+struct osmobb_fbsb_res {
+ struct osmocom_ms *ms;
+ int8_t snr;
+ uint8_t bsic;
+ uint16_t band_arfcn;
+};
+
+struct osmobb_meas_res {
+ struct osmocom_ms *ms;
+ uint16_t band_arfcn;
+ uint8_t rx_lev;
+};
+
+struct osmobb_ccch_mode_conf {
+ struct osmocom_ms *ms;
+ uint8_t ccch_mode;
+};
+
+struct osmobb_tch_mode_conf {
+ struct osmocom_ms *ms;
+ uint8_t tch_mode;
+ uint8_t audio_mode;
+};
+
+struct osmobb_neigh_pm_ind {
+ struct osmocom_ms *ms;
+ uint16_t band_arfcn;
+ uint8_t rx_lev;
+};
+
+#endif
diff --git a/src/host/layer23/include/osmocom/bb/common/sap_interface.h b/src/host/layer23/include/osmocom/bb/common/sap_interface.h
new file mode 100644
index 00000000..f2f577a7
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/sap_interface.h
@@ -0,0 +1,11 @@
+#ifndef _SAP_INTERFACE_H
+#define _SAP_INTERFACE_H
+
+typedef int (*osmosap_cb_t)(struct msgb *msg, struct osmocom_ms *ms);
+
+int sap_open(struct osmocom_ms *ms, const char *socket_path);
+int sap_close(struct osmocom_ms *ms);
+int osmosap_send(struct osmocom_ms *ms, struct msgb *msg);
+int osmosap_register_handler(struct osmocom_ms *ms, osmosap_cb_t cb);
+
+#endif /* _SAP_INTERFACE_H */
diff --git a/src/host/layer23/include/osmocom/bb/common/sim.h b/src/host/layer23/include/osmocom/bb/common/sim.h
new file mode 100644
index 00000000..95d2147c
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/sim.h
@@ -0,0 +1,284 @@
+/*
+ * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+
+/* 9.2 commands */
+#define GSM1111_CLASS_GSM 0xa0
+#define GSM1111_INST_SELECT 0xa4
+#define GSM1111_INST_STATUS 0xf2
+#define GSM1111_INST_READ_BINARY 0xb0
+#define GSM1111_INST_UPDATE_BINARY 0xd6
+#define GSM1111_INST_READ_RECORD 0xb2
+#define GSM1111_INST_UPDATE_RECORD 0xdc
+#define GSM1111_INST_SEEK 0xa2
+#define GSM1111_INST_INCREASE 0x32
+#define GSM1111_INST_VERIFY_CHV 0x20
+#define GSM1111_INST_CHANGE_CHV 0x24
+#define GSM1111_INST_DISABLE_CHV 0x26
+#define GSM1111_INST_ENABLE_CHV 0x28
+#define GSM1111_INST_UNBLOCK_CHV 0x2c
+#define GSM1111_INST_INVALIDATE 0x04
+#define GSM1111_INST_REHABLILITATE 0x44
+#define GSM1111_INST_RUN_GSM_ALGO 0x88
+#define GSM1111_INST_SLEEP 0xfa
+#define GSM1111_INST_GET_RESPONSE 0xc0
+#define GSM1111_INST_TERMINAL_PROFILE 0x10
+#define GSM1111_INST_ENVELOPE 0xc2
+#define GSM1111_INST_FETCH 0x12
+#define GSM1111_INST_TERMINAL_RESPONSE 0x14
+
+/* 9.3 access conditions */
+#define GSM1111_ACC_ALWAYS 0x0
+#define GSM1111_ACC_CHV1 0x1
+#define GSM1111_ACC_CHV2 0x2
+#define GSM1111_ACC_RFU 0x3
+#define GSM1111_ACC_NEW 0xf
+/* others are ADM */
+
+/* 9.3 type of file */
+#define GSM1111_TOF_RFU 0x00
+#define GSM1111_TOF_MF 0x01
+#define GSM1111_TOF_DF 0x02
+#define GSM1111_TOF_EF 0x04
+
+/* 9.3 struct of file */
+#define GSM1111_SOF_TRANSPARENT 0x00
+#define GSM1111_SOF_LINEAR 0x01
+#define GSM1111_SOF_CYCLIC 0x03
+
+/* 9.4 status */
+#define GSM1111_STAT_NORMAL 0x90
+#define GSM1111_STAT_PROACTIVE 0x91
+#define GSM1111_STAT_DL_ERROR 0x9e
+#define GSM1111_STAT_RESPONSE 0x9f
+#define GSM1111_STAT_RESPONSE_TOO 0x61
+#define GSM1111_STAT_APP_TK_BUSY 0x93
+#define GSM1111_STAT_MEM_PROBLEM 0x92
+#define GSM1111_STAT_REFERENCING 0x94
+#define GSM1111_STAT_SECURITY 0x98
+#define GSM1111_STAT_INCORR_P3 0x67
+#define GSM1111_STAT_INCORR_P1_P2 0x6b
+#define GSM1111_STAT_UKN_INST 0x6d
+#define GSM1111_STAT_WRONG_CLASS 0x6e
+#define GSM1111_STAT_TECH_PROBLEM 0x6f
+
+/* 9.4.4 Referencing management SW2 */
+#define GSM1111_REF_NO_EF 0x00
+#define GSM1111_REF_OUT_OF_RANGE 0x02
+#define GSM1111_REF_FILE_NOT_FOUND 0x04
+#define GSM1111_REF_FILE_INCONSI 0x08
+
+/* 9.4.5 Security management SW2 */
+#define GSM1111_SEC_NO_CHV 0x02
+#define GSM1111_SEC_NO_ACCESS 0x04
+#define GSM1111_SEC_CONTRA_CHV 0x08
+#define GSM1111_SEC_CONTRA_INVAL 0x10
+#define GSM1111_SEC_BLOCKED 0x40
+#define GSM1111_SEC_MAX_VALUE 0x50
+
+/* messages from application to sim client */
+enum {
+ /* requests */
+ SIM_JOB_READ_BINARY,
+ SIM_JOB_UPDATE_BINARY,
+ SIM_JOB_READ_RECORD,
+ SIM_JOB_UPDATE_RECORD,
+ SIM_JOB_SEEK_RECORD,
+ SIM_JOB_INCREASE,
+ SIM_JOB_INVALIDATE,
+ SIM_JOB_REHABILITATE,
+ SIM_JOB_RUN_GSM_ALGO,
+ SIM_JOB_PIN1_UNLOCK,
+ SIM_JOB_PIN1_CHANGE,
+ SIM_JOB_PIN1_DISABLE,
+ SIM_JOB_PIN1_ENABLE,
+ SIM_JOB_PIN1_UNBLOCK,
+ SIM_JOB_PIN2_UNLOCK,
+ SIM_JOB_PIN2_CHANGE,
+ SIM_JOB_PIN2_UNBLOCK,
+
+ /* results */
+ SIM_JOB_OK,
+ SIM_JOB_ERROR,
+};
+
+/* messages from sim client to application */
+#define SIM_JOB_OK 0
+#define SIM_JOB_ERROR 1
+
+/* error causes */
+#define SIM_CAUSE_NO_SIM 0 /* no SIM present, if detectable */
+#define SIM_CAUSE_SIM_ERROR 1 /* any error while reading SIM */
+#define SIM_CAUSE_REQUEST_ERROR 2 /* error in request */
+#define SIM_CAUSE_PIN1_REQUIRED 3 /* CHV1 is required for access */
+#define SIM_CAUSE_PIN2_REQUIRED 4 /* CHV2 is required for access */
+#define SIM_CAUSE_PIN1_BLOCKED 5 /* CHV1 was entered too many times */
+#define SIM_CAUSE_PIN2_BLOCKED 6 /* CHV2 was entered too many times */
+#define SIM_CAUSE_PUC_BLOCKED 7 /* unblock entered too many times */
+
+/* job states */
+enum {
+ SIM_JST_IDLE = 0,
+ SIM_JST_SELECT_MFDF, /* SELECT sent */
+ SIM_JST_SELECT_MFDF_RESP, /* GET RESPONSE sent */
+ SIM_JST_SELECT_EF, /* SELECT sent */
+ SIM_JST_SELECT_EF_RESP, /* GET RESPONSE sent */
+ SIM_JST_WAIT_FILE, /* file command sent */
+ SIM_JST_RUN_GSM_ALGO, /* wait for algorithm to process */
+ SIM_JST_RUN_GSM_ALGO_RESP, /* wait for response */
+ SIM_JST_PIN1_UNLOCK,
+ SIM_JST_PIN1_CHANGE,
+ SIM_JST_PIN1_DISABLE,
+ SIM_JST_PIN1_ENABLE,
+ SIM_JST_PIN1_UNBLOCK,
+ SIM_JST_PIN2_UNLOCK,
+ SIM_JST_PIN2_CHANGE,
+ SIM_JST_PIN2_UNBLOCK,
+};
+
+#define MAX_SIM_PATH_LENGTH 6 + 1 /* one for the termination */
+
+struct gsm_sim_handler {
+ struct llist_head entry;
+
+ uint32_t handle;
+ void (*cb)(struct osmocom_ms *ms, struct msgb *msg);
+};
+
+struct gsm_sim {
+ struct llist_head handlers; /* gsm_sim_handler */
+ struct llist_head jobs; /* messages */
+ uint16_t path[MAX_SIM_PATH_LENGTH];
+ uint16_t file;
+
+ struct msgb *job_msg;
+ uint32_t job_handle;
+ int job_state;
+
+ uint8_t reset;
+ uint8_t chv1_remain, chv2_remain;
+ uint8_t unblk1_remain, unblk2_remain;
+};
+
+struct sim_hdr {
+ int handle;
+ uint8_t job_type;
+ uint16_t path[MAX_SIM_PATH_LENGTH];
+ uint16_t file;
+ uint8_t rec_no, rec_mode; /* in case of record */
+ uint8_t seek_type_mode; /* in case of seek command */
+};
+
+#define SIM_ALLOC_SIZE 512
+#define SIM_ALLOC_HEADROOM 64
+
+struct msgb *gsm_sim_msgb_alloc(uint32_t handle, uint8_t job_type);
+uint32_t sim_open(struct osmocom_ms *ms,
+ void (*cb)(struct osmocom_ms *ms, struct msgb *msg));
+void sim_close(struct osmocom_ms *ms, uint32_t handle);
+void sim_job(struct osmocom_ms *ms, struct msgb *msg);
+
+/* Section 9.2.1 (response to selecting DF or MF) */
+struct gsm1111_response_mfdf {
+ uint16_t rfu1;
+ uint16_t free_mem;
+ uint16_t file_id;
+ uint8_t tof;
+ uint8_t rfu2[5];
+ uint8_t length;
+ uint8_t gsm_data[0];
+} __attribute__ ((packed));
+
+struct gsm1111_response_mfdf_gsm {
+ uint8_t file_char;
+ uint8_t num_df;
+ uint8_t num_ef;
+ uint8_t num_codes;
+ uint8_t rfu1;
+ uint8_t chv1_remain:4,
+ rfu2:3,
+ chv1_init:1;
+ uint8_t unblk1_remain:4,
+ rfu3:3,
+ unblk1_init:1;
+ uint8_t chv2_remain:4,
+ rfu4:3,
+ chv2_init:1;
+ uint8_t unblk2_remain:4,
+ rfu5:3,
+ unblk2_init:1;
+ uint8_t more_data[0];
+} __attribute__ ((packed));
+
+/* Section 9.2.1 (response to selecting EF) */
+struct gsm1111_response_ef {
+ uint16_t rfu1;
+ uint16_t file_size;
+ uint16_t file_id;
+ uint8_t tof;
+ uint8_t inc_allowed;
+ uint8_t acc_update:4,
+ acc_read:4;
+ uint8_t rfu2:4,
+ acc_inc:4;
+ uint8_t acc_inval:4,
+ acc_reha:4;
+ uint8_t not_inval:1,
+ rfu3:1,
+ ru_inval:1,
+ rfu4:5;
+ uint8_t length;
+ uint8_t structure;
+} __attribute__ ((packed));
+
+/* Section 10.3.17 */
+struct gsm1111_ef_loci {
+ uint32_t tmsi;
+ struct gsm48_loc_area_id lai;
+ uint8_t tmsi_time;
+ uint8_t lupd_status;
+} __attribute__ ((packed));
+
+/* Section 10.5.1 */
+struct gsm1111_ef_adn {
+ uint8_t len_bcd;
+ uint8_t ton_npi;
+ uint8_t number[10];
+ uint8_t capa_conf;
+ uint8_t ext_id;
+} __attribute__ ((packed));
+
+/* Section 10.5.6 */
+struct gsm1111_ef_smsp {
+ uint8_t par_ind;
+ uint8_t tp_da[12];
+ uint8_t ts_sca[12];
+ uint8_t tp_proto;
+ uint8_t tp_dcs;
+ uint8_t tp_vp;
+} __attribute__ ((packed));
+
+int sim_apdu_resp(struct osmocom_ms *ms, struct msgb *msg);
+int gsm_sim_init(struct osmocom_ms *ms);
+int gsm_sim_exit(struct osmocom_ms *ms);
+int gsm_sim_job_dequeue(struct osmocom_ms *ms);
+
+
diff --git a/src/host/layer23/include/osmocom/bb/common/sysinfo.h b/src/host/layer23/include/osmocom/bb/common/sysinfo.h
new file mode 100644
index 00000000..f843f271
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/sysinfo.h
@@ -0,0 +1,162 @@
+#ifndef _SYSINFO_H
+#define _SYSINFO_H
+
+#include <osmocom/gsm/gsm48_ie.h>
+
+/* collection of system information of the current cell */
+
+/* frequency mask flags of frequency type */
+#define FREQ_TYPE_SERV 0x01 /* frequency of the serving cell */
+#define FREQ_TYPE_HOPP 0x02 /* frequency used for channel hopping */
+#define FREQ_TYPE_NCELL 0x1c /* frequency of the neighbor cell */
+#define FREQ_TYPE_NCELL_2 0x04 /* sub channel of SI 2 */
+#define FREQ_TYPE_NCELL_2bis 0x08 /* sub channel of SI 2bis */
+#define FREQ_TYPE_NCELL_2ter 0x10 /* sub channel of SI 2ter */
+#define FREQ_TYPE_REP 0xe0 /* frequency to be reported */
+#define FREQ_TYPE_REP_5 0x20 /* sub channel of SI 5 */
+#define FREQ_TYPE_REP_5bis 0x40 /* sub channel of SI 5bis */
+#define FREQ_TYPE_REP_5ter 0x80 /* sub channel of SI 5ter */
+
+/* structure of all received system informations */
+struct gsm48_sysinfo {
+ /* flags of available information */
+ uint8_t si1, si2, si2bis, si2ter, si3,
+ si4, si5, si5bis, si5ter, si6;
+
+ /* memory maps to simply detect change in system info messages */
+ uint8_t si1_msg[23];
+ uint8_t si2_msg[23];
+ uint8_t si2b_msg[23];
+ uint8_t si2t_msg[23];
+ uint8_t si3_msg[23];
+ uint8_t si4_msg[23];
+ uint8_t si5_msg[18];
+ uint8_t si5b_msg[18];
+ uint8_t si5t_msg[18];
+ uint8_t si6_msg[18];
+
+ struct gsm_sysinfo_freq freq[1024]; /* all frequencies */
+ uint16_t hopping[64]; /* hopping arfcn */
+ uint8_t hopp_len;
+
+ /* serving cell */
+ uint8_t bsic;
+ uint16_t cell_id;
+ uint16_t mcc, mnc, lac; /* LAI */
+ uint8_t max_retrans; /* decoded */
+ uint8_t tx_integer; /* decoded */
+ uint8_t reest_denied; /* 1 = denied */
+ uint8_t cell_barr; /* 1 = barred */
+ uint16_t class_barr; /* bit 10 is emergency */
+
+ /* si1 rest */
+ uint8_t nch;
+ uint8_t nch_position;
+ uint8_t band_ind; /* set for DCS */
+
+ /* si3 rest */
+ uint8_t sp;
+ uint8_t sp_cbq;
+ uint8_t sp_cro;
+ uint8_t sp_to;
+ uint8_t sp_pt;
+ uint8_t po;
+ uint8_t po_value;
+ uint8_t si2ter_ind;
+ uint8_t ecsm;
+ uint8_t sched;
+ uint8_t sched_where;
+ uint8_t gprs;
+ uint8_t gprs_ra_colour;
+ uint8_t gprs_si13_pos;
+
+ /* cell selection */
+ int8_t ms_txpwr_max_cch;
+ int8_t cell_resel_hyst_db;
+ int8_t rxlev_acc_min_db;
+ uint8_t neci;
+ uint8_t acs;
+ /* bcch options */
+ uint8_t bcch_radio_link_timeout;
+ uint8_t bcch_dtx;
+ uint8_t bcch_pwrc;
+ /* sacch options */
+ uint8_t sacch_radio_link_timeout;
+ uint8_t sacch_dtx;
+ uint8_t sacch_pwrc;
+ /* control channel */
+ uint8_t ccch_conf;
+ uint8_t bs_ag_blks_res;
+ uint8_t att_allowed;
+ uint8_t pag_mf_periods;
+ int32_t t3212; /* real value in seconds */
+ /* channel description */
+ uint8_t tsc;
+ uint8_t h; /* using hopping */
+ uint16_t arfcn;
+ uint8_t maio;
+ uint8_t hsn;
+ uint8_t chan_nr; /* type, slot, sub slot */
+
+ /* neighbor cell */
+ uint8_t nb_ext_ind_si2;
+ uint8_t nb_ba_ind_si2;
+ uint8_t nb_ext_ind_si2bis;
+ uint8_t nb_ba_ind_si2bis;
+ uint8_t nb_multi_rep_si2ter; /* see GSM 05.08 8.4.3 */
+ uint8_t nb_ba_ind_si2ter;
+ uint8_t nb_ext_ind_si5;
+ uint8_t nb_ba_ind_si5;
+ uint8_t nb_ext_ind_si5bis;
+ uint8_t nb_ba_ind_si5bis;
+ uint8_t nb_multi_rep_si5ter;
+ uint8_t nb_ba_ind_si5ter;
+ uint8_t nb_ncc_permitted_si2;
+ uint8_t nb_ncc_permitted_si6;
+ uint8_t nb_max_retrans; /* decoded */
+ uint8_t nb_tx_integer; /* decoded */
+ uint8_t nb_reest_denied; /* 1 = denied */
+ uint8_t nb_cell_barr; /* 1 = barred */
+ uint16_t nb_class_barr; /* bit 10 is emergency */
+};
+
+char *gsm_print_arfcn(uint16_t arfcn);
+uint8_t gsm_refer_pcs(uint16_t arfcn, struct gsm48_sysinfo *s);
+int gsm48_sysinfo_dump(struct gsm48_sysinfo *s, uint16_t arfcn,
+ void (*print)(void *, const char *, ...), void *priv,
+ uint8_t *freq_map);
+int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,
+ uint16_t *mnc, uint16_t *lac);
+int gsm48_decode_chan_h0(struct gsm48_chan_desc *cd, uint8_t *tsc,
+ uint16_t *arfcn);
+int gsm48_decode_chan_h1(struct gsm48_chan_desc *cd, uint8_t *tsc,
+ uint8_t *maio, uint8_t *hsn);
+int gsm48_decode_sysinfo1(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_1 *si, int len);
+int gsm48_decode_sysinfo2(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_2 *si, int len);
+int gsm48_decode_sysinfo2bis(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_2bis *si, int len);
+int gsm48_decode_sysinfo2ter(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_2ter *si, int len);
+int gsm48_decode_sysinfo3(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_3 *si, int len);
+int gsm48_decode_sysinfo4(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_4 *si, int len);
+int gsm48_decode_sysinfo5(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_5 *si, int len);
+int gsm48_decode_sysinfo5bis(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_5bis *si, int len);
+int gsm48_decode_sysinfo5ter(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_5ter *si, int len);
+int gsm48_decode_sysinfo6(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_6 *si, int len);
+int gsm48_decode_mobile_alloc(struct gsm_sysinfo_freq *freq,
+ uint8_t *ma, uint8_t len, uint16_t *hopping, uint8_t *hopp_len,
+ int si4);
+int gsm48_encode_lai_hex(struct gsm48_loc_area_id *lai, uint16_t mcc,
+ uint16_t mnc, uint16_t lac);
+int gsm48_decode_lai_hex(struct gsm48_loc_area_id *lai, uint16_t *mcc,
+ uint16_t *mnc, uint16_t *lac);
+
+#endif /* _SYSINFO_H */
diff --git a/src/host/layer23/include/osmocom/bb/misc/Makefile.am b/src/host/layer23/include/osmocom/bb/misc/Makefile.am
new file mode 100644
index 00000000..71c9d389
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/misc/Makefile.am
@@ -0,0 +1 @@
+noinst_HEADERS = layer3.h rslms.h
diff --git a/src/host/layer23/include/osmocom/bb/misc/cell_log.h b/src/host/layer23/include/osmocom/bb/misc/cell_log.h
new file mode 100644
index 00000000..bce066eb
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/misc/cell_log.h
@@ -0,0 +1,25 @@
+/* Cell Scanning code for OsmocomBB */
+
+/* (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+int scan_init(struct osmocom_ms *_ms);
+int scan_exit(void);
+
diff --git a/src/host/layer23/include/osmocom/bb/misc/layer3.h b/src/host/layer23/include/osmocom/bb/misc/layer3.h
new file mode 100644
index 00000000..bbf242d5
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/misc/layer3.h
@@ -0,0 +1,17 @@
+#ifndef _OSMOCOM_L3_H
+#define _OSMOCOM_L3_H
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/bb/common/osmocom_data.h>
+
+int gsm48_rx_ccch(struct msgb *msg, struct osmocom_ms *ms);
+int gsm48_rx_dcch(struct msgb *msg, struct osmocom_ms *ms);
+int gsm48_rx_bcch(struct msgb *msg, struct osmocom_ms *ms);
+
+/* Initialize layer3 for the MS, hook it to L2 */
+int layer3_init(struct osmocom_ms *ms);
+
+/* Reset the 'aplication' state */
+void layer3_app_reset(void);
+
+#endif
diff --git a/src/host/layer23/include/osmocom/bb/misc/rslms.h b/src/host/layer23/include/osmocom/bb/misc/rslms.h
new file mode 100644
index 00000000..94fe99c8
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/misc/rslms.h
@@ -0,0 +1,23 @@
+#ifndef _OSMOCOM_RSLMS_H
+#define _OSMOCOM_RSLMS_H
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/bb/common/osmocom_data.h>
+
+/* From L3 into RSLMS (direction -> L2) */
+
+/* Send a 'simple' RLL request to L2 */
+int rslms_tx_rll_req(struct osmocom_ms *ms, uint8_t msg_type,
+ uint8_t chan_nr, uint8_t link_id);
+
+/* Send a RLL request (including L3 info) to L2 */
+int rslms_tx_rll_req_l3(struct osmocom_ms *ms, uint8_t msg_type,
+ uint8_t chan_nr, uint8_t link_id, struct msgb *msg);
+
+
+/* From L2 into RSLMS (direction -> L3) */
+
+/* input function that L2 calls when sending messages up to L3 */
+//int rslms_sendmsg(struct msgb *msg, struct osmocom_ms *ms);
+
+#endif /* _OSMOCOM_RSLMS_H */
diff --git a/src/host/layer23/include/osmocom/bb/mobile/Makefile.am b/src/host/layer23/include/osmocom/bb/mobile/Makefile.am
new file mode 100644
index 00000000..b58b9529
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/Makefile.am
@@ -0,0 +1,3 @@
+noinst_HEADERS = gsm322.h gsm480_ss.h gsm411_sms.h gsm48_cc.h gsm48_mm.h \
+ gsm48_rr.h mncc.h settings.h subscriber.h support.h \
+ transaction.h vty.h mncc_sock.h
diff --git a/src/host/layer23/include/osmocom/bb/mobile/app_mobile.h b/src/host/layer23/include/osmocom/bb/mobile/app_mobile.h
new file mode 100644
index 00000000..351dec39
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/app_mobile.h
@@ -0,0 +1,17 @@
+#ifndef APP_MOBILE_H
+#define APP_MOBILE_H
+
+char *config_dir;
+
+int l23_app_init(int (*mncc_recv)(struct osmocom_ms *ms, int, void *),
+ const char *config_file, const char *vty_ip, uint16_t vty_port);
+int l23_app_exit(void);
+int l23_app_work(int *quit);
+int mobile_delete(struct osmocom_ms *ms, int force);
+struct osmocom_ms *mobile_new(char *name);
+int mobile_init(struct osmocom_ms *ms);
+int mobile_exit(struct osmocom_ms *ms, int force);
+int mobile_work(struct osmocom_ms *ms);
+
+#endif
+
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm322.h b/src/host/layer23/include/osmocom/bb/mobile/gsm322.h
new file mode 100644
index 00000000..f39e5668
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm322.h
@@ -0,0 +1,255 @@
+#ifndef _GSM322_H
+#define _GSM322_H
+
+/* 4.3.1.1 List of states for PLMN slection process (automatic mode) */
+#define GSM322_A0_NULL 0
+#define GSM322_A1_TRYING_RPLMN 1
+#define GSM322_A2_ON_PLMN 2
+#define GSM322_A3_TRYING_PLMN 3
+#define GSM322_A4_WAIT_FOR_PLMN 4
+#define GSM322_A5_HPLMN_SEARCH 5
+#define GSM322_A6_NO_SIM 6
+
+/* 4.3.1.2 List of states for PLMN slection process (manual mode) */
+#define GSM322_M0_NULL 0
+#define GSM322_M1_TRYING_RPLMN 1
+#define GSM322_M2_ON_PLMN 2
+#define GSM322_M3_NOT_ON_PLMN 3
+#define GSM322_M4_TRYING_PLMN 4
+#define GSM322_M5_NO_SIM 5
+
+/* 4.3.2 List of states for cell selection process */
+#define GSM322_C0_NULL 0
+#define GSM322_C1_NORMAL_CELL_SEL 1
+#define GSM322_C2_STORED_CELL_SEL 2
+#define GSM322_C3_CAMPED_NORMALLY 3
+#define GSM322_C4_NORMAL_CELL_RESEL 4
+#define GSM322_C5_CHOOSE_CELL 5
+#define GSM322_C6_ANY_CELL_SEL 6
+#define GSM322_C7_CAMPED_ANY_CELL 7
+#define GSM322_C8_ANY_CELL_RESEL 8
+#define GSM322_C9_CHOOSE_ANY_CELL 9
+#define GSM322_CONNECTED_MODE_1 10
+#define GSM322_CONNECTED_MODE_2 11
+#define GSM322_PLMN_SEARCH 12
+#define GSM322_HPLMN_SEARCH 13
+#define GSM322_ANY_SEARCH 14
+
+/* GSM 03.22 events */
+#define GSM322_EVENT_SWITCH_ON 1
+#define GSM322_EVENT_SWITCH_OFF 2
+#define GSM322_EVENT_SIM_INSERT 3
+#define GSM322_EVENT_SIM_REMOVE 4
+#define GSM322_EVENT_REG_SUCCESS 5
+#define GSM322_EVENT_REG_FAILED 6
+#define GSM322_EVENT_ROAMING_NA 7
+#define GSM322_EVENT_INVALID_SIM 8
+#define GSM322_EVENT_NEW_PLMN 9
+#define GSM322_EVENT_ON_PLMN 10
+#define GSM322_EVENT_PLMN_SEARCH_START 11
+#define GSM322_EVENT_PLMN_SEARCH_END 12
+#define GSM322_EVENT_USER_RESEL 13
+#define GSM322_EVENT_PLMN_AVAIL 14
+#define GSM322_EVENT_CHOOSE_PLMN 15
+#define GSM322_EVENT_SEL_MANUAL 16
+#define GSM322_EVENT_SEL_AUTO 17
+#define GSM322_EVENT_CELL_FOUND 18
+#define GSM322_EVENT_NO_CELL_FOUND 19
+#define GSM322_EVENT_LEAVE_IDLE 20
+#define GSM322_EVENT_RET_IDLE 21
+#define GSM322_EVENT_CELL_RESEL 22
+#define GSM322_EVENT_SYSINFO 23
+#define GSM322_EVENT_HPLMN_SEARCH 24
+
+enum {
+ PLMN_MODE_MANUAL,
+ PLMN_MODE_AUTO
+};
+
+/* node for each PLMN */
+struct gsm322_plmn_list {
+ struct llist_head entry;
+ uint16_t mcc, mnc;
+ int8_t rxlev; /* rx level in range format */
+ uint8_t cause; /* cause value, if PLMN is not allowed */
+};
+
+/* node for each forbidden LA */
+struct gsm322_la_list {
+ struct llist_head entry;
+ uint16_t mcc, mnc, lac;
+ uint8_t cause;
+};
+
+/* node for each BA-List */
+struct gsm322_ba_list {
+ struct llist_head entry;
+ uint16_t mcc, mnc;
+ /* Band allocation for 1024+299 frequencies.
+ * First bit of first index is frequency 0.
+ */
+ uint8_t freq[128+38];
+};
+
+#define GSM322_CS_FLAG_SUPPORT 0x01 /* frequency is supported by radio */
+#define GSM322_CS_FLAG_BA 0x02 /* frequency is part of the current ba */
+#define GSM322_CS_FLAG_POWER 0x04 /* frequency was power scanned */
+#define GSM322_CS_FLAG_SIGNAL 0x08 /* valid signal detected */
+#define GSM322_CS_FLAG_SYSINFO 0x10 /* complete sysinfo received */
+#define GSM322_CS_FLAG_BARRED 0x20 /* cell is barred */
+#define GSM322_CS_FLAG_FORBIDD 0x40 /* cell in list of forbidden LAs */
+#define GSM322_CS_FLAG_TEMP_AA 0x80 /* if temporary available and allowable */
+
+/* Cell selection list */
+struct gsm322_cs_list {
+ uint8_t flags; /* see GSM322_CS_FLAG_* */
+ int8_t rxlev; /* rx level range format */
+ struct gsm48_sysinfo *sysinfo;
+};
+
+/* PLMN search process */
+struct gsm322_plmn {
+ struct osmocom_ms *ms;
+ int state; /* GSM322_Ax_* or GSM322_Mx_* */
+
+ struct llist_head event_queue; /* event messages */
+ struct llist_head sorted_plmn; /* list of sorted PLMN */
+ struct llist_head forbidden_la; /* forbidden LAs */
+
+ struct osmo_timer_list timer;
+
+ int plmn_curr; /* current index in sorted_plmn */
+ uint16_t mcc, mnc; /* current network selected */
+};
+
+/* state of CCCH activation */
+#define GSM322_CCCH_ST_IDLE 0 /* no connection */
+#define GSM322_CCCH_ST_INIT 1 /* initalized */
+#define GSM322_CCCH_ST_SYNC 2 /* got sync */
+#define GSM322_CCCH_ST_DATA 3 /* receiveing data */
+
+/* neighbour cell info list entry */
+struct gsm322_neighbour {
+ struct llist_head entry;
+ struct gsm322_cellsel *cs;
+ uint16_t arfcn; /* ARFCN identity of that neighbour */
+
+ uint8_t state; /* GSM322_NB_* */
+ time_t created; /* when was this neighbour created */
+ time_t when; /* when did we sync / read */
+ int16_t rxlev_dbm; /* sum of received levels */
+ uint8_t rxlev_count; /* number of received levels */
+ int8_t rla_c_dbm; /* average of the reveive level */
+ uint8_t c12_valid; /* both C1 and C2 are calculated */
+ int16_t c1, c2, crh;
+ uint8_t checked_for_resel;
+ uint8_t suitable_allowable;
+ uint8_t prio_low;
+};
+
+#define GSM322_NB_NEW 0 /* new NB instance */
+#define GSM322_NB_NOT_SUP 1 /* ARFCN not supported */
+#define GSM322_NB_RLA_C 2 /* valid measurement available */
+#define GSM322_NB_NO_SYNC 3 /* cannot sync to neighbour */
+#define GSM322_NB_NO_BCCH 4 /* sync */
+#define GSM322_NB_SYSINFO 5 /* sysinfo */
+
+struct gsm48_sysinfo;
+/* Cell selection process */
+struct gsm322_cellsel {
+ struct osmocom_ms *ms;
+ int state; /* GSM322_Cx_* */
+
+ struct llist_head event_queue; /* event messages */
+ struct llist_head ba_list; /* BCCH Allocation per PLMN */
+ struct gsm322_cs_list list[1024+299];
+ /* cell selection list per frequency. */
+ /* scan and tune state */
+ struct osmo_timer_list timer; /* cell selection timer */
+ uint16_t mcc, mnc; /* current network to search for */
+ uint8_t powerscan; /* currently scanning for power */
+ uint8_t ccch_state; /* special state of current ccch */
+ uint32_t scan_state; /* special state of current scan */
+ uint16_t arfcn; /* current tuned idle mode arfcn */
+ int arfci; /* list index of frequency above */
+ uint8_t ccch_mode; /* curren CCCH_MODE_* */
+ uint8_t sync_retries; /* number retries to sync */
+ uint8_t sync_pending; /* to prevent double sync req. */
+ struct gsm48_sysinfo *si; /* current sysinfo of tuned cell */
+ uint8_t tuned; /* if a cell is selected */
+ struct osmo_timer_list any_timer; /* restart search 'any cell' */
+
+ /* serving cell */
+ uint8_t selected; /* if a cell is selected */
+ uint16_t sel_arfcn; /* current selected serving cell! */
+ struct gsm48_sysinfo sel_si; /* copy of selected cell, will update */
+ uint16_t sel_mcc, sel_mnc, sel_lac, sel_id;
+
+ /* cell re-selection */
+ struct llist_head nb_list; /* list of neighbour cells */
+ uint16_t last_serving_arfcn; /* the ARFCN of last cell */
+ uint8_t last_serving_valid; /* there is a last cell */
+ struct gsm322_neighbour *neighbour; /* when selecting neighbour cell */
+ time_t resel_when; /* timestamp of last re-selection */
+ int8_t nb_meas_set;
+ int16_t rxlev_dbm; /* sum of received levels */
+ uint8_t rxlev_count; /* number of received levels */
+ int8_t rla_c_dbm; /* average of received level */
+ uint8_t c12_valid; /* both C1 and C2 values are
+ calculated */
+ int16_t c1, c2;
+ uint8_t prio_low;
+};
+
+/* GSM 03.22 message */
+struct gsm322_msg {
+ int msg_type;
+ uint16_t mcc, mnc;
+ uint8_t sysinfo; /* system information type */
+ uint8_t same_cell; /* select same cell when RET_IDLE */
+ uint8_t reject; /* location update reject cause */
+ uint8_t limited; /* trigger search for limited serv. */
+};
+
+#define GSM322_ALLOC_SIZE sizeof(struct gsm322_msg)
+#define GSM322_ALLOC_HEADROOM 0
+
+uint16_t index2arfcn(int index);
+int arfcn2index(uint16_t arfcn);
+int gsm322_init(struct osmocom_ms *ms);
+int gsm322_exit(struct osmocom_ms *ms);
+struct msgb *gsm322_msgb_alloc(int msg_type);
+int gsm322_plmn_sendmsg(struct osmocom_ms *ms, struct msgb *msg);
+int gsm322_cs_sendmsg(struct osmocom_ms *ms, struct msgb *msg);
+int gsm322_c_event(struct osmocom_ms *ms, struct msgb *msg);
+int gsm322_plmn_dequeue(struct osmocom_ms *ms);
+int gsm322_cs_dequeue(struct osmocom_ms *ms);
+int gsm322_add_forbidden_la(struct osmocom_ms *ms, uint16_t mcc,
+ uint16_t mnc, uint16_t lac, uint8_t cause);
+int gsm322_del_forbidden_la(struct osmocom_ms *ms, uint16_t mcc,
+ uint16_t mnc, uint16_t lac);
+int gsm322_is_forbidden_la(struct osmocom_ms *ms, uint16_t mcc, uint16_t mnc,
+ uint16_t lac);
+int gsm322_dump_sorted_plmn(struct osmocom_ms *ms);
+int gsm322_dump_cs_list(struct gsm322_cellsel *cs, uint8_t flags,
+ void (*print)(void *, const char *, ...), void *priv);
+int gsm322_dump_forbidden_la(struct osmocom_ms *ms,
+ void (*print)(void *, const char *, ...), void *priv);
+int gsm322_dump_ba_list(struct gsm322_cellsel *cs, uint16_t mcc, uint16_t mnc,
+ void (*print)(void *, const char *, ...), void *priv);
+int gsm322_dump_nb_list(struct gsm322_cellsel *cs,
+ void (*print)(void *, const char *, ...), void *priv);
+void start_cs_timer(struct gsm322_cellsel *cs, int sec, int micro);
+void start_loss_timer(struct gsm322_cellsel *cs, int sec, int micro);
+const char *get_a_state_name(int value);
+const char *get_m_state_name(int value);
+const char *get_cs_state_name(int value);
+int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data);
+
+int gsm322_meas(struct osmocom_ms *ms, uint8_t rx_lev);
+
+char *gsm_print_rxlev(uint8_t rxlev);
+
+
+#endif /* _GSM322_H */
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm411_sms.h b/src/host/layer23/include/osmocom/bb/mobile/gsm411_sms.h
new file mode 100644
index 00000000..d14e6db8
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm411_sms.h
@@ -0,0 +1,33 @@
+#ifndef _GSM411_SMS_H
+#define _GSM411_SMS_H
+
+#define SMS_HDR_SIZE 128
+#define SMS_TEXT_SIZE 256
+
+struct gsm_sms {
+ unsigned long validity_minutes;
+ uint8_t reply_path_req;
+ uint8_t status_rep_req;
+ uint8_t ud_hdr_ind;
+ uint8_t protocol_id;
+ uint8_t data_coding_scheme;
+ uint8_t msg_ref;
+ char address[20+1]; /* DA LV is 12 bytes max, i.e. 10 bytes
+ * BCD == 20 bytes string */
+ time_t time;
+ uint8_t user_data_len;
+ uint8_t user_data[SMS_TEXT_SIZE];
+
+ char text[SMS_TEXT_SIZE];
+};
+
+int gsm411_sms_init(struct osmocom_ms *ms);
+int gsm411_sms_exit(struct osmocom_ms *ms);
+struct gsm_sms *sms_alloc(void);
+void sms_free(struct gsm_sms *sms);
+struct gsm_sms *sms_from_text(const char *receiver, int dcs, const char *text);
+int gsm411_rcv_sms(struct osmocom_ms *ms, struct msgb *msg);
+int sms_send(struct osmocom_ms *ms, const char *sms_sca, const char *number,
+ const char *text);
+
+#endif /* _GSM411_SMS_H */
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm480_ss.h b/src/host/layer23/include/osmocom/bb/mobile/gsm480_ss.h
new file mode 100644
index 00000000..ecd778e4
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm480_ss.h
@@ -0,0 +1,9 @@
+#ifndef _GSM480_SS_H
+#define _GSM480_SS_H
+
+int gsm480_ss_init(struct osmocom_ms *ms);
+int gsm480_ss_exit(struct osmocom_ms *ms);
+int gsm480_rcv_ss(struct osmocom_ms *ms, struct msgb *msg);
+int ss_send(struct osmocom_ms *ms, const char *code, int new_trans);
+
+#endif /* _GSM480_SS_H */
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h
new file mode 100644
index 00000000..282ffe5b
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h
@@ -0,0 +1,18 @@
+#ifndef _GSM48_CC_H
+#define _GSM48_CC_H
+
+struct gsm48_cclayer {
+ struct osmocom_ms *ms;
+
+ struct llist_head mncc_upqueue;
+};
+
+int gsm48_cc_init(struct osmocom_ms *ms);
+int gsm48_cc_exit(struct osmocom_ms *ms);
+int gsm48_rcv_cc(struct osmocom_ms *ms, struct msgb *msg);
+int mncc_dequeue(struct osmocom_ms *ms);
+int mncc_tx_to_cc(void *inst, int msg_type, void *arg);
+int mncc_clear_trans(void *inst, uint8_t protocol);
+
+#endif /* _GSM48_CC_H */
+
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
new file mode 100644
index 00000000..fb62aae1
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
@@ -0,0 +1,235 @@
+#ifndef _GSM48_MM_H
+#define _GSM48_MM_H
+
+/* GSM 04.07 9.2.2 */
+#define GSM48_MMXX_MASK 0xf00
+#define GSM48_MMCC_CLASS 0x100
+#define GSM48_MMSS_CLASS 0x200
+#define GSM48_MMSMS_CLASS 0x300
+#define GSM48_MMCC_EST_REQ 0x110
+#define GSM48_MMCC_EST_IND 0x112
+#define GSM48_MMCC_EST_CNF 0x111
+#define GSM48_MMCC_REL_REQ 0x120
+#define GSM48_MMCC_REL_IND 0x122
+#define GSM48_MMCC_DATA_REQ 0x130
+#define GSM48_MMCC_DATA_IND 0x132
+#define GSM48_MMCC_UNIT_DATA_REQ 0x140
+#define GSM48_MMCC_UNIT_DATA_IND 0x142
+#define GSM48_MMCC_SYNC_IND 0x152
+#define GSM48_MMCC_REEST_REQ 0x160
+#define GSM48_MMCC_REEST_CNF 0x161
+#define GSM48_MMCC_ERR_IND 0x172
+#define GSM48_MMCC_PROMPT_IND 0x182
+#define GSM48_MMCC_PROMPT_REJ 0x184
+#define GSM48_MMSS_EST_REQ 0x210
+#define GSM48_MMSS_EST_IND 0x212
+#define GSM48_MMSS_EST_CNF 0x211
+#define GSM48_MMSS_REL_REQ 0x220
+#define GSM48_MMSS_REL_IND 0x222
+#define GSM48_MMSS_DATA_REQ 0x230
+#define GSM48_MMSS_DATA_IND 0x232
+#define GSM48_MMSS_UNIT_DATA_REQ 0x240
+#define GSM48_MMSS_UNIT_DATA_IND 0x242
+#define GSM48_MMSS_REEST_REQ 0x260
+#define GSM48_MMSS_REEST_CNF 0x261
+#define GSM48_MMSS_ERR_IND 0x272
+#define GSM48_MMSS_PROMPT_IND 0x282
+#define GSM48_MMSS_PROMPT_REJ 0x284
+#define GSM48_MMSMS_EST_REQ 0x310
+#define GSM48_MMSMS_EST_IND 0x312
+#define GSM48_MMSMS_EST_CNF 0x311
+#define GSM48_MMSMS_REL_REQ 0x320
+#define GSM48_MMSMS_REL_IND 0x322
+#define GSM48_MMSMS_DATA_REQ 0x330
+#define GSM48_MMSMS_DATA_IND 0x332
+#define GSM48_MMSMS_UNIT_DATA_REQ 0x340
+#define GSM48_MMSMS_UNIT_DATA_IND 0x342
+#define GSM48_MMSMS_REEST_REQ 0x360
+#define GSM48_MMSMS_REEST_CNF 0x361
+#define GSM48_MMSMS_ERR_IND 0x372
+#define GSM48_MMSMS_PROMPT_IND 0x382
+#define GSM48_MMSMS_PROMPT_REJ 0x384
+
+#define MMXX_ALLOC_SIZE 256
+#define MMXX_ALLOC_HEADROOM 64
+
+/* MMxx-SAP header */
+struct gsm48_mmxx_hdr {
+ int msg_type; /* MMxx_* primitive */
+ uint32_t ref; /* reference to transaction */
+ uint32_t transaction_id; /* transaction identifier */
+ uint8_t sapi; /* sapi */
+ uint8_t emergency; /* emergency type of call */
+ uint8_t cause; /* cause used for release */
+};
+
+/* GSM 6.1.2 */
+#define GSM48_MMR_REG_REQ 0x01
+#define GSM48_MMR_REG_CNF 0x02
+#define GSM48_MMR_NREG_REQ 0x03
+#define GSM48_MMR_NREG_IND 0x04
+
+/* MMR-SAP header */
+struct gsm48_mmr {
+ int msg_type;
+
+ uint8_t cause;
+};
+
+/* GSM 04.07 9.2.1 */
+#define GSM48_MMXX_ST_IDLE 0
+#define GSM48_MMXX_ST_CONN_PEND 1
+#define GSM48_MMXX_ST_DEDICATED 2
+#define GSM48_MMXX_ST_CONN_SUSP 3
+#define GSM48_MMXX_ST_REESTPEND 4
+
+/* GSM 04.08 4.1.2.1 */
+#define GSM48_MM_ST_NULL 0
+#define GSM48_MM_ST_LOC_UPD_INIT 3
+#define GSM48_MM_ST_WAIT_OUT_MM_CONN 5
+#define GSM48_MM_ST_MM_CONN_ACTIVE 6
+#define GSM48_MM_ST_IMSI_DETACH_INIT 7
+#define GSM48_MM_ST_PROCESS_CM_SERV_P 8
+#define GSM48_MM_ST_WAIT_NETWORK_CMD 9
+#define GSM48_MM_ST_LOC_UPD_REJ 10
+#define GSM48_MM_ST_WAIT_RR_CONN_LUPD 13
+#define GSM48_MM_ST_WAIT_RR_CONN_MM_CON 14
+#define GSM48_MM_ST_WAIT_RR_CONN_IMSI_D 15
+#define GSM48_MM_ST_WAIT_REEST 17
+#define GSM48_MM_ST_WAIT_RR_ACTIVE 18
+#define GSM48_MM_ST_MM_IDLE 19
+#define GSM48_MM_ST_WAIT_ADD_OUT_MM_CON 20
+#define GSM48_MM_ST_MM_CONN_ACTIVE_VGCS 21
+#define GSM48_MM_ST_WAIT_RR_CONN_VGCS 22
+#define GSM48_MM_ST_LOC_UPD_PEND 23
+#define GSM48_MM_ST_IMSI_DETACH_PEND 24
+#define GSM48_MM_ST_RR_CONN_RELEASE_NA 25
+
+/* GSM 04.08 4.1.2.1 */
+#define GSM48_MM_SST_NORMAL_SERVICE 1
+#define GSM48_MM_SST_ATTEMPT_UPDATE 2
+#define GSM48_MM_SST_LIMITED_SERVICE 3
+#define GSM48_MM_SST_NO_IMSI 4
+#define GSM48_MM_SST_NO_CELL_AVAIL 5
+#define GSM48_MM_SST_LOC_UPD_NEEDED 6
+#define GSM48_MM_SST_PLMN_SEARCH 7
+#define GSM48_MM_SST_PLMN_SEARCH_NORMAL 8
+#define GSM48_MM_SST_RX_VGCS_NORMAL 9
+#define GSM48_MM_SST_RX_VGCS_LIMITED 10
+
+/* MM events */
+#define GSM48_MM_EVENT_CELL_SELECTED 1
+#define GSM48_MM_EVENT_NO_CELL_FOUND 2
+#define GSM48_MM_EVENT_TIMEOUT_T3210 3
+#define GSM48_MM_EVENT_TIMEOUT_T3211 4
+#define GSM48_MM_EVENT_TIMEOUT_T3212 5
+#define GSM48_MM_EVENT_TIMEOUT_T3213 6
+#define GSM48_MM_EVENT_TIMEOUT_T3220 7
+#define GSM48_MM_EVENT_TIMEOUT_T3230 8
+#define GSM48_MM_EVENT_TIMEOUT_T3240 9
+#define GSM48_MM_EVENT_IMSI_DETACH 10
+#define GSM48_MM_EVENT_POWER_OFF 11
+#define GSM48_MM_EVENT_PAGING 12
+#define GSM48_MM_EVENT_AUTH_RESPONSE 13
+#define GSM48_MM_EVENT_SYSINFO 14
+#define GSM48_MM_EVENT_USER_PLMN_SEL 15
+#define GSM48_MM_EVENT_LOST_COVERAGE 16
+
+/* message for MM events */
+struct gsm48_mm_event {
+ uint32_t msg_type;
+
+ uint8_t sres[4];
+};
+
+/* GSM 04.08 MM timers */
+#define GSM_T3210_MS 20, 0
+#define GSM_T3211_MS 15, 0
+/* T3212 is given by SYSTEM INFORMATION */
+#define GSM_T3213_MS 4, 0
+#define GSM_T3220_MS 5, 0
+#define GSM_T3230_MS 15, 0
+#define GSM_T3240_MS 10, 0
+#define GSM_T3241_MS 300, 0
+
+/* MM sublayer instance */
+struct gsm48_mmlayer {
+ struct osmocom_ms *ms;
+ int state;
+ int substate;
+
+ /* queue for RR-SAP, MMxx-SAP, MMR-SAP, events message upwards */
+ struct llist_head rr_upqueue;
+ struct llist_head mmxx_upqueue;
+ struct llist_head mmr_downqueue;
+ struct llist_head event_queue;
+
+ /* timers */
+ struct osmo_timer_list t3210, t3211, t3212, t3213;
+ struct osmo_timer_list t3220, t3230, t3240;
+ int t3212_value;
+ int start_t3211; /* remember to start timer */
+
+ /* list of MM connections */
+ struct llist_head mm_conn;
+
+ /* network name */
+ char name_short[32];
+ char name_long[32];
+
+ /* location update */
+ uint8_t lupd_pending; /* current pending loc. upd. */
+ uint8_t lupd_type; /* current coded type */
+ uint8_t lupd_attempt; /* attempt counter */
+ uint8_t lupd_ra_failure;/* random access failed */
+ uint8_t lupd_rej_cause; /* cause of last reject */
+ uint8_t lupd_periodic; /* periodic update pending */
+ uint8_t lupd_retry; /* pending T3211/T3213 to */
+ uint16_t lupd_mcc, lupd_mnc, lupd_lac;
+
+ /* imsi detach */
+ uint8_t delay_detach; /* do detach when possible */
+
+ /* other */
+ uint8_t est_cause; /* cause of establishment msg */
+ int mr_substate; /* rem most recent substate */
+ uint8_t power_off_idle; /* waits for IDLE before po */
+
+ /* sapi 3 */
+ int sapi3_link;
+};
+
+/* MM connection entry */
+struct gsm48_mm_conn {
+ struct llist_head list;
+ struct gsm48_mmlayer *mm;
+
+ /* ref and type form a unique tupple */
+ uint32_t ref; /* reference to trans */
+ uint8_t protocol;
+ uint8_t transaction_id;
+ uint8_t sapi;
+
+ int state;
+};
+
+uint8_t gsm48_current_pwr_lev(struct gsm_settings *set, uint16_t arfcn);
+int gsm48_mm_init(struct osmocom_ms *ms);
+int gsm48_mm_exit(struct osmocom_ms *ms);
+struct msgb *gsm48_mmr_msgb_alloc(int msg_type);
+struct msgb *gsm48_mmevent_msgb_alloc(int msg_type);
+int gsm48_mmevent_msg(struct osmocom_ms *ms, struct msgb *msg);
+int gsm48_mmr_downmsg(struct osmocom_ms *ms, struct msgb *msg);
+int gsm48_rr_dequeue(struct osmocom_ms *ms);
+int gsm48_mmxx_dequeue(struct osmocom_ms *ms);
+int gsm48_mmr_dequeue(struct osmocom_ms *ms);
+int gsm48_mmevent_dequeue(struct osmocom_ms *ms);
+int gsm48_mmxx_downmsg(struct osmocom_ms *ms, struct msgb *msg);
+struct msgb *gsm48_mmxx_msgb_alloc(int msg_type, uint32_t ref,
+ uint8_t transaction_id, uint8_t sapi);
+const char *get_mmr_name(int value);
+const char *get_mmxx_name(int value);
+extern const char *gsm48_mm_state_names[];
+extern const char *gsm48_mm_substate_names[];
+
+#endif /* _GSM48_MM_H */
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h
new file mode 100644
index 00000000..20121695
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h
@@ -0,0 +1,215 @@
+#ifndef _GSM48_RR_H
+#define _GSM48_RR_H
+
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+#define GSM_TA_CM 55385
+
+#define T200_DCCH 1 /* SDCCH/FACCH */
+#define T200_DCCH_SHARED 2 /* SDCCH shares SAPI 0 and 3 */
+#define T200_ACCH 2 /* SACCH SAPI 3 */
+
+
+/* GSM 04.07 9.1.2 */
+#define GSM48_RR_EST_REQ 0x10
+#define GSM48_RR_EST_IND 0x12
+#define GSM48_RR_EST_CNF 0x11
+#define GSM48_RR_REL_IND 0x22
+#define GSM48_RR_SYNC_IND 0x32
+#define GSM48_RR_DATA_REQ 0x40
+#define GSM48_RR_DATA_IND 0x42
+#define GSM48_RR_UNIT_DATA_IND 0x52
+#define GSM48_RR_ABORT_REQ 0x60
+#define GSM48_RR_ABORT_IND 0x62
+#define GSM48_RR_ACT_REQ 0x70
+
+#define RR_EST_CAUSE_EMERGENCY 1
+#define RR_EST_CAUSE_REESTAB_TCH_F 2
+#define RR_EST_CAUSE_REESTAB_TCH_H 3
+#define RR_EST_CAUSE_REESTAB_2_TCH_H 4
+#define RR_EST_CAUSE_ANS_PAG_ANY 5
+#define RR_EST_CAUSE_ANS_PAG_SDCCH 6
+#define RR_EST_CAUSE_ANS_PAG_TCH_F 7
+#define RR_EST_CAUSE_ANS_PAG_TCH_ANY 8
+#define RR_EST_CAUSE_ORIG_TCHF 9
+#define RR_EST_CAUSE_LOC_UPD 12
+#define RR_EST_CAUSE_OTHER_SDCCH 13
+
+#define RR_REL_CAUSE_UNDEFINED 0
+#define RR_REL_CAUSE_NORMAL 1
+#define RR_REL_CAUSE_NOT_AUTHORIZED 2
+#define RR_REL_CAUSE_RA_FAILURE 3
+#define RR_REL_CAUSE_T3122 4
+#define RR_REL_CAUSE_TRY_LATER 5
+#define RR_REL_CAUSE_EMERGENCY_ONLY 6
+#define RR_REL_CAUSE_LOST_SIGNAL 7
+#define RR_REL_CAUSE_LINK_FAILURE 8
+
+#define RR_SYNC_CAUSE_CIPHERING 1
+
+#define L3_ALLOC_SIZE 256
+#define L3_ALLOC_HEADROOM 64
+
+#define RSL_ALLOC_SIZE 256
+#define RSL_ALLOC_HEADROOM 64
+
+#define RR_ALLOC_SIZE 256
+#define RR_ALLOC_HEADROOM 64
+
+/* GSM 04.08 RR-SAP header */
+struct gsm48_rr_hdr {
+ uint32_t msg_type; /* RR-* primitive */
+ uint8_t sapi;
+ uint8_t cause;
+};
+
+/* GSM 04.07 9.1.1 */
+#define GSM48_RR_ST_IDLE 0
+#define GSM48_RR_ST_CONN_PEND 1
+#define GSM48_RR_ST_DEDICATED 2
+#define GSM48_RR_ST_REL_PEND 3
+
+/* special states for SAPI 3 link */
+#define GSM48_RR_SAPI3ST_IDLE 0
+#define GSM48_RR_SAPI3ST_WAIT_EST 1
+#define GSM48_RR_SAPI3ST_ESTAB 2
+#define GSM48_RR_SAPI3ST_WAIT_REL 3
+
+/* modify state */
+#define GSM48_RR_MOD_NONE 0
+#define GSM48_RR_MOD_IMM_ASS 1
+#define GSM48_RR_MOD_ASSIGN 2
+#define GSM48_RR_MOD_HANDO 3
+#define GSM48_RR_MOD_ASSIGN_RESUME 4
+#define GSM48_RR_MOD_HANDO_RESUME 5
+
+/* channel description */
+struct gsm48_rr_cd {
+ uint8_t tsc;
+ uint8_t h; /* using hopping */
+ uint16_t arfcn; /* dedicated mode */
+ uint8_t maio;
+ uint8_t hsn;
+ uint8_t chan_nr; /* type, slot, sub slot */
+ uint8_t ind_tx_power; /* last indicated power */
+ uint8_t ind_ta; /* last indicated ta */
+ uint8_t mob_alloc_lv[9]; /* len + up to 64 bits */
+ uint8_t freq_list_lv[131]; /* len + 130 octets */
+ uint8_t freq_seq_lv[10]; /* len + 9 octets */
+ uint8_t cell_desc_lv[17]; /* len + 16 octets */
+ uint8_t start; /* start time available */
+ struct gsm_time start_tm; /* start time */
+ uint8_t mode; /* mode of channel */
+ uint8_t cipher; /* ciphering of channel */
+};
+
+struct gsm48_cr_hist {
+ uint8_t valid;
+ struct gsm48_req_ref ref;
+};
+
+/* neighbor cell measurements */
+struct gsm48_rr_meas {
+ /* note: must be sorted by arfcn 1..1023,0 according to SI5* */
+ uint8_t nc_num; /* number of measured cells (32 max) */
+ int8_t nc_rxlev[32]; /* -128 = no value */
+ uint8_t nc_bsic[32];
+ uint16_t nc_arfcn[32];
+};
+
+/* RR sublayer instance */
+struct gsm48_rrlayer {
+ struct osmocom_ms *ms;
+ int state;
+
+ /* queue for RSL-SAP message upwards */
+ struct llist_head rsl_upqueue;
+
+ /* queue for messages while RR connection is built up */
+ struct llist_head downqueue;
+
+ /* timers */
+ struct osmo_timer_list t_starting; /* starting time for chan. access */
+ struct osmo_timer_list t_rel_wait; /* wait for L2 to transmit UA */
+ struct osmo_timer_list t3110;
+ struct osmo_timer_list t3122;
+ struct osmo_timer_list t3124;
+ struct osmo_timer_list t3126;
+ int t3126_value;
+#ifndef TODO
+ struct osmo_timer_list temp_rach_ti; /* temporary timer */
+#endif
+
+ /* states if RR-EST-REQ was used */
+ uint8_t rr_est_req;
+ struct msgb *rr_est_msg;
+ uint8_t est_cause; /* cause used for establishment */
+ uint8_t paging_mi_type; /* how did we got paged? */
+
+ /* channel request states */
+ uint8_t wait_assign; /* waiting for assignment state */
+ uint8_t n_chan_req; /* number left, incl. current */
+ uint8_t chan_req_val; /* current request value */
+ uint8_t chan_req_mask; /* mask of random bits */
+
+ /* state of dedicated mdoe */
+ uint8_t dm_est;
+
+ /* cr_hist */
+ uint8_t cr_ra; /* stores requested ra until confirmed */
+ struct gsm48_cr_hist cr_hist[3];
+
+ /* V(SD) sequence numbers */
+ uint16_t v_sd; /* 16 PD 1-bit sequence numbers packed */
+
+ /* current channel descriptions */
+ struct gsm48_rr_cd cd_now;
+
+ /* current cipering */
+ uint8_t cipher_on;
+ uint8_t cipher_type; /* 10.5.2.9 */
+
+ /* special states when assigning channel */
+ uint8_t modify_state;
+ uint8_t hando_sync_ind, hando_rot, hando_nci, hando_act;
+ struct gsm48_rr_cd cd_last; /* store last cd in case of failure */
+ struct gsm48_rr_cd cd_before; /* before start time */
+ struct gsm48_rr_cd cd_after; /* after start time */
+
+ /* BA range */
+ uint8_t ba_ranges;
+ uint32_t ba_range[16];
+
+ /* measurements */
+ struct osmo_timer_list t_meas;
+ struct gsm48_rr_meas meas;
+ uint8_t monitor;
+
+ /* audio flow */
+ uint8_t audio_mode;
+
+ /* sapi 3 */
+ uint8_t sapi3_state;
+ uint8_t sapi3_link_id;
+};
+
+const char *get_rr_name(int value);
+extern int gsm48_rr_init(struct osmocom_ms *ms);
+extern int gsm48_rr_exit(struct osmocom_ms *ms);
+int gsm48_rsl_dequeue(struct osmocom_ms *ms);
+int gsm48_rr_downmsg(struct osmocom_ms *ms, struct msgb *msg);
+struct msgb *gsm48_l3_msgb_alloc(void);
+struct msgb *gsm48_rr_msgb_alloc(int msg_type);
+int gsm48_rr_enc_cm2(struct osmocom_ms *ms, struct gsm48_classmark2 *cm,
+ uint16_t arfcn);
+int gsm48_rr_tx_rand_acc(struct osmocom_ms *ms, struct msgb *msg);
+int gsm48_rr_los(struct osmocom_ms *ms);
+int gsm48_rr_rach_conf(struct osmocom_ms *ms, uint32_t fn);
+extern const char *gsm48_rr_state_names[];
+int gsm48_rr_start_monitor(struct osmocom_ms *ms);
+int gsm48_rr_stop_monitor(struct osmocom_ms *ms);
+int gsm48_rr_alter_delay(struct osmocom_ms *ms);
+int gsm48_rr_tx_voice(struct osmocom_ms *ms, struct msgb *msg);
+int gsm48_rr_audio_mode(struct osmocom_ms *ms, uint8_t mode);
+
+#endif /* _GSM48_RR_H */
diff --git a/src/host/layer23/include/osmocom/bb/mobile/mncc.h b/src/host/layer23/include/osmocom/bb/mobile/mncc.h
new file mode 100644
index 00000000..cad1883c
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/mncc.h
@@ -0,0 +1,179 @@
+/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
+ * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
+
+/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _MNCC_H
+#define _MNCC_H
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/mncc.h>
+
+struct gsm_call {
+ struct llist_head entry;
+
+ struct osmocom_ms *ms;
+
+ uint32_t callref;
+
+ uint8_t init; /* call initiated, no response yet */
+ uint8_t hold; /* call on hold */
+ uint8_t ring; /* call ringing/knocking */
+
+ struct osmo_timer_list dtmf_timer;
+ uint8_t dtmf_state;
+ uint8_t dtmf_index;
+ char dtmf[32]; /* dtmf sequence */
+};
+
+#define DTMF_ST_IDLE 0 /* no DTMF active */
+#define DTMF_ST_START 1 /* DTMF started, waiting for resp. */
+#define DTMF_ST_MARK 2 /* wait tone duration */
+#define DTMF_ST_STOP 3 /* DTMF stopped, waiting for resp. */
+#define DTMF_ST_SPACE 4 /* wait space between tones */
+
+#define MNCC_SETUP_REQ 0x0101
+#define MNCC_SETUP_IND 0x0102
+#define MNCC_SETUP_RSP 0x0103
+#define MNCC_SETUP_CNF 0x0104
+#define MNCC_SETUP_COMPL_REQ 0x0105
+#define MNCC_SETUP_COMPL_IND 0x0106
+/* MNCC_REJ_* is perfomed via MNCC_REL_* */
+#define MNCC_CALL_CONF_IND 0x0107
+#define MNCC_CALL_PROC_REQ 0x0108
+#define MNCC_PROGRESS_REQ 0x0109
+#define MNCC_ALERT_REQ 0x010a
+#define MNCC_ALERT_IND 0x010b
+#define MNCC_NOTIFY_REQ 0x010c
+#define MNCC_NOTIFY_IND 0x010d
+#define MNCC_DISC_REQ 0x010e
+#define MNCC_DISC_IND 0x010f
+#define MNCC_REL_REQ 0x0110
+#define MNCC_REL_IND 0x0111
+#define MNCC_REL_CNF 0x0112
+#define MNCC_FACILITY_REQ 0x0113
+#define MNCC_FACILITY_IND 0x0114
+#define MNCC_START_DTMF_IND 0x0115
+#define MNCC_START_DTMF_RSP 0x0116
+#define MNCC_START_DTMF_REJ 0x0117
+#define MNCC_STOP_DTMF_IND 0x0118
+#define MNCC_STOP_DTMF_RSP 0x0119
+#define MNCC_MODIFY_REQ 0x011a
+#define MNCC_MODIFY_IND 0x011b
+#define MNCC_MODIFY_RSP 0x011c
+#define MNCC_MODIFY_CNF 0x011d
+#define MNCC_MODIFY_REJ 0x011e
+#define MNCC_HOLD_IND 0x011f
+#define MNCC_HOLD_CNF 0x0120
+#define MNCC_HOLD_REJ 0x0121
+#define MNCC_RETRIEVE_IND 0x0122
+#define MNCC_RETRIEVE_CNF 0x0123
+#define MNCC_RETRIEVE_REJ 0x0124
+#define MNCC_USERINFO_REQ 0x0125
+#define MNCC_USERINFO_IND 0x0126
+#define MNCC_REJ_REQ 0x0127
+#define MNCC_REJ_IND 0x0128
+#define MNCC_PROGRESS_IND 0x0129
+#define MNCC_CALL_PROC_IND 0x012a
+#define MNCC_CALL_CONF_REQ 0x012b
+#define MNCC_START_DTMF_REQ 0x012c
+#define MNCC_STOP_DTMF_REQ 0x012d
+#define MNCC_HOLD_REQ 0x012e
+#define MNCC_RETRIEVE_REQ 0x012f
+
+#define MNCC_BRIDGE 0x0200
+#define MNCC_FRAME_RECV 0x0201
+#define MNCC_FRAME_DROP 0x0202
+#define MNCC_LCHAN_MODIFY 0x0203
+
+#define GSM_TCHF_FRAME 0x0300
+#define GSM_TCHF_FRAME_EFR 0x0301
+
+#define GSM_MAX_FACILITY 128
+#define GSM_MAX_SSVERSION 128
+#define GSM_MAX_USERUSER 128
+
+#define MNCC_F_BEARER_CAP 0x0001
+#define MNCC_F_CALLED 0x0002
+#define MNCC_F_CALLING 0x0004
+#define MNCC_F_REDIRECTING 0x0008
+#define MNCC_F_CONNECTED 0x0010
+#define MNCC_F_CAUSE 0x0020
+#define MNCC_F_USERUSER 0x0040
+#define MNCC_F_PROGRESS 0x0080
+#define MNCC_F_EMERGENCY 0x0100
+#define MNCC_F_FACILITY 0x0200
+#define MNCC_F_SSVERSION 0x0400
+#define MNCC_F_CCCAP 0x0800
+#define MNCC_F_KEYPAD 0x1000
+#define MNCC_F_SIGNAL 0x2000
+
+struct gsm_mncc {
+ /* context based information */
+ uint32_t msg_type;
+ uint32_t callref;
+
+ /* which fields are present */
+ uint32_t fields;
+
+ /* data derived informations (MNCC_F_ based) */
+ struct gsm_mncc_bearer_cap bearer_cap;
+ struct gsm_mncc_number called;
+ struct gsm_mncc_number calling;
+ struct gsm_mncc_number redirecting;
+ struct gsm_mncc_number connected;
+ struct gsm_mncc_cause cause;
+ struct gsm_mncc_progress progress;
+ struct gsm_mncc_useruser useruser;
+ struct gsm_mncc_facility facility;
+ struct gsm_mncc_cccap cccap;
+ struct gsm_mncc_ssversion ssversion;
+ struct {
+ int sup;
+ int inv;
+ } clir;
+ int signal;
+
+ /* data derived information, not MNCC_F based */
+ int keypad;
+ int more;
+ int notify; /* 0..127 */
+ int emergency;
+ char imsi[16];
+
+ unsigned char lchan_type;
+ unsigned char lchan_mode;
+};
+
+struct gsm_data_frame {
+ uint32_t msg_type;
+ uint32_t callref;
+ unsigned char data[0];
+};
+
+const char *get_mncc_name(int value);
+int mncc_recv(struct osmocom_ms *ms, int msg_type, void *arg);
+void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
+
+#endif
+
diff --git a/src/host/layer23/include/osmocom/bb/mobile/mncc_sock.h b/src/host/layer23/include/osmocom/bb/mobile/mncc_sock.h
new file mode 100644
index 00000000..b38c5bc6
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/mncc_sock.h
@@ -0,0 +1,16 @@
+#ifndef _MNCC_SOCK_H
+#define _MNCC_SOCK_H
+
+struct mncc_sock_state {
+ void *inst;
+ struct osmo_fd listen_bfd; /* fd for listen socket */
+ struct osmo_fd conn_bfd; /* fd for connection to lcr */
+ struct llist_head upqueue;
+};
+
+int mncc_sock_from_cc(struct mncc_sock_state *state, struct msgb *msg);
+void mncc_sock_write_pending(struct mncc_sock_state *state);
+struct mncc_sock_state *mncc_sock_init(void *inst, const char *name, void *tall_ctx);
+void mncc_sock_exit(struct mncc_sock_state *state);
+
+#endif /* _MNCC_SOCK_H */
diff --git a/src/host/layer23/include/osmocom/bb/mobile/settings.h b/src/host/layer23/include/osmocom/bb/mobile/settings.h
new file mode 100644
index 00000000..6d446967
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/settings.h
@@ -0,0 +1,124 @@
+#ifndef _settings_h
+#define _settings_h
+
+/* type of test SIM key */
+enum {
+ GSM_SIM_KEY_XOR = 0,
+ GSM_SIM_KEY_COMP128
+};
+
+struct gsm_settings {
+ char layer2_socket_path[128];
+ char sap_socket_path[128];
+
+ /* IMEI */
+ char imei[16];
+ char imeisv[17];
+ char imei_random;
+
+ /* network search */
+ int plmn_mode; /* PLMN_MODE_* */
+
+ /* SIM */
+ int sim_type; /* selects card on power on */
+ char emergency_imsi[16];
+
+ /* SMS */
+ char sms_sca[22];
+
+ /* test card simulator settings */
+ char test_imsi[16];
+ uint32_t test_tmsi;
+ uint8_t test_ki_type;
+ uint8_t test_ki[16]; /* 128 bit max */
+ uint8_t test_barr;
+ uint8_t test_rplmn_valid;
+ uint16_t test_rplmn_mcc, test_rplmn_mnc;
+ uint16_t test_lac;
+ uint8_t test_always; /* ...search hplmn... */
+
+ /* call related settings */
+ uint8_t cw; /* set if call-waiting is allowed */
+ uint8_t auto_answer;
+ uint8_t clip, clir;
+ uint8_t half, half_prefer;
+
+ /* changing default behavior */
+ uint8_t alter_tx_power;
+ uint8_t alter_tx_power_value;
+ int8_t alter_delay;
+ uint8_t stick;
+ uint16_t stick_arfcn;
+ uint8_t skip_max_per_band;
+ uint8_t no_lupd;
+ uint8_t no_neighbour;
+
+ /* supported by configuration */
+ uint8_t cc_dtmf;
+ uint8_t sms_ptp;
+ uint8_t a5_1;
+ uint8_t a5_2;
+ uint8_t a5_3;
+ uint8_t a5_4;
+ uint8_t a5_5;
+ uint8_t a5_6;
+ uint8_t a5_7;
+ uint8_t p_gsm;
+ uint8_t e_gsm;
+ uint8_t r_gsm;
+ uint8_t dcs;
+ uint8_t gsm_850;
+ uint8_t pcs;
+ uint8_t gsm_480;
+ uint8_t gsm_450;
+ uint8_t class_900;
+ uint8_t class_dcs;
+ uint8_t class_850;
+ uint8_t class_pcs;
+ uint8_t class_400;
+ uint8_t freq_map[128+38];
+ uint8_t full_v1;
+ uint8_t full_v2;
+ uint8_t full_v3;
+ uint8_t half_v1;
+ uint8_t half_v3;
+ uint8_t ch_cap; /* channel capability */
+ int8_t min_rxlev_db; /* min DB to access */
+
+ /* radio */
+ uint16_t dsc_max;
+ uint8_t force_rekey;
+
+ /* dialing */
+ struct llist_head abbrev;
+
+ /* EDGE / UMTS / CDMA */
+ uint8_t edge_ms_sup;
+ uint8_t edge_psk_sup;
+ uint8_t edge_psk_uplink;
+ uint8_t class_900_edge;
+ uint8_t class_dcs_pcs_edge;
+ uint8_t umts_fdd;
+ uint8_t umts_tdd;
+ uint8_t cdma_2000;
+ uint8_t dtm;
+ uint8_t class_dtm;
+ uint8_t dtm_mac;
+ uint8_t dtm_egprs;
+};
+
+struct gsm_settings_abbrev {
+ struct llist_head list;
+ char abbrev[4];
+ char number[32];
+ char name[32];
+};
+
+int gsm_settings_arfcn(struct osmocom_ms *ms);
+int gsm_settings_init(struct osmocom_ms *ms);
+int gsm_settings_exit(struct osmocom_ms *ms);
+char *gsm_check_imei(const char *imei, const char *sv);
+int gsm_random_imei(struct gsm_settings *set);
+
+#endif /* _settings_h */
+
diff --git a/src/host/layer23/include/osmocom/bb/mobile/subscriber.h b/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
new file mode 100644
index 00000000..3e50e29d
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
@@ -0,0 +1,111 @@
+#ifndef _SUBSCRIBER_H
+#define _SUBSCRIBER_H
+
+/* GSM 04.08 4.1.2.2 SIM update status */
+#define GSM_SIM_U0_NULL 0
+#define GSM_SIM_U1_UPDATED 1
+#define GSM_SIM_U2_NOT_UPDATED 2
+#define GSM_SIM_U3_ROAMING_NA 3
+
+struct gsm_sub_plmn_list {
+ struct llist_head entry;
+ uint16_t mcc, mnc;
+};
+
+struct gsm_sub_plmn_na {
+ struct llist_head entry;
+ uint16_t mcc, mnc;
+ uint8_t cause;
+};
+
+#define GSM_IMSI_LENGTH 16
+
+enum {
+ GSM_SIM_TYPE_NONE = 0,
+ GSM_SIM_TYPE_READER,
+ GSM_SIM_TYPE_TEST
+};
+
+struct gsm_subscriber {
+ struct osmocom_ms *ms;
+
+ /* status */
+ uint8_t sim_type; /* type of sim */
+ uint8_t sim_valid; /* sim inserted and valid */
+ uint8_t ustate; /* update status */
+ uint8_t imsi_attached; /* attached state */
+
+ /* IMSI & co */
+ char imsi[GSM_IMSI_LENGTH];
+ char msisdn[31]; /* may include access codes */
+ char iccid[21]; /* 20 + termination */
+
+ /* TMSI / LAI */
+ uint32_t tmsi; /* invalid tmsi: 0xffffffff */
+ uint16_t mcc, mnc, lac; /* invalid lac: 0x0000 */
+
+
+ /* key */
+ uint8_t key_seq; /* ciphering key sequence number */
+ uint8_t key[8]; /* 64 bit */
+
+ /* other */
+ struct llist_head plmn_list; /* PLMN Selector field */
+ struct llist_head plmn_na; /* not allowed PLMNs */
+ uint8_t t6m_hplmn; /* timer for hplmn search */
+
+ /* special things */
+ uint8_t always_search_hplmn;
+ /* search hplmn in other countries also (for test cards) */
+ uint8_t any_timeout;
+ /* timer to restart 'any cell selection' */
+ char sim_name[31]; /* name to load/save sim */
+ char sim_spn[17]; /* name of service privider */
+
+ /* PLMN last registered */
+ uint8_t plmn_valid;
+ uint16_t plmn_mcc, plmn_mnc;
+
+ /* our access */
+ uint8_t acc_barr; /* if we may access, if cell barred */
+ uint16_t acc_class; /* bitmask of what we may access */
+
+ /* talk to SIM */
+ uint8_t sim_state;
+ uint8_t sim_pin_required; /* state: wait for PIN */
+ uint8_t sim_file_index;
+ uint32_t sim_handle_query;
+ uint32_t sim_handle_update;
+ uint32_t sim_handle_key;
+
+ /* SMS */
+ char sms_sca[22];
+};
+
+int gsm_subscr_init(struct osmocom_ms *ms);
+int gsm_subscr_exit(struct osmocom_ms *ms);
+int gsm_subscr_testcard(struct osmocom_ms *ms, uint16_t mcc, uint16_t mnc,
+ uint16_t lac, uint32_t tmsi);
+int gsm_subscr_simcard(struct osmocom_ms *ms);
+void gsm_subscr_sim_pin(struct osmocom_ms *ms, char *pin1, char *pin2,
+ int8_t mode);
+int gsm_subscr_write_loci(struct osmocom_ms *ms);
+int gsm_subscr_generate_kc(struct osmocom_ms *ms, uint8_t key_seq,
+ uint8_t *rand, uint8_t no_sim);
+int gsm_subscr_remove(struct osmocom_ms *ms);
+void new_sim_ustate(struct gsm_subscriber *subscr, int state);
+int gsm_subscr_del_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
+ uint16_t mnc);
+int gsm_subscr_add_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
+ uint16_t mnc, uint8_t cause);
+int gsm_subscr_is_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
+ uint16_t mnc);
+int gsm_subscr_dump_forbidden_plmn(struct osmocom_ms *ms,
+ void (*print)(void *, const char *, ...), void *priv);
+void gsm_subscr_dump(struct gsm_subscriber *subscr,
+ void (*print)(void *, const char *, ...), void *priv);
+char *gsm_check_imsi(const char *imsi);
+int gsm_subscr_get_key_seq(struct osmocom_ms *ms, struct gsm_subscriber *subscr);
+
+#endif /* _SUBSCRIBER_H */
+
diff --git a/src/host/layer23/include/osmocom/bb/mobile/support.h b/src/host/layer23/include/osmocom/bb/mobile/support.h
new file mode 100644
index 00000000..035e10a3
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/support.h
@@ -0,0 +1,122 @@
+#ifndef _SUPPORT_H
+#define _SUPPORT_H
+
+#define GSM_CIPHER_A5_1 0
+#define GSM_CIPHER_A5_2 1
+#define GSM_CIPHER_A5_3 2
+#define GSM_CIPHER_A5_4 3
+#define GSM_CIPHER_A5_5 4
+#define GSM_CIPHER_A5_6 5
+#define GSM_CIPHER_A5_7 6
+#define GSM_CIPHER_RESERVED 7
+
+#define GSM_CAP_SDCCH 0
+#define GSM_CAP_SDCCH_TCHF 1
+#define GSM_CAP_SDCCH_TCHF_TCHH 2
+
+struct gsm_support {
+ struct osmocom_ms *ms;
+
+ /* controlled early classmark sending */
+ uint8_t es_ind;
+ /* revision level */
+ uint8_t rev_lev;
+ /* support of VGCS */
+ uint8_t vgcs;
+ /* support of VBS */
+ uint8_t vbs;
+ /* support of SMS */
+ uint8_t sms_ptp;
+ /* screening indicator */
+ uint8_t ss_ind;
+ /* pseudo synchronised capability */
+ uint8_t ps_cap;
+ /* CM service prompt */
+ uint8_t cmsp;
+ /* solsa support */
+ uint8_t solsa;
+ /* location service support */
+ uint8_t lcsva;
+ /* codec supprot */
+ uint8_t a5_1;
+ uint8_t a5_2;
+ uint8_t a5_3;
+ uint8_t a5_4;
+ uint8_t a5_5;
+ uint8_t a5_6;
+ uint8_t a5_7;
+ /* radio support */
+ uint8_t p_gsm;
+ uint8_t e_gsm;
+ uint8_t r_gsm;
+ uint8_t dcs;
+ uint8_t gsm_850;
+ uint8_t pcs;
+ uint8_t gsm_480;
+ uint8_t gsm_450;
+ uint8_t class_900;
+ uint8_t class_dcs;
+ uint8_t class_850;
+ uint8_t class_pcs;
+ uint8_t class_400;
+ /* multi slot support */
+ uint8_t ms_sup;
+ /* ucs2 treatment */
+ uint8_t ucs2_treat;
+ /* support extended measurements */
+ uint8_t ext_meas;
+ /* support switched measurement capability */
+ uint8_t meas_cap;
+ uint8_t sms_val;
+ uint8_t sm_val;
+ /* positioning method capability */
+ uint8_t loc_serv;
+ uint8_t e_otd_ass;
+ uint8_t e_otd_based;
+ uint8_t gps_ass;
+ uint8_t gps_based;
+ uint8_t gps_conv;
+
+ /* radio */
+ uint8_t ch_cap; /* channel capability */
+ int8_t min_rxlev_db;
+ uint8_t scan_to;
+ uint8_t sync_to;
+ uint16_t dsc_max; /* maximum dl signal failure counter */
+
+ /* codecs */
+ uint8_t full_v1;
+ uint8_t full_v2;
+ uint8_t full_v3;
+ uint8_t half_v1;
+ uint8_t half_v3;
+
+ /* EDGE / UMTS / CDMA */
+ uint8_t edge_ms_sup;
+ uint8_t edge_psk_sup;
+ uint8_t edge_psk_uplink;
+ uint8_t class_900_edge;
+ uint8_t class_dcs_pcs_edge;
+ uint8_t umts_fdd;
+ uint8_t umts_tdd;
+ uint8_t cdma_2000;
+ uint8_t dtm;
+ uint8_t class_dtm;
+ uint8_t dtm_mac;
+ uint8_t dtm_egprs;
+};
+
+struct gsm_support_scan_max {
+ uint16_t start;
+ uint16_t end;
+ uint16_t max;
+ uint16_t temp;
+};
+extern struct gsm_support_scan_max gsm_sup_smax[];
+
+void gsm_support_init(struct osmocom_ms *ms);
+void gsm_support_dump(struct osmocom_ms *ms,
+ void (*print)(void *, const char *, ...), void *priv);
+
+#endif /* _SUPPORT_H */
+
diff --git a/src/host/layer23/include/osmocom/bb/mobile/transaction.h b/src/host/layer23/include/osmocom/bb/mobile/transaction.h
new file mode 100644
index 00000000..8c06d5d9
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/transaction.h
@@ -0,0 +1,76 @@
+#ifndef _TRANSACT_H
+#define _TRANSACT_H
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/gsm0411_smc.h>
+#include <osmocom/gsm/gsm0411_smr.h>
+
+/* One transaction */
+struct gsm_trans {
+ /* Entry in list of all transactions */
+ struct llist_head entry;
+
+ /* The protocol within which we live */
+ uint8_t protocol;
+
+ /* The current transaction ID */
+ uint8_t transaction_id;
+
+ /* To whom we belong */
+ struct osmocom_ms *ms;
+
+ /* reference from MNCC or other application */
+ uint32_t callref;
+
+ /* if traffic channel receive was requested */
+ int tch_recv;
+
+ union {
+ struct {
+
+ /* current call state */
+ int state;
+
+ /* most recent progress indicator */
+ uint8_t prog_ind;
+
+ /* current timer and message queue */
+ int Tcurrent; /* current CC timer */
+ int T308_second; /* used to send release again */
+ struct osmo_timer_list timer;
+ struct gsm_mncc msg; /* stores setup/disconnect/release message */
+ } cc;
+ struct {
+ /* current supp.serv. state */
+ int state;
+
+ uint8_t invoke_id;
+ struct msgb *msg;
+ } ss;
+ struct {
+ uint8_t sapi; /* SAPI to be used for this trans */
+
+ struct gsm411_smc_inst smc_inst;
+ struct gsm411_smr_inst smr_inst;
+
+ struct gsm_sms *sms;
+ } sms;
+ };
+};
+
+
+
+struct gsm_trans *trans_find_by_id(struct osmocom_ms *ms,
+ uint8_t proto, uint8_t trans_id);
+struct gsm_trans *trans_find_by_callref(struct osmocom_ms *ms,
+ uint32_t callref);
+
+struct gsm_trans *trans_alloc(struct osmocom_ms *ms,
+ uint8_t protocol, uint8_t trans_id,
+ uint32_t callref);
+void trans_free(struct gsm_trans *trans);
+
+int trans_assign_trans_id(struct osmocom_ms *ms,
+ uint8_t protocol, uint8_t ti_flag);
+
+#endif
diff --git a/src/host/layer23/include/osmocom/bb/mobile/voice.h b/src/host/layer23/include/osmocom/bb/mobile/voice.h
new file mode 100644
index 00000000..a0524183
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/voice.h
@@ -0,0 +1,7 @@
+#ifndef _voice_h
+#define _voice_h
+
+int gsm_voice_init(struct osmocom_ms *ms);
+int gsm_send_voice(struct osmocom_ms *ms, struct gsm_data_frame *data);
+
+#endif /* _voice_h */
diff --git a/src/host/layer23/include/osmocom/bb/mobile/vty.h b/src/host/layer23/include/osmocom/bb/mobile/vty.h
new file mode 100644
index 00000000..1f1341bc
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/vty.h
@@ -0,0 +1,20 @@
+#ifndef OSMOCOM_VTY_H
+#define OSMOCOM_VTY_H
+
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/command.h>
+
+enum ms_vty_node {
+ MS_NODE = _LAST_OSMOVTY_NODE + 1,
+ TESTSIM_NODE,
+ SUPPORT_NODE,
+};
+
+enum node_type ms_vty_go_parent(struct vty *vty);
+int ms_vty_init(void);
+extern void vty_notify(struct osmocom_ms *ms, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
+#endif
+
diff --git a/src/host/layer23/src/Makefile.am b/src/host/layer23/src/Makefile.am
new file mode 100644
index 00000000..58a5f7fb
--- /dev/null
+++ b/src/host/layer23/src/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = common misc mobile
diff --git a/src/host/layer23/src/common/Makefile.am b/src/host/layer23/src/common/Makefile.am
new file mode 100644
index 00000000..8d96ed2c
--- /dev/null
+++ b/src/host/layer23/src/common/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBGPS_CFLAGS)
+
+noinst_LIBRARIES = liblayer23.a
+liblayer23_a_SOURCES = l1ctl.c l1l2_interface.c sap_interface.c \
+ logging.c networks.c sim.c sysinfo.c gps.c l1ctl_lapdm_glue.c
diff --git a/src/host/layer23/src/common/gps.c b/src/host/layer23/src/common/gps.c
new file mode 100644
index 00000000..e9aaa97c
--- /dev/null
+++ b/src/host/layer23/src/common/gps.c
@@ -0,0 +1,402 @@
+/*
+ * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <sys/file.h>
+#include <termios.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <stdbool.h>
+
+#ifdef _HAVE_GPSD
+#include <gps.h>
+#endif
+
+#include <osmocom/core/utils.h>
+
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/gps.h>
+
+struct osmo_gps g = {
+ 0,
+ GPS_TYPE_UNDEF,
+#ifdef _HAVE_GPSD
+ "localhost",
+ "2947",
+#endif
+ "/dev/ttyACM0",
+ 0,
+ 0,
+ 0,
+ 0,0
+};
+
+static struct osmo_fd gps_bfd;
+
+#ifdef _HAVE_GPSD
+
+static struct gps_data_t* gdata = NULL;
+
+#if GPSD_API_MAJOR_VERSION >= 5
+static struct gps_data_t _gdata;
+#define gps_poll gps_read
+#endif
+
+int osmo_gpsd_cb(struct osmo_fd *bfd, unsigned int what)
+{
+ struct tm *tm;
+ unsigned diff = 0;
+
+ g.valid = 0;
+
+ /* gps is offline */
+ if (gdata->online)
+ goto gps_not_ready;
+
+#if GPSD_API_MAJOR_VERSION >= 5
+ /* gps has no data */
+ if (gps_waiting(gdata, 500))
+ goto gps_not_ready;
+#else
+ /* gps has no data */
+ if (gps_waiting(gdata))
+ goto gps_not_ready;
+#endif
+
+ /* polling returned an error */
+ if (gps_poll(gdata))
+ goto gps_not_ready;
+
+ /* data are valid */
+ if (gdata->set & LATLON_SET) {
+ g.valid = 1;
+ g.gmt = gdata->fix.time;
+ tm = localtime(&g.gmt);
+ diff = time(NULL) - g.gmt;
+ g.latitude = gdata->fix.latitude;
+ g.longitude = gdata->fix.longitude;
+
+ LOGP(DGPS, LOGL_INFO, " time=%02d:%02d:%02d %04d-%02d-%02d, "
+ "diff-to-host=%d, latitude=%do%.4f, longitude=%do%.4f\n",
+ tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_year + 1900,
+ tm->tm_mday, tm->tm_mon + 1, diff,
+ (int)g.latitude,
+ (g.latitude - ((int)g.latitude)) * 60.0,
+ (int)g.longitude,
+ (g.longitude - ((int)g.longitude)) * 60.0);
+ }
+
+ return 0;
+
+gps_not_ready:
+ LOGP(DGPS, LOGL_DEBUG, "gps is offline");
+ return -1;
+}
+
+int osmo_gpsd_open(void)
+{
+ LOGP(DGPS, LOGL_INFO, "Connecting to gpsd at '%s:%s'\n", g.gpsd_host, g.gpsd_port);
+
+ gps_bfd.data = NULL;
+ gps_bfd.when = BSC_FD_READ;
+ gps_bfd.cb = osmo_gpsd_cb;
+
+#if GPSD_API_MAJOR_VERSION >= 5
+ if (gps_open(g.gpsd_host, g.gpsd_port, &_gdata) == -1)
+ gdata = NULL;
+ else
+ gdata = &_gdata;
+#else
+ gdata = gps_open(g.gpsd_host, g.gpsd_port);
+#endif
+ if (gdata == NULL) {
+ LOGP(DGPS, LOGL_ERROR, "Can't connect to gpsd\n");
+ return -1;
+ }
+ gps_bfd.fd = gdata->gps_fd;
+ if (gps_bfd.fd < 0)
+ return gps_bfd.fd;
+
+ if (gps_stream(gdata, WATCH_ENABLE, NULL) == -1) {
+ LOGP(DGPS, LOGL_ERROR, "Error in gps_stream()\n");
+ return -1;
+ }
+
+ osmo_fd_register(&gps_bfd);
+
+ return 0;
+}
+
+void osmo_gpsd_close(void)
+{
+ if (gps_bfd.fd <= 0)
+ return;
+
+ LOGP(DGPS, LOGL_INFO, "Disconnecting from gpsd\n");
+
+ osmo_fd_unregister(&gps_bfd);
+
+#if GPSD_API_MAJOR_VERSION >= 5
+ gps_stream(gdata, WATCH_DISABLE, NULL);
+#endif
+ gps_close(gdata);
+ gps_bfd.fd = -1; /* -1 or 0 indicates: 'close' */
+}
+
+#endif
+
+static struct termios gps_termios, gps_old_termios;
+
+static int osmo_serialgps_line(char *line)
+{
+ time_t gps_now, host_now;
+ struct tm *tm;
+ int32_t diff;
+ double latitude, longitude;
+
+ if (!!strncmp(line, "$GPGLL", 6))
+ return 0;
+ line += 7;
+ if (strlen(line) < 37)
+ return 0;
+ line[37] = '\0';
+ /* ddmm.mmmm,N,dddmm.mmmm,E,hhmmss.mmm,A */
+
+ /* valid position */
+ if (line[36] != 'A') {
+ LOGP(DGPS, LOGL_INFO, "%s (invalid)\n", line);
+ g.valid = 0;
+ return 0;
+ }
+ g.valid = 1;
+
+ /* time stamp */
+ gps_now = line[30] - '0';
+ gps_now += (line[29] - '0') * 10;
+ gps_now += (line[28] - '0') * 60;
+ gps_now += (line[27] - '0') * 600;
+ gps_now += (line[26] - '0') * 3600;
+ gps_now += (line[25] - '0') * 36000;
+ time(&host_now);
+ /* calculate the number of seconds the host differs from GPS */
+ diff = host_now % 86400 - gps_now;
+ if (diff < 0)
+ diff += 86400;
+ if (diff >= 43200)
+ diff -= 86400;
+ /* apply the "date" part to the GPS time */
+ gps_now = host_now - diff;
+ g.gmt = gps_now;
+ tm = localtime(&gps_now);
+
+ /* position */
+ latitude = (double)(line[0] - '0') * 10.0;
+ latitude += (double)(line[1] - '0');
+ latitude += (double)(line[2] - '0') / 6.0;
+ latitude += (double)(line[3] - '0') / 60.0;
+ latitude += (double)(line[5] - '0') / 600.0;
+ latitude += (double)(line[6] - '0') / 6000.0;
+ latitude += (double)(line[7] - '0') / 60000.0;
+ latitude += (double)(line[8] - '0') / 600000.0;
+ if (line[10] == 'S')
+ latitude = 0.0 - latitude;
+ g.latitude = latitude;
+ longitude = (double)(line[12] - '0') * 100.0;
+ longitude += (double)(line[13] - '0') * 10.0;
+ longitude += (double)(line[14] - '0');
+ longitude += (double)(line[15] - '0') / 6.0;
+ longitude += (double)(line[16] - '0') / 60.0;
+ longitude += (double)(line[18] - '0') / 600.0;
+ longitude += (double)(line[19] - '0') / 6000.0;
+ longitude += (double)(line[20] - '0') / 60000.0;
+ longitude += (double)(line[21] - '0') / 600000.0;
+ if (line[23] == 'W')
+ longitude = 360.0 - longitude;
+ g.longitude = longitude;
+
+ LOGP(DGPS, LOGL_DEBUG, "%s\n", line);
+ LOGP(DGPS, LOGL_INFO, " time=%02d:%02d:%02d %04d-%02d-%02d, "
+ "diff-to-host=%d, latitude=%do%.4f, longitude=%do%.4f\n",
+ tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_year + 1900,
+ tm->tm_mday, tm->tm_mon + 1, diff,
+ (int)g.latitude,
+ (g.latitude - ((int)g.latitude)) * 60.0,
+ (int)g.longitude,
+ (g.longitude - ((int)g.longitude)) * 60.0);
+ return 0;
+}
+
+static int nmea_checksum(char *line)
+{
+ uint8_t checksum = 0;
+
+ while (*line) {
+ if (*line == '$') {
+ line++;
+ continue;
+ }
+ if (*line == '*')
+ break;
+ checksum ^= *line++;
+ }
+ return (strtoul(line+1, NULL, 16) == checksum);
+}
+
+int osmo_serialgps_cb(struct osmo_fd *bfd, unsigned int what)
+{
+ char buff[128];
+ static char line[128];
+ static int lpos = 0;
+ int i = 0, len;
+
+ len = read(bfd->fd, buff, sizeof(buff));
+ if (len <= 0) {
+ fprintf(stderr, "error reading GPS device (errno=%d)\n", errno);
+ return len;
+ }
+ while(i < len) {
+ if (buff[i] == 13) {
+ i++;
+ continue;
+ }
+ if (buff[i] == 10) {
+ line[lpos] = '\0';
+ lpos = 0;
+ i++;
+ if (!nmea_checksum(line))
+ fprintf(stderr, "NMEA checksum error\n");
+ else
+ osmo_serialgps_line(line);
+ continue;
+ }
+ line[lpos++] = buff[i++];
+ if (lpos == sizeof(line))
+ lpos--;
+ }
+
+ return 0;
+}
+
+int osmo_serialgps_open(void)
+{
+ int baud = 0;
+
+ if (gps_bfd.fd > 0)
+ return 0;
+
+ LOGP(DGPS, LOGL_INFO, "Open GPS device '%s'\n", g.device);
+
+ gps_bfd.data = NULL;
+ gps_bfd.when = BSC_FD_READ;
+ gps_bfd.cb = osmo_serialgps_cb;
+ gps_bfd.fd = open(g.device, O_RDONLY);
+ if (gps_bfd.fd < 0)
+ return gps_bfd.fd;
+
+ switch (g.baud) {
+ case 4800:
+ baud = B4800; break;
+ case 9600:
+ baud = B9600; break;
+ case 19200:
+ baud = B19200; break;
+ case 38400:
+ baud = B38400; break;
+ case 57600:
+ baud = B57600; break;
+ case 115200:
+ baud = B115200; break;
+ }
+
+ if (isatty(gps_bfd.fd))
+ {
+ /* get termios */
+ tcgetattr(gps_bfd.fd, &gps_old_termios);
+ tcgetattr(gps_bfd.fd, &gps_termios);
+ /* set baud */
+ if (baud) {
+ gps_termios.c_cflag |= baud;
+ cfsetispeed(&gps_termios, baud);
+ cfsetospeed(&gps_termios, baud);
+ }
+ if (tcsetattr(gps_bfd.fd, TCSANOW, &gps_termios))
+ printf("Failed to set termios for GPS\n");
+ }
+
+ osmo_fd_register(&gps_bfd);
+
+ return 0;
+}
+
+void osmo_serialgps_close(void)
+{
+ if (gps_bfd.fd <= 0)
+ return;
+
+ LOGP(DGPS, LOGL_INFO, "Close GPS device\n");
+
+ osmo_fd_unregister(&gps_bfd);
+
+ if (isatty(gps_bfd.fd))
+ tcsetattr(gps_bfd.fd, TCSANOW, &gps_old_termios);
+
+ close(gps_bfd.fd);
+ gps_bfd.fd = -1; /* -1 or 0 indicates: 'close' */
+}
+
+void osmo_gps_init(void)
+{
+ memset(&gps_bfd, 0, sizeof(gps_bfd));
+}
+
+int osmo_gps_open(void)
+{
+ switch (g.gps_type) {
+#ifdef _HAVE_GPSD
+ case GPS_TYPE_GPSD:
+ return osmo_gpsd_open();
+#endif
+ case GPS_TYPE_SERIAL:
+ return osmo_serialgps_open();
+
+ default:
+ return 0;
+ }
+}
+
+void osmo_gps_close(void)
+{
+ switch (g.gps_type) {
+#ifdef _HAVE_GPSD
+ case GPS_TYPE_GPSD:
+ return osmo_gpsd_close();
+#endif
+ case GPS_TYPE_SERIAL:
+ return osmo_serialgps_close();
+
+ default:
+ return;
+ }
+}
+
diff --git a/src/host/layer23/src/common/l1ctl.c b/src/host/layer23/src/common/l1ctl.c
new file mode 100644
index 00000000..521949c1
--- /dev/null
+++ b/src/host/layer23/src/common/l1ctl.c
@@ -0,0 +1,967 @@
+/* Layer1 control code, talking L1CTL protocol with L1 on the phone */
+
+/* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <arpa/inet.h>
+
+#include <l1ctl_proto.h>
+
+#include <osmocom/core/signal.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/core/gsmtap_util.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/protocol/gsm_08_58.h>
+#include <osmocom/gsm/rsl.h>
+
+#include <osmocom/bb/common/l1ctl.h>
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/l1l2_interface.h>
+#include <osmocom/gsm/lapdm.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/codec/codec.h>
+
+extern struct gsmtap_inst *gsmtap_inst;
+
+static struct msgb *osmo_l1_alloc(uint8_t msg_type)
+{
+ struct l1ctl_hdr *l1h;
+ struct msgb *msg = msgb_alloc_headroom(256, 4, "osmo_l1");
+
+ if (!msg) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to allocate memory.\n");
+ return NULL;
+ }
+
+ msg->l1h = msgb_put(msg, sizeof(*l1h));
+ l1h = (struct l1ctl_hdr *) msg->l1h;
+ l1h->msg_type = msg_type;
+
+ return msg;
+}
+
+
+static inline int msb_get_bit(uint8_t *buf, int bn)
+{
+ int pos_byte = bn >> 3;
+ int pos_bit = 7 - (bn & 7);
+
+ return (buf[pos_byte] >> pos_bit) & 1;
+}
+
+static inline void msb_set_bit(uint8_t *buf, int bn, int bit)
+{
+ int pos_byte = bn >> 3;
+ int pos_bit = 7 - (bn & 7);
+
+ buf[pos_byte] |= (bit << pos_bit);
+}
+
+
+static int osmo_make_band_arfcn(struct osmocom_ms *ms, uint16_t arfcn)
+{
+ /* TODO: Include the band */
+ return arfcn;
+}
+
+static int rx_l1_fbsb_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct l1ctl_info_dl *dl;
+ struct l1ctl_fbsb_conf *sb;
+ struct gsm_time tm;
+ struct osmobb_fbsb_res fr;
+
+ if (msgb_l3len(msg) < sizeof(*dl) + sizeof(*sb)) {
+ LOGP(DL1C, LOGL_ERROR, "FBSB RESP: MSG too short %u\n",
+ msgb_l3len(msg));
+ return -1;
+ }
+
+ dl = (struct l1ctl_info_dl *) msg->l1h;
+ sb = (struct l1ctl_fbsb_conf *) dl->payload;
+
+ LOGP(DL1C, LOGL_INFO, "snr=%04x, arfcn=%u result=%u\n", dl->snr,
+ ntohs(dl->band_arfcn), sb->result);
+
+ if (sb->result != 0) {
+ LOGP(DL1C, LOGL_ERROR, "FBSB RESP: result=%u\n", sb->result);
+ fr.ms = ms;
+ fr.band_arfcn = ntohs(dl->band_arfcn);
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_FBSB_ERR, &fr);
+ return 0;
+ }
+
+ gsm_fn2gsmtime(&tm, ntohl(dl->frame_nr));
+ DEBUGP(DL1C, "SCH: SNR: %u TDMA: (%.4u/%.2u/%.2u) bsic: %d\n",
+ dl->snr, tm.t1, tm.t2, tm.t3, sb->bsic);
+ fr.ms = ms;
+ fr.snr = dl->snr;
+ fr.bsic = sb->bsic;
+ fr.band_arfcn = ntohs(dl->band_arfcn);
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_FBSB_RESP, &fr);
+
+ return 0;
+}
+
+static int rx_l1_rach_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct lapdm_entity *le = &ms->lapdm_channel.lapdm_dcch;
+ struct osmo_phsap_prim pp;
+ struct l1ctl_info_dl *dl;
+
+ if (msgb_l2len(msg) < sizeof(*dl)) {
+ LOGP(DL1C, LOGL_ERROR, "RACH CONF: MSG too short %u\n",
+ msgb_l3len(msg));
+ msgb_free(msg);
+ return -1;
+ }
+
+ dl = (struct l1ctl_info_dl *) msg->l1h;
+
+ osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_RACH,
+ PRIM_OP_CONFIRM, msg);
+ pp.u.rach_ind.fn = ntohl(dl->frame_nr);
+
+ return lapdm_phsap_up(&pp.oph, le);
+}
+
+/* Receive L1CTL_DATA_IND (Data Indication from L1) */
+static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct osmo_phsap_prim pp;
+ struct l1ctl_info_dl *dl;
+ struct l1ctl_data_ind *ccch;
+ struct lapdm_entity *le;
+ struct rx_meas_stat *meas = &ms->meas;
+ uint8_t chan_type, chan_ts, chan_ss;
+ uint8_t gsmtap_chan_type;
+ struct gsm_time tm;
+
+ if (msgb_l3len(msg) < sizeof(*ccch)) {
+ LOGP(DL1C, LOGL_ERROR, "MSG too short Data Ind: %u\n",
+ msgb_l3len(msg));
+ msgb_free(msg);
+ return -1;
+ }
+
+ dl = (struct l1ctl_info_dl *) msg->l1h;
+ msg->l2h = dl->payload;
+ ccch = (struct l1ctl_data_ind *) msg->l2h;
+
+ gsm_fn2gsmtime(&tm, ntohl(dl->frame_nr));
+ rsl_dec_chan_nr(dl->chan_nr, &chan_type, &chan_ss, &chan_ts);
+ DEBUGP(DL1C, "%s (%.4u/%.2u/%.2u) %d dBm: %s\n",
+ rsl_chan_nr_str(dl->chan_nr), tm.t1, tm.t2, tm.t3,
+ (int)dl->rx_level-110,
+ osmo_hexdump(ccch->data, sizeof(ccch->data)));
+
+ meas->last_fn = ntohl(dl->frame_nr);
+ meas->frames++;
+ meas->snr += dl->snr;
+ meas->berr += dl->num_biterr;
+ meas->rxlev += dl->rx_level;
+
+ /* counting loss criteria */
+ if (!(dl->link_id & 0x40)) {
+ switch (chan_type) {
+ case RSL_CHAN_PCH_AGCH:
+ if (!meas->ds_fail)
+ break;
+ if (dl->fire_crc >= 2)
+ meas->dsc -= 4;
+ else
+ meas->dsc += 1;
+ if (meas->dsc > meas->ds_fail)
+ meas->dsc = meas->ds_fail;
+ if (meas->dsc < meas->ds_fail)
+ printf("LOSS counter for CCCH %d\n", meas->dsc);
+ if (meas->dsc > 0)
+ break;
+ meas->ds_fail = 0;
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_LOSS_IND, ms);
+ break;
+ }
+ } else {
+ switch (chan_type) {
+ case RSL_CHAN_Bm_ACCHs:
+ case RSL_CHAN_Lm_ACCHs:
+ case RSL_CHAN_SDCCH4_ACCH:
+ case RSL_CHAN_SDCCH8_ACCH:
+ if (!meas->rl_fail)
+ break;
+ if (dl->fire_crc >= 2)
+ meas->s -= 1;
+ else
+ meas->s += 2;
+ if (meas->s > meas->rl_fail)
+ meas->s = meas->rl_fail;
+ if (meas->s < meas->rl_fail)
+ printf("LOSS counter for ACCH %d\n", meas->s);
+ if (meas->s > 0)
+ break;
+ meas->rl_fail = 0;
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_LOSS_IND, ms);
+ break;
+ }
+ }
+
+ if (dl->fire_crc >= 2) {
+printf("Dropping frame with %u bit errors\n", dl->num_biterr);
+ LOGP(DL1C, LOGL_NOTICE, "Dropping frame with %u bit errors\n",
+ dl->num_biterr);
+ msgb_free(msg);
+ return 0;
+ }
+
+ /* send CCCH data via GSMTAP */
+ gsmtap_chan_type = chantype_rsl2gsmtap(chan_type, dl->link_id);
+ gsmtap_send(gsmtap_inst, ntohs(dl->band_arfcn), chan_ts,
+ gsmtap_chan_type, chan_ss, tm.fn, dl->rx_level-110,
+ dl->snr, ccch->data, sizeof(ccch->data));
+
+ /* determine LAPDm entity based on SACCH or not */
+ if (dl->link_id & 0x40)
+ le = &ms->lapdm_channel.lapdm_acch;
+ else
+ le = &ms->lapdm_channel.lapdm_dcch;
+
+ /* pull the L1 header from the msgb */
+ msgb_pull(msg, msg->l2h - (msg->l1h-sizeof(struct l1ctl_hdr)));
+ msg->l1h = NULL;
+
+ osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA,
+ PRIM_OP_INDICATION, msg);
+ pp.u.data.chan_nr = dl->chan_nr;
+ pp.u.data.link_id = dl->link_id;
+
+ /* send it up into LAPDm */
+ return lapdm_phsap_up(&pp.oph, le);
+}
+
+/* Receive L1CTL_DATA_CONF (Data Confirm from L1) */
+static int rx_ph_data_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct osmo_phsap_prim pp;
+ struct l1ctl_info_dl *dl = (struct l1ctl_info_dl *) msg->l1h;
+ struct lapdm_entity *le;
+
+ osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_RTS,
+ PRIM_OP_INDICATION, msg);
+
+ /* determine LAPDm entity based on SACCH or not */
+ if (dl->link_id & 0x40)
+ le = &ms->lapdm_channel.lapdm_acch;
+ else
+ le = &ms->lapdm_channel.lapdm_dcch;
+
+ /* send it up into LAPDm */
+ return lapdm_phsap_up(&pp.oph, le);
+}
+
+/* Transmit L1CTL_DATA_REQ */
+int l1ctl_tx_data_req(struct osmocom_ms *ms, struct msgb *msg,
+ uint8_t chan_nr, uint8_t link_id)
+{
+ struct l1ctl_hdr *l1h;
+ struct l1ctl_info_ul *l1i_ul;
+ uint8_t chan_type, chan_ts, chan_ss;
+ uint8_t gsmtap_chan_type;
+
+ DEBUGP(DL1C, "(%s)\n", osmo_hexdump(msg->l2h, msgb_l2len(msg)));
+
+ if (msgb_l2len(msg) > 23) {
+ LOGP(DL1C, LOGL_ERROR, "L1 cannot handle message length "
+ "> 23 (%u)\n", msgb_l2len(msg));
+ msgb_free(msg);
+ return -EINVAL;
+ } else if (msgb_l2len(msg) < 23)
+ LOGP(DL1C, LOGL_ERROR, "L1 message length < 23 (%u) "
+ "doesn't seem right!\n", msgb_l2len(msg));
+
+ /* send copy via GSMTAP */
+ rsl_dec_chan_nr(chan_nr, &chan_type, &chan_ss, &chan_ts);
+ gsmtap_chan_type = chantype_rsl2gsmtap(chan_type, link_id);
+ gsmtap_send(gsmtap_inst, 0|0x4000, chan_ts, gsmtap_chan_type,
+ chan_ss, 0, 127, 255, msg->l2h, msgb_l2len(msg));
+
+ /* prepend uplink info header */
+ l1i_ul = (struct l1ctl_info_ul *) msgb_push(msg, sizeof(*l1i_ul));
+
+ l1i_ul->chan_nr = chan_nr;
+ l1i_ul->link_id = link_id;
+
+ /* prepend l1 header */
+ msg->l1h = msgb_push(msg, sizeof(*l1h));
+ l1h = (struct l1ctl_hdr *) msg->l1h;
+ l1h->msg_type = L1CTL_DATA_REQ;
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit FBSB_REQ */
+int l1ctl_tx_fbsb_req(struct osmocom_ms *ms, uint16_t arfcn,
+ uint8_t flags, uint16_t timeout, uint8_t sync_info_idx,
+ uint8_t ccch_mode)
+{
+ struct msgb *msg;
+ struct l1ctl_fbsb_req *req;
+
+ LOGP(DL1C, LOGL_INFO, "Sync Req\n");
+
+ msg = osmo_l1_alloc(L1CTL_FBSB_REQ);
+ if (!msg)
+ return -1;
+
+ req = (struct l1ctl_fbsb_req *) msgb_put(msg, sizeof(*req));
+ req->band_arfcn = htons(osmo_make_band_arfcn(ms, arfcn));
+ req->timeout = htons(timeout);
+ /* Threshold when to consider FB_MODE1: 4kHz - 1kHz */
+ req->freq_err_thresh1 = htons(11000 - 1000);
+ /* Threshold when to consider SCH: 1kHz - 200Hz */
+ req->freq_err_thresh2 = htons(1000 - 200);
+ /* not used yet! */
+ req->num_freqerr_avg = 3;
+ req->flags = flags;
+ req->sync_info_idx = sync_info_idx;
+ req->ccch_mode = ccch_mode;
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_CCCH_MODE_REQ */
+int l1ctl_tx_ccch_mode_req(struct osmocom_ms *ms, uint8_t ccch_mode)
+{
+ struct msgb *msg;
+ struct l1ctl_ccch_mode_req *req;
+
+ LOGP(DL1C, LOGL_INFO, "CCCH Mode Req\n");
+
+ msg = osmo_l1_alloc(L1CTL_CCCH_MODE_REQ);
+ if (!msg)
+ return -1;
+
+ req = (struct l1ctl_ccch_mode_req *) msgb_put(msg, sizeof(*req));
+ req->ccch_mode = ccch_mode;
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_TCH_MODE_REQ */
+int l1ctl_tx_tch_mode_req(struct osmocom_ms *ms, uint8_t tch_mode,
+ uint8_t audio_mode)
+{
+ struct msgb *msg;
+ struct l1ctl_tch_mode_req *req;
+
+ LOGP(DL1C, LOGL_INFO, "TCH Mode Req\n");
+
+ msg = osmo_l1_alloc(L1CTL_TCH_MODE_REQ);
+ if (!msg)
+ return -1;
+
+ req = (struct l1ctl_tch_mode_req *) msgb_put(msg, sizeof(*req));
+ req->tch_mode = tch_mode;
+ req->audio_mode = audio_mode;
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_PARAM_REQ */
+int l1ctl_tx_param_req(struct osmocom_ms *ms, uint8_t ta, uint8_t tx_power)
+{
+ struct msgb *msg;
+ struct l1ctl_info_ul *ul;
+ struct l1ctl_par_req *req;
+
+ msg = osmo_l1_alloc(L1CTL_PARAM_REQ);
+ if (!msg)
+ return -1;
+
+ DEBUGP(DL1C, "PARAM Req. ta=%d, tx_power=%d\n", ta, tx_power);
+ ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
+ req = (struct l1ctl_par_req *) msgb_put(msg, sizeof(*req));
+ req->tx_power = tx_power;
+ req->ta = ta;
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_CRYPTO_REQ */
+int l1ctl_tx_crypto_req(struct osmocom_ms *ms, uint8_t algo, uint8_t *key,
+ uint8_t len)
+{
+ struct msgb *msg;
+ struct l1ctl_info_ul *ul;
+ struct l1ctl_crypto_req *req;
+
+ msg = osmo_l1_alloc(L1CTL_CRYPTO_REQ);
+ if (!msg)
+ return -1;
+
+ DEBUGP(DL1C, "CRYPTO Req. algo=%d, len=%d\n", algo, len);
+ ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
+ req = (struct l1ctl_crypto_req *) msgb_put(msg, sizeof(*req) + len);
+ req->algo = algo;
+ if (len)
+ memcpy(req->key, key, len);
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_RACH_REQ */
+int l1ctl_tx_rach_req(struct osmocom_ms *ms, uint8_t ra, uint16_t offset,
+ uint8_t combined)
+{
+ struct msgb *msg;
+ struct l1ctl_info_ul *ul;
+ struct l1ctl_rach_req *req;
+
+ msg = osmo_l1_alloc(L1CTL_RACH_REQ);
+ if (!msg)
+ return -1;
+
+ DEBUGP(DL1C, "RACH Req. offset=%d combined=%d\n", offset, combined);
+ ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
+ req = (struct l1ctl_rach_req *) msgb_put(msg, sizeof(*req));
+ req->ra = ra;
+ req->offset = htons(offset);
+ req->combined = combined;
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_DM_EST_REQ */
+int l1ctl_tx_dm_est_req_h0(struct osmocom_ms *ms, uint16_t band_arfcn,
+ uint8_t chan_nr, uint8_t tsc, uint8_t tch_mode,
+ uint8_t audio_mode)
+{
+ struct msgb *msg;
+ struct l1ctl_info_ul *ul;
+ struct l1ctl_dm_est_req *req;
+
+ msg = osmo_l1_alloc(L1CTL_DM_EST_REQ);
+ if (!msg)
+ return -1;
+
+ LOGP(DL1C, LOGL_INFO, "Tx Dedic.Mode Est Req (arfcn=%u, "
+ "chan_nr=0x%02x)\n", band_arfcn, chan_nr);
+
+ ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
+ ul->chan_nr = chan_nr;
+ ul->link_id = 0;
+
+ req = (struct l1ctl_dm_est_req *) msgb_put(msg, sizeof(*req));
+ req->tsc = tsc;
+ req->h = 0;
+ req->h0.band_arfcn = htons(band_arfcn);
+ req->tch_mode = tch_mode;
+ req->audio_mode = audio_mode;
+
+ return osmo_send_l1(ms, msg);
+}
+
+int l1ctl_tx_dm_est_req_h1(struct osmocom_ms *ms, uint8_t maio, uint8_t hsn,
+ uint16_t *ma, uint8_t ma_len,
+ uint8_t chan_nr, uint8_t tsc, uint8_t tch_mode,
+ uint8_t audio_mode)
+{
+ struct msgb *msg;
+ struct l1ctl_info_ul *ul;
+ struct l1ctl_dm_est_req *req;
+ int i;
+
+ msg = osmo_l1_alloc(L1CTL_DM_EST_REQ);
+ if (!msg)
+ return -1;
+
+ LOGP(DL1C, LOGL_INFO, "Tx Dedic.Mode Est Req (maio=%u, hsn=%u, "
+ "chan_nr=0x%02x)\n", maio, hsn, chan_nr);
+
+ ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
+ ul->chan_nr = chan_nr;
+ ul->link_id = 0;
+
+ req = (struct l1ctl_dm_est_req *) msgb_put(msg, sizeof(*req));
+ req->tsc = tsc;
+ req->h = 1;
+ req->h1.maio = maio;
+ req->h1.hsn = hsn;
+ req->h1.n = ma_len;
+ for (i = 0; i < ma_len; i++)
+ req->h1.ma[i] = htons(ma[i]);
+ req->tch_mode = tch_mode;
+ req->audio_mode = audio_mode;
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_DM_FREQ_REQ */
+int l1ctl_tx_dm_freq_req_h0(struct osmocom_ms *ms, uint16_t band_arfcn,
+ uint8_t tsc, uint16_t fn)
+{
+ struct msgb *msg;
+ struct l1ctl_info_ul *ul;
+ struct l1ctl_dm_freq_req *req;
+
+ msg = osmo_l1_alloc(L1CTL_DM_FREQ_REQ);
+ if (!msg)
+ return -1;
+
+ LOGP(DL1C, LOGL_INFO, "Tx Dedic.Mode Freq Req (arfcn=%u, fn=%d)\n",
+ band_arfcn, fn);
+
+ ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
+ ul->chan_nr = 0;
+ ul->link_id = 0;
+
+ req = (struct l1ctl_dm_freq_req *) msgb_put(msg, sizeof(*req));
+ req->fn = htons(fn);
+ req->tsc = tsc;
+ req->h = 0;
+ req->h0.band_arfcn = htons(band_arfcn);
+
+ return osmo_send_l1(ms, msg);
+}
+
+int l1ctl_tx_dm_freq_req_h1(struct osmocom_ms *ms, uint8_t maio, uint8_t hsn,
+ uint16_t *ma, uint8_t ma_len,
+ uint8_t tsc, uint16_t fn)
+{
+ struct msgb *msg;
+ struct l1ctl_info_ul *ul;
+ struct l1ctl_dm_freq_req *req;
+ int i;
+
+ msg = osmo_l1_alloc(L1CTL_DM_FREQ_REQ);
+ if (!msg)
+ return -1;
+
+ LOGP(DL1C, LOGL_INFO, "Tx Dedic.Mode Freq Req (maio=%u, hsn=%u, "
+ "fn=%d)\n", maio, hsn, fn);
+
+ ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
+ ul->chan_nr = 0;
+ ul->link_id = 0;
+
+ req = (struct l1ctl_dm_freq_req *) msgb_put(msg, sizeof(*req));
+ req->fn = htons(fn);
+ req->tsc = tsc;
+ req->h = 1;
+ req->h1.maio = maio;
+ req->h1.hsn = hsn;
+ req->h1.n = ma_len;
+ for (i = 0; i < ma_len; i++)
+ req->h1.ma[i] = htons(ma[i]);
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_DM_REL_REQ */
+int l1ctl_tx_dm_rel_req(struct osmocom_ms *ms)
+{
+ struct msgb *msg;
+ struct l1ctl_info_ul *ul;
+
+ msg = osmo_l1_alloc(L1CTL_DM_REL_REQ);
+ if (!msg)
+ return -1;
+
+ LOGP(DL1C, LOGL_INFO, "Tx Dedic.Mode Rel Req\n");
+
+ ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
+
+ return osmo_send_l1(ms, msg);
+}
+
+int l1ctl_tx_echo_req(struct osmocom_ms *ms, unsigned int len)
+{
+ struct msgb *msg;
+ uint8_t *data;
+ unsigned int i;
+
+ msg = osmo_l1_alloc(L1CTL_ECHO_REQ);
+ if (!msg)
+ return -1;
+
+ data = msgb_put(msg, len);
+ for (i = 0; i < len; i++)
+ data[i] = i % 8;
+
+ return osmo_send_l1(ms, msg);
+}
+
+int l1ctl_tx_sim_req(struct osmocom_ms *ms, uint8_t *data, uint16_t length)
+{
+ struct msgb *msg;
+ uint8_t *dat;
+
+ msg = osmo_l1_alloc(L1CTL_SIM_REQ);
+ if (!msg)
+ return -1;
+
+ dat = msgb_put(msg, length);
+ memcpy(dat, data, length);
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* just forward the SIM response to the SIM handler */
+static int rx_l1_sim_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+ uint16_t len = msg->len - sizeof(struct l1ctl_hdr);
+ uint8_t *data = msg->data + sizeof(struct l1ctl_hdr);
+
+ LOGP(DL1C, LOGL_INFO, "SIM %s\n", osmo_hexdump(data, len));
+
+ /* pull the L1 header from the msgb */
+ msgb_pull(msg, sizeof(struct l1ctl_hdr));
+ msg->l1h = NULL;
+
+ sim_apdu_resp(ms, msg);
+
+ return 0;
+}
+
+/* Transmit L1CTL_PM_REQ */
+int l1ctl_tx_pm_req_range(struct osmocom_ms *ms, uint16_t arfcn_from,
+ uint16_t arfcn_to)
+{
+ struct msgb *msg;
+ struct l1ctl_pm_req *pm;
+
+ msg = osmo_l1_alloc(L1CTL_PM_REQ);
+ if (!msg)
+ return -1;
+
+ LOGP(DL1C, LOGL_INFO, "Tx PM Req (%u-%u)\n", arfcn_from, arfcn_to);
+ pm = (struct l1ctl_pm_req *) msgb_put(msg, sizeof(*pm));
+ pm->type = 1;
+ pm->range.band_arfcn_from = htons(arfcn_from);
+ pm->range.band_arfcn_to = htons(arfcn_to);
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_RESET_REQ */
+int l1ctl_tx_reset_req(struct osmocom_ms *ms, uint8_t type)
+{
+ struct msgb *msg;
+ struct l1ctl_reset *res;
+
+ msg = osmo_l1_alloc(L1CTL_RESET_REQ);
+ if (!msg)
+ return -1;
+
+ LOGP(DL1C, LOGL_INFO, "Tx Reset Req (%u)\n", type);
+ res = (struct l1ctl_reset *) msgb_put(msg, sizeof(*res));
+ res->type = type;
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Receive L1CTL_RESET_IND */
+static int rx_l1_reset(struct osmocom_ms *ms)
+{
+ LOGP(DL1C, LOGL_INFO, "Layer1 Reset indication\n");
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_RESET, ms);
+
+ return 0;
+}
+
+/* Receive L1CTL_PM_CONF */
+static int rx_l1_pm_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct l1ctl_pm_conf *pmr;
+
+ for (pmr = (struct l1ctl_pm_conf *) msg->l1h;
+ (uint8_t *) pmr < msg->tail; pmr++) {
+ struct osmobb_meas_res mr;
+ DEBUGP(DL1C, "PM MEAS: ARFCN: %4u RxLev: %3d %3d\n",
+ ntohs(pmr->band_arfcn), pmr->pm[0], pmr->pm[1]);
+ mr.band_arfcn = ntohs(pmr->band_arfcn);
+ mr.rx_lev = pmr->pm[0];
+ mr.ms = ms;
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_PM_RES, &mr);
+ }
+ return 0;
+}
+
+/* Receive L1CTL_CCCH_MODE_CONF */
+static int rx_l1_ccch_mode_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct osmobb_ccch_mode_conf mc;
+ struct l1ctl_ccch_mode_conf *conf;
+
+ if (msgb_l3len(msg) < sizeof(*conf)) {
+ LOGP(DL1C, LOGL_ERROR, "CCCH MODE CONF: MSG too short %u\n",
+ msgb_l3len(msg));
+ return -1;
+ }
+
+ conf = (struct l1ctl_ccch_mode_conf *) msg->l1h;
+
+ LOGP(DL1C, LOGL_INFO, "CCCH MODE CONF: mode=%u\n", conf->ccch_mode);
+
+ mc.ccch_mode = conf->ccch_mode;
+ mc.ms = ms;
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_CCCH_MODE_CONF, &mc);
+
+ return 0;
+}
+
+/* Receive L1CTL_TCH_MODE_CONF */
+static int rx_l1_tch_mode_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct osmobb_tch_mode_conf mc;
+ struct l1ctl_tch_mode_conf *conf;
+
+ if (msgb_l3len(msg) < sizeof(*conf)) {
+ LOGP(DL1C, LOGL_ERROR, "TCH MODE CONF: MSG too short %u\n",
+ msgb_l3len(msg));
+ return -1;
+ }
+
+ conf = (struct l1ctl_tch_mode_conf *) msg->l1h;
+
+ LOGP(DL1C, LOGL_INFO, "TCH MODE CONF: mode=%u\n", conf->tch_mode);
+
+ mc.tch_mode = conf->tch_mode;
+ mc.audio_mode = conf->audio_mode;
+ mc.ms = ms;
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_TCH_MODE_CONF, &mc);
+
+ return 0;
+}
+
+/* Receive L1CTL_TRAFFIC_IND (Traffic Indication from L1) */
+static int rx_l1_traffic_ind(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct l1ctl_info_dl *dl;
+ struct l1ctl_traffic_ind *ti;
+ uint8_t fr[33];
+ int i, di, si;
+
+ /* Header handling */
+ dl = (struct l1ctl_info_dl *) msg->l1h;
+ msg->l2h = dl->payload;
+ ti = (struct l1ctl_traffic_ind *) msg->l2h;
+
+ memset(fr, 0x00, 33);
+ fr[0] = 0xd0;
+ for (i = 0; i < 260; i++) {
+ di = gsm610_bitorder[i];
+ si = (i > 181) ? i + 4 : i;
+ msb_set_bit(fr, 4 + di, msb_get_bit(ti->data, si));
+ }
+ memcpy(ti->data, fr, 33);
+
+ DEBUGP(DL1C, "TRAFFIC IND (%s)\n", osmo_hexdump(ti->data, 33));
+
+ /* distribute or drop */
+ if (ms->l1_entity.l1_traffic_ind) {
+ /* pull the L1 header from the msgb */
+ msgb_pull(msg, msg->l2h - (msg->l1h-sizeof(struct l1ctl_hdr)));
+ msg->l1h = NULL;
+
+ return ms->l1_entity.l1_traffic_ind(ms, msg);
+ }
+
+ msgb_free(msg);
+ return 0;
+}
+
+/* Transmit L1CTL_TRAFFIC_REQ (Traffic Request to L1) */
+int l1ctl_tx_traffic_req(struct osmocom_ms *ms, struct msgb *msg,
+ uint8_t chan_nr, uint8_t link_id)
+{
+ struct l1ctl_hdr *l1h;
+ struct l1ctl_info_ul *l1i_ul;
+ struct l1ctl_traffic_req *tr;
+ uint8_t fr[33];
+ int i, di, si;
+
+ /* Header handling */
+ tr = (struct l1ctl_traffic_req *) msg->l2h;
+
+ DEBUGP(DL1C, "TRAFFIC REQ (%s)\n",
+ osmo_hexdump(msg->l2h, msgb_l2len(msg)));
+
+ if (msgb_l2len(msg) != 33) {
+ LOGP(DL1C, LOGL_ERROR, "Traffic Request has incorrect length "
+ "(%u != 33)\n", msgb_l2len(msg));
+ msgb_free(msg);
+ return -EINVAL;
+ }
+
+ if ((tr->data[0] >> 4) != 0xd) {
+ LOGP(DL1C, LOGL_ERROR, "Traffic Request has incorrect magic "
+ "(%u != 0xd)\n", tr->data[0] >> 4);
+ msgb_free(msg);
+ return -EINVAL;
+ }
+
+ memset(fr, 0x00, 33);
+ for (i = 0; i < 260; i++) {
+ si = gsm610_bitorder[i];
+ di = (i > 181) ? i + 4 : i;
+ msb_set_bit(fr, di, msb_get_bit(tr->data, 4 + si));
+ }
+ memcpy(tr->data, fr, 33);
+// printf("TX %s\n", osmo_hexdump(tr->data, 33));
+
+ /* prepend uplink info header */
+ l1i_ul = (struct l1ctl_info_ul *) msgb_push(msg, sizeof(*l1i_ul));
+
+ l1i_ul->chan_nr = chan_nr;
+ l1i_ul->link_id = link_id;
+
+ /* prepend l1 header */
+ msg->l1h = msgb_push(msg, sizeof(*l1h));
+ l1h = (struct l1ctl_hdr *) msg->l1h;
+ l1h->msg_type = L1CTL_TRAFFIC_REQ;
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_NEIGH_PM_REQ */
+int l1ctl_tx_neigh_pm_req(struct osmocom_ms *ms, int num, uint16_t *arfcn)
+{
+ struct msgb *msg;
+ struct l1ctl_neigh_pm_req *pm_req;
+ int i;
+
+ msg = osmo_l1_alloc(L1CTL_NEIGH_PM_REQ);
+ if (!msg)
+ return -1;
+
+ LOGP(DL1C, LOGL_INFO, "Tx NEIGH PM Req (num %u)\n", num);
+ pm_req = (struct l1ctl_neigh_pm_req *) msgb_put(msg, sizeof(*pm_req));
+ pm_req->n = num;
+ for (i = 0; i < num; i++) {
+ pm_req->band_arfcn[i] = htons(*arfcn++);
+ pm_req->tn[i] = 0;
+ }
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Receive L1CTL_NEIGH_PM_IND */
+static int rx_l1_neigh_pm_ind(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct l1ctl_neigh_pm_ind *pm_ind;
+
+ for (pm_ind = (struct l1ctl_neigh_pm_ind *) msg->l1h;
+ (uint8_t *) pm_ind < msg->tail; pm_ind++) {
+ struct osmobb_neigh_pm_ind mi;
+ DEBUGP(DL1C, "NEIGH_PM IND: ARFCN: %4u RxLev: %3d %3d\n",
+ ntohs(pm_ind->band_arfcn), pm_ind->pm[0],
+ pm_ind->pm[1]);
+ mi.band_arfcn = ntohs(pm_ind->band_arfcn);
+ mi.rx_lev = pm_ind->pm[0];
+ mi.ms = ms;
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_NEIGH_PM_IND, &mi);
+ }
+ return 0;
+}
+
+/* Receive incoming data from L1 using L1CTL format */
+int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
+{
+ int rc = 0;
+ struct l1ctl_hdr *l1h;
+ struct l1ctl_info_dl *dl;
+
+ if (msgb_l2len(msg) < sizeof(*dl)) {
+ LOGP(DL1C, LOGL_ERROR, "Short Layer2 message: %u\n",
+ msgb_l2len(msg));
+ msgb_free(msg);
+ return -1;
+ }
+
+ l1h = (struct l1ctl_hdr *) msg->l1h;
+
+ /* move the l1 header pointer to point _BEHIND_ l1ctl_hdr,
+ as the l1ctl header is of no interest to subsequent code */
+ msg->l1h = l1h->data;
+
+ switch (l1h->msg_type) {
+ case L1CTL_FBSB_CONF:
+ rc = rx_l1_fbsb_conf(ms, msg);
+ msgb_free(msg);
+ break;
+ case L1CTL_DATA_IND:
+ rc = rx_ph_data_ind(ms, msg);
+ break;
+ case L1CTL_DATA_CONF:
+ rc = rx_ph_data_conf(ms, msg);
+ break;
+ case L1CTL_RESET_IND:
+ case L1CTL_RESET_CONF:
+ rc = rx_l1_reset(ms);
+ msgb_free(msg);
+ break;
+ case L1CTL_PM_CONF:
+ rc = rx_l1_pm_conf(ms, msg);
+ if (l1h->flags & L1CTL_F_DONE)
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_PM_DONE, ms);
+ msgb_free(msg);
+ break;
+ case L1CTL_RACH_CONF:
+ rc = rx_l1_rach_conf(ms, msg);
+ break;
+ case L1CTL_CCCH_MODE_CONF:
+ rc = rx_l1_ccch_mode_conf(ms, msg);
+ msgb_free(msg);
+ break;
+ case L1CTL_TCH_MODE_CONF:
+ rc = rx_l1_tch_mode_conf(ms, msg);
+ msgb_free(msg);
+ break;
+ case L1CTL_SIM_CONF:
+ rc = rx_l1_sim_conf(ms, msg);
+ break;
+ case L1CTL_NEIGH_PM_IND:
+ rc = rx_l1_neigh_pm_ind(ms, msg);
+ msgb_free(msg);
+ break;
+ case L1CTL_TRAFFIC_IND:
+ rc = rx_l1_traffic_ind(ms, msg);
+ break;
+ case L1CTL_TRAFFIC_CONF:
+ msgb_free(msg);
+ break;
+ default:
+ LOGP(DL1C, LOGL_ERROR, "Unknown MSG: %u\n", l1h->msg_type);
+ msgb_free(msg);
+ break;
+ }
+
+ return rc;
+}
diff --git a/src/host/layer23/src/common/l1ctl_lapdm_glue.c b/src/host/layer23/src/common/l1ctl_lapdm_glue.c
new file mode 100644
index 00000000..0b2a8ed5
--- /dev/null
+++ b/src/host/layer23/src/common/l1ctl_lapdm_glue.c
@@ -0,0 +1,62 @@
+/* Glue code between L1CTL and LAPDm */
+
+/* (C) 2011 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+
+#include <l1ctl_proto.h>
+
+#include <osmocom/gsm/prim.h>
+
+#include <osmocom/bb/common/l1ctl.h>
+#include <osmocom/gsm/lapdm.h>
+
+/* LAPDm wants to send a PH-* primitive to the physical layer (L1) */
+int l1ctl_ph_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
+{
+ struct osmocom_ms *ms = ctx;
+ struct osmo_phsap_prim *pp = (struct osmo_phsap_prim *) oph;
+ int rc = 0;
+
+ if (oph->sap != SAP_GSM_PH)
+ return -ENODEV;
+
+ if (oph->operation != PRIM_OP_REQUEST)
+ return -EINVAL;
+
+ switch (oph->primitive) {
+ case PRIM_PH_DATA:
+ rc = l1ctl_tx_data_req(ms, oph->msg, pp->u.data.chan_nr,
+ pp->u.data.link_id);
+ break;
+ case PRIM_PH_RACH:
+ l1ctl_tx_param_req(ms, pp->u.rach_req.ta,
+ pp->u.rach_req.tx_power);
+ rc = l1ctl_tx_rach_req(ms, pp->u.rach_req.ra,
+ pp->u.rach_req.offset,
+ pp->u.rach_req.is_combined_ccch);
+ break;
+ default:
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
diff --git a/src/host/layer23/src/common/l1l2_interface.c b/src/host/layer23/src/common/l1l2_interface.c
new file mode 100644
index 00000000..d89995d9
--- /dev/null
+++ b/src/host/layer23/src/common/l1l2_interface.c
@@ -0,0 +1,180 @@
+/* Layer 1 socket interface of layer2/3 stack */
+
+/* (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/l1ctl.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/l1l2_interface.h>
+
+#include <osmocom/core/utils.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <arpa/inet.h>
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define GSM_L2_LENGTH 256
+#define GSM_L2_HEADROOM 32
+
+static int layer2_read(struct osmo_fd *fd)
+{
+ struct msgb *msg;
+ uint16_t len;
+ int rc;
+
+ msg = msgb_alloc_headroom(GSM_L2_LENGTH+GSM_L2_HEADROOM, GSM_L2_HEADROOM, "Layer2");
+ if (!msg) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to allocate msg.\n");
+ return -ENOMEM;
+ }
+
+ rc = read(fd->fd, &len, sizeof(len));
+ if (rc < sizeof(len)) {
+ fprintf(stderr, "Layer2 socket failed\n");
+ msgb_free(msg);
+ if (rc >= 0)
+ rc = -EIO;
+ layer2_close((struct osmocom_ms *) fd->data);
+ return rc;
+ }
+
+ len = ntohs(len);
+ if (len > GSM_L2_LENGTH) {
+ LOGP(DL1C, LOGL_ERROR, "Length is too big: %u\n", len);
+ msgb_free(msg);
+ return -EINVAL;
+ }
+
+
+ msg->l1h = msgb_put(msg, len);
+ rc = read(fd->fd, msg->l1h, msgb_l1len(msg));
+ if (rc != msgb_l1len(msg)) {
+ LOGP(DL1C, LOGL_ERROR, "Can not read data: len=%d rc=%d "
+ "errno=%d\n", len, rc, errno);
+ msgb_free(msg);
+ return rc;
+ }
+
+ l1ctl_recv((struct osmocom_ms *) fd->data, msg);
+
+ return 0;
+}
+
+static int layer2_write(struct osmo_fd *fd, struct msgb *msg)
+{
+ int rc;
+
+ if (fd->fd <= 0)
+ return -EINVAL;
+
+ rc = write(fd->fd, msg->data, msg->len);
+ if (rc != msg->len) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to write data: rc: %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+int layer2_open(struct osmocom_ms *ms, const char *socket_path)
+{
+ int rc;
+ struct sockaddr_un local;
+
+ ms->l2_wq.bfd.fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (ms->l2_wq.bfd.fd < 0) {
+ fprintf(stderr, "Failed to create unix domain socket.\n");
+ return ms->l2_wq.bfd.fd;
+ }
+
+ local.sun_family = AF_UNIX;
+ strncpy(local.sun_path, socket_path, sizeof(local.sun_path));
+ local.sun_path[sizeof(local.sun_path) - 1] = '\0';
+
+ rc = connect(ms->l2_wq.bfd.fd, (struct sockaddr *) &local,
+ sizeof(local));
+ if (rc < 0) {
+ fprintf(stderr, "Failed to connect to '%s': %s\n", local.sun_path,
+ strerror(errno));
+ close(ms->l2_wq.bfd.fd);
+ return rc;
+ }
+
+ osmo_wqueue_init(&ms->l2_wq, 100);
+ ms->l2_wq.bfd.data = ms;
+ ms->l2_wq.bfd.when = BSC_FD_READ;
+ ms->l2_wq.read_cb = layer2_read;
+ ms->l2_wq.write_cb = layer2_write;
+
+ rc = osmo_fd_register(&ms->l2_wq.bfd);
+ if (rc != 0) {
+ fprintf(stderr, "Failed to register fd.\n");
+ close(ms->l2_wq.bfd.fd);
+ return rc;
+ }
+
+ return 0;
+}
+
+int layer2_close(struct osmocom_ms *ms)
+{
+ if (ms->l2_wq.bfd.fd <= 0)
+ return -EINVAL;
+
+ close(ms->l2_wq.bfd.fd);
+ ms->l2_wq.bfd.fd = -1;
+ osmo_fd_unregister(&ms->l2_wq.bfd);
+ osmo_wqueue_clear(&ms->l2_wq);
+
+ return 0;
+}
+
+int osmo_send_l1(struct osmocom_ms *ms, struct msgb *msg)
+{
+ uint16_t *len;
+
+ DEBUGP(DL1C, "Sending: '%s'\n", osmo_hexdump(msg->data, msg->len));
+
+ if (msg->l1h != msg->data)
+ LOGP(DL1C, LOGL_ERROR, "Message L1 header != Message Data\n");
+
+ /* prepend 16bit length before sending */
+ len = (uint16_t *) msgb_push(msg, sizeof(*len));
+ *len = htons(msg->len - sizeof(*len));
+
+ if (osmo_wqueue_enqueue(&ms->l2_wq, msg) != 0) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to enqueue msg.\n");
+ msgb_free(msg);
+ return -1;
+ }
+
+ return 0;
+}
+
+
diff --git a/src/host/layer23/src/common/logging.c b/src/host/layer23/src/common/logging.c
new file mode 100644
index 00000000..d8fd076b
--- /dev/null
+++ b/src/host/layer23/src/common/logging.c
@@ -0,0 +1,137 @@
+/* Logging/Debug support of the layer2/3 stack */
+
+/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/bb/common/logging.h>
+
+static const struct log_info_cat default_categories[] = {
+ [DRSL] = {
+ .name = "DRSL",
+ .description = "Radio Signalling Link (MS)",
+ .color = "\033[1;35m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DCS] = {
+ .name = "DCS",
+ .description = "Cell selection",
+ .color = "\033[34m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DNB] = {
+ .name = "DNB",
+ .description = "Neighbour cell measurement",
+ .color = "\033[0;31m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DPLMN] = {
+ .name = "DPLMN",
+ .description = "PLMN selection",
+ .color = "\033[32m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DRR] = {
+ .name = "DRR",
+ .description = "Radio Resource",
+ .color = "\033[1;34m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DMM] = {
+ .name = "DMM",
+ .description = "Mobility Management",
+ .color = "\033[1;32m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DCC] = {
+ .name = "DCC",
+ .description = "Call Control",
+ .color = "\033[1;33m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DSS] = {
+ .name = "DSS",
+ .description = "Supplenmentary Services",
+ .color = "\033[1;35m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DSMS] = {
+ .name = "DSMS",
+ .description = "Short Message Service",
+ .color = "\033[1;37m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DMNCC] = {
+ .name = "DMNCC",
+ .description = "Mobile Network Call Control",
+ .color = "\033[1;37m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DMEAS] = {
+ .name = "DMEAS",
+ .description = "MEasurement Reporting",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DPAG] = {
+ .name = "DPAG",
+ .description = "Paging",
+ .color = "\033[33m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DL1C] = {
+ .name = "DL1C",
+ .description = "Layer 1 Control",
+ .color = "\033[1;31m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DSAP] = {
+ .name = "DSAP",
+ .description = "SAP Control",
+ .color = "\033[1;31m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DSUM] = {
+ .name = "DSUM",
+ .description = "Summary of Process",
+ .color = "\033[1;37m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DSIM] = {
+ .name = "DSIM",
+ .description = "SIM client",
+ .color = "\033[0;35m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DGPS] = {
+ .name = "DGPS",
+ .description = "GPS",
+ .color = "\033[1;35m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+};
+
+const struct log_info log_info = {
+ .filter_fn = NULL,
+ .cat = default_categories,
+ .num_cat = ARRAY_SIZE(default_categories),
+};
+
diff --git a/src/host/layer23/src/common/main.c b/src/host/layer23/src/common/main.c
new file mode 100644
index 00000000..59cee03d
--- /dev/null
+++ b/src/host/layer23/src/common/main.c
@@ -0,0 +1,297 @@
+/* Main method of the layer2/3 stack */
+
+/* (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/l1ctl.h>
+#include <osmocom/bb/common/l1l2_interface.h>
+#include <osmocom/bb/common/sap_interface.h>
+#include <osmocom/bb/misc/layer3.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/l23_app.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/gsmtap_util.h>
+#include <osmocom/core/gsmtap.h>
+#include <osmocom/core/utils.h>
+
+#include <arpa/inet.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+
+struct log_target *stderr_target;
+
+void *l23_ctx = NULL;
+
+static char *layer2_socket_path = "/tmp/osmocom_l2";
+static char *sap_socket_path = "/tmp/osmocom_sap";
+struct llist_head ms_list;
+static struct osmocom_ms *ms = NULL;
+static char *gsmtap_ip = NULL;
+static char *vty_ip = "127.0.0.1";
+
+unsigned short vty_port = 4247;
+int (*l23_app_work) (struct osmocom_ms *ms) = NULL;
+int (*l23_app_exit) (struct osmocom_ms *ms) = NULL;
+int quit = 0;
+struct gsmtap_inst *gsmtap_inst;
+
+const char *openbsc_copyright =
+ "%s"
+ "%s\n"
+ "License GPLv2+: GNU GPL version 2 or later "
+ "<http://gnu.org/licenses/gpl.html>\n"
+ "This is free software: you are free to change and redistribute it.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n\n";
+
+static void print_usage(const char *app)
+{
+ printf("Usage: %s\n", app);
+}
+
+static void print_help()
+{
+ int options = 0xff;
+ struct l23_app_info *app = l23_app_info();
+
+ if (app && app->cfg_supported != 0)
+ options = app->cfg_supported();
+
+ printf(" Some help...\n");
+ printf(" -h --help this text\n");
+ printf(" -s --socket /tmp/osmocom_l2. Path to the unix "
+ "domain socket (l2)\n");
+
+ if (options & L23_OPT_SAP)
+ printf(" -S --sap /tmp/osmocom_sap. Path to the "
+ "unix domain socket (BTSAP)\n");
+
+ if (options & L23_OPT_ARFCN)
+ printf(" -a --arfcn NR The ARFCN to be used for layer2.\n");
+
+ if (options & L23_OPT_TAP)
+ printf(" -i --gsmtap-ip The destination IP used for GSMTAP.\n");
+
+ if (options & L23_OPT_VTY)
+ printf(" -v --vty-port The VTY port number to telnet "
+ "to. (default %u)\n", vty_port);
+
+ if (options & L23_OPT_DBG)
+ printf(" -d --debug Change debug flags.\n");
+
+ if (options & L23_OPT_VTYIP)
+ printf(" -u --vty-ip The VTY IP to bind telnet to. "
+ "(default %s)\n", vty_ip);
+
+ if (app && app->cfg_print_help)
+ app->cfg_print_help();
+}
+
+static void build_config(char **opt, struct option **option)
+{
+ struct l23_app_info *app;
+ struct option *app_opp = NULL;
+ int app_len = 0, len;
+
+ static struct option long_options[] = {
+ {"help", 0, 0, 'h'},
+ {"socket", 1, 0, 's'},
+ {"sap", 1, 0, 'S'},
+ {"arfcn", 1, 0, 'a'},
+ {"gsmtap-ip", 1, 0, 'i'},
+ {"vty-ip", 1, 0, 'u'},
+ {"vty-port", 1, 0, 'v'},
+ {"debug", 1, 0, 'd'},
+ };
+
+
+ app = l23_app_info();
+ *opt = talloc_asprintf(l23_ctx, "hs:S:a:i:v:d:u:%s",
+ app && app->getopt_string ? app->getopt_string : "");
+
+ len = ARRAY_SIZE(long_options);
+ if (app && app->cfg_getopt_opt)
+ app_len = app->cfg_getopt_opt(&app_opp);
+
+ *option = talloc_zero_array(l23_ctx, struct option, len + app_len + 1);
+ memcpy(*option, long_options, sizeof(long_options));
+ memcpy(*option + len, app_opp, app_len * sizeof(struct option));
+}
+
+static void handle_options(int argc, char **argv)
+{
+ struct l23_app_info *app = l23_app_info();
+ struct option *long_options;
+ char *opt;
+
+ build_config(&opt, &long_options);
+
+ while (1) {
+ int option_index = 0, c;
+
+ c = getopt_long(argc, argv, opt,
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_usage(argv[0]);
+ print_help();
+ exit(0);
+ break;
+ case 's':
+ layer2_socket_path = talloc_strdup(l23_ctx, optarg);
+ break;
+ case 'S':
+ sap_socket_path = talloc_strdup(l23_ctx, optarg);
+ break;
+ case 'a':
+ ms->test_arfcn = atoi(optarg);
+ break;
+ case 'i':
+ gsmtap_ip = optarg;
+ break;
+ case 'u':
+ vty_ip = optarg;
+ break;
+ case 'v':
+ vty_port = atoi(optarg);
+ break;
+ case 'd':
+ log_parse_category_mask(stderr_target, optarg);
+ break;
+ default:
+ if (app && app->cfg_handle_opt)
+ app->cfg_handle_opt(c, optarg);
+ break;
+ }
+ }
+
+ talloc_free(opt);
+ talloc_free(long_options);
+}
+
+void sighandler(int sigset)
+{
+ int rc = 0;
+
+ if (sigset == SIGHUP || sigset == SIGPIPE)
+ return;
+
+ fprintf(stderr, "Signal %d recevied.\n", sigset);
+ if (l23_app_exit)
+ rc = l23_app_exit(ms);
+
+ if (rc != -EBUSY)
+ exit (0);
+}
+
+static void print_copyright()
+{
+ struct l23_app_info *app;
+ app = l23_app_info();
+ printf(openbsc_copyright,
+ app && app->copyright ? app->copyright : "",
+ app && app->contribution ? app->contribution : "");
+}
+
+int main(int argc, char **argv)
+{
+ int rc;
+
+ INIT_LLIST_HEAD(&ms_list);
+ log_init(&log_info, NULL);
+ stderr_target = log_target_create_stderr();
+ log_add_target(stderr_target);
+ log_set_all_filter(stderr_target, 1);
+
+ l23_ctx = talloc_named_const(NULL, 1, "layer2 context");
+
+ ms = talloc_zero(l23_ctx, struct osmocom_ms);
+ if (!ms) {
+ fprintf(stderr, "Failed to allocate MS\n");
+ exit(1);
+ }
+
+ print_copyright();
+
+ llist_add_tail(&ms->entity, &ms_list);
+
+ sprintf(ms->name, "1");
+
+ ms->test_arfcn = 871;
+
+ handle_options(argc, argv);
+
+ rc = layer2_open(ms, layer2_socket_path);
+ if (rc < 0) {
+ fprintf(stderr, "Failed during layer2_open()\n");
+ exit(1);
+ }
+
+ rc = sap_open(ms, sap_socket_path);
+ if (rc < 0)
+ fprintf(stderr, "Failed during sap_open(), no SIM reader\n");
+
+ ms->lapdm_channel.lapdm_dcch.l1_ctx = ms;
+ ms->lapdm_channel.lapdm_dcch.l3_ctx = ms;
+ ms->lapdm_channel.lapdm_acch.l1_ctx = ms;
+ ms->lapdm_channel.lapdm_acch.l3_ctx = ms;
+ lapdm_channel_init(&ms->lapdm_channel, LAPDM_MODE_MS);
+ lapdm_channel_set_l1(&ms->lapdm_channel, l1ctl_ph_prim_cb, ms);
+
+ rc = l23_app_init(ms);
+ if (rc < 0)
+ exit(1);
+
+ if (gsmtap_ip) {
+ gsmtap_inst = gsmtap_source_init(gsmtap_ip, GSMTAP_UDP_PORT, 1);
+ if (!gsmtap_inst) {
+ fprintf(stderr, "Failed during gsmtap_init()\n");
+ exit(1);
+ }
+ gsmtap_source_add_sink(gsmtap_inst);
+ }
+
+ signal(SIGINT, sighandler);
+ signal(SIGHUP, sighandler);
+ signal(SIGTERM, sighandler);
+ signal(SIGPIPE, sighandler);
+
+ while (!quit) {
+ if (l23_app_work)
+ l23_app_work(ms);
+ osmo_select_main(0);
+ }
+
+ return 0;
+}
diff --git a/src/host/layer23/src/common/networks.c b/src/host/layer23/src/common/networks.c
new file mode 100644
index 00000000..40b70a10
--- /dev/null
+++ b/src/host/layer23/src/common/networks.c
@@ -0,0 +1,1986 @@
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <osmocom/bb/common/networks.h>
+
+/* list of networks */
+
+struct gsm_networks gsm_networks[] = {
+ { 0x001, -1, "Test" },
+ { 0x001, 0x01f, "Test" },
+ { 0x412, -1, "Afghanistan" },
+ { 0x412, 0x01f, "AWCC" },
+ { 0x412, 0x20f, "Roshan" },
+ { 0x412, 0x30f, "New1" },
+ { 0x412, 0x40f, "Areeba" },
+ { 0x412, 0x50f, "Etisalat" }, /* ? */
+ { 0x412, 0x88f, "Afghan Telecom" },
+ { 0x276, -1, "Albania" },
+ { 0x276, 0x01f, "AMC" },
+ { 0x276, 0x02f, "Vodafone" },
+ { 0x276, 0x03f, "Eagle Mobile" },
+ { 0x276, 0x04f, "Mobile 4 AL" },
+ { 0x603, -1, "Algeria" },
+ { 0x603, 0x01f, "Algerie Telecom" },
+ { 0x603, 0x02f, "Orascom Telecom Algerie" },
+ { 0x603, 0x03f, "Nedjma" }, /* ? */
+ { 0x213, -1, "Andorra" },
+ { 0x213, 0x03f, "Mobiland" },
+ { 0x631, -1, "Angola" },
+ { 0x631, 0x02f, "UNITEL" },
+ { 0x365, -1, "Anguilla" },
+ { 0x365, 0x010, "Weblinks Limited" },
+ { 0x365, 0x840, "Cable & Wireless" }, /* ? */
+ { 0x344, -1, "Antigua and Barbuda" },
+ { 0x344, 0x030, "APUA PCS" },
+ { 0x338, 0x050, "Digicel" }, /* ? */
+ { 0x344, 0x920, "Cable & Wireless (Antigua)" },
+ { 0x344, 0x930, "AT&T Wireless (Antigua)" },
+ { 0x722, -1, "Argentina" },
+ { 0x722, 0x010, "Companie de Radiocomunicatciones Moviles S.A." },
+ { 0x722, 0x020, "Nextel Argentina srl" },
+ { 0x722, 0x070, "Telefonica Communicationes Personales S.A." },
+ { 0x722, 0x310, "CTI PCS S.A" },
+ { 0x722, 0x320, "Compania de Telefonos del Interior Norte S.A." },
+ { 0x722, 0x330, "Companie de Telefonos del Interior S.A." },
+ { 0x722, 0x340, "Personal" }, /* ? */
+ { 0x722, 0x341, "Telecom Personal S.A." },
+ { 0x722, 0x350, "Hutchinson (PORT HABLE)" }, /* ? */
+ { 0x283, -1, "Armenia" },
+ { 0x283, 0x01f, "Beeline" },
+ { 0x283, 0x05f, "VivaCell-MTS" },
+ { 0x283, 0x10f, "Orange" },
+ { 0x363, -1, "Aruba" },
+ { 0x363, 0x01f, "SETAR" },
+ { 0x363, 0x02f, "Digicel" }, /* ? */
+ { 0x505, -1, "Australia" },
+ { 0x505, 0x01f, "Telstra" },
+ { 0x505, 0x02f, "Optus" },
+ { 0x505, 0x03f, "Vodafone" },
+ { 0x505, 0x04f, "Department of Defence" },
+ { 0x505, 0x05f, "Ozitel" },
+ { 0x505, 0x06f, "Hutchison 3G"},
+ { 0x505, 0x07f, "Vodafone" },
+ { 0x505, 0x08f, "One.Tel" },
+ { 0x505, 0x09f, "Airnet" },
+ { 0x505, 0x10f, "Norfolk Telecom" },
+ { 0x505, 0x11f, "Telstra" },
+ { 0x505, 0x12f, "3" },
+ { 0x505, 0x13f, "Railcorp" },
+ { 0x505, 0x14f, "AAPT" },
+ { 0x505, 0x15f, "3GIS" },
+ { 0x505, 0x16f, "Victorian Rail Track" },
+ { 0x505, 0x17f, "Vivid Wireless Pty Ltd" },
+ { 0x505, 0x18f, "Pactel International Pty Ltd" },
+ { 0x505, 0x19f, "Lycamobile Pty Ltd" },
+ { 0x505, 0x21f, "SOUL" }, /* ? */
+ { 0x505, 0x24f, "Advanced Communications Technologies Pty. Ltd." },
+ { 0x505, 0x38f, "Crazy John's" }, /* ? */
+ { 0x505, 0x71f, "Telstra" },
+ { 0x505, 0x72f, "Telstra" },
+ { 0x505, 0x88f, "Localstar Holding Pty. Ltd." },
+ { 0x505, 0x90f, "Optus" },
+ { 0x505, 0x99f, "One.Tel" },
+ { 0x232, -1, "Austria" },
+ { 0x232, 0x01f, "A1" },
+ { 0x232, 0x02f, "A1" },
+ { 0x232, 0x03f, "T-Mobile" },
+ { 0x232, 0x04f, "T-Mobile" },
+ { 0x232, 0x05f, "Orange" },
+ { 0x232, 0x06f, "Orange" },
+ { 0x232, 0x07f, "T-Mobile (tele.ring)" },
+ { 0x232, 0x09f, "Mobilkom Austria" },
+ { 0x232, 0x10f, "Hutchison 3G Austria" },
+ { 0x232, 0x11f, "Mobilkom Austria" },
+ { 0x232, 0x12f, "Orange Austria" },
+ { 0x232, 0x14f, "Hutchison 3G Austria" },
+ { 0x232, 0x15f, "Barablu Mobile Austria" },
+ { 0x232, 0x16f, "3" }, /* ? */
+ { 0x232, 0x91f, "OBB - Infrastruktur Bau AG" },
+ { 0x400, -1, "Azerbaijan" },
+ { 0x400, 0x01f, "Azercell" },
+ { 0x400, 0x02f, "Bakcell" },
+ { 0x400, 0x03f, "Catel JV" },
+ { 0x400, 0x04f, "Azerphone LLC" },
+ { 0x364, -1, "Bahamas" },
+ { 0x364, 0x390, "BaTelCo" },
+ { 0x426, -1, "Bahrain" },
+ { 0x426, 0x01f, "BHR Mobile Plus" },
+ { 0x426, 0x02f, "zain BH" }, /* ? */
+ { 0x426, 0x04f, "VIVA" }, /* ? */
+ { 0x470, -1, "Bangladesh" },
+ { 0x470, 0x01f, "Grameenphone" },
+ { 0x470, 0x02f, "Aktel" },
+ { 0x470, 0x03f, "Mobile 2000" },
+ { 0x470, 0x04f, "TeleTalk" }, /* ? */
+ { 0x470, 0x05f, "Citycell" }, /* ? */
+ { 0x470, 0x06f, "Warid" }, /* ? */
+ { 0x470, 0x07f, "WTBL" }, /* ? */
+ { 0x342, -1, "Barbados" },
+ { 0x342, 0x600, "Cable & Wireless (Barbados) Ltd." },
+ { 0x342, 0x750, "Digicel" }, /* ? */
+ { 0x342, 0x820, "Sunbeach Communications" },
+ { 0x257, -1, "Belarus" },
+ { 0x257, 0x01f, "MCD Velcom" },
+ { 0x257, 0x02f, "MTS" },
+ { 0x257, 0x04f, "life:)" }, /* ? */
+ { 0x257, 0x03f, "DIALLOG" }, /* ? */
+ { 0x206, -1, "Belgium" },
+ { 0x206, 0x01f, "Proximus" },
+ { 0x206, 0x02f, "SNCB GSM-R" }, /* ? */
+ { 0x206, 0x10f, "Mobistar" },
+ { 0x206, 0x20f, "BASE" },
+ { 0x702, -1, "Belize" },
+ { 0x702, 0x67f, "Belize Telemedia" },
+ { 0x702, 0x68f, "International Telecommunications Ltd." },
+ { 0x702, 0x00f, "Smart" }, /* ? */
+ { 0x616, -1, "Benin" },
+ { 0x616, 0x01f, "Libercom" },
+ { 0x616, 0x02f, "Telecel" },
+ { 0x616, 0x03f, "Spacetel Benin" },
+ { 0x616, 0x04f, "BBCOM" }, /* ? */
+ { 0x616, 0x05f, "Glo" }, /* ? */
+ { 0x350, -1, "Bermuda" },
+ { 0x350, 0x01f, "Digicel Bermuda" }, /* ? */
+ { 0x350, 0x02f, "Mobility" }, /* ? */
+ { 0x338, 0x050, "Digicel Bermuda" }, /* ? */
+ { 0x310, 0x00f, "Cellular One" }, /* ? */
+ { 0x402, -1, "Bhutan" },
+ { 0x402, 0x11f, "Bhutan Telecom Ltd" },
+ { 0x402, 0x77f, "B-Mobile" },
+ { 0x736, -1, "Bolivia" },
+ { 0x736, 0x01f, "Nuevatel" },
+ { 0x736, 0x02f, "Entel" },
+ { 0x736, 0x03f, "Telecel" },
+ { 0x218, -1, "Bosnia and Herzegovina" },
+ { 0x218, 0x03f, "HT-ERONET" },
+ { 0x218, 0x05f, "MOBI'S" },
+ { 0x218, 0x90f, "GSMBIH" },
+ { 0x652, -1, "Botswana" },
+ { 0x652, 0x01f, "Mascom" },
+ { 0x652, 0x02f, "Orange" },
+ { 0x652, 0x04f, "BTC Mobile" },
+ { 0x724, -1, "Brazil" },
+ { 0x724, 0x00f, "Telet" },
+ { 0x724, 0x01f, "CRT Cellular" },
+ { 0x724, 0x02f, "TIM" },
+ { 0x724, 0x03f, "TIM" },
+ { 0x724, 0x04f, "TIM" },
+ { 0x724, 0x05f, "Claro" },
+ { 0x724, 0x06f, "Vivo" },
+ { 0x724, 0x07f, "CTBC Celular" },
+ { 0x724, 0x08f, "TIM" },
+ { 0x724, 0x10f, "Vivo" },
+ { 0x724, 0x11f, "Vivo" },
+ { 0x724, 0x15f, "Sercomtel" },
+ { 0x724, 0x16f, "Oi / Brasil Telecom" },
+ { 0x724, 0x23f, "Vivo" },
+ { 0x724, 0x24f, "Oi / Amazonia Celular" },
+ { 0x724, 0x31f, "Oi" },
+ { 0x724, 0x32f, "CTBC Celular" },
+ { 0x724, 0x33f, "CTBC Celular" },
+ { 0x724, 0x34f, "CTBC Celular" },
+ { 0x724, 0x35f, "TIM" },
+ { 0x724, 0x37f, "aeiou" },
+ { 0x724, 0x39f, "TIM" },
+ { 0x724, 0x41f, "TIM" },
+ { 0x724, 0x43f, "TIM" },
+ { 0x724, 0x45f, "TIM" },
+ { 0x724, 0x47f, "TIM" },
+ { 0x724, 0x48f, "TIM" },
+ { 0x724, 0x51f, "TIM" },
+ { 0x724, 0x53f, "TIM" },
+ { 0x724, 0x55f, "TIM" },
+ { 0x724, 0x57f, "TIM" },
+ { 0x724, 0x59f, "TIM" },
+ { 0x724, 0x00f, "Nextel" },
+ { 0x348, -1, "British Virgin Islands" },
+ { 0x348, 0x170, "Cable & Wireless" },
+ { 0x348, 0x370, "BVI Cable TV Ltd" },
+ { 0x348, 0x570, "CCT Boatphone" },
+ { 0x348, 0x770, "Digicel (BVI) Ltd" },
+ { 0x528, -1, "Brunei" },
+ { 0x528, 0x01f, "Jabatan Telekom" }, /* ? */
+ { 0x528, 0x02f, "B-Mobile" }, /* ? */
+ { 0x528, 0x11f, "DSTCom" },
+ { 0x284, -1, "Bulgaria" },
+ { 0x284, 0x01f, "M-Tel" },
+ { 0x284, 0x03f, "Vivacom" }, /* ? */
+ { 0x284, 0x05f, "GLOBUL" },
+ { 0x613, -1, "Burkina Faso" },
+ { 0x613, 0x01f, "Onatel" }, /* ? */
+ { 0x613, 0x02f, "Celtel / Zain" },
+ { 0x613, 0x03f, "Telecel Faso" },
+ { 0x642, -1, "Burundi" },
+ { 0x642, 0x01f, "Econet / Spacetel" },
+ { 0x642, 0x02f, "Africell" },
+ { 0x642, 0x03f, "Onamob" },
+ { 0x642, 0x07f, "Lacell" },
+ { 0x642, 0x08f, "Hits" },
+ { 0x642, 0x82f, "U.COM / Onatel" },
+ { 0x456, -1, "Cambodia" },
+ { 0x456, 0x01f, "Mobitel" },
+ { 0x456, 0x02f, "hello" },
+ { 0x456, 0x03f, "S Telecom" },
+ { 0x456, 0x04f, "Cadcomms / qb" },
+ { 0x456, 0x05f, "Star-Cell" },
+ { 0x456, 0x06f, "Smart" },
+ { 0x456, 0x08f, "Viettel" },
+ { 0x456, 0x18f, "Mfone" },
+// { 0x456, ?, "Excell" }, /* ? */
+ { 0x456, 0x09f, "Beeline" }, /* ? */
+ { 0x456, 0x08f, "Metfone" }, /* ? */
+ { 0x624, -1, "Cameroon" },
+ { 0x624, 0x01f, "MTN Cameroon" },
+ { 0x624, 0x02f, "Orange" },
+ { 0x302, -1, "Canada" },
+ { 0x302, 0x220, "Telus" },
+ { 0x302, 0x221, "Telus" },
+ { 0x302, 0x290, "Airtel Wireless" },
+ { 0x302, 0x350, "FIRST" },
+ { 0x302, 0x360, "MiKe" },
+ { 0x302, 0x361, "Telus" },
+ { 0x302, 0x370, "Fido" },
+ { 0x302, 0x380, "DMTS" },
+ { 0x302, 0x490, "WIND Mobile" },
+ { 0x302, 0x500, "Videotron" },
+ { 0x302, 0x510, "Videotron" },
+ { 0x302, 0x610, "Bell" },
+ { 0x302, 0x620, "ICE Wireless" },
+ { 0x302, 0x640, "Bell" },
+ { 0x302, 0x651, "Bell" },
+ { 0x302, 0x652, "BC Tel Mobility (Telus)" },
+ { 0x302, 0x653, "Telus" },
+ { 0x302, 0x655, "MTS" },
+ { 0x302, 0x656, "TBay" },
+ { 0x302, 0x657, "Telus" },
+ { 0x302, 0x680, "SaskTel" },
+ { 0x302, 0x701, "MB Tel Mobility" },
+ { 0x302, 0x702, "MT&T Mobility (Aliant)" },
+ { 0x302, 0x703, "New Tel Mobility (Aliant)" },
+ { 0x302, 0x710, "Globalstar" },
+ { 0x302, 0x720, "Rogers Wireless" },
+ { 0x302, 0x780, "SaskTel" },
+ { 0x302, 0x880, "Bell / Telus" },
+ { 0x625, -1, "Cape Verde" },
+ { 0x625, 0x01f, "CVMOVEL" },
+ { 0x625, 0x02f, "T+" },
+ { 0x346, -1, "Cayman Islands" },
+ { 0x346, 0x140, "Cable & Wireless" },
+ { 0x338, 0x050, "Digicel" }, /* ? */
+ { 0x623, -1, "Central African Republic" },
+ { 0x623, 0x01f, "CTP" },
+ { 0x623, 0x02f, "TC" },
+ { 0x623, 0x03f, "Celca / Socatel / Orange" },
+ { 0x623, 0x04f, "Nationlink" }, /* ? */
+ { 0x622, -1, "Chad" },
+ { 0x622, 0x01f, "Celtel / Zain" },
+ { 0x622, 0x02f, "Tchad Mobile" },
+ { 0x622, 0x03f, "TIGO - Millicom" }, /* ? */
+ { 0x622, 0x02f, "TAWALI" }, /* ? */
+ { 0x622, 0x04f, "Salam" }, /* ? */
+ { 0x730, -1, "Chile" },
+ { 0x730, 0x01f, "Entel" },
+ { 0x730, 0x02f, "movistar" },
+ { 0x730, 0x03f, "Smartcom / Claro" },
+ { 0x730, 0x04f, "Centennial Cayman Corp / Nextel" },
+ { 0x730, 0x05f, "Multikom S.A." },
+ { 0x730, 0x06f, "Blue Two Chile S.A." },
+ { 0x730, 0x07f, "Telefonica" },
+ { 0x730, 0x10f, "Entel" },
+ { 0x730, 0x99f, "WILL" }, /* ? */
+ { 0x460, -1, "China" },
+ { 0x460, 0x00f, "China Mobile" },
+ { 0x460, 0x01f, "China Unicom" },
+ { 0x460, 0x02f, "China Mobile" },
+ { 0x460, 0x03f, "China Unicom CMDA" },
+ { 0x460, 0x04f, "China Satellite Global Star Network" },
+ { 0x460, 0x05f, "China Telecom" }, /* ? */
+ { 0x460, 0x06f, "China Unicom" }, /* ? */
+ { 0x460, 0x20f, "China TIETONG" }, /* ? */
+ { 0x732, -1, "Colombia" },
+ { 0x732, 0x001, "Colombia Telecomunicaciones S.A." },
+ { 0x732, 0x002, "Edatel" },
+ { 0x732, 0x020, "Emtelsa" },
+ { 0x732, 0x099, "Emcali" },
+ { 0x732, 0x101, "Comcel" },
+ { 0x732, 0x102, "Bellsouth / movistar" },
+ { 0x732, 0x103, "Colombia Movil / Tigo" },
+ { 0x732, 0x111, "Colombia Movil / Tigo" },
+ { 0x732, 0x123, "movistar" },
+ { 0x732, 0x12f, "movistar" }, /* ? */
+ { 0x732, 0x130, "Avantel" },
+ { 0x654, -1, "Comoros" },
+ { 0x654, 0x01f, "HURI - SNPT" },
+ { 0x629, -1, "Republic of the Congo" },
+ { 0x629, 0x01f, "Celtel / Zain" },
+ { 0x629, 0x10f, "Libertis Telecom" },
+// { 0x629, ?, "Warid Telecom" },
+ { 0x548, -1, "Cook Islands" },
+ { 0x548, 0x01f, "Telecom Cook" },
+ { 0x712, -1, "Costa Rica" },
+ { 0x712, 0x01f, "ICE" },
+ { 0x712, 0x02f, "ICE" }, /* ? */
+ { 0x712, 0x03f, "ICE" }, /* ? */
+ { 0x219, -1, "Croatia" },
+ { 0x219, 0x01f, "T-Mobile" },
+ { 0x219, 0x02f, "Tele2" },
+ { 0x219, 0x10f, "VIPnet" },
+ { 0x368, -1, "Cuba" },
+ { 0x368, 0x01f, "ETECSA" },
+ { 0x280, -1, "Cyprus" },
+ { 0x280, 0x01f, "Cytamobile-Vodafone" },
+ { 0x280, 0x10f, "Scanacom / MTN" },
+ { 0x230, -1, "Czech Republic" },
+ { 0x230, 0x01f, "T-Mobile" },
+ { 0x230, 0x02f, "O2" },
+ { 0x230, 0x03f, "Vodafone" },
+ { 0x230, 0x04f, "Mobilkom / U:fon" },
+ { 0x230, 0x98f, "SZDC s.o." },
+ { 0x230, 0x99f, "Vodafone" },
+ { 0x630, -1, "Democratic Republic of the Congo" },
+ { 0x630, 0x01f, "Vodacom" },
+ { 0x630, 0x02f, "Zain" }, /* ? */
+ { 0x630, 0x04f, "Cellco" }, /* ? */
+ { 0x630, 0x05f, "Supercell" },
+ { 0x630, 0x86f, "CCT" },
+ { 0x630, 0x89f, "SAIT Telecom" }, /* ? */
+// { 0x630, ?, "Africell" },
+ { 0x238, -1, "Denmark" },
+ { 0x238, 0x01f, "TDC" },
+ { 0x238, 0x02f, "Sonofon / Telenor" },
+ { 0x238, 0x03f, "MIGway A/S" },
+ { 0x238, 0x05f, "ApS KBUS" },
+ { 0x238, 0x06f, "Hi3G" },
+ { 0x238, 0x07f, "Lycamobile / Barablu Mobile" },
+ { 0x238, 0x09f, "Dansk Beredskabskommunikation A/S" }, /* ? */
+ { 0x238, 0x10f, "TDC" },
+ { 0x238, 0x11f, "Dansk Beredskabskommunikation A/S" }, /* ? */
+ { 0x238, 0x12f, "Lycamobile Denmark Ltd" },
+ { 0x238, 0x20f, "Telia" },
+ { 0x238, 0x30f, "Telia" },
+ { 0x238, 0x40f, "Ericsson Danmark A/S" }, /* ? */
+ { 0x238, 0x77f, "Tele2 / Telenor" },
+ { 0x638, -1, "Djibouti" },
+ { 0x638, 0x01f, "Evatis" },
+ { 0x366, -1, "Dominica" },
+ { 0x366, 0x020, "Digicel" }, /* ? */
+ { 0x366, 0x110, "Cable & Wireless" }, /* ? */
+ { 0x370, -1, "Dominican Republic" },
+ { 0x370, 0x01f, "Orange" },
+ { 0x370, 0x02f, "Verizon / Claro" },
+ { 0x370, 0x03f, "Tricom" },
+ { 0x370, 0x04f, "CentennialDominicana / Viva" },
+ { 0x514, -1, "East Timor" },
+ { 0x514, 0x02f, "Timor Telecom" }, /* ? */
+ { 0x740, -1, "Ecuador" },
+ { 0x740, 0x00f, "Otecel / Bellsouth / Movistar" },
+ { 0x740, 0x01f, "Porta GSM" },
+ { 0x740, 0x02f, "Telecsa / Alegro" },
+ { 0x602, -1, "Egypt" },
+ { 0x602, 0x01f, "Mobinil" },
+ { 0x602, 0x02f, "Vodafone" },
+ { 0x602, 0x03f, "Etisalat" },
+ { 0x706, -1, "El Salvador" },
+ { 0x706, 0x01f, "CTE Telecom Personal" },
+ { 0x706, 0x02f, "digicel" },
+ { 0x706, 0x03f, "Telemovil EL Salvador" },
+ { 0x706, 0x04f, "movistar" }, /* ? */
+ { 0x706, 0x10f, "Claro" }, /* ? */
+ { 0x627, -1, "Equatorial Guinea" },
+ { 0x627, 0x01f, "Orange GQ" },
+ { 0x627, 0x03f, "Hits GQ" },
+ { 0x657, -1, "Eritrea" },
+ { 0x657, 0x01f, "Eritel" }, /* ? */
+ { 0x248, -1, "Estonia" },
+ { 0x248, 0x01f, "EMT" },
+ { 0x248, 0x02f, "RLE / Elisa" },
+ { 0x248, 0x03f, "Tele 2" },
+ { 0x248, 0x04f, "OY Top Connect" },
+ { 0x248, 0x05f, "AS Bravocom Mobiil" },
+ { 0x248, 0x06f, "Pro Group Holding / ViaTel" },
+ { 0x248, 0x07f, "Televorgu AS" },
+ { 0x248, 0x71f, "Siseministeerium" },
+ { 0x636, -1, "Ethiopia" },
+ { 0x636, 0x01f, "ETMTN" },
+ { 0x750, -1, "Falkland Islands (Malvinas)" },
+ { 0x750, 0x001, "Touch" },
+ { 0x288, -1, "Faroe Islands" },
+ { 0x288, 0x01f, "Faroese Telecom" },
+ { 0x288, 0x02f, "Kall / Vodafone" },
+ { 0x274, 0x02f, "P/F Kall" },
+ { 0x542, -1, "Fiji" },
+ { 0x542, 0x01f, "Vodafone" },
+ { 0x542, 0x02f, "Digicel" },
+ { 0x542, 0x03f, "Telecom Fiji" },
+ { 0x244, -1, "Finland" },
+ { 0x244, 0x03f, "DNA" }, /* ? */
+ { 0x244, 0x04f, "Finnet" },
+ { 0x244, 0x05f, "Elisa" },
+ { 0x244, 0x07f, "Nokia" },
+ { 0x244, 0x08f, "Unknown" },
+ { 0x244, 0x09f, "Finnet Group" },
+ { 0x244, 0x10f, "TDC Oy" },
+ { 0x244, 0x12f, "Finnet Networks / DNA" },
+ { 0x244, 0x14f, "AMT" },
+ { 0x244, 0x16f, "Oy Finland Tele2" },
+ { 0x244, 0x21f, "Saunalahti" },
+ { 0x244, 0x29f, "Scnl Truphone" }, /* ? */
+ { 0x244, 0x91f, "Sonera" },
+ { 0x208, -1, "France" },
+ { 0x208, 0x00f, "Orange" }, /* ? */
+ { 0x208, 0x01f, "Orange" },
+ { 0x208, 0x02f, "Orange" },
+ { 0x208, 0x05f, "Globalstar Europe" },
+ { 0x208, 0x06f, "Globalstar Europe" },
+ { 0x208, 0x07f, "Globalstar Europe" },
+ { 0x208, 0x10f, "SFR" },
+ { 0x208, 0x11f, "SFR" },
+ { 0x208, 0x13f, "SFR" }, /* ? */
+ { 0x208, 0x20f, "Bouygues" },
+ { 0x208, 0x21f, "Bouygues" },
+ { 0x208, 0x22f, "Transatel Mobile" },
+ { 0x208, 0x88f, "Bouygues" },
+ { 0x628, -1, "Gabon" },
+ { 0x628, 0x01f, "Libertis" },
+ { 0x628, 0x02f, "Moov (Telecel) Gabon S.A." },
+ { 0x628, 0x03f, "Celtel / Zain" },
+ { 0x628, 0x04f, "USAN Gabon" },
+ { 0x607, -1, "Gambia" },
+ { 0x607, 0x01f, "Gamcel" },
+ { 0x607, 0x02f, "Africel" },
+ { 0x607, 0x03f, "Comium" },
+ { 0x607, 0x04f, "QCell" }, /* ? */
+ { 0x282, -1, "Georgia" },
+ { 0x282, 0x01f, "Geocell" },
+ { 0x282, 0x02f, "MagtiCom" },
+ { 0x282, 0x03f, "Iberiatel" },
+ { 0x282, 0x04f, "Beeline" },
+ { 0x282, 0x05f, "Silknet JSC" },
+ { 0x289, 0x67f, "Aquafon" }, /* ? */
+ { 0x289, 0x88f, "A-Mobile" }, /* ? */
+ { 0x262, -1, "Germany" },
+ { 0x262, 0x01f, "T-Mobile" },
+ { 0x262, 0x02f, "Vodafone" },
+ { 0x262, 0x03f, "E-Plus" },
+ { 0x262, 0x04f, "Vodafone" },
+ { 0x262, 0x05f, "E-Plus" },
+ { 0x262, 0x06f, "T-Mobile" },
+ { 0x262, 0x07f, "O2" },
+ { 0x262, 0x08f, "O2" },
+ { 0x262, 0x09f, "Vodafone" },
+ { 0x262, 0x10f, "DB Systel GSM-R" },
+ { 0x262, 0x11f, "O2" },
+ { 0x262, 0x12f, "Dolphin Telecom" },
+ { 0x262, 0x13f, "Mobilcom Multimedia" },
+ { 0x262, 0x14f, "Group 3G UMTS" },
+ { 0x262, 0x15f, "Airdata" },
+ { 0x262, 0x16f, "Vistream" }, /* ? */
+ { 0x262, 0x42f, "OpenBSC" }, /* ? */
+ { 0x262, 0x60f, "DB Telematik" },
+ { 0x262, 0x76f, "Siemens AG" },
+ { 0x262, 0x77f, "E-Plus" },
+ { 0x262, 0x901, "Debitel" }, /* ? */
+ { 0x620, -1, "Ghana" },
+ { 0x620, 0x01f, "Spacefon / MTN" },
+ { 0x620, 0x02f, "Ghana Telecom Mobile / Vodafone" },
+ { 0x620, 0x03f, "Mobiltel / tiGO" },
+ { 0x620, 0x04f, "Kasapa / Hutchison Telecom" },
+ { 0x620, 0x06f, "Zain" }, /* ? */
+ { 0x620, 0x10f, "Netafriques" }, /* ? */
+ { 0x266, -1, "Gibraltar" },
+ { 0x266, 0x01f, "GibTel" },
+ { 0x266, 0x06f, "CTS Mobile" },
+ { 0x266, 0x09f, "Cloud9 Mobile Communications" },
+ { 0x202, -1, "Greece" },
+ { 0x202, 0x01f, "Cosmote" },
+ { 0x202, 0x05f, "Vodafone" },
+ { 0x202, 0x09f, "Infoquest / Wind" },
+ { 0x202, 0x10f, "Wind" },
+ { 0x290, -1, "Greenland" },
+ { 0x290, 0x01f, "TELE Greenland A/S" },
+ { 0x352, -1, "Grenada" },
+ { 0x352, 0x030, "Digicel" },
+ { 0x352, 0x110, "Cable & Wireless" },
+ { 0x340, -1, "Guadeloupe" },
+ { 0x340, 0x01f, "Orange" },
+ { 0x340, 0x02f, "Outremer" },
+ { 0x340, 0x03f, "Telcell" },
+ { 0x340, 0x08f, "MIO GSM" },
+ { 0x340, 0x10f, "Guadeloupe Telephone Mobile" },
+ { 0x340, 0x20f, "Digicel" },
+ { 0x310, -1, "United States of America" },
+ { 0x310, 0x010, "Verizon Wireless" },
+ { 0x310, 0x012, "Verizon Wireless" },
+ { 0x310, 0x013, "Verizon Wireless" },
+ { 0x310, 0x016, "Cricket Communications" },
+ { 0x310, 0x017, "North Sight Communications Inc." },
+ { 0x310, 0x020, "Union Telephone Company" },
+ { 0x310, 0x030, "Centennial Communications" },
+ { 0x310, 0x035, "ETEX Communications dba ETEX Wireless" },
+ { 0x310, 0x040, "MTA Communications dba MTA Wireless" },
+ { 0x310, 0x050, "ACS Wireless Inc." },
+ { 0x310, 0x060, "Consolidated Telecom" },
+ { 0x310, 0x070, "Cingular Wireless" },
+ { 0x310, 0x080, "Corr Wireless Communications LLC" },
+ { 0x310, 0x090, "Cingular Wireless" },
+ { 0x310, 0x100, "New Mexicu RSA 4 East Ltd. Partnership" },
+ { 0x310, 0x110, "Pacific Telecom Inc." },
+ { 0x310, 0x130, "Carolina West Wireless" },
+ { 0x310, 0x140, "GTA Wireless LLC" },
+ { 0x310, 0x150, "Cingular Wireless" },
+ { 0x310, 0x160, "T-Mobile USA" },
+ { 0x310, 0x170, "Cingular Wireless" },
+ { 0x310, 0x180, "West Central Wireless" },
+ { 0x310, 0x190, "Alaska Wireless Communications LLC" },
+ { 0x310, 0x200, "T-Mobile USA" },
+ { 0x310, 0x210, "T-Mobile USA" },
+ { 0x310, 0x220, "T-Mobile USA" },
+ { 0x310, 0x230, "T-Mobile USA" },
+ { 0x310, 0x240, "T-Mobile USA" },
+ { 0x310, 0x250, "T-Mobile USA" },
+ { 0x310, 0x260, "T-Mobile USA" },
+ { 0x310, 0x270, "T-Mobile USA" },
+ { 0x310, 0x280, "Contennial Puerto Rio License Corp." },
+ { 0x310, 0x290, "Nep Cellcorp Inc." },
+ { 0x310, 0x300, "Blanca Telephone Company" },
+ { 0x310, 0x310, "T-Mobile USA" },
+ { 0x310, 0x320, "Simth Bagley Inc, dba Cellular One" },
+ { 0x310, 0x340, "High Plains Midwest LLC, dba Wetlink Communications" },
+ { 0x310, 0x350, "Mohave Cellular L.P." },
+ { 0x310, 0x360, "Cellular Network Partnership dba Pioneer Cellular" },
+ { 0x310, 0x370, "Guamcell Cellular and Paging" },
+ { 0x310, 0x380, "New Cingular Wireless PCS, LLC" },
+ { 0x310, 0x390, "TX-11 Acquisition LLC" },
+ { 0x310, 0x400, "Wave Runner LLC" },
+ { 0x310, 0x410, "Cingular Wireless" },
+ { 0x310, 0x420, "Cincinnati Bell Wireless LLC" },
+ { 0x310, 0x430, "Alaska Digital LLC" },
+ { 0x310, 0x440, "Numerex Corp" },
+ { 0x310, 0x450, "North East Cellular Inc" },
+ { 0x310, 0x460, "TMP Corporation" },
+ { 0x310, 0x470, "nTELOS Communications Inc" },
+ { 0x310, 0x480, "Choice Phone LLC" },
+ { 0x310, 0x490, "T-Mobile USA" },
+ { 0x310, 0x500, "Public Service Cellular, Inc." },
+ { 0x310, 0x520, "Transactions Network Services" },
+ { 0x310, 0x530, "Iowa Wireless Services LLC" },
+ { 0x310, 0x540, "Oklahoma Western Telephone Company" },
+ { 0x310, 0x550, "Wireless Solutions International" },
+ { 0x310, 0x560, "Cingular Wireless" },
+ { 0x310, 0x570, "MTPCS LLC" },
+ { 0x310, 0x580, "Inland Celluar Telephone Company" },
+ { 0x310, 0x590, "Western Wireless Corporation" },
+ { 0x310, 0x600, "New Cell Inc. dba Cellcom" },
+ { 0x310, 0x610, "Elkhart Telephone Co. Inc. dba Epic Touch Co." },
+ { 0x310, 0x620, "Coleman County Telecommunications Inc. (Trans Texas PCS)" },
+ { 0x310, 0x640, "Airadigm Communications" },
+ { 0x310, 0x650, "Jasper Wireless Inc." },
+ { 0x310, 0x660, "T-Mobile USA" },
+ { 0x310, 0x670, "AT&T Mobility Vanguard Services" },
+ { 0x310, 0x680, "Cingular Wireless" },
+ { 0x310, 0x690, "Keystane Wireless LLC" },
+ { 0x310, 0x700, "Cross Valiant Cellular Partnership" },
+ { 0x310, 0x710, "Arctic Slope Telephone Association Cooperative" },
+ { 0x310, 0x720, "Wireless Solutions International Inc." },
+ { 0x310, 0x730, "US Cellular" },
+ { 0x310, 0x740, "Convey Communications Inc" },
+ { 0x310, 0x750, "East Kentucky Network LLC dba Appalachian Wireless" },
+ { 0x310, 0x760, "Lynch 3G Communcations Corporation" },
+ { 0x310, 0x770, "Iowa Wireless Services LLC dba I Wireless" },
+ { 0x310, 0x780, "Connect Net Inc" },
+ { 0x310, 0x790, "PinPoint Communications Inc."},
+ { 0x310, 0x800, "T-Mobile USA" },
+ { 0x310, 0x810, "LCFR LLC" },
+ { 0x310, 0x820, "South Canaan Cellular Communications Co. LP" },
+ { 0x310, 0x830, "Caprock Cellular Ltd. Partnership" },
+ { 0x310, 0x840, "Telecom North America Mobile Inc" },
+ { 0x310, 0x850, "Aeris Communications Inc." },
+ { 0x310, 0x860, "TX RSA 15B2, LP dba Five Star Wireless" },
+ { 0x310, 0x870, "Kaplan Telephone Company, Inc" },
+ { 0x310, 0x890, "Rural Cellular Corporation" },
+ { 0x310, 0x900, "Cable & Communications Corporation dba Mid-Rivers Wireless" },
+ { 0x310, 0x910, "Verizon Wireless" },
+ { 0x310, 0x930, "Copper Valley Wireless" },
+ { 0x310, 0x940, "Iris Wireless LLC" },
+ { 0x310, 0x950, "Texas RSA 1 dba XIT Wireless" },
+ { 0x310, 0x960, "UBET Wireless" },
+ { 0x310, 0x970, "Globalstar USA" },
+ { 0x310, 0x980, "Texas RSA 7B3 dba Peoples Wireless Services" },
+ { 0x310, 0x99, "Worldcall Interconnect" },
+
+ { 0x704, -1, "Guatemala" },
+ { 0x704, 0x01f, "Claro" },
+ { 0x704, 0x02f, "Comcel / Tigo" },
+ { 0x704, 0x03f, "movistar" },
+// { 0x704, ?, "digicel" },
+ { 0x234, -1, "Guernsey" },
+ { 0x234, 0x55f, "Sure Mobile" },
+ { 0x234, 0x50f, "Wave Telecom" },
+ { 0x234, 0x03f, "Airtel Vodafone" },
+ { 0x611, -1, "Guinea" },
+ { 0x611, 0x01f, "Orange / Spacetel" },
+ { 0x611, 0x02f, "Sotelgui / Lagui" },
+ { 0x611, 0x03f, "Telecel Guinee" }, /* ? */
+ { 0x611, 0x04f, "MTN" }, /* ? */
+ { 0x611, 0x05f, "Cellcom Guinee" },
+ { 0x632, -1, "Guinea-Bissau" },
+ { 0x632, 0x01f, "Guinetel" },
+ { 0x632, 0x02f, "Spacetel / Areeba" },
+ { 0x632, 0x03f, "Orange" },
+ { 0x738, -1, "Guyana" },
+ { 0x738, 0x01f, "Digicel" },
+ { 0x738, 0x02f, "GT&T Cellink Plus" }, /* ? */
+ { 0x372, -1, "Haiti" },
+ { 0x372, 0x01f, "Comcel / Voila" },
+ { 0x338, 0x050, "Digicel" },
+ { 0x338, 0x03f, "Rectel" },
+ { 0x708, -1, "Honduras" },
+ { 0x708, 0x01f, "Claro" },
+ { 0x708, 0x02f, "Celtel / Tigo" },
+ { 0x708, 0x30f, "Hondutel" }, /* ? */
+ { 0x708, 0x40f, "DIGICEL" },
+ { 0x454, -1, "Hong Kong" },
+ { 0x454, 0x00f, "1O1O and One2Free" },
+ { 0x454, 0x01f, "CITIC Telecom 1616" },
+ { 0x454, 0x02f, "CSL Limited" },
+ { 0x454, 0x03f, "3 (3G)" },
+ { 0x454, 0x04f, "3 DualBand (2G)" },
+ { 0x454, 0x05f, "3 CDMA" },
+ { 0x454, 0x06f, "SmarTone-Vodafone" },
+ { 0x454, 0x07f, "China Unicom (Hong Kong) Limited" },
+ { 0x454, 0x08f, "Trident" },
+ { 0x454, 0x09f, "China Motion Telecom" },
+ { 0x454, 0x10f, "New World Mobility" },
+ { 0x454, 0x11f, "China-Hongkong Telecom" },
+ { 0x454, 0x12f, "CMCC HK" },
+ { 0x454, 0x14f, "Hutchison Telecom" },
+ { 0x454, 0x15f, "SmarTone Mobile Communications Limited" },
+ { 0x454, 0x16f, "PCCW Mobile (2G)" },
+ { 0x454, 0x17f, "SmarTone Mobile Communications Limited" },
+ { 0x454, 0x18f, "CSL Limited" },
+ { 0x454, 0x19f, "Sunday3G" },
+ { 0x454, 0x19f, "PCCW Mobile (3G)" },
+ { 0x454, 0x29f, "PCCW Mobile (CDMA)" },
+ { 0x216, -1, "Hungary" },
+ { 0x216, 0x01f, "Pannon GSM" },
+ { 0x216, 0x30f, "Westel 900" },
+ { 0x216, 0x70f, "Vodafone" },
+ { 0x274, -1, "Iceland" },
+ { 0x274, 0x01f, "Siminn" },
+ { 0x274, 0x02f, "Vodafone" },
+ { 0x274, 0x03f, "Vodafone" },
+ { 0x274, 0x04f, "IMC Viking" },
+ { 0x274, 0x06f, "N?ll n?u ehf" }, /* ? */
+ { 0x274, 0x07f, "IceCell" },
+ { 0x274, 0x08f, "On-waves" },
+ { 0x274, 0x11f, "Nova" },
+ /* FIXME: update the list from here below */
+ { 0x404, -1, "India" },
+ { 0x404, 0x01f, "Vodafone IN" },
+ { 0x404, 0x02f, "AirTel" },
+ { 0x404, 0x04f, "IDEA" },
+ { 0x404, 0x05f, "Vodafone IN" },
+ { 0x404, 0x07f, "IDEA" },
+ { 0x404, 0x09f, "Reliance" },
+ { 0x404, 0x10f, "AirTel" },
+ { 0x404, 0x11f, "Vodafone IN" },
+ { 0x404, 0x12f, "IDEA" },
+ { 0x404, 0x13f, "Vodafone IN" },
+ { 0x404, 0x14f, "IDEA" },
+ { 0x404, 0x15f, "Vodafone IN" },
+ { 0x404, 0x17f, "AIRCEL" },
+ { 0x404, 0x19f, "IDEA" },
+ { 0x404, 0x20f, "Vodafone IN" },
+ { 0x404, 0x21f, "Loop Mobile" },
+ { 0x404, 0x22f, "IDEA" },
+ { 0x404, 0x24f, "IDEA" },
+ { 0x404, 0x27f, "Vodafone IN" },
+ { 0x404, 0x28f, "AIRCEL" },
+ { 0x404, 0x29f, "AIRCEL" },
+ { 0x404, 0x30f, "Vodafone IN" },
+ { 0x404, 0x31f, "AirTel" },
+ { 0x404, 0x34f, "CellOne" },
+ { 0x404, 0x36f, "Reliance" },
+ { 0x404, 0x37f, "Aircel" },
+ { 0x404, 0x38f, "CellOne" },
+ { 0x404, 0x41f, "Aircel" },
+ { 0x404, 0x42f, "Aircel" },
+ { 0x404, 0x44f, "IDEA" },
+ { 0x404, 0x45f, "Airtel" },
+ { 0x404, 0x51f, "CellOne" },
+ { 0x404, 0x52f, "Reliance" },
+ { 0x404, 0x53f, "CellOne" },
+ { 0x404, 0x54f, "CellOne" },
+ { 0x404, 0x55f, "CellOne" },
+ { 0x404, 0x56f, "IDEA" },
+ { 0x404, 0x57f, "CellOne" },
+ { 0x404, 0x58f, "CellOne" },
+ { 0x404, 0x59f, "CellOne" },
+ { 0x404, 0x60f, "Vodafone IN" },
+ { 0x404, 0x62f, "CellOne" },
+ { 0x404, 0x64f, "CellOne" },
+ { 0x404, 0x66f, "CellOne" },
+ { 0x404, 0x67f, "Reliance GSM" },
+ { 0x404, 0x68f, "DOLPHIN" },
+ { 0x404, 0x69f, "DOLPHIN" },
+ { 0x404, 0x72f, "CellOne" },
+ { 0x404, 0x74f, "CellOne" },
+ { 0x404, 0x76f, "CellOne" },
+ { 0x404, 0x78f, "Idea Cellular Ltd" },
+ { 0x404, 0x80f, "BSNL MOBILE" },
+ { 0x404, 0x81f, "CellOne" },
+ { 0x404, 0x82f, "Idea" },
+ { 0x404, 0x83f, "Reliance Smart GSM" },
+ { 0x404, 0x84f, "Vodafone IN" },
+ { 0x404, 0x85f, "Reliance" },
+ { 0x404, 0x86f, "Vodafone IN" },
+ { 0x404, 0x90f, "AirTel" },
+ { 0x404, 0x91f, "AIRCEL" },
+ { 0x404, 0x92f, "AirTel" },
+ { 0x404, 0x93f, "AirTel" },
+ { 0x404, 0x96f, "AirTel" },
+ { 0x405, 0x05f, "Reliance" },
+ { 0x405, 0x10f, "Reliance" },
+ { 0x405, 0x13f, "Reliance" },
+ { 0x405, 0x025, "TATA DOCOMO" },
+ { 0x405, 0x026, "TATA DOCOMO" },
+ { 0x405, 0x027, "TATA DOCOMO" },
+ { 0x405, 0x029, "TATA DOCOMO" },
+ { 0x405, 0x030, "TATA DOCOMO" },
+ { 0x405, 0x031, "TATA DOCOMO" },
+ { 0x405, 0x032, "TATA DOCOMO" },
+ { 0x405, 0x034, "TATA DOCOMO" },
+ { 0x405, 0x035, "TATA DOCOMO" },
+ { 0x405, 0x036, "TATA DOCOMO" },
+ { 0x405, 0x037, "TATA DOCOMO" },
+ { 0x405, 0x038, "TATA DOCOMO" },
+ { 0x405, 0x039, "TATA DOCOMO" },
+ { 0x405, 0x041, "TATA DOCOMO" },
+ { 0x405, 0x042, "TATA DOCOMO" },
+ { 0x405, 0x043, "TATA DOCOMO" },
+ { 0x405, 0x044, "TATA DOCOMO" },
+ { 0x405, 0x045, "TATA DOCOMO" },
+ { 0x405, 0x046, "TATA DOCOMO" },
+ { 0x405, 0x047, "TATA DOCOMO" },
+ { 0x405, 0x51f, "AirTel" },
+ { 0x405, 0x52f, "AirTel" },
+ { 0x405, 0x54f, "AirTel" },
+ { 0x405, 0x56f, "AirTel" },
+ { 0x405, 0x66f, "Vodafone IN" },
+ { 0x405, 0x70f, "IDEA" },
+ { 0x405, 0x750, "Vodafone IN" },
+ { 0x405, 0x751, "Vodafone IN" },
+ { 0x405, 0x752, "Vodafone IN" },
+ { 0x405, 0x753, "Vodafone IN" },
+ { 0x405, 0x754, "Vodafone IN" },
+ { 0x405, 0x755, "Vodafone IN" },
+ { 0x405, 0x756, "Vodafone IN" },
+ { 0x405, 0x799, "IDEA" },
+ { 0x405, 0x800, "AIRCEL" },
+ { 0x405, 0x801, "AIRCEL" },
+ { 0x405, 0x802, "AIRCEL" },
+ { 0x405, 0x803, "AIRCEL" },
+ { 0x405, 0x804, "AIRCEL" },
+ { 0x405, 0x805, "AIRCEL" },
+ { 0x405, 0x806, "AIRCEL" },
+ { 0x405, 0x807, "AIRCEL" },
+ { 0x405, 0x808, "AIRCEL" },
+ { 0x405, 0x809, "AIRCEL" },
+ { 0x405, 0x810, "AIRCEL" },
+ { 0x405, 0x811, "AIRCEL" },
+ { 0x405, 0x812, "AIRCEL" },
+ { 0x405, 0x819, "Uninor" },
+ { 0x405, 0x818, "[Uninor]" },
+ { 0x405, 0x820, "Uninor" },
+ { 0x405, 0x821, "Uninor" },
+ { 0x405, 0x822, "Uninor" },
+ { 0x405, 0x880, "Uninor" },
+ { 0x405, 0x824, "Videocon Datacom" },
+ { 0x405, 0x834, "Videocon Datacom" },
+ { 0x405, 0x844, "Uninor" },
+ { 0x405, 0x845, "IDEA" },
+ { 0x405, 0x848, "IDEA" },
+ { 0x405, 0x850, "IDEA" },
+ { 0x405, 0x855, "Loop Mobile" },
+ { 0x405, 0x864, "Loop Mobile" },
+ { 0x405, 0x865, "Loop Mobile" },
+ { 0x405, 0x875, "Uninor" },
+ { 0x405, 0x881, "S Tel" },
+ { 0x405, 0x912, "Etisalat DB" },
+ { 0x405, 0x913, "Etisalat DB" },
+ { 0x405, 0x917, "Etisalat DB" },
+ { 0x405, 0x929, "Uninor" },
+ { 0x510, -1, "Indonesia" },
+ { 0x510, 0x00f, "PSN" },
+ { 0x510, 0x01f, "INDOSAT" },
+ { 0x510, 0x03f, "StarOne" },
+ { 0x510, 0x07f, "TelkomFlexi" },
+ { 0x510, 0x08f, "AXIS" },
+ { 0x510, 0x09f, "SMART" },
+ { 0x510, 0x10f, "Telkomsel" },
+ { 0x510, 0x11f, "XL" },
+ { 0x510, 0x20f, "TELKOMMobile" },
+ { 0x510, 0x21f, "IM3" },
+ { 0x510, 0x27f, "Ceria" },
+ { 0x510, 0x28f, "Fren/Hepi" },
+ { 0x510, 0x89f, "3" },
+ { 0x510, 0x99f, "Esia " },
+ { 0x432, -1, "Iran" },
+ { 0x432, 0x11f, "MCI" },
+ { 0x432, 0x14f, "TKC" },
+ { 0x432, 0x19f, "MTCE" },
+ { 0x432, 0x32f, "Taliya" },
+ { 0x432, 0x35f, "Irancell" },
+ { 0x418, -1, "Iraq" },
+ { 0x418, 0x20f, "Zain IQ" },
+ { 0x418, 0x30f, "Zain IQ" },
+ { 0x418, 0x05f, "Asia Cell" },
+ { 0x418, 0x40f, "Korek" },
+ { 0x418, 0x08f, "SanaTel" },
+// { 0x418, ?, "IRAQNA" },
+ { 0x272, -1, "Ireland" },
+ { 0x272, 0x01f, "Vodafone" },
+ { 0x272, 0x02f, "O2" },
+ { 0x272, 0x03f, "Meteor" },
+ { 0x272, 0x04f, "Access Telecom" },
+ { 0x272, 0x05f, "3" },
+ { 0x272, 0x07f, "Eircom" },
+ { 0x272, 0x09f, "Clever Communications" },
+ { 0x234, -1, "Isle of Man" },
+ { 0x234, 0x58f, "Pronto GSM" },
+ { 0x425, -1, "Israel" },
+ { 0x425, 0x01f, "Orange" },
+ { 0x425, 0x02f, "Cellcom" },
+ { 0x425, 0x03f, "Pelephone" },
+ { 0x425, 0x77f, "Mirs" },
+ { 0x222, -1, "Italy" },
+ { 0x222, 0x01f, "TIM" },
+ { 0x222, 0x02f, "Elsacom" },
+ { 0x222, 0x10f, "Vodafone" },
+ { 0x222, 0x30f, "RFI" },
+ { 0x222, 0x77f, "IPSE 2000" },
+ { 0x222, 0x88f, "Wind" },
+ { 0x222, 0x98f, "Blu" },
+ { 0x222, 0x99f, "3 Italia" },
+ { 0x612, -1, "Ivory Coast" },
+ { 0x612, 0x01f, "Cora de Comstar" },
+ { 0x612, 0x02f, "Moov" },
+ { 0x612, 0x03f, "Orange" },
+ { 0x612, 0x04f, "KoZ" },
+ { 0x612, 0x05f, "MTN" },
+ { 0x612, 0x06f, "ORICEL" },
+ { 0x338, -1, "Jamaica" },
+ { 0x338, 0x020, "LIME (formerly known as Cable & Wireless)" },
+ { 0x338, 0x050, "Digicel" },
+ { 0x338, 0x070, "Claro" },
+ { 0x338, 0x180, "LIME (formerly known as Cable & Wireless)" },
+ { 0x440, -1, "Japan" },
+ { 0x440, 0x00f, "eMobile" },
+ { 0x440, 0x01f, "NTT docomo" },
+ { 0x440, 0x02f, "NTT docomo" },
+ { 0x440, 0x03f, "NTT docomo" },
+ { 0x440, 0x04f, "SoftBank" },
+ { 0x440, 0x06f, "SoftBank" },
+ { 0x440, 0x07f, "KDDI" },
+ { 0x440, 0x08f, "KDDI" },
+ { 0x440, 0x09f, "NTT docomo" },
+ { 0x440, 0x10f, "NTT docomo" },
+ { 0x440, 0x11f, "NTT docomo" },
+ { 0x440, 0x12f, "NTT docomo" },
+ { 0x440, 0x13f, "NTT docomo" },
+ { 0x440, 0x14f, "NTT docomo" },
+ { 0x440, 0x15f, "NTT docomo" },
+ { 0x440, 0x16f, "NTT docomo" },
+ { 0x440, 0x17f, "NTT docomo" },
+ { 0x440, 0x18f, "NTT docomo" },
+ { 0x440, 0x19f, "NTT docomo" },
+ { 0x440, 0x20f, "SoftBank" },
+ { 0x440, 0x21f, "NTT docomo" },
+ { 0x440, 0x22f, "NTT docomo" },
+ { 0x440, 0x23f, "DoCoMo" },
+ { 0x440, 0x24f, "DoCoMo" },
+ { 0x440, 0x25f, "DoCoMo" },
+ { 0x440, 0x26f, "DoCoMo" },
+ { 0x440, 0x27f, "DoCoMo" },
+ { 0x440, 0x28f, "DoCoMo" },
+ { 0x440, 0x29f, "DoCoMo" },
+ { 0x440, 0x30f, "DoCoMo" },
+ { 0x440, 0x31f, "DoCoMo" },
+ { 0x440, 0x32f, "DoCoMo" },
+ { 0x440, 0x33f, "DoCoMo" },
+ { 0x440, 0x34f, "DoCoMo" },
+ { 0x440, 0x35f, "DoCoMo" },
+ { 0x440, 0x36f, "DoCoMo" },
+ { 0x440, 0x37f, "DoCoMo" },
+ { 0x440, 0x38f, "DoCoMo" },
+ { 0x440, 0x39f, "DoCoMo" },
+ { 0x440, 0x40f, "SoftBank" },
+ { 0x440, 0x41f, "SoftBank" },
+ { 0x440, 0x42f, "SoftBank" },
+ { 0x440, 0x43f, "SoftBank" },
+ { 0x440, 0x44f, "SoftBank" },
+ { 0x440, 0x45f, "SoftBank" },
+ { 0x440, 0x46f, "SoftBank" },
+ { 0x440, 0x47f, "SoftBank" },
+ { 0x440, 0x48f, "SoftBank" },
+ { 0x440, 0x49f, "DoCoMo" },
+ { 0x440, 0x50f, "KDDI" },
+ { 0x440, 0x51f, "KDDI" },
+ { 0x440, 0x52f, "KDDI" },
+ { 0x440, 0x53f, "KDDI" },
+ { 0x440, 0x54f, "KDDI" },
+ { 0x440, 0x55f, "KDDI" },
+ { 0x440, 0x56f, "KDDI" },
+ { 0x440, 0x58f, "DoCoMo" },
+ { 0x440, 0x60f, "DoCoMo" },
+ { 0x440, 0x61f, "DoCoMo" },
+ { 0x440, 0x62f, "DoCoMo" },
+ { 0x440, 0x63f, "DoCoMo" },
+ { 0x440, 0x64f, "DoCoMo" },
+ { 0x440, 0x65f, "DoCoMo" },
+ { 0x440, 0x66f, "DoCoMo" },
+ { 0x440, 0x67f, "DoCoMo" },
+ { 0x440, 0x68f, "DoCoMo" },
+ { 0x440, 0x69f, "DoCoMo" },
+ { 0x440, 0x70f, "au" },
+ { 0x440, 0x71f, "KDDI" },
+ { 0x440, 0x72f, "KDDI" },
+ { 0x440, 0x73f, "KDDI" },
+ { 0x440, 0x74f, "KDDI" },
+ { 0x440, 0x75f, "KDDI" },
+ { 0x440, 0x76f, "KDDI" },
+ { 0x440, 0x77f, "KDDI" },
+ { 0x440, 0x78f, "Okinawa Cellular Telephone" },
+ { 0x440, 0x79f, "KDDI" },
+ { 0x440, 0x80f, "TU-KA" },
+ { 0x440, 0x81f, "TU-KA" },
+ { 0x440, 0x82f, "TU-KA" },
+ { 0x440, 0x83f, "TU-KA" },
+ { 0x440, 0x84f, "TU-KA" },
+ { 0x440, 0x85f, "TU-KA" },
+ { 0x440, 0x86f, "TU-KA" },
+ { 0x440, 0x87f, "DoCoMo" },
+ { 0x440, 0x88f, "KDDI" },
+ { 0x440, 0x89f, "KDDI" },
+ { 0x440, 0x90f, "SoftBank" },
+ { 0x440, 0x92f, "SoftBank" },
+ { 0x440, 0x93f, "SoftBank" },
+ { 0x440, 0x94f, "SoftBank" },
+ { 0x440, 0x95f, "SoftBank" },
+ { 0x440, 0x96f, "SoftBank" },
+ { 0x440, 0x97f, "SoftBank" },
+ { 0x440, 0x98f, "SoftBank" },
+ { 0x440, 0x99f, "DoCoMo" },
+ { 0x234, -1, "Jersey" },
+ { 0x234, 0x50f, "JT-Wave" },
+ { 0x234, 0x55f, "Sure Mobile" },
+ { 0x234, 0x03f, "Airtel Vodafone" },
+ { 0x416, -1, "Jordan" },
+ { 0x416, 0x01f, "zain JO" },
+ { 0x416, 0x02f, "XPress Telecom" },
+ { 0x416, 0x03f, "Umniah" },
+ { 0x416, 0x77f, "Orange" },
+ { 0x401, -1, "Kazakhstan" },
+ { 0x401, 0x01f, "Beeline" },
+ { 0x401, 0x02f, "Kcell" },
+ { 0x401, 0x07f, "Dalacom" },
+ { 0x401, 0x77f, "Mobile Telecom Service" },
+ { 0x639, -1, "Kenya" },
+ { 0x639, 0x02f, "Safaricom" },
+ { 0x639, 0x03f, "Zain" },
+ { 0x639, 0x07f, "Orange Kenya" },
+ { 0x545, -1, "Kiribati" },
+ { 0x545, 0x09f, "Kiribati Frigate" },
+ { 0x467, -1, "North Korea" },
+ { 0x467, 0x193, "SUN NET" },
+ { 0x450, -1, "South Korea" },
+ { 0x450, 0x02f, "KT" },
+ { 0x450, 0x03f, "Power 017" },
+ { 0x450, 0x04f, "KT" },
+ { 0x450, 0x05f, "SKT" },
+ { 0x450, 0x06f, "LGT" },
+ { 0x450, 0x08f, "KT SHOW" },
+ { 0x212, -1, "Kosovo" },
+ { 0x212, 0x01f, "Vala" },
+ { 0x293, 0x41f, "iPKO" },
+ { 0x293, 0x41f, "D3 Mobile" },
+ { 0x212, 0x01f, "Z Mobile" },
+ { 0x419, -1, "Kuwait" },
+ { 0x419, 0x02f, "zain KW" },
+ { 0x419, 0x03f, "Wataniya" },
+ { 0x419, 0x04f, "Viva" },
+ { 0x437, -1, "Kyrgyzstan" },
+ { 0x437, 0x01f, "Beeline" },
+ { 0x437, 0x05f, "MegaCom" },
+ { 0x437, 0x09f, "O!" },
+ { 0x457, -1, "Laos" },
+ { 0x457, 0x01f, "LaoTel" },
+ { 0x457, 0x02f, "ETL" },
+ { 0x457, 0x03f, "Unitel" },
+ { 0x457, 0x08f, "Tigo" },
+ { 0x247, -1, "Latvia" },
+ { 0x247, 0x01f, "LMT" },
+ { 0x247, 0x02f, "Tele2" },
+ { 0x247, 0x03f, "TRIATEL" },
+ { 0x247, 0x05f, "Bite" },
+ { 0x247, 0x06f, "Rigatta" },
+ { 0x247, 0x07f, "MTS" },
+ { 0x247, 0x08f, "IZZI" },
+ { 0x247, 0x09f, "Camel Mobile" },
+ { 0x415, -1, "Lebanon" },
+ { 0x415, 0x01f, "Alfa" },
+ { 0x415, 0x03f, "MTC-Touch" },
+ { 0x651, -1, "Lesotho" },
+ { 0x651, 0x01f, "Vodacom" },
+ { 0x651, 0x02f, "Econet Ezin-cel" },
+ { 0x618, -1, "Liberia" },
+ { 0x618, 0x01f, "Lonestar Cell" },
+ { 0x618, 0x04f, "Comium" },
+ { 0x618, 0x20f, "LIBTELCO" },
+ { 0x606, -1, "Libya" },
+ { 0x606, 0x00f, "Libyana" },
+ { 0x606, 0x01f, "Madar" },
+ { 0x295, -1, "Liechtenstein" },
+ { 0x295, 0x01f, "Swisscom" },
+ { 0x295, 0x02f, "Orange" },
+ { 0x295, 0x05f, "FL1" },
+ { 0x295, 0x77f, "Tele 2" },
+ { 0x246, -1, "Lithuania" },
+ { 0x246, 0x01f, "Omnitel" },
+ { 0x246, 0x02f, "BITE" },
+ { 0x246, 0x03f, "Tele 2" },
+ { 0x270, -1, "Luxembourg" },
+ { 0x270, 0x01f, "LuxGSM" },
+ { 0x270, 0x77f, "Tango" },
+ { 0x270, 0x99f, "Orange" },
+ { 0x455, -1, "Macau" },
+ { 0x455, 0x00f, "SmarTone" },
+ { 0x455, 0x01f, "CTM" },
+ { 0x455, 0x02f, "China Telecom" },
+ { 0x455, 0x03f, "3" },
+ { 0x455, 0x04f, "CTM" },
+ { 0x455, 0x05f, "3" },
+ { 0x294, -1, "Republic of Macedonia" },
+ { 0x294, 0x01f, "T-Mobile MK" },
+ { 0x294, 0x02f, "ONE" },
+ { 0x294, 0x03f, "Vip MK" },
+ { 0x646, -1, "Madagascar" },
+ { 0x646, 0x01f, "Zain" },
+ { 0x646, 0x02f, "Orange" },
+ { 0x646, 0x03f, "Sacel" },
+ { 0x646, 0x04f, "Telma" },
+ { 0x650, -1, "Malawi" },
+ { 0x650, 0x01f, "TNM" },
+ { 0x650, 0x10f, "Zain" },
+ { 0x502, -1, "Malaysia" },
+ { 0x502, 0x12f, "Maxis" },
+ { 0x502, 0x13f, "Celcom" },
+ { 0x502, 0x16f, "DiGi" },
+ { 0x502, 0x17f, "Maxis" },
+ { 0x502, 0x18f, "U Mobile" },
+ { 0x502, 0x19f, "Celcom" },
+ { 0x472, -1, "Maldives" },
+ { 0x472, 0x01f, "Dhiraagu" },
+ { 0x472, 0x02f, "Wataniya" },
+ { 0x610, -1, "Mali" },
+ { 0x610, 0x01f, "Malitel" },
+ { 0x610, 0x02f, "Orange" },
+ { 0x278, -1, "Malta" },
+ { 0x278, 0x01f, "Vodafone" },
+ { 0x278, 0x21f, "GO" },
+ { 0x278, 0x77f, "Melita" },
+ { 0x000, -1, "Marshall Islands" },
+// { 0x000, ?, "?" },
+ { 0x340, -1, "Martinique" },
+ { 0x340, 0x01f, "Orange" },
+ { 0x340, 0x02f, "Outremer" },
+ { 0x340, 0x20f, "Digicel" },
+ { 0x609, -1, "Mauritania" },
+ { 0x609, 0x01f, "Mattel" },
+ { 0x609, 0x10f, "Mauritel" },
+ { 0x617, -1, "Mauritius" },
+ { 0x617, 0x01f, "Orange" },
+ { 0x617, 0x02f, "MTML" },
+ { 0x617, 0x10f, "Emtel" },
+ { 0x334, -1, "Mexico" },
+ { 0x334, 0x01f, "Nextel" },
+ { 0x334, 0x02f, "Telcel" },
+ { 0x334, 0x03f, "movistar" },
+ { 0x334, 0x04f, "Iusacell / Unefon" },
+ { 0x550, -1, "Federated States of Micronesia" },
+ { 0x550, 0x01f, "FSM Telecom" },
+ { 0x259, -1, "Moldova" },
+ { 0x259, 0x01f, "Orange" },
+ { 0x259, 0x02f, "Moldcell" },
+ { 0x259, 0x03f, "IDC" },
+ { 0x259, 0x03f, "Unit?" },
+ { 0x259, 0x04f, "Eventis" },
+ { 0x259, 0x05f, "Unit?" },
+ { 0x212, -1, "Monaco" },
+ { 0x212, 0x01f, "Office des Telephones" },
+ { 0x428, -1, "Mongolia" },
+ { 0x428, 0x99f, "MobiCom" },
+ { 0x428, 0x88f, "Unitel" },
+ { 0x428, 0x91f, "Skytel" },
+ { 0x428, 0x98f, "G.Mobile" },
+ { 0x297, -1, "Montenegro" },
+ { 0x297, 0x01f, "Telenor" },
+ { 0x297, 0x02f, "T-Mobile" },
+ { 0x297, 0x03f, "m:tel CG" },
+ { 0x604, -1, "Morocco" },
+ { 0x604, 0x00f, "Moditel" },
+ { 0x604, 0x01f, "IAM" },
+ { 0x604, 0x02f, "INWI" },
+ { 0x605, 0x03f, "yassine" },
+ { 0x643, -1, "Mozambique" },
+ { 0x643, 0x01f, "mCel" },
+ { 0x643, 0x04f, "Vodacom" },
+ { 0x414, -1, "Myanmar" },
+ { 0x414, 0x01f, "MPT" },
+ { 0x649, -1, "Namibia" },
+ { 0x649, 0x01f, "MTC" },
+ { 0x649, 0x02f, "switch" },
+ { 0x649, 0x03f, "Leo" },
+ { 0x536, -1, "Nauru" },
+ { 0x429, -1, "Nepal" },
+ { 0x429, 0x01f, "Namaste / NT Mobile" },
+ { 0x429, 0x02f, "Ncell" },
+ { 0x429, 0x03f, "Sky/C-Phone" },
+ { 0x204, -1, "Netherlands" },
+ { 0x204, 0x01f, "OneFoon" },
+ { 0x204, 0x02f, "Tele2" },
+ { 0x204, 0x03f, "Blyk" },
+ { 0x204, 0x04f, "Vodafone" },
+ { 0x204, 0x05f, "Elephant Talk" },
+ { 0x204, 0x06f, "Barablu Mobile" },
+ { 0x204, 0x07f, "Teleena" },
+ { 0x204, 0x08f, "KPN" },
+ { 0x204, 0x09f, "Lycamobile" },
+ { 0x204, 0x10f, "KPN" },
+ { 0x204, 0x12f, "Telfort" },
+ { 0x204, 0x14f, "6Gmobile" },
+ { 0x204, 0x16f, "T-Mobile" },
+ { 0x204, 0x18f, "Telfort" },
+ { 0x204, 0x20f, "Orange Nederland" },
+ { 0x204, 0x21f, "NS Railinfrabeheer B.V." },
+ { 0x204, 0x67f, "RadioAccess" },
+ { 0x204, 0x69f, "KPN Mobile" },
+ { 0x362, -1, "Netherlands Antilles" },
+ { 0x362, 0x51f, "Telcell" },
+ { 0x362, 0x69f, "Digicel" },
+ { 0x362, 0x91f, "UTS" },
+ { 0x362, 0x00f, "East Caribbean Cellular" },
+ { 0x362, 0x00f, "Antiliano Por N.V." },
+ { 0x362, 0x95f, "MIO" },
+ { 0x362, 0x94f, "Bay?s" },
+ { 0x546, -1, "New Caledonia" },
+ { 0x546, 0x01f, "Mobilis" },
+ { 0x530, -1, "New Zealand" },
+ { 0x530, 0x00f, "Telecom" },
+ { 0x530, 0x01f, "Vodafone" },
+ { 0x530, 0x02f, "Telecom" },
+ { 0x530, 0x03f, "Woosh" },
+ { 0x530, 0x04f, "TelstraClear" },
+ { 0x530, 0x05f, "XT Mobile Network" },
+ { 0x530, 0x12f, "360" },
+ { 0x530, 0x24f, "2degrees" },
+ { 0x710, -1, "Nicaragua" },
+ { 0x710, 0x21f, "Claro" },
+ { 0x710, 0x30f, "movistar" },
+ { 0x710, 0x73f, "SERCOM" },
+ { 0x614, -1, "Niger" },
+ { 0x614, 0x01f, "SahelCom" },
+ { 0x614, 0x02f, "Zain" },
+ { 0x614, 0x03f, "Telecel" },
+ { 0x614, 0x04f, "Orange" },
+ { 0x621, -1, "Nigeria" },
+ { 0x621, 0x20f, "Zain" },
+ { 0x621, 0x30f, "MTN" },
+ { 0x621, 0x40f, "M-Tel" },
+ { 0x621, 0x50f, "Glo" },
+ { 0x621, 0x60f, "Etisalat" },
+ { 0x242, -1, "Norway" },
+ { 0x242, 0x01f, "Telenor" },
+ { 0x242, 0x02f, "NetCom" },
+ { 0x242, 0x03f, "Teletopia" },
+ { 0x242, 0x04f, "Tele2" },
+ { 0x242, 0x05f, "Network Norway" },
+ { 0x242, 0x06f, "Ice" },
+ { 0x242, 0x07f, "Ventelo" },
+ { 0x242, 0x08f, "TDC Mobil AS" },
+ { 0x242, 0x09f, "Barablu Mobile Norway Ltd" },
+ { 0x242, 0x20f, "Jernbaneverket AS" },
+ { 0x422, -1, "Oman" },
+ { 0x422, 0x02f, "Oman Mobile" },
+ { 0x422, 0x03f, "Nawras" },
+ { 0x410, -1, "Pakistan" },
+ { 0x410, 0x01f, "Mobilink" },
+ { 0x410, 0x03f, "Ufone" },
+ { 0x410, 0x04f, "Zong" },
+ { 0x410, 0x06f, "Telenor" },
+ { 0x410, 0x07f, "Warid" },
+ { 0x552, -1, "Palau" },
+ { 0x552, 0x01f, "PNCC" },
+ { 0x552, 0x80f, "Palau Mobile" },
+ { 0x423, -1, "Palestinian Authority" },
+ { 0x423, 0x05f, "Jawwal" },
+ { 0x423, 0x06f, "Wataniya" },
+ { 0x714, -1, "Panama" },
+ { 0x714, 0x01f, "Cable & Wireless" },
+ { 0x714, 0x02f, "movistar" },
+ { 0x714, 0x04f, "Digicel" },
+ { 0x714, 0x03f, "Claro" },
+ { 0x537, -1, "Papua New Guinea" },
+ { 0x537, 0x01f, "B-Mobile" },
+ { 0x537, 0x03f, "Digicel" },
+ { 0x744, -1, "Paraguay" },
+ { 0x744, 0x01f, "VOX" },
+ { 0x744, 0x02f, "Claro" },
+ { 0x744, 0x04f, "Tigo" },
+ { 0x744, 0x05f, "Personal" },
+ { 0x716, -1, "Peru" },
+ { 0x716, 0x06f, "movistar" },
+ { 0x716, 0x10f, "Claro" },
+ { 0x716, 0x17f, "NEXTEL" },
+ { 0x515, -1, "Philippines" },
+ { 0x515, 0x01f, "Islacom" },
+ { 0x515, 0x02f, "Globe" },
+ { 0x515, 0x03f, "Smart" },
+ { 0x515, 0x05f, "Sun" },
+ { 0x515, 0x11f, "PLDT via ACeS Philippines" },
+ { 0x515, 0x18f, "Cure" },
+ { 0x515, 0x88f, "Nextel" },
+ { 0x260, -1, "Poland" },
+ { 0x260, 0x01f, "Plus" },
+ { 0x260, 0x02f, "Era" },
+ { 0x260, 0x03f, "Orange" },
+ { 0x260, 0x04f, "Netia S.A." },
+ { 0x260, 0x05f, "Polska Telefonia Kom?rkowa Centertel Sp. z o.o." },
+ { 0x260, 0x06f, "Play" },
+ { 0x260, 0x07f, "Netia" },
+ { 0x260, 0x08f, "E-Telko Sp. z o.o." },
+ { 0x260, 0x09f, "Telekomunikacja Kolejowa Sp. z o.o." },
+ { 0x260, 0x10f, "Sferia" },
+ { 0x260, 0x11f, "Nordisk Polska" },
+ { 0x260, 0x12f, "Cyfrowy Polsat" },
+ { 0x260, 0x13f, "Sferia" },
+ { 0x260, 0x14f, "Sferia" },
+ { 0x260, 0x15f, "CenterNet" },
+ { 0x260, 0x16f, "Mobyland" },
+ { 0x260, 0x17f, "Aero2" },
+ { 0x268, -1, "Portugal" },
+ { 0x268, 0x01f, "Vodafone" },
+ { 0x268, 0x03f, "Optimus" },
+ { 0x268, 0x06f, "TMN" },
+ { 0x268, 0x21f, "Zapp" },
+ { 0x330, -1, "Puerto Rico" },
+ { 0x330, 0x11f, "Claro" },
+ { 0x427, -1, "Qatar" },
+ { 0x427, 0x01f, "Qatarnet" },
+ { 0x427, 0x02f, "Vodafone Qatar" },
+ { 0x647, -1, "R&?union" },
+ { 0x647, 0x00f, "Orange" },
+ { 0x647, 0x02f, "Outremer" },
+ { 0x647, 0x10f, "SFR Reunion" },
+ { 0x226, -1, "Romania" },
+ { 0x226, 0x01f, "Vodafone" },
+ { 0x226, 0x02f, "Romtelecom" },
+ { 0x226, 0x03f, "Cosmote" },
+ { 0x226, 0x04f, "Cosmote" },
+ { 0x226, 0x05f, "Digi.Mobil" },
+ { 0x226, 0x06f, "Cosmote" },
+ { 0x226, 0x10f, "Orange" },
+ { 0x250, -1, "Russian Federation" },
+ { 0x250, 0x01f, "MTS" },
+ { 0x250, 0x02f, "MegaFon" },
+ { 0x250, 0x03f, "NCC" },
+ { 0x250, 0x04f, "Sibchallenge" },
+ { 0x250, 0x05f, "ETK" },
+ { 0x250, 0x06f, "Skylink" },
+ { 0x250, 0x07f, "SMARTS" },
+ { 0x250, 0x09f, "Skylink" },
+ { 0x250, 0x10f, "DTC" },
+ { 0x250, 0x11f, "Orensot" },
+ { 0x250, 0x12f, "Baykalwestcom" },
+ { 0x250, 0x12f, "Akos" },
+ { 0x250, 0x13f, "KUGSM" },
+ { 0x250, 0x15f, "SMARTS" },
+ { 0x250, 0x16f, "NTC" },
+ { 0x250, 0x17f, "Utel" },
+ { 0x250, 0x19f, "INDIGO" },
+ { 0x250, 0x20f, "Tele2" },
+ { 0x250, 0x23f, "Mobicom - Novosibirsk" },
+ { 0x250, 0x28f, "Beeline" },
+ { 0x250, 0x35f, "MOTIV" },
+ { 0x250, 0x38f, "Tambov GSM" },
+ { 0x250, 0x39f, "Utel" },
+ { 0x250, 0x44f, "Stavtelesot / North Caucasian GSM" },
+ { 0x250, 0x92f, "Primtelefon" },
+ { 0x250, 0x93f, "Telecom XXI" },
+ { 0x250, 0x99f, "Beeline" },
+// { 0x250, ?, "SkyLink/MTS/the Moscow Cellular communication" },
+ { 0x635, -1, "Rwanda" },
+ { 0x635, 0x10f, "MTN" },
+ { 0x635, 0x13f, "Tigo" },
+ { 0x356, -1, "Saint Kitts and Nevis" },
+ { 0x356, 0x050, "Digicel" },
+ { 0x356, 0x110, "Cable & Wireless" },
+ { 0x358, -1, "Saint Lucia" },
+ { 0x358, 0x050, "Digicel" },
+ { 0x358, 0x110, "Cable & Wireless" },
+ { 0x308, -1, "Saint Pierre and Miquelon" },
+ { 0x308, 0x01f, "Ameris" },
+ { 0x360, -1, "Saint Vincent and the Grenadines" },
+ { 0x360, 0x070, "Digicel" },
+ { 0x360, 0x100, "Cingular Wireless" },
+ { 0x360, 0x110, "Cable & Wireless" },
+ { 0x549, -1, "Samoa" },
+ { 0x549, 0x01f, "Digicel" },
+ { 0x549, 0x27f, "SamoaTel" },
+ { 0x292, -1, "San Marino" },
+ { 0x292, 0x01f, "PRIMA" },
+ { 0x626, -1, "Sao Tome and Principe" },
+ { 0x626, 0x01f, "CSTmovel" },
+ { 0x420, -1, "Saudi Arabia" },
+ { 0x420, 0x01f, "Al Jawal" },
+ { 0x420, 0x03f, "Mobily" },
+ { 0x420, 0x07f, "EAE" },
+ { 0x420, 0x04f, "Zain SA" },
+ { 0x608, -1, "Senegal" },
+ { 0x608, 0x01f, "Orange (telecommunications)" },
+ { 0x608, 0x02f, "Tigo" },
+ { 0x608, 0x03f, "Expresso" },
+ { 0x220, -1, "Serbia" },
+ { 0x220, 0x01f, "Telenor" },
+ { 0x220, 0x03f, "mt:s" },
+ { 0x220, 0x05f, "VIP" },
+ { 0x633, -1, "Seychelles" },
+ { 0x633, 0x01f, "Cable & Wireless" },
+ { 0x633, 0x02f, "Mediatech International" },
+ { 0x633, 0x10f, "Airtel" },
+ { 0x619, -1, "Sierra Leone" },
+ { 0x619, 0x01f, "Zain" },
+ { 0x619, 0x02f, "Millicom" },
+ { 0x619, 0x03f, "Datatel" },
+ { 0x619, 0x04f, "Comium" },
+ { 0x619, 0x05f, "Africell" },
+ { 0x619, 0x25f, "Mobitel" },
+// { 0x619, ?, "LeoneCel" },
+ { 0x525, -1, "Singapore" },
+ { 0x525, 0x01f, "SingTel" },
+ { 0x525, 0x02f, "SingTel-G18" },
+ { 0x525, 0x03f, "M1" },
+ { 0x525, 0x05f, "StarHub" },
+ { 0x525, 0x12f, "Digital Trunked Radio Network" },
+ { 0x231, -1, "Slovakia" },
+ { 0x231, 0x01f, "Orange" },
+ { 0x231, 0x02f, "T-Mobile" },
+ { 0x231, 0x03f, "Unient Communications" },
+ { 0x231, 0x04f, "T-Mobile" },
+ { 0x231, 0x05f, "Mobile Entertainment Company" },
+ { 0x231, 0x06f, "O2" },
+ { 0x231, 0x99f, "?SR" },
+ { 0x293, -1, "Slovenia" },
+ { 0x293, 0x40f, "Si.mobil" },
+ { 0x293, 0x41f, "Mobitel" },
+ { 0x293, 0x64f, "T-2" },
+ { 0x293, 0x70f, "Tu?mobil" },
+ { 0x540, -1, "Solomon Islands" },
+ { 0x637, -1, "Somalia" },
+ { 0x637, 0x01f, "Telesom" },
+ { 0x637, 0x04f, "Somafone" },
+ { 0x637, 0x10f, "Nationlink" },
+ { 0x637, 0x25f, "Hormuud" },
+ { 0x637, 0x30f, "Golis" },
+ { 0x637, 0x82f, "Telcom" },
+ { 0x655, -1, "South Africa" },
+ { 0x655, 0x01f, "Vodacom" },
+ { 0x655, 0x06f, "Sentech" },
+ { 0x655, 0x07f, "Cell C" },
+ { 0x655, 0x10f, "MTN" },
+ { 0x655, 0x11f, "SAPS Gauteng" },
+ { 0x655, 0x13f, "Neotel" },
+ { 0x655, 0x21f, "Cape Town Metropolitan Council" },
+ { 0x655, 0x30f, "Bokamoso Consortium" },
+ { 0x655, 0x31f, "Karabo Telecoms (Pty) Ltd." },
+ { 0x655, 0x32f, "Ilizwi Telecommunications" },
+ { 0x655, 0x33f, "Thinta Thinta Telecommunications" },
+ { 0x655, 0x02f, "Telkom" },
+ { 0x214, -1, "Spain" },
+ { 0x214, 0x01f, "Vodafone" },
+ { 0x214, 0x03f, "Orange" },
+ { 0x214, 0x04f, "Yoigo" },
+ { 0x214, 0x05f, "TME" },
+ { 0x214, 0x06f, "Vodafone" },
+ { 0x214, 0x07f, "movistar" },
+ { 0x214, 0x08f, "Euskaltel" },
+ { 0x214, 0x09f, "Orange" },
+ { 0x214, 0x15f, "BT" },
+ { 0x214, 0x16f, "TeleCable" },
+ { 0x214, 0x17f, "M?bil R" },
+ { 0x214, 0x18f, "ONO" },
+ { 0x214, 0x19f, "Simyo" },
+ { 0x214, 0x21f, "Jazztel" },
+ { 0x214, 0x22f, "DigiMobil" },
+ { 0x214, 0x23f, "Barablu" },
+ { 0x413, -1, "Sri Lanka" },
+ { 0x413, 0x01f, "Mobitel" },
+ { 0x413, 0x02f, "Dialog" },
+ { 0x413, 0x03f, "Etisalat" },
+ { 0x413, 0x05f, "Airtel" },
+ { 0x413, 0x08f, "Hutch" },
+ { 0x413, 0x00f, "RTEC Mobile" },
+ { 0x634, -1, "Sudan" },
+ { 0x634, 0x01f, "Zain SD" },
+ { 0x634, 0x02f, "MTN" },
+ { 0x634, 0x05f, "Vivacell" },
+ { 0x746, -1, "Suriname" },
+ { 0x746, 0x05f, "Telesur" },
+ { 0x653, -1, "Swaziland" },
+ { 0x653, 0x10f, "Swazi MTN" },
+ { 0x240, -1, "Sweden" },
+ { 0x240, 0x01f, "Telia" },
+ { 0x240, 0x02f, "3" },
+ { 0x240, 0x03f, "Ice.net" },
+ { 0x240, 0x04f, "3G Infrastructure Services" },
+ { 0x240, 0x05f, "Sweden 3G" },
+ { 0x240, 0x06f, "Telenor" },
+ { 0x240, 0x07f, "Tele2" },
+ { 0x240, 0x08f, "Telenor" },
+ { 0x240, 0x09f, "djuice" },
+ { 0x240, 0x10f, "Spring Mobil" },
+ { 0x240, 0x11f, "Lindholmen Science Park" },
+ { 0x240, 0x12f, "Barablu Mobile Scandinavia" },
+ { 0x240, 0x13f, "Ventelo Sverige" },
+ { 0x240, 0x14f, "TDC Mobil" },
+ { 0x240, 0x15f, "Wireless Maingate Nordic" },
+ { 0x240, 0x16f, "42IT" },
+ { 0x240, 0x17f, "G?talandsn?tet" },
+ { 0x240, 0x20f, "Wireless Maingate Message Services" },
+ { 0x240, 0x21f, "MobiSir" },
+ { 0x240, 0x25f, "DigiTelMobile" },
+ { 0x228, -1, "Switzerland" },
+ { 0x228, 0x01f, "Swisscom" },
+ { 0x228, 0x02f, "Sunrise" },
+ { 0x228, 0x03f, "Orange" },
+ { 0x228, 0x05f, "Togewanet AG (Comfone)" },
+ { 0x228, 0x06f, "SBB AG" },
+ { 0x228, 0x07f, "IN&Phone" },
+ { 0x228, 0x08f, "Tele2" },
+ { 0x228, 0x50f, "3G Mobile AG" },
+ { 0x228, 0x51f, "BebbiCell AG" },
+ { 0x417, -1, "Syria" },
+ { 0x417, 0x01f, "Syriatel" },
+ { 0x417, 0x02f, "MTN" },
+ { 0x466, -1, "Taiwan" },
+ { 0x466, 0x01f, "FarEasTone" },
+ { 0x466, 0x02f, "APTG" },
+ { 0x466, 0x06f, "Tuntex" },
+ { 0x466, 0x11f, "Chunghwa LDM" },
+ { 0x466, 0x88f, "KG Telecom" },
+ { 0x466, 0x89f, "VIBO" },
+ { 0x466, 0x92f, "Chungwa" },
+ { 0x466, 0x93f, "MobiTai" },
+ { 0x466, 0x97f, "Taiwan Mobile" },
+ { 0x466, 0x99f, "TransAsia" },
+ { 0x436, -1, "Tajikistan" },
+ { 0x436, 0x01f, "Tcell" },
+ { 0x436, 0x02f, "Indigo" },
+ { 0x436, 0x03f, "MLT" },
+ { 0x436, 0x04f, "Babilon-M" },
+ { 0x436, 0x05f, "Beeline" },
+ { 0x640, -1, "Tanzania" },
+ { 0x640, 0x06f, "SasaTel" },
+ { 0x640, 0x02f, "tiGO" },
+ { 0x640, 0x03f, "Zantel" },
+ { 0x640, 0x04f, "Vodacom" },
+ { 0x640, 0x05f, "Zain" },
+ { 0x520, -1, "Thailand" },
+ { 0x520, 0x00f, "Hutch" },
+ { 0x520, 0x01f, "AIS" },
+ { 0x520, 0x02f, "CAT CDMA" },
+ { 0x520, 0x10f, "?" },
+ { 0x520, 0x15f, "Thai Mobile" },
+ { 0x520, 0x15f, "TOT 3G" },
+ { 0x520, 0x18f, "dtac" },
+ { 0x520, 0x23f, "AIS GSM 1800" },
+ { 0x520, 0x99f, "True Move" },
+ { 0x520, 0x00f, "WE PCT" },
+ { 0x615, -1, "Togo" },
+ { 0x615, 0x01f, "Togo Cell" },
+ { 0x615, 0x03f, "Moov" },
+ { 0x539, -1, "Tonga" },
+ { 0x539, 0x01f, "Tonga Communications Corporation" },
+ { 0x539, 0x43f, "Shoreline Communication" },
+ { 0x539, 0x88f, "Digicel" },
+ { 0x374, -1, "Trinidad and Tobago" },
+ { 0x374, 0x12f, "bmobile" },
+ { 0x374, 0x13f, "Digicel" },
+ { 0x605, -1, "Tunisia" },
+ { 0x605, 0x01f, "Orange" },
+ { 0x605, 0x02f, "Tunicell" },
+ { 0x605, 0x03f, "Tunisiana" },
+ { 0x286, -1, "Turkey" },
+ { 0x286, 0x01f, "Turkcell" },
+ { 0x286, 0x02f, "Vodafone" },
+ { 0x286, 0x03f, "Avea" },
+ { 0x286, 0x04f, "Aycell" },
+ { 0x438, -1, "Turkmenistan" },
+ { 0x438, 0x01f, "MTS" },
+ { 0x438, 0x02f, "TM-Cell" },
+ { 0x376, -1, "Turks and Caicos Islands" },
+ { 0x376, 0x350, "C&W" },
+ { 0x376, 0x352, "Islandcom" },
+ { 0x338, 0x05f, "Digicel" },
+ { 0x553, -1, "Tuvalu" },
+ { 0x553, 0x01f, "TTC" },
+ { 0x641, -1, "Uganda" },
+ { 0x641, 0x01f, "Zain" },
+ { 0x641, 0x10f, "MTN" },
+ { 0x641, 0x11f, "Uganda Telecom Ltd." },
+ { 0x641, 0x22f, "Warid Telecom" },
+ { 0x641, 0x14f, "Orange" },
+ { 0x255, -1, "Ukraine" },
+ { 0x255, 0x01f, "MTS" },
+ { 0x255, 0x02f, "Beeline" },
+ { 0x255, 0x03f, "Kyivstar" },
+ { 0x255, 0x04f, "IT" },
+ { 0x255, 0x05f, "Golden Telecom" },
+ { 0x255, 0x06f, "life:)" },
+ { 0x255, 0x07f, "Ukrtelecom" },
+ { 0x255, 0x21f, "PEOPLEnet" },
+ { 0x255, 0x23f, "CDMA Ukraine" },
+ { 0x424, -1, "United Arab Emirates" },
+ { 0x424, 0x02f, "Etisalat" },
+ { 0x424, 0x03f, "du" },
+ { 0x234, -1, "United Kingdom" },
+ { 0x234, 0x00f, "BT" },
+ { 0x234, 0x01f, "UK01" },
+ { 0x234, 0x02f, "O2" },
+ { 0x234, 0x03f, "Airtel-Vodafone" },
+ { 0x234, 0x04f, "FMS Solutions Ltd" },
+ { 0x234, 0x07f, "Cable and Wireless UK" },
+ { 0x234, 0x08f, "OnePhone Ltd" },
+ { 0x234, 0x10f, "O2" },
+ { 0x234, 0x11f, "O2" },
+ { 0x234, 0x12f, "Railtrack" },
+ { 0x234, 0x14f, "Hay Systems Ltd" },
+ { 0x234, 0x15f, "Vodafone" },
+ { 0x234, 0x16f, "Opal Telecom Ltd" },
+ { 0x234, 0x18f, "Cloud9" },
+ { 0x234, 0x19f, "Teleware" },
+ { 0x234, 0x20f, "3" },
+ { 0x234, 0x22f, "RoutoMessaging" },
+ { 0x234, 0x25f, "Truphone" },
+ { 0x234, 0x30f, "T-Mobile" },
+ { 0x234, 0x31f, "Virgin" },
+ { 0x234, 0x32f, "Virgin" },
+ { 0x234, 0x33f, "Orange" },
+ { 0x234, 0x34f, "Orange" },
+ { 0x234, 0x50f, "JT-Wave" },
+ { 0x234, 0x55f, "Cable & Wireless Guernsey / Sure Mobile (Jersey)" },
+ { 0x234, 0x58f, "Manx Telecom" },
+ { 0x234, 0x75f, "Inquam" },
+ { 0x234, 0x77f, "BT" },
+ { 0x200, -1, "United States of America" },
+ { 0x200, 0x053, "Virgin Mobile US" },
+ { 0x200, 0x054, "Alltel US" },
+ { 0x200, 0x066, "U.S. Cellular" },
+ /* 0x310 taken from Annex to ITU Operational Bulletin No. 958 – 15.VI.2010 */
+ { 0x310, 0x00f, "nTelos" },
+ { 0x310, 0x000, "Mid-Tex Cellular" },
+ { 0x310, 0x004, "Verizon" },
+ { 0x310, 0x010, "MCI" },
+ { 0x310, 0x012, "Verizon" },
+ { 0x310, 0x013, "MobileTel" },
+ { 0x310, 0x014, "Testing" },
+ { 0x310, 0x016, "Cricket Communications" },
+ { 0x310, 0x017, "North Sight Communications Inc." },
+ { 0x310, 0x020, "Union Telephone Company" },
+ { 0x310, 0x026, "T-Mobile" },
+ { 0x310, 0x030, "Centennial" },
+ { 0x310, 0x034, "Airpeak" },
+ { 0x310, 0x038, "AT&T" },
+ { 0x310, 0x040, "Concho" },
+ { 0x310, 0x046, "SIMMETRY" },
+ { 0x310, 0x060, "Consolidated Telcom" },
+ { 0x310, 0x070, "Highland Cellular" },
+ { 0x310, 0x080, "Corr" },
+ { 0x310, 0x090, "AT&T" },
+ { 0x310, 0x100, "Plateau Wireless" },
+ { 0x310, 0x110, "PTI Pacifica" },
+ { 0x310, 0x120, "Sprint" },
+ { 0x310, 0x150, "AT&T" },
+ { 0x310, 0x160, "T-Mobile" },
+ { 0x310, 0x170, "T-Mobile" },
+ { 0x310, 0x180, "West Central" },
+ { 0x310, 0x190, "Dutch Harbor" },
+ { 0x310, 0x200, "T-Mobile" },
+ { 0x310, 0x210, "T-Mobile" },
+ { 0x310, 0x220, "T-Mobile" },
+ { 0x310, 0x230, "T-Mobile" },
+ { 0x310, 0x240, "T-Mobile" },
+ { 0x310, 0x250, "T-Mobile" },
+ { 0x310, 0x260, "T-Mobile" },
+ { 0x310, 0x270, "T-Mobile" },
+ { 0x310, 0x280, "T-Mobile" },
+ { 0x310, 0x290, "T-Mobile" },
+ { 0x310, 0x300, "iSmart Mobile" },
+ { 0x310, 0x310, "T-Mobile" },
+ { 0x310, 0x311, "Farmers Wireless" },
+ { 0x310, 0x320, "Cellular One" },
+ { 0x310, 0x330, "T-Mobile" },
+ { 0x310, 0x340, "Westlink" },
+ { 0x310, 0x350, "Carolina Phone" },
+ { 0x310, 0x380, "AT&T Mobility" },
+ { 0x310, 0x390, "Cellular One of East Texas" },
+ { 0x310, 0x400, "i CAN_GSM" },
+ { 0x310, 0x410, "AT&T" },
+ { 0x310, 0x420, "Cincinnati Bell" },
+ { 0x310, 0x430, "Alaska Digitel" },
+ { 0x310, 0x440, "Cellular One" },
+ { 0x310, 0x450, "Viaero" },
+ { 0x310, 0x460, "Simmetry" },
+ { 0x310, 0x480, "Choice Phone" },
+ { 0x310, 0x490, "T-Mobile" },
+ { 0x310, 0x500, "Alltel" },
+ { 0x310, 0x510, "Airtel" },
+ { 0x310, 0x520, "VeriSign" },
+ { 0x310, 0x530, "West Virginia Wireless" },
+ { 0x310, 0x540, "Oklahoma Western" },
+ { 0x310, 0x560, "AT&T" },
+ { 0x310, 0x570, "Cellular One" },
+ { 0x310, 0x580, "T-Mobile" },
+ { 0x310, 0x590, "Alltel" },
+ { 0x310, 0x610, "Epic Touch" },
+ { 0x310, 0x620, "Coleman County Telecom" },
+ { 0x310, 0x630, "AmeriLink PCS" },
+ { 0x310, 0x640, "Airadigm" },
+ { 0x310, 0x650, "Jasper" },
+ { 0x310, 0x660, "T-Mobile" },
+ { 0x310, 0x670, "Northstar" },
+ { 0x310, 0x680, "AT&T" },
+ { 0x310, 0x690, "Conestoga" },
+ { 0x310, 0x730, "SeaMobile" },
+ { 0x310, 0x740, "Convey" },
+ { 0x310, 0x760, "Panhandle" },
+ { 0x310, 0x770, "i wireless" },
+ { 0x310, 0x780, "Airlink PCS" },
+ { 0x310, 0x790, "PinPoint" },
+ { 0x310, 0x800, "T-Mobile" },
+ { 0x310, 0x830, "Caprock" },
+ { 0x310, 0x850, "Aeris" },
+ { 0x310, 0x870, "PACE" },
+ { 0x310, 0x880, "Advantage" },
+ { 0x310, 0x890, "Unicel" },
+ { 0x310, 0x900, "Mid-Rivers Wireless" },
+ { 0x310, 0x910, "First Cellular" },
+ { 0x310, 0x940, "Iris Wireless LLC" },
+ { 0x310, 0x950, "XIT Wireless" },
+ { 0x310, 0x960, "Plateau Wireless" },
+ { 0x310, 0x970, "Globalstar" },
+ { 0x310, 0x980, "AT&T Mobility" },
+ { 0x310, 0x990, "AT&T Mobility" },
+ { 0x311, 0x000, "Mid-Tex Cellular" },
+ { 0x311, 0x010, "Chariton Valley" },
+ { 0x311, 0x020, "Missouri RSA 5 Partnership" },
+ { 0x311, 0x030, "Indigo Wireless" },
+ { 0x311, 0x040, "Commnet Wireless" },
+ { 0x311, 0x050, "Wikes Cellular" },
+ { 0x311, 0x060, "Farmers Cellular" },
+ { 0x311, 0x070, "Easterbrooke" },
+ { 0x311, 0x080, "Pine Cellular" },
+ { 0x311, 0x090, "Long Lines Wireless" },
+ { 0x311, 0x100, "High Plains Wireless" },
+ { 0x311, 0x110, "High Plains Wireless" },
+ { 0x311, 0x120, "Choice Phone" },
+ { 0x311, 0x130, "Cell One Amarillo" },
+ { 0x311, 0x140, "Sprocket" },
+ { 0x311, 0x150, "Wilkes Cellular" },
+ { 0x311, 0x160, "Endless Mountains Wireless" },
+ { 0x311, 0x170, "PetroCom" },
+ { 0x311, 0x180, "Cingular Wireless" },
+ { 0x311, 0x190, "Cellular Properties" },
+ { 0x311, 0x210, "Farmers Cellular" },
+ { 0x316, 0x010, "Nextel" },
+ { 0x316, 0x011, "Southern Communications Services" },
+ { 0x748, -1, "Uruguay" },
+ { 0x748, 0x00f, "Ancel" },
+ { 0x748, 0x01f, "Ancel" },
+ { 0x748, 0x07f, "Movistar" },
+ { 0x748, 0x10f, "Claro" },
+ { 0x434, -1, "Uzbekistan" },
+ { 0x434, 0x01f, "Buztel" },
+ { 0x434, 0x02f, "Uzmacom" },
+ { 0x434, 0x04f, "Beeline" },
+ { 0x434, 0x05f, "Ucell" },
+ { 0x434, 0x06f, "Perfectum Mobile" },
+ { 0x434, 0x07f, "MTS" },
+ { 0x541, -1, "Vanuatu" },
+ { 0x541, 0x01f, "SMILE" },
+ { 0x225, -1, "Vatican" },
+ { 0x734, -1, "Venezuela" },
+ { 0x734, 0x01f, "Digitel" },
+ { 0x734, 0x02f, "Digitel" },
+ { 0x734, 0x03f, "Digitel" },
+ { 0x734, 0x04f, "movistar" },
+ { 0x734, 0x06f, "Movilnet" },
+ { 0x452, -1, "Vietnam" },
+ { 0x452, 0x01f, "MobiFone" },
+ { 0x452, 0x02f, "Vinaphone" },
+ { 0x452, 0x03f, "S-Fone" },
+ { 0x452, 0x04f, "Viettel Mobile" },
+ { 0x452, 0x05f, "Vietnamobile" },
+ { 0x452, 0x06f, "E-Mobile" },
+ { 0x452, 0x07f, "Beeline VN" },
+ { 0x421, -1, "Yemen" },
+ { 0x421, 0x01f, "SabaFon" },
+ { 0x421, 0x02f, "MTN" },
+ { 0x421, 0x03f, "Yemen Mobile" },
+ { 0x421, 0x04f, "HiTS-UNITEL" },
+ { 0x645, -1, "Zambia" },
+ { 0x645, 0x01f, "Zain" },
+ { 0x645, 0x02f, "MTN" },
+ { 0x645, 0x03f, "ZAMTEL" },
+ { 0x648, -1, "Zimbabwe" },
+ { 0x648, 0x01f, "Net*One" },
+ { 0x648, 0x03f, "Telecel" },
+ { 0x648, 0x04f, "Econet" },
+ { 0x901, -1, "International" },
+ { 0x901, 0x01f, "ICO" },
+ { 0x901, 0x02f, "Sense Communications International" },
+ { 0x901, 0x03f, "Iridium" },
+ { 0x901, 0x04f, "Globalstar" },
+ { 0x901, 0x05f, "Thuraya RMSS Network" },
+ { 0x901, 0x06f, "Thuraya Satellite Telecommunications Company" },
+ { 0x901, 0x07f, "Ellipso" },
+ { 0x901, 0x08f, "" },
+ { 0x901, 0x09f, "Tele1 Europe" },
+ { 0x901, 0x10f, "ACeS" },
+ { 0x901, 0x11f, "Inmarsat" },
+ { 0x901, 0x12f, "MCP" },
+ { 0x901, 0x13f, "GSM.AQ" },
+ { 0x901, 0x14f, "AeroMobile AS" },
+ { 0x901, 0x15f, "OnAir Switzerland Sarl" },
+ { 0x901, 0x16f, "Jasper Systems" },
+ { 0x901, 0x17f, "Navitas" },
+ { 0x901, 0x18f, "Cellular @Sea" },
+ { 0x901, 0x19f, "Vodafone Malta Maritime" },
+ { 0x901, 0x21f, "Seanet" },
+ { 0x901, 0x24f, "iNum" },
+ { 0x901, 0x29f, "Telenor" },
+ { 0, 0, NULL }
+};
+
+/* GSM 03.22 Annex A */
+int gsm_match_mcc(uint16_t mcc, char *imsi)
+{
+ uint16_t sim_mcc;
+
+ sim_mcc = ((imsi[0] - '0') << 8)
+ + ((imsi[1] - '0') << 4)
+ + imsi[2] - '0';
+
+ return (mcc == sim_mcc);
+}
+
+/* GSM 03.22 Annex A */
+int gsm_match_mnc(uint16_t mcc, uint16_t mnc, char *imsi)
+{
+ uint16_t sim_mnc;
+
+ /* 1. SIM-MCC = BCCH-MCC */
+ if (!gsm_match_mcc(mcc, imsi))
+ return 0;
+
+ /* 2. 3rd digit of BCCH-MNC is not 0xf */
+ if ((mnc & 0x00f) != 0x00f) {
+ /* 3. 3 digit SIM-MNC = BCCH-MNC */
+ sim_mnc = ((imsi[3] - '0') << 8)
+ + ((imsi[4] - '0') << 4)
+ + imsi[5] - '0';
+
+ return (mnc == sim_mnc);
+ }
+
+ /* 4. BCCH-MCC in the range 310-316 */
+ if (mcc >= 310 && mcc <= 316) {
+ /* 5. 3rd diit of SIM-MNC is 0 */
+ if (imsi[5] != 0)
+ return 0;
+ }
+
+ /* 6. 1st 2 digits of SIM-MNC and BCCH-MNC match */
+ sim_mnc = ((imsi[3] - '0') << 8)
+ + ((imsi[4] - '0') << 4)
+ + 0x00f;
+
+ return (mnc == sim_mnc);
+}
+
+const char *gsm_print_mcc(uint16_t mcc)
+{
+ static char string[5] = "000";
+
+ snprintf(string, 4, "%03x", mcc);
+ return string;
+}
+
+const char *gsm_print_mnc(uint16_t mnc)
+{
+ static char string[7];
+
+ /* invalid format: return hex value */
+ if ((mnc & 0xf000)
+ || (mnc & 0x0f00) > 0x0900
+ || (mnc & 0x00f0) > 0x0090
+ || ((mnc & 0x000f) > 0x0009 && (mnc & 0x000f) < 0x000f)) {
+ snprintf(string, 6, "0x%03x", mnc);
+ return string;
+ }
+
+ /* two digits */
+ if ((mnc & 0x000f) == 0x000f) {
+ snprintf(string, 6, "%02x", mnc >> 4);
+ return string;
+ }
+
+ /* three digits */
+ snprintf(string, 6, "%03x", mnc);
+ return string;
+}
+
+const uint16_t gsm_input_mcc(char *string)
+{
+ uint16_t mcc;
+
+ if (strlen(string) != 3)
+ return GSM_INPUT_INVALID;
+ if (string[0] < '0' || string [0] > '9'
+ || string[1] < '0' || string [1] > '9'
+ || string[2] < '0' || string [2] > '9')
+ return GSM_INPUT_INVALID;
+
+ mcc = ((string[0] - '0') << 8)
+ | ((string[1] - '0') << 4)
+ | ((string[2] - '0'));
+
+ if (mcc == 0x000)
+ return GSM_INPUT_INVALID;
+
+ return mcc;
+}
+
+const uint16_t gsm_input_mnc(char *string)
+{
+ uint16_t mnc = 0;
+
+ if (strlen(string) == 2) {
+ if (string[0] < '0' || string [0] > '9'
+ || string[1] < '0' || string [1] > '9')
+ return GSM_INPUT_INVALID;
+
+ mnc = ((string[0] - '0') << 8)
+ | ((string[1] - '0') << 4)
+ | 0x00f;
+ } else
+ if (strlen(string) == 3) {
+ if (string[0] < '0' || string [0] > '9'
+ || string[1] < '0' || string [1] > '9'
+ || string[2] < '0' || string [2] > '9')
+ return GSM_INPUT_INVALID;
+
+ mnc = ((string[0] - '0') << 8)
+ | ((string[1] - '0') << 4)
+ | ((string[2] - '0'));
+ }
+
+ return mnc;
+}
+
+const char *gsm_get_mcc(uint16_t mcc)
+{
+ int i;
+
+ for (i = 0; gsm_networks[i].name; i++)
+ if (gsm_networks[i].mnc < 0 && gsm_networks[i].mcc == mcc)
+ return gsm_networks[i].name;
+
+ return gsm_print_mcc(mcc);
+}
+
+const char *gsm_get_mnc(uint16_t mcc, uint16_t mnc)
+{
+ int i;
+
+ for (i = 0; gsm_networks[i].name; i++)
+ if (gsm_networks[i].mcc == mcc && gsm_networks[i].mnc == mnc)
+ return gsm_networks[i].name;
+
+ return gsm_print_mnc(mnc);
+}
+
+/* get MCC from IMSI */
+const char *gsm_imsi_mcc(char *imsi)
+{
+ int i, found = 0;
+ uint16_t mcc;
+
+ mcc = ((imsi[0] - '0') << 8)
+ | ((imsi[1] - '0') << 4)
+ | ((imsi[2] - '0'));
+
+ for (i = 0; gsm_networks[i].name; i++) {
+ if (gsm_networks[i].mcc == mcc) {
+ found = 1;
+ break;
+ }
+ }
+ if (found == 0)
+ return "Unknown";
+
+ return gsm_networks[i].name;
+}
+
+/* get MNC from IMSI */
+const char *gsm_imsi_mnc(char *imsi)
+{
+ int i, found = 0, position = 0;
+ uint16_t mcc, mnc2, mnc3;
+
+ mcc = ((imsi[0] - '0') << 8)
+ | ((imsi[1] - '0') << 4)
+ | ((imsi[2] - '0'));
+ mnc2 = ((imsi[3] - '0') << 8)
+ + ((imsi[4] - '0') << 4)
+ + 0x00f;
+ mnc3 = ((imsi[3] - '0') << 8)
+ + ((imsi[4] - '0') << 4)
+ + imsi[5] - '0';
+
+ for (i = 0; gsm_networks[i].name; i++) {
+ if (gsm_networks[i].mcc != mcc)
+ continue;
+ if ((gsm_networks[i].mnc & 0x00f) == 0x00f) {
+ if (mnc2 == gsm_networks[i].mnc) {
+ found++;
+ position = i;
+ }
+ } else {
+ if (mnc3 == gsm_networks[i].mnc) {
+ found++;
+ position = i;
+ }
+ }
+ }
+
+ if (found == 0)
+ return "Unknown";
+ if (found > 1)
+ return "Ambiguous";
+ return gsm_networks[position].name;
+}
+
+
diff --git a/src/host/layer23/src/common/sap_interface.c b/src/host/layer23/src/common/sap_interface.c
new file mode 100644
index 00000000..1dad748d
--- /dev/null
+++ b/src/host/layer23/src/common/sap_interface.c
@@ -0,0 +1,190 @@
+/* BTSAP socket interface of layer2/3 stack */
+
+/* (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/sap_interface.h>
+
+#include <osmocom/core/utils.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <arpa/inet.h>
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define GSM_SAP_LENGTH 300
+#define GSM_SAP_HEADROOM 32
+
+static int sap_read(struct osmo_fd *fd)
+{
+ struct msgb *msg;
+ uint16_t len;
+ int rc;
+ struct osmocom_ms *ms = (struct osmocom_ms *) fd->data;
+
+ msg = msgb_alloc_headroom(GSM_SAP_LENGTH+GSM_SAP_HEADROOM, GSM_SAP_HEADROOM, "Layer2");
+ if (!msg) {
+ LOGP(DSAP, LOGL_ERROR, "Failed to allocate msg.\n");
+ return -ENOMEM;
+ }
+
+ rc = read(fd->fd, &len, sizeof(len));
+ if (rc < sizeof(len)) {
+ fprintf(stderr, "SAP socket failed\n");
+ msgb_free(msg);
+ if (rc >= 0)
+ rc = -EIO;
+ sap_close(ms);
+ return rc;
+ }
+
+ len = ntohs(len);
+ if (len > GSM_SAP_LENGTH) {
+ LOGP(DSAP, LOGL_ERROR, "Length is too big: %u\n", len);
+ msgb_free(msg);
+ return -EINVAL;
+ }
+
+
+ msg->l1h = msgb_put(msg, len);
+ rc = read(fd->fd, msg->l1h, msgb_l1len(msg));
+ if (rc != msgb_l1len(msg)) {
+ LOGP(DSAP, LOGL_ERROR, "Can not read data: len=%d rc=%d "
+ "errno=%d\n", len, rc, errno);
+ msgb_free(msg);
+ return rc;
+ }
+
+ if (ms->sap_entity.msg_handler)
+ ms->sap_entity.msg_handler(msg, ms);
+
+ return 0;
+}
+
+static int sap_write(struct osmo_fd *fd, struct msgb *msg)
+{
+ int rc;
+
+ if (fd->fd <= 0)
+ return -EINVAL;
+
+ rc = write(fd->fd, msg->data, msg->len);
+ if (rc != msg->len) {
+ LOGP(DSAP, LOGL_ERROR, "Failed to write data: rc: %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+int sap_open(struct osmocom_ms *ms, const char *socket_path)
+{
+ int rc;
+ struct sockaddr_un local;
+
+ ms->sap_wq.bfd.fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (ms->sap_wq.bfd.fd < 0) {
+ fprintf(stderr, "Failed to create unix domain socket.\n");
+ return ms->sap_wq.bfd.fd;
+ }
+
+ local.sun_family = AF_UNIX;
+ strncpy(local.sun_path, socket_path, sizeof(local.sun_path));
+ local.sun_path[sizeof(local.sun_path) - 1] = '\0';
+
+ rc = connect(ms->sap_wq.bfd.fd, (struct sockaddr *) &local,
+ sizeof(local.sun_family) + strlen(local.sun_path));
+ if (rc < 0) {
+ fprintf(stderr, "Failed to connect to '%s'.\n", local.sun_path);
+ close(ms->sap_wq.bfd.fd);
+ return rc;
+ }
+
+ osmo_wqueue_init(&ms->sap_wq, 100);
+ ms->sap_wq.bfd.data = ms;
+ ms->sap_wq.bfd.when = BSC_FD_READ;
+ ms->sap_wq.read_cb = sap_read;
+ ms->sap_wq.write_cb = sap_write;
+
+ rc = osmo_fd_register(&ms->sap_wq.bfd);
+ if (rc != 0) {
+ fprintf(stderr, "Failed to register fd.\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+int sap_close(struct osmocom_ms *ms)
+{
+ if (ms->sap_wq.bfd.fd <= 0)
+ return -EINVAL;
+
+ close(ms->sap_wq.bfd.fd);
+ ms->sap_wq.bfd.fd = -1;
+ osmo_fd_unregister(&ms->sap_wq.bfd);
+ osmo_wqueue_clear(&ms->sap_wq);
+
+ return 0;
+}
+
+int osmosap_send(struct osmocom_ms *ms, struct msgb *msg)
+{
+ uint16_t *len;
+
+ if (ms->sap_wq.bfd.fd <= 0)
+ return -EINVAL;
+
+ DEBUGP(DSAP, "Sending: '%s'\n", osmo_hexdump(msg->data, msg->len));
+
+ if (msg->l1h != msg->data)
+ LOGP(DSAP, LOGL_ERROR, "Message SAP header != Message Data\n");
+
+ /* prepend 16bit length before sending */
+ len = (uint16_t *) msgb_push(msg, sizeof(*len));
+ *len = htons(msg->len - sizeof(*len));
+
+ if (osmo_wqueue_enqueue(&ms->sap_wq, msg) != 0) {
+ LOGP(DSAP, LOGL_ERROR, "Failed to enqueue msg.\n");
+ msgb_free(msg);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* register message handler for messages that are sent from L2->L3 */
+int osmosap_register_handler(struct osmocom_ms *ms, osmosap_cb_t cb)
+{
+ ms->sap_entity.msg_handler = cb;
+
+ return 0;
+}
+
diff --git a/src/host/layer23/src/common/sim.c b/src/host/layer23/src/common/sim.c
new file mode 100644
index 00000000..8c89cf0b
--- /dev/null
+++ b/src/host/layer23/src/common/sim.c
@@ -0,0 +1,1253 @@
+/*
+ * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
+
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/l1ctl.h>
+
+extern void *l23_ctx;
+static int sim_process_job(struct osmocom_ms *ms);
+
+/*
+ * support
+ */
+
+uint32_t new_handle = 1;
+
+static struct gsm1111_df_name {
+ uint16_t file;
+ const char *name;
+} gsm1111_df_name[] = {
+ { 0x3f00, "MF" },
+ { 0x7f20, "DFgsm" },
+ { 0x7f10, "DFtelecom" },
+ { 0x7f22, "DFis-41" },
+ { 0x7f23, "DFfp-cts" },
+ { 0x5f50, "DFgraphics" },
+ { 0x5f30, "DFiridium" },
+ { 0x5f31, "DFglobst" },
+ { 0x5f32, "DFico" },
+ { 0x5f33, "DFaces" },
+ { 0x5f40, "DFeia/tia-553" },
+ { 0x5f60, "DFcts" },
+ { 0x5f70, "DFsolsa" },
+ { 0x5f3c, "DFmexe" },
+ { 0, NULL }
+};
+
+static const char *get_df_name(uint16_t fid)
+{
+ int i;
+ static char text[7];
+
+ for (i = 0; gsm1111_df_name[i].file; i++)
+ if (gsm1111_df_name[i].file == fid)
+ break;
+ if (gsm1111_df_name[i].file)
+ return gsm1111_df_name[i].name;
+
+ sprintf(text, "0x%04x", fid);
+ return text;
+}
+
+static struct gsm_sim_handler *sim_get_handler(struct gsm_sim *sim,
+ uint32_t handle)
+{
+ struct gsm_sim_handler *handler;
+
+ llist_for_each_entry(handler, &sim->handlers, entry)
+ if (handler->handle == handle)
+ return handler;
+
+ return NULL;
+}
+
+/*
+ * messages
+ */
+
+static const struct value_string sim_job_names[] = {
+ { SIM_JOB_READ_BINARY, "SIM_JOB_READ_BINARY" },
+ { SIM_JOB_UPDATE_BINARY, "SIM_JOB_UPDATE_BINARY" },
+ { SIM_JOB_READ_RECORD, "SIM_JOB_READ_RECORD" },
+ { SIM_JOB_UPDATE_RECORD, "SIM_JOB_UPDATE_RECORD" },
+ { SIM_JOB_SEEK_RECORD, "SIM_JOB_SEEK_RECORD" },
+ { SIM_JOB_INCREASE, "SIM_JOB_INCREASE" },
+ { SIM_JOB_INVALIDATE, "SIM_JOB_INVALIDATE" },
+ { SIM_JOB_REHABILITATE, "SIM_JOB_REHABILITATE" },
+ { SIM_JOB_RUN_GSM_ALGO, "SIM_JOB_RUN_GSM_ALGO" },
+ { SIM_JOB_PIN1_UNLOCK, "SIM_JOB_PIN1_UNLOCK" },
+ { SIM_JOB_PIN1_CHANGE, "SIM_JOB_PIN1_CHANGE" },
+ { SIM_JOB_PIN1_DISABLE, "SIM_JOB_PIN1_DISABLE" },
+ { SIM_JOB_PIN1_ENABLE, "SIM_JOB_PIN1_ENABLE" },
+ { SIM_JOB_PIN1_UNBLOCK, "SIM_JOB_PIN1_UNBLOCK" },
+ { SIM_JOB_PIN2_UNLOCK, "SIM_JOB_PIN2_UNLOCK" },
+ { SIM_JOB_PIN2_CHANGE, "SIM_JOB_PIN2_CHANGE" },
+ { SIM_JOB_PIN2_UNBLOCK, "SIM_JOB_PIN2_UNBLOCK" },
+ { SIM_JOB_OK, "SIM_JOB_OK" },
+ { SIM_JOB_ERROR, "SIM_JOB_ERROR" },
+ { 0, NULL }
+};
+
+static const char *get_job_name(int value)
+{
+ return get_value_string(sim_job_names, value);
+}
+
+/* allocate sim client message (upper layer) */
+struct msgb *gsm_sim_msgb_alloc(uint32_t handle, uint8_t job_type)
+{
+ struct msgb *msg;
+ struct sim_hdr *nsh;
+
+ msg = msgb_alloc_headroom(SIM_ALLOC_SIZE+SIM_ALLOC_HEADROOM,
+ SIM_ALLOC_HEADROOM, "SIM");
+ if (!msg)
+ return NULL;
+
+ nsh = (struct sim_hdr *) msgb_put(msg, sizeof(*nsh));
+ nsh->handle = handle;
+ nsh->job_type = job_type;
+
+ return msg;
+}
+
+/* reply to job, after it is done. reuse the msgb in the job */
+void gsm_sim_reply(struct osmocom_ms *ms, uint8_t result_type, uint8_t *result,
+ uint16_t result_len)
+{
+ struct gsm_sim *sim = &ms->sim;
+ struct msgb *msg = sim->job_msg;
+ struct sim_hdr *sh;
+ uint8_t *payload;
+ uint16_t payload_len;
+ struct gsm_sim_handler *handler;
+
+ LOGP(DSIM, LOGL_INFO, "sending result to callback function "
+ "(type=%d)\n", result_type);
+
+ /* if no handler, or no callback, just free the job */
+ sh = (struct sim_hdr *)msg->data;
+ handler = sim_get_handler(sim, sh->handle);
+ if (!handler || !handler->cb) {
+ LOGP(DSIM, LOGL_INFO, "no callback or no handler, "
+ "dropping result\n");
+ msgb_free(sim->job_msg);
+ sim->job_msg = NULL;
+ sim->job_state = SIM_JST_IDLE;
+ return;
+ }
+
+ payload = msg->data + sizeof(*sh);
+ payload_len = msg->len - sizeof(*sh);
+
+ /* remove data */
+ msg->tail -= payload_len;
+ msg->len -= payload_len;
+
+ /* add reply data */
+ sh->job_type = result_type;
+ if (result_len)
+ memcpy(msgb_put(msg, result_len), result, result_len);
+
+ /* callback */
+ sim->job_state = SIM_JST_IDLE;
+ sim->job_msg = NULL;
+ handler->cb(ms, msg);
+}
+
+/* send APDU to card reader */
+static int sim_apdu_send(struct osmocom_ms *ms, uint8_t *data, uint16_t length)
+{
+ LOGP(DSIM, LOGL_INFO, "sending APDU (class 0x%02x, ins 0x%02x)\n",
+ data[0], data[1]);
+ l1ctl_tx_sim_req(ms, data, length);
+ return 0;
+}
+
+/* dequeue messages (RSL-SAP) */
+int gsm_sim_job_dequeue(struct osmocom_ms *ms)
+{
+ struct gsm_sim *sim = &ms->sim;
+ struct sim_hdr *sh;
+ struct msgb *msg;
+ struct gsm_sim_handler *handler;
+
+ /* already have a job */
+ if (sim->job_msg)
+ return 0;
+
+ /* get next job */
+ while ((msg = msgb_dequeue(&sim->jobs))) {
+ /* resolve handler */
+ sh = (struct sim_hdr *) msg->data;
+ LOGP(DSIM, LOGL_INFO, "got new job: %s (handle=%08x)\n",
+ get_job_name(sh->job_type), sh->handle);
+ handler = sim_get_handler(sim, sh->handle);
+ if (!handler) {
+ LOGP(DSIM, LOGL_INFO, "no handler, ignoring job\n");
+ /* does not exist anymore */
+ msgb_free(msg);
+ continue;
+ }
+
+ /* init job */
+ sim->job_state = SIM_JST_IDLE;
+ sim->job_msg = msg;
+ sim->job_handle = sh->handle;
+
+ /* process current job, message is freed there */
+ sim_process_job(ms);
+ return 1; /* work done */
+ }
+
+ return 0;
+}
+
+
+/*
+ * SIM commands
+ */
+
+/* 9.2.1 */
+static int gsm1111_tx_select(struct osmocom_ms *ms, uint16_t fid)
+{
+ uint8_t buffer[5 + 2];
+
+ LOGP(DSIM, LOGL_INFO, "SELECT (file=0x%04x)\n", fid);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_SELECT;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = 2;
+ buffer[5] = fid >> 8;
+ buffer[6] = fid;
+
+ return sim_apdu_send(ms, buffer, 5 + 2);
+}
+
+#if 0
+/* 9.2.2 */
+static int gsm1111_tx_status(struct osmocom_ms *ms)
+{
+ uint8_t buffer[5];
+
+ LOGP(DSIM, LOGL_INFO, "STATUS\n");
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_STATUS;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = 0;
+
+ return sim_apdu_send(ms, buffer, 5);
+}
+#endif
+
+/* 9.2.3 */
+static int gsm1111_tx_read_binary(struct osmocom_ms *ms, uint16_t offset,
+ uint8_t length)
+{
+ uint8_t buffer[5];
+
+ LOGP(DSIM, LOGL_INFO, "READ BINARY (offset=%d len=%d)\n", offset,
+ length);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_READ_BINARY;
+ buffer[2] = offset >> 8;
+ buffer[3] = offset;
+ buffer[4] = length;
+
+ return sim_apdu_send(ms, buffer, 5);
+}
+
+/* 9.2.4 */
+static int gsm1111_tx_update_binary(struct osmocom_ms *ms, uint16_t offset,
+ uint8_t *data, uint8_t length)
+{
+ uint8_t buffer[5 + length];
+
+ LOGP(DSIM, LOGL_INFO, "UPDATE BINARY (offset=%d len=%d)\n", offset,
+ length);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_UPDATE_BINARY;
+ buffer[2] = offset >> 8;
+ buffer[3] = offset;
+ buffer[4] = length;
+ memcpy(buffer + 5, data, length);
+
+ return sim_apdu_send(ms, buffer, 5 + length);
+}
+
+/* 9.2.5 */
+static int gsm1111_tx_read_record(struct osmocom_ms *ms, uint8_t rec_no,
+ uint8_t mode, uint8_t length)
+{
+ uint8_t buffer[5];
+
+ LOGP(DSIM, LOGL_INFO, "READ RECORD (rec_no=%d mode=%d len=%d)\n",
+ rec_no, mode, length);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_READ_RECORD;
+ buffer[2] = rec_no;
+ buffer[3] = mode;
+ buffer[4] = length;
+
+ return sim_apdu_send(ms, buffer, 5);
+}
+
+/* 9.2.6 */
+static int gsm1111_tx_update_record(struct osmocom_ms *ms, uint8_t rec_no,
+ uint8_t mode, uint8_t *data, uint8_t length)
+{
+ uint8_t buffer[5 + length];
+
+ LOGP(DSIM, LOGL_INFO, "UPDATE RECORD (rec_no=%d mode=%d len=%d)\n",
+ rec_no, mode, length);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_UPDATE_RECORD;
+ buffer[2] = rec_no;
+ buffer[3] = mode;
+ buffer[4] = length;
+ memcpy(buffer + 5, data, length);
+
+ return sim_apdu_send(ms, buffer, 5 + length);
+}
+
+/* 9.2.7 */
+static int gsm1111_tx_seek(struct osmocom_ms *ms, uint8_t type_mode,
+ uint8_t *pattern, uint8_t length)
+{
+ uint8_t buffer[5 + length];
+ uint8_t type = type_mode >> 4;
+ uint8_t mode = type_mode & 0x0f;
+
+ LOGP(DSIM, LOGL_INFO, "SEEK (type=%d mode=%d len=%d)\n", type, mode,
+ length);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_SEEK;
+ buffer[2] = 0x00;
+ buffer[3] = type_mode;
+ buffer[4] = length;
+ memcpy(buffer + 5, pattern, length);
+
+ return sim_apdu_send(ms, buffer, 5 + length);
+}
+
+/* 9.2.8 */
+static int gsm1111_tx_increase(struct osmocom_ms *ms, uint32_t value)
+{
+ uint8_t buffer[5 + 3];
+
+ LOGP(DSIM, LOGL_INFO, "INCREASE (value=%d)\n", value);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_INCREASE;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = 3;
+ buffer[5] = value >> 16;
+ buffer[6] = value >> 8;
+ buffer[7] = value;
+
+ return sim_apdu_send(ms, buffer, 5 + 3);
+}
+
+/* 9.2.9 */
+static int gsm1111_tx_verify_chv(struct osmocom_ms *ms, uint8_t chv_no,
+ uint8_t *chv, uint8_t length)
+{
+ uint8_t buffer[5 + 8];
+ int i;
+
+ LOGP(DSIM, LOGL_INFO, "VERIFY CHV (CHV%d)\n", chv_no);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_VERIFY_CHV;
+ buffer[2] = 0x00;
+ buffer[3] = chv_no;
+ buffer[4] = 8;
+ for (i = 0; i < 8; i++) {
+ if (i < length)
+ buffer[5 + i] = chv[i];
+ else
+ buffer[5 + i] = 0xff;
+ }
+
+ return sim_apdu_send(ms, buffer, 5 + 8);
+}
+
+/* 9.2.10 */
+static int gsm1111_tx_change_chv(struct osmocom_ms *ms, uint8_t chv_no,
+ uint8_t *chv_old, uint8_t length_old, uint8_t *chv_new,
+ uint8_t length_new)
+{
+ uint8_t buffer[5 + 16];
+ int i;
+
+ LOGP(DSIM, LOGL_INFO, "CHANGE CHV (CHV%d)\n", chv_no);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_CHANGE_CHV;
+ buffer[2] = 0x00;
+ buffer[3] = chv_no;
+ buffer[4] = 16;
+ for (i = 0; i < 8; i++) {
+ if (i < length_old)
+ buffer[5 + i] = chv_old[i];
+ else
+ buffer[5 + i] = 0xff;
+ if (i < length_new)
+ buffer[13 + i] = chv_new[i];
+ else
+ buffer[13 + i] = 0xff;
+ }
+
+ return sim_apdu_send(ms, buffer, 5 + 16);
+}
+
+/* 9.2.11 */
+static int gsm1111_tx_disable_chv(struct osmocom_ms *ms, uint8_t *chv,
+ uint8_t length)
+{
+ uint8_t buffer[5 + 8];
+ int i;
+
+ LOGP(DSIM, LOGL_INFO, "DISABLE CHV (CHV1)\n");
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_DISABLE_CHV;
+ buffer[2] = 0x00;
+ buffer[3] = 0x01;
+ buffer[4] = 8;
+ for (i = 0; i < 8; i++) {
+ if (i < length)
+ buffer[5 + i] = chv[i];
+ else
+ buffer[5 + i] = 0xff;
+ }
+
+ return sim_apdu_send(ms, buffer, 5 + 8);
+}
+
+/* 9.2.12 */
+static int gsm1111_tx_enable_chv(struct osmocom_ms *ms, uint8_t *chv,
+ uint8_t length)
+{
+ uint8_t buffer[5 + 8];
+ int i;
+
+ LOGP(DSIM, LOGL_INFO, "ENABLE CHV (CHV1)\n");
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_ENABLE_CHV;
+ buffer[2] = 0x00;
+ buffer[3] = 0x01;
+ buffer[4] = 8;
+ for (i = 0; i < 8; i++) {
+ if (i < length)
+ buffer[5 + i] = chv[i];
+ else
+ buffer[5 + i] = 0xff;
+ }
+
+ return sim_apdu_send(ms, buffer, 5 + 8);
+}
+
+/* 9.2.13 */
+static int gsm1111_tx_unblock_chv(struct osmocom_ms *ms, uint8_t chv_no,
+ uint8_t *chv_unblk, uint8_t length_unblk, uint8_t *chv_new,
+ uint8_t length_new)
+{
+ uint8_t buffer[5 + 16];
+ int i;
+
+ LOGP(DSIM, LOGL_INFO, "UNBLOCK CHV (CHV%d)\n", (chv_no == 2) ? 2 : 1);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_UNBLOCK_CHV;
+ buffer[2] = 0x00;
+ buffer[3] = (chv_no == 1) ? 0 : chv_no;
+ buffer[4] = 16;
+ for (i = 0; i < 8; i++) {
+ if (i < length_unblk)
+ buffer[5 + i] = chv_unblk[i];
+ else
+ buffer[5 + i] = 0xff;
+ if (i < length_new)
+ buffer[13 + i] = chv_new[i];
+ else
+ buffer[13 + i] = 0xff;
+ }
+
+ return sim_apdu_send(ms, buffer, 5 + 16);
+}
+
+/* 9.2.14 */
+static int gsm1111_tx_invalidate(struct osmocom_ms *ms)
+{
+ uint8_t buffer[5];
+
+ LOGP(DSIM, LOGL_INFO, "INVALIDATE\n");
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_INVALIDATE;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = 0;
+
+ return sim_apdu_send(ms, buffer, 5);
+}
+
+/* 9.2.15 */
+static int gsm1111_tx_rehabilitate(struct osmocom_ms *ms)
+{
+ uint8_t buffer[5];
+
+ LOGP(DSIM, LOGL_INFO, "REHABILITATE\n");
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_REHABLILITATE;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = 0;
+
+ return sim_apdu_send(ms, buffer, 5);
+}
+
+/* 9.2.16 */
+static int gsm1111_tx_run_gsm_algo(struct osmocom_ms *ms, uint8_t *rand)
+{
+ uint8_t buffer[5 + 16];
+
+ LOGP(DSIM, LOGL_INFO, "RUN GSM ALGORITHM\n");
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_RUN_GSM_ALGO;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = 16;
+ memcpy(buffer + 5, rand, 16);
+
+ return sim_apdu_send(ms, buffer, 5 + 16);
+}
+
+#if 0
+/* 9.2.17 */
+static int gsm1111_tx_sleep(struct osmocom_ms *ms)
+{
+ uint8_t buffer[5];
+
+ LOGP(DSIM, LOGL_INFO, "\n");
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_SLEEP;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = 0;
+
+ return sim_apdu_send(ms, buffer, 5);
+}
+#endif
+
+/* 9.2.18 */
+static int gsm1111_tx_get_response(struct osmocom_ms *ms, uint8_t length)
+{
+ uint8_t buffer[5];
+
+ LOGP(DSIM, LOGL_INFO, "GET RESPONSE (len=%d)\n", length);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_GET_RESPONSE;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = length;
+
+ return sim_apdu_send(ms, buffer, 5);
+}
+
+#if 0
+/* 9.2.19 */
+static int gsm1111_tx_terminal_profile(struct osmocom_ms *ms, uint8_t *data,
+ uint8_t length)
+{
+ uint8_t buffer[5 + length];
+
+ LOGP(DSIM, LOGL_INFO, "TERMINAL PROFILE (len=%d)\n", length);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_TERMINAL_PROFILE;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = length;
+ memcpy(buffer + 5, data, length);
+
+ return sim_apdu_send(ms, buffer, 5 + length);
+}
+
+/* 9.2.20 */
+static int gsm1111_tx_envelope(struct osmocom_ms *ms, uint8_t *data,
+ uint8_t length)
+{
+ uint8_t buffer[5 + length];
+
+ LOGP(DSIM, LOGL_INFO, "ENVELOPE (len=%d)\n", length);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_ENVELOPE;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = length;
+ memcpy(buffer + 5, data, length);
+
+ return sim_apdu_send(ms, buffer, 5 + length);
+}
+
+/* 9.2.21 */
+static int gsm1111_tx_fetch(struct osmocom_ms *ms, uint8_t length)
+{
+ uint8_t buffer[5];
+
+ LOGP(DSIM, LOGL_INFO, "FETCH (len=%d)\n", length);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_FETCH;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = length;
+
+ return sim_apdu_send(ms, buffer, 5);
+}
+
+/* 9.2.22 */
+static int gsm1111_tx_terminal_response(struct osmocom_ms *ms, uint8_t *data,
+ uint8_t length)
+{
+ uint8_t buffer[5 + length];
+
+ LOGP(DSIM, LOGL_INFO, "TERMINAL RESPONSE (len=%d)\n", length);
+ buffer[0] = GSM1111_CLASS_GSM;
+ buffer[1] = GSM1111_INST_TERMINAL_RESPONSE;
+ buffer[2] = 0x00;
+ buffer[3] = 0x00;
+ buffer[4] = length;
+ memcpy(buffer + 5, data, length);
+
+ return sim_apdu_send(ms, buffer, 5 + length);
+}
+#endif
+
+/*
+ * SIM state machine
+ */
+
+/* process job */
+static int sim_process_job(struct osmocom_ms *ms)
+{
+ struct gsm_sim *sim = &ms->sim;
+ uint8_t *payload, *payload2;
+ uint16_t payload_len, payload_len2;
+ struct sim_hdr *sh;
+ uint8_t cause;
+ int i;
+
+ /* no current */
+ if (!sim->job_msg)
+ return 0;
+
+ sh = (struct sim_hdr *)sim->job_msg->data;
+ payload = sim->job_msg->data + sizeof(*sh);
+ payload_len = sim->job_msg->len - sizeof(*sh);
+
+ /* do reset before sim reading */
+ if (!sim->reset) {
+ sim->reset = 1;
+ // FIXME: send reset command to L1
+ }
+
+ /* navigate to right DF */
+ switch (sh->job_type) {
+ case SIM_JOB_READ_BINARY:
+ case SIM_JOB_UPDATE_BINARY:
+ case SIM_JOB_READ_RECORD:
+ case SIM_JOB_UPDATE_RECORD:
+ case SIM_JOB_SEEK_RECORD:
+ case SIM_JOB_INCREASE:
+ case SIM_JOB_INVALIDATE:
+ case SIM_JOB_REHABILITATE:
+ case SIM_JOB_RUN_GSM_ALGO:
+ /* check MF / DF */
+ i = 0;
+ while (sh->path[i] && sim->path[i]) {
+ if (sh->path[i] != sim->path[i])
+ break;
+ i++;
+ }
+ /* if path in message is shorter or if paths are different */
+ if (sim->path[i]) {
+ LOGP(DSIM, LOGL_INFO, "go MF\n");
+ sim->job_state = SIM_JST_SELECT_MFDF;
+ /* go MF */
+ sim->path[0] = 0;
+ return gsm1111_tx_select(ms, 0x3f00);
+ }
+ /* if path in message is longer */
+ if (sh->path[i]) {
+ LOGP(DSIM, LOGL_INFO, "requested path is longer, go "
+ "child %s\n", get_df_name(sh->path[i]));
+ sim->job_state = SIM_JST_SELECT_MFDF;
+ /* select child */
+ sim->path[i] = sh->path[i];
+ sim->path[i + 1] = 0;
+ return gsm1111_tx_select(ms, sh->path[i]);
+ }
+ /* if paths are equal, continue */
+ }
+
+ /* set state and trigger SIM process */
+ switch (sh->job_type) {
+ case SIM_JOB_READ_BINARY:
+ case SIM_JOB_UPDATE_BINARY:
+ case SIM_JOB_READ_RECORD:
+ case SIM_JOB_UPDATE_RECORD:
+ case SIM_JOB_SEEK_RECORD:
+ case SIM_JOB_INCREASE:
+ case SIM_JOB_INVALIDATE:
+ case SIM_JOB_REHABILITATE:
+ sim->job_state = SIM_JST_SELECT_EF;
+ sim->file = sh->file;
+ return gsm1111_tx_select(ms, sh->file);
+ case SIM_JOB_RUN_GSM_ALGO:
+ if (payload_len != 16) {
+ LOGP(DSIM, LOGL_ERROR, "random not 16 bytes\n");
+ break;
+ }
+ sim->job_state = SIM_JST_RUN_GSM_ALGO;
+ return gsm1111_tx_run_gsm_algo(ms, payload);
+ case SIM_JOB_PIN1_UNLOCK:
+ payload_len = strlen((char *)payload);
+ if (payload_len < 4 || payload_len > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
+ break;
+ }
+ sim->job_state = SIM_JST_PIN1_UNLOCK;
+ return gsm1111_tx_verify_chv(ms, 0x01, payload, payload_len);
+ case SIM_JOB_PIN2_UNLOCK:
+ payload_len = strlen((char *)payload);
+ if (payload_len < 4 || payload_len > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
+ break;
+ }
+ sim->job_state = SIM_JST_PIN2_UNLOCK;
+ return gsm1111_tx_verify_chv(ms, 0x02, payload, payload_len);
+ case SIM_JOB_PIN1_CHANGE:
+ payload_len = strlen((char *)payload);
+ payload2 = payload + payload_len + 1;
+ payload_len2 = strlen((char *)payload2);
+ if (payload_len < 4 || payload_len > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key1 not in range 4..8\n");
+ break;
+ }
+ if (payload_len2 < 4 || payload_len2 > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
+ break;
+ }
+ sim->job_state = SIM_JST_PIN1_CHANGE;
+ return gsm1111_tx_change_chv(ms, 0x01, payload, payload_len,
+ payload2, payload_len2);
+ case SIM_JOB_PIN2_CHANGE:
+ payload_len = strlen((char *)payload);
+ payload2 = payload + payload_len + 1;
+ payload_len2 = strlen((char *)payload2);
+ if (payload_len < 4 || payload_len > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key1 not in range 4..8\n");
+ break;
+ }
+ if (payload_len2 < 4 || payload_len2 > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
+ break;
+ }
+ sim->job_state = SIM_JST_PIN2_CHANGE;
+ return gsm1111_tx_change_chv(ms, 0x02, payload, payload_len,
+ payload2, payload_len2);
+ case SIM_JOB_PIN1_DISABLE:
+ payload_len = strlen((char *)payload);
+ if (payload_len < 4 || payload_len > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
+ break;
+ }
+ sim->job_state = SIM_JST_PIN1_DISABLE;
+ return gsm1111_tx_disable_chv(ms, payload, payload_len);
+ case SIM_JOB_PIN1_ENABLE:
+ payload_len = strlen((char *)payload);
+ if (payload_len < 4 || payload_len > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
+ break;
+ }
+ sim->job_state = SIM_JST_PIN1_ENABLE;
+ return gsm1111_tx_enable_chv(ms, payload, payload_len);
+ case SIM_JOB_PIN1_UNBLOCK:
+ payload_len = strlen((char *)payload);
+ payload2 = payload + payload_len + 1;
+ payload_len2 = strlen((char *)payload2);
+ if (payload_len != 8) {
+ LOGP(DSIM, LOGL_ERROR, "key1 not 8 digits\n");
+ break;
+ }
+ if (payload_len2 < 4 || payload_len2 > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
+ break;
+ }
+ sim->job_state = SIM_JST_PIN1_UNBLOCK;
+ /* NOTE: CHV1 is coded 0x00 here */
+ return gsm1111_tx_unblock_chv(ms, 0x00, payload, payload_len,
+ payload2, payload_len2);
+ case SIM_JOB_PIN2_UNBLOCK:
+ payload_len = strlen((char *)payload);
+ payload2 = payload + payload_len + 1;
+ payload_len2 = strlen((char *)payload2);
+ if (payload_len != 8) {
+ LOGP(DSIM, LOGL_ERROR, "key1 not 8 digits\n");
+ break;
+ }
+ if (payload_len2 < 4 || payload_len2 > 8) {
+ LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
+ break;
+ }
+ sim->job_state = SIM_JST_PIN2_UNBLOCK;
+ return gsm1111_tx_unblock_chv(ms, 0x02, payload, payload_len,
+ payload2, payload_len2);
+ }
+
+ LOGP(DSIM, LOGL_ERROR, "unknown job %x, please fix\n", sh->job_type);
+ cause = SIM_CAUSE_REQUEST_ERROR;
+ gsm_sim_reply(ms, SIM_JOB_ERROR, &cause, 1);
+
+ return 0;
+}
+
+/* receive SIM response */
+int sim_apdu_resp(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm_sim *sim = &ms->sim;
+ uint8_t *payload;
+ uint16_t payload_len;
+ uint8_t *data = msg->data;
+ int length = msg->len, ef_len;
+ uint8_t sw1, sw2;
+ uint8_t cause;
+ uint8_t pin_cause[2];
+ struct sim_hdr *sh;
+ struct gsm1111_response_ef *ef;
+ struct gsm1111_response_mfdf *mfdf;
+ struct gsm1111_response_mfdf_gsm *mfdf_gsm;
+ int i;
+
+ /* ignore, if current job already gone */
+ if (!sim->job_msg) {
+ LOGP(DSIM, LOGL_ERROR, "received APDU but no job, "
+ "please fix!\n");
+ msgb_free(msg);
+ return 0;
+ }
+
+ sh = (struct sim_hdr *)sim->job_msg->data;
+ payload = sim->job_msg->data + sizeof(*sh);
+ payload_len = sim->job_msg->len - sizeof(*sh);
+
+ /* process status */
+ if (length < 2) {
+ msgb_free(msg);
+ return 0;
+ }
+ sw1 = data[length - 2];
+ sw2 = data[length - 1];
+ length -= 2;
+ LOGP(DSIM, LOGL_INFO, "received APDU (len=%d sw1=0x%02x sw2=0x%02x)\n",
+ length, sw1, sw2);
+
+ switch (sw1) {
+ case GSM1111_STAT_SECURITY:
+ LOGP(DSIM, LOGL_NOTICE, "SIM Security\n");
+ /* error */
+ if (sw2 != GSM1111_SEC_NO_ACCESS && sw2 != GSM1111_SEC_BLOCKED)
+ goto sim_error;
+
+ /* select the right remaining counter an cause */
+ // FIXME: read status to replace "*_remain"-counters
+ switch (sim->job_state) {
+ case SIM_JST_PIN1_UNBLOCK:
+ if (sw2 == GSM1111_SEC_NO_ACCESS) {
+ pin_cause[0] = SIM_CAUSE_PIN1_BLOCKED;
+ pin_cause[1] = --sim->unblk1_remain;
+ } else {
+ pin_cause[0] = SIM_CAUSE_PUC_BLOCKED;
+ pin_cause[1] = 0;
+ }
+ break;
+ case SIM_JST_PIN2_UNLOCK:
+ case SIM_JST_PIN2_CHANGE:
+ if (sw2 == GSM1111_SEC_NO_ACCESS && sim->chv2_remain) {
+ pin_cause[0] = SIM_CAUSE_PIN2_REQUIRED;
+ pin_cause[1] = sim->chv2_remain--;
+ } else {
+ pin_cause[0] = SIM_CAUSE_PIN2_BLOCKED;
+ pin_cause[1] = sim->unblk2_remain;
+ }
+ break;
+ case SIM_JST_PIN2_UNBLOCK:
+ if (sw2 == GSM1111_SEC_NO_ACCESS) {
+ pin_cause[0] = SIM_CAUSE_PIN2_BLOCKED;
+ pin_cause[1] = --sim->unblk2_remain;
+ } else {
+ pin_cause[0] = SIM_CAUSE_PUC_BLOCKED;
+ pin_cause[1] = 0;
+ }
+ case SIM_JST_PIN1_UNLOCK:
+ case SIM_JST_PIN1_CHANGE:
+ case SIM_JST_PIN1_DISABLE:
+ case SIM_JST_PIN1_ENABLE:
+ default:
+ if (sw2 == GSM1111_SEC_NO_ACCESS && sim->chv1_remain) {
+ pin_cause[0] = SIM_CAUSE_PIN1_REQUIRED;
+ pin_cause[1] = sim->chv1_remain--;
+ } else {
+ pin_cause[0] = SIM_CAUSE_PIN1_BLOCKED;
+ pin_cause[1] = sim->unblk1_remain;
+ }
+ break;
+ }
+ gsm_sim_reply(ms, SIM_JOB_ERROR, pin_cause, 2);
+ msgb_free(msg);
+ return 0;
+ case GSM1111_STAT_MEM_PROBLEM:
+ if (sw2 >= 0x40) {
+ LOGP(DSIM, LOGL_NOTICE, "memory of SIM failed\n");
+ sim_error:
+ cause = SIM_CAUSE_SIM_ERROR;
+ gsm_sim_reply(ms, SIM_JOB_ERROR, &cause, 1);
+ msgb_free(msg);
+ return 0;
+ }
+ LOGP(DSIM, LOGL_NOTICE, "memory of SIM is bad (write took %d "
+ "times to succeed)\n", sw2);
+ /* fall through */
+ case GSM1111_STAT_NORMAL:
+ case GSM1111_STAT_PROACTIVE:
+ case GSM1111_STAT_DL_ERROR:
+ case GSM1111_STAT_RESPONSE:
+ case GSM1111_STAT_RESPONSE_TOO:
+ LOGP(DSIM, LOGL_INFO, "command successfull\n");
+ break;
+ default:
+ LOGP(DSIM, LOGL_INFO, "command failed\n");
+ request_error:
+ cause = SIM_CAUSE_REQUEST_ERROR;
+ gsm_sim_reply(ms, SIM_JOB_ERROR, &cause, 1);
+ msgb_free(msg);
+ return 0;
+ }
+
+
+ switch (sim->job_state) {
+ /* step 1: after selecting MF / DF, request the response */
+ case SIM_JST_SELECT_MFDF:
+ /* not enough data */
+ if (sw2 < 22) {
+ LOGP(DSIM, LOGL_NOTICE, "expecting minimum 22 bytes\n");
+ goto sim_error;
+ }
+ /* request response */
+ sim->job_state = SIM_JST_SELECT_MFDF_RESP;
+ gsm1111_tx_get_response(ms, sw2);
+ msgb_free(msg);
+ return 0;
+ /* step 2: after getting response of selecting MF / DF, continue
+ * to "process_job".
+ */
+ case SIM_JST_SELECT_MFDF_RESP:
+ if (length < 22) {
+ LOGP(DSIM, LOGL_NOTICE, "expecting minimum 22 bytes\n");
+ goto sim_error;
+ }
+ mfdf = (struct gsm1111_response_mfdf *)data;
+ mfdf_gsm = (struct gsm1111_response_mfdf_gsm *)(data + 13);
+ sim->chv1_remain = mfdf_gsm->chv1_remain;
+ sim->chv2_remain = mfdf_gsm->chv2_remain;
+ sim->unblk1_remain = mfdf_gsm->unblk1_remain;
+ sim->unblk2_remain = mfdf_gsm->unblk2_remain;
+ /* if MF was selected */
+ if (sim->path[0] == 0) {
+ /* if MF was selected, but MF is not indicated */
+ if (ntohs(mfdf->file_id) != 0x3f00) {
+ LOGP(DSIM, LOGL_NOTICE, "Not MF\n");
+ goto sim_error;
+ }
+ /* if MF was selected, but type is not indicated */
+ if (mfdf->tof != GSM1111_TOF_MF) {
+ LOGP(DSIM, LOGL_NOTICE, "MF %02x != %02x "
+ "%04x\n", mfdf->tof, GSM1111_TOF_MF,
+ sim->path[0]);
+ goto sim_error;
+ }
+ /* now continue */
+ msgb_free(msg);
+ return sim_process_job(ms);
+ }
+ /* if DF was selected, but this DF is not indicated */
+ i = 0;
+ while (sim->path[i + 1])
+ i++;
+ if (ntohs(mfdf->file_id) != sim->path[i]) {
+ LOGP(DSIM, LOGL_NOTICE, "Path %04x != %04x\n",
+ ntohs(mfdf->file_id), sim->path[i]);
+ goto sim_error;
+ }
+ /* if DF was selected, but type is not indicated */
+ if (mfdf->tof != GSM1111_TOF_DF) {
+ LOGP(DSIM, LOGL_NOTICE, "TOF error\n");
+ goto sim_error;
+ }
+ /* now continue */
+ msgb_free(msg);
+ return sim_process_job(ms);
+ /* step 1: after selecting EF, request response of SELECT */
+ case SIM_JST_SELECT_EF:
+ /* not enough data */
+ if (sw2 < 14) {
+ LOGP(DSIM, LOGL_NOTICE, "expecting minimum 14 bytes\n");
+ goto sim_error;
+ }
+ /* request response */
+ sim->job_state = SIM_JST_SELECT_EF_RESP;
+ gsm1111_tx_get_response(ms, sw2);
+ msgb_free(msg);
+ return 0;
+ /* step 2: after getting response of selecting EF, do file command */
+ case SIM_JST_SELECT_EF_RESP:
+ if (length < 14) {
+ LOGP(DSIM, LOGL_NOTICE, "expecting minimum 14 bytes\n");
+ goto sim_error;
+ }
+ ef = (struct gsm1111_response_ef *)data;
+ /* if EF was selected, but type is not indicated */
+ if (ntohs(ef->file_id) != sim->file) {
+ LOGP(DSIM, LOGL_NOTICE, "EF ID %04x != %04x\n",
+ ntohs(ef->file_id), sim->file);
+ goto sim_error;
+ }
+ /* check for record */
+ if (length >= 15 && ef->length >= 2 && ef->structure != 0x00) {
+ /* get length of record */
+ ef_len = ntohs(ef->file_size);
+ if (ef_len < data[14]) {
+ LOGP(DSIM, LOGL_NOTICE, "total length is "
+ "smaller (%d) than record size (%d)\n",
+ ef_len, data[14]);
+ goto request_error;
+ }
+ ef_len = data[14];
+ LOGP(DSIM, LOGL_NOTICE, "selected record (len %d "
+ "structure %d)\n", ef_len, ef->structure);
+ } else {
+ /* get length of file */
+ ef_len = ntohs(ef->file_size);
+ LOGP(DSIM, LOGL_NOTICE, "selected file (len %d)\n",
+ ef_len);
+ }
+ /* do file command */
+ sim->job_state = SIM_JST_WAIT_FILE;
+ switch (sh->job_type) {
+ case SIM_JOB_READ_BINARY:
+ // FIXME: do chunks when greater or equal 256 bytes */
+ gsm1111_tx_read_binary(ms, 0, ef_len);
+ break;
+ case SIM_JOB_UPDATE_BINARY:
+ // FIXME: do chunks when greater or equal 256 bytes */
+ if (ef_len < payload_len) {
+ LOGP(DSIM, LOGL_NOTICE, "selected file is "
+ "smaller (%d) than data to update "
+ "(%d)\n", ef_len, payload_len);
+ goto request_error;
+ }
+ gsm1111_tx_update_binary(ms, 0, payload, payload_len);
+ break;
+ case SIM_JOB_READ_RECORD:
+ gsm1111_tx_read_record(ms, sh->rec_no, sh->rec_mode,
+ ef_len);
+ break;
+ case SIM_JOB_UPDATE_RECORD:
+ if (ef_len != payload_len) {
+ LOGP(DSIM, LOGL_NOTICE, "selected file length "
+ "(%d) does not equal record to update "
+ "(%d)\n", ef_len, payload_len);
+ goto request_error;
+ }
+ gsm1111_tx_update_record(ms, sh->rec_no, sh->rec_mode,
+ payload, payload_len);
+ break;
+ case SIM_JOB_SEEK_RECORD:
+ gsm1111_tx_seek(ms, sh->seek_type_mode, data, length);
+ break;
+ case SIM_JOB_INCREASE:
+ if (length != 4) {
+ LOGP(DSIM, LOGL_ERROR, "expecting uint32_t as "
+ "value lenght, but got %d bytes\n",
+ length);
+ goto request_error;
+ }
+ gsm1111_tx_increase(ms, *((uint32_t *)data));
+ break;
+ case SIM_JOB_INVALIDATE:
+ gsm1111_tx_invalidate(ms);
+ break;
+ case SIM_JOB_REHABILITATE:
+ gsm1111_tx_rehabilitate(ms);
+ break;
+ }
+ msgb_free(msg);
+ return 0;
+ /* step 3: after processing file command, job is done */
+ case SIM_JST_WAIT_FILE:
+ /* reply job with data */
+ gsm_sim_reply(ms, SIM_JOB_OK, data, length);
+ msgb_free(msg);
+ return 0;
+ /* step 1: after running GSM algorithm, request response */
+ case SIM_JST_RUN_GSM_ALGO:
+ /* not enough data */
+ if (sw2 < 12) {
+ LOGP(DSIM, LOGL_NOTICE, "expecting minimum 12 bytes\n");
+ goto sim_error;
+ }
+ /* request response */
+ sim->job_state = SIM_JST_RUN_GSM_ALGO_RESP;
+ gsm1111_tx_get_response(ms, sw2);
+ msgb_free(msg);
+ return 0;
+ /* step 2: after processing GSM command, job is done */
+ case SIM_JST_RUN_GSM_ALGO_RESP:
+ /* reply job with data */
+ gsm_sim_reply(ms, SIM_JOB_OK, data, length);
+ msgb_free(msg);
+ return 0;
+ case SIM_JST_PIN1_UNLOCK:
+ case SIM_JST_PIN1_CHANGE:
+ case SIM_JST_PIN1_DISABLE:
+ case SIM_JST_PIN1_ENABLE:
+ case SIM_JST_PIN1_UNBLOCK:
+ case SIM_JST_PIN2_UNLOCK:
+ case SIM_JST_PIN2_CHANGE:
+ case SIM_JST_PIN2_UNBLOCK:
+ /* reply job with data */
+ gsm_sim_reply(ms, SIM_JOB_OK, data, length);
+ msgb_free(msg);
+ return 0;
+ }
+
+ LOGP(DSIM, LOGL_ERROR, "unknown state %u, please fix!\n",
+ sim->job_state);
+ goto request_error;
+}
+
+/*
+ * API
+ */
+
+/* open access to sim */
+uint32_t sim_open(struct osmocom_ms *ms,
+ void (*cb)(struct osmocom_ms *ms, struct msgb *msg))
+{
+ struct gsm_sim *sim = &ms->sim;
+ struct gsm_sim_handler *handler;
+
+ /* create handler and attach */
+ handler = talloc_zero(l23_ctx, struct gsm_sim_handler);
+ if (!handler)
+ return 0;
+ handler->handle = new_handle++;
+ handler->cb = cb;
+ llist_add_tail(&handler->entry, &sim->handlers);
+
+ return handler->handle;
+}
+
+/* close access to sim */
+void sim_close(struct osmocom_ms *ms, uint32_t handle)
+{
+ struct gsm_sim *sim = &ms->sim;
+ struct gsm_sim_handler *handler;
+
+ handler = sim_get_handler(sim, handle);
+ if (!handle)
+ return;
+
+ /* kill ourself */
+ llist_del(&handler->entry);
+ talloc_free(handler);
+}
+
+/* send job */
+void sim_job(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm_sim *sim = &ms->sim;
+
+ msgb_enqueue(&sim->jobs, msg);
+}
+
+/*
+ * init
+ */
+
+int gsm_sim_init(struct osmocom_ms *ms)
+{
+ struct gsm_sim *sim = &ms->sim;
+
+ /* current path is undefined, forching MF */
+ sim->path[0] = 0x0bad;
+ sim->path[1] = 0;
+ sim->file = 0;
+
+ INIT_LLIST_HEAD(&sim->handlers);
+ INIT_LLIST_HEAD(&sim->jobs);
+
+ LOGP(DSIM, LOGL_INFO, "init SIM client\n");
+
+ return 0;
+}
+
+int gsm_sim_exit(struct osmocom_ms *ms)
+{
+ struct gsm_sim *sim = &ms->sim;
+ struct gsm_sim_handler *handler, *handler2;
+ struct msgb *msg;
+
+ LOGP(DSIM, LOGL_INFO, "exit SIM client\n");
+
+ /* remove pending job msg */
+ if (sim->job_msg) {
+ msgb_free(sim->job_msg);
+ sim->job_msg = NULL;
+ }
+ /* flush handlers */
+ llist_for_each_entry_safe(handler, handler2, &sim->handlers, entry)
+ sim_close(ms, handler->handle);
+ /* flush jobs */
+ while ((msg = msgb_dequeue(&sim->jobs)))
+ msgb_free(msg);
+
+ return 0;
+}
+
+
+
+
diff --git a/src/host/layer23/src/common/sysinfo.c b/src/host/layer23/src/common/sysinfo.c
new file mode 100644
index 00000000..2816c266
--- /dev/null
+++ b/src/host/layer23/src/common/sysinfo.c
@@ -0,0 +1,870 @@
+/*
+ * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include <osmocom/core/bitvec.h>
+
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/networks.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/sysinfo.h>
+
+#define MIN(a, b) ((a < b) ? a : b)
+
+/*
+ * dumping
+ */
+
+// FIXME: move to libosmocore
+char *gsm_print_arfcn(uint16_t arfcn)
+{
+ static char text[10];
+
+ sprintf(text, "%d", arfcn & 1023);
+ if ((arfcn & ARFCN_PCS))
+ strcat(text, "(PCS)");
+ else if (arfcn >= 512 && arfcn <= 885)
+ strcat(text, "(DCS)");
+
+ return text;
+}
+
+/* check if the cell 'talks' about DCS (0) or PCS (1) */
+uint8_t gsm_refer_pcs(uint16_t arfcn, struct gsm48_sysinfo *s)
+{
+ /* If ARFCN is PCS band, the cell refers to PCS */
+ if ((arfcn & ARFCN_PCS))
+ return 1;
+
+ /* If no SI1 is available, we assume DCS. Be sure to call this
+ * function only if SI 1 is available. */
+ if (!s->si1)
+ return 0;
+
+ /* If band indicator indicates PCS band, the cell refers to PCSThe */
+ return s->band_ind;
+}
+
+int gsm48_sysinfo_dump(struct gsm48_sysinfo *s, uint16_t arfcn,
+ void (*print)(void *, const char *, ...), void *priv, uint8_t *freq_map)
+{
+ char buffer[81];
+ int i, j, k, index;
+ int refer_pcs = gsm_refer_pcs(arfcn, s);
+
+ /* available sysinfos */
+ print(priv, "ARFCN = %s channels 512+ refer to %s\n",
+ gsm_print_arfcn(arfcn),
+ (refer_pcs) ? "PCS (1900)" : "DCS (1800)");
+ print(priv, "Available SYSTEM INFORMATIONS =");
+ if (s->si1)
+ print(priv, " 1");
+ if (s->si2)
+ print(priv, " 2");
+ if (s->si2bis)
+ print(priv, " 2bis");
+ if (s->si2ter)
+ print(priv, " 2ter");
+ if (s->si3)
+ print(priv, " 3");
+ if (s->si4)
+ print(priv, " 4");
+ if (s->si5)
+ print(priv, " 5");
+ if (s->si5bis)
+ print(priv, " 5bis");
+ if (s->si5ter)
+ print(priv, " 5ter");
+ if (s->si6)
+ print(priv, " 6");
+ print(priv, "\n");
+ print(priv, "\n");
+
+ /* frequency list */
+ j = 0; k = 0;
+ for (i = 0; i < 1024; i++) {
+ if ((s->freq[i].mask & FREQ_TYPE_SERV)) {
+ if (!k) {
+ sprintf(buffer, "serv. cell : ");
+ j = strlen(buffer);
+ }
+ if (j >= 75) {
+ buffer[j - 1] = '\0';
+ print(priv, "%s\n", buffer);
+ sprintf(buffer, " ");
+ j = strlen(buffer);
+ }
+ sprintf(buffer + j, "%d,", i);
+ j = strlen(buffer);
+ k++;
+ }
+ }
+ if (j) {
+ buffer[j - 1] = '\0';
+ print(priv, "%s\n", buffer);
+ }
+ j = 0; k = 0;
+ for (i = 0; i < 1024; i++) {
+ if ((s->freq[i].mask & FREQ_TYPE_NCELL)) {
+ if (!k) {
+ sprintf(buffer, "SI2 (neigh.) BA=%d: ",
+ s->nb_ba_ind_si2);
+ j = strlen(buffer);
+ }
+ if (j >= 70) {
+ buffer[j - 1] = '\0';
+ print(priv, "%s\n", buffer);
+ sprintf(buffer, " ");
+ j = strlen(buffer);
+ }
+ sprintf(buffer + j, "%d,", i);
+ j = strlen(buffer);
+ k++;
+ }
+ }
+ if (j) {
+ buffer[j - 1] = '\0';
+ print(priv, "%s\n", buffer);
+ }
+ j = 0; k = 0;
+ for (i = 0; i < 1024; i++) {
+ if ((s->freq[i].mask & FREQ_TYPE_REP)) {
+ if (!k) {
+ sprintf(buffer, "SI5 (report) BA=%d: ",
+ s->nb_ba_ind_si5);
+ j = strlen(buffer);
+ }
+ if (j >= 70) {
+ buffer[j - 1] = '\0';
+ print(priv, "%s\n", buffer);
+ sprintf(buffer, " ");
+ j = strlen(buffer);
+ }
+ sprintf(buffer + j, "%d,", i);
+ j = strlen(buffer);
+ k++;
+ }
+ }
+ if (j) {
+ buffer[j - 1] = '\0';
+ print(priv, "%s\n", buffer);
+ }
+ print(priv, "\n");
+
+ /* frequency map */
+ for (i = 0; i < 1024; i += 64) {
+ sprintf(buffer, " %3d ", i);
+ for (j = 0; j < 64; j++) {
+ index = i+j;
+ if (refer_pcs && index >= 512 && index <= 885)
+ index = index-512+1024;
+ if ((s->freq[i+j].mask & FREQ_TYPE_SERV))
+ buffer[j + 5] = 'S';
+ else if ((s->freq[i+j].mask & FREQ_TYPE_NCELL)
+ && (s->freq[i+j].mask & FREQ_TYPE_REP))
+ buffer[j + 5] = 'b';
+ else if ((s->freq[i+j].mask & FREQ_TYPE_NCELL))
+ buffer[j + 5] = 'n';
+ else if ((s->freq[i+j].mask & FREQ_TYPE_REP))
+ buffer[j + 5] = 'r';
+ else if (!freq_map || (freq_map[index >> 3]
+ & (1 << (index & 7))))
+ buffer[j + 5] = '.';
+ else
+ buffer[j + 5] = ' ';
+ }
+ for (; j < 64; j++)
+ buffer[j + 5] = ' ';
+ sprintf(buffer + 69, " %d", i + 63);
+ print(priv, "%s\n", buffer);
+ }
+ print(priv, " 'S' = serv. cell 'n' = SI2 (neigh.) 'r' = SI5 (rep.) "
+ "'b' = SI2+SI5\n\n");
+
+ /* serving cell */
+ print(priv, "Serving Cell:\n");
+ print(priv, " BSIC = %d,%d MCC = %s MNC = %s LAC = 0x%04x Cell ID "
+ "= 0x%04x\n", s->bsic >> 3, s->bsic & 0x7,
+ gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc), s->lac,
+ s->cell_id);
+ print(priv, " Country = %s Network Name = %s\n", gsm_get_mcc(s->mcc),
+ gsm_get_mnc(s->mcc, s->mnc));
+ print(priv, " MAX_RETRANS = %d TX_INTEGER = %d re-establish = %s\n",
+ s->max_retrans, s->tx_integer,
+ (s->reest_denied) ? "denied" : "allowed");
+ print(priv, " Cell barred = %s barred classes =",
+ (s->cell_barr ? "yes" : "no"));
+ for (i = 0; i < 16; i++) {
+ if ((s->class_barr & (1 << i)))
+ print(priv, " C%d", i);
+ }
+ print(priv, "\n");
+ if (s->sp)
+ print(priv, " CBQ = %d CRO = %d TEMP_OFFSET = %d "
+ "PENALTY_TIME = %d\n", s->sp_cbq, s->sp_cro, s->sp_to,
+ s->sp_pt);
+ if (s->nb_ncc_permitted_si2) {
+ print(priv, "NCC Permitted BCCH =");
+ for (i = 0; i < 8; i++)
+ if ((s->nb_ncc_permitted_si2 & (1 << i)))
+ print(priv, " %d", i);
+ print(priv, "\n");
+ }
+ if (s->nb_ncc_permitted_si6) {
+ print(priv, "NCC Permitted SACCH/TCH =");
+ for (i = 0; i < 8; i++)
+ if ((s->nb_ncc_permitted_si6 & (1 << i)))
+ print(priv, " %d", i);
+ print(priv, "\n");
+ }
+ print(priv, "\n");
+
+ /* neighbor cell */
+ print(priv, "Neighbor Cell:\n");
+ print(priv, " MAX_RETRANS = %d TX_INTEGER = %d re-establish = %s\n",
+ s->nb_max_retrans, s->nb_tx_integer,
+ (s->nb_reest_denied) ? "denied" : "allowed");
+ print(priv, " Cell barred = %s barred classes =",
+ (s->nb_cell_barr ? "yes" : "no"));
+ for (i = 0; i < 16; i++) {
+ if ((s->nb_class_barr & (1 << i)))
+ print(priv, " C%d", i);
+ }
+ print(priv, "\n");
+ print(priv, "\n");
+
+ /* cell selection */
+ print(priv, "MX_TXPWR_MAX_CCCH = %d CRH = %d RXLEV_MIN = %d "
+ "NECI = %d ACS = %d\n", s->ms_txpwr_max_cch,
+ s->cell_resel_hyst_db, s->rxlev_acc_min_db, s->neci, s->acs);
+
+ /* bcch options */
+ print(priv, "BCCH link timeout = %d DTX = %d PWRC = %d\n",
+ s->bcch_radio_link_timeout, s->bcch_dtx, s->bcch_pwrc);
+
+ /* sacch options */
+ print(priv, "SACCH link timeout = %d DTX = %d PWRC = %d\n",
+ s->sacch_radio_link_timeout, s->sacch_dtx, s->sacch_pwrc);
+
+ /* control channel */
+ switch(s->ccch_conf) {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ print(priv, "CCCH Config = %d CCCH", (s->ccch_conf >> 1) + 1);
+ break;
+ case 1:
+ print(priv, "CCCH Config = 1 CCCH + SDCCH");
+ break;
+ default:
+ print(priv, "CCCH Config = reserved");
+ }
+ print(priv, " BS-PA-MFMS = %d Attachment = %s\n",
+ s->pag_mf_periods, (s->att_allowed) ? "allowed" : "denied");
+ print(priv, "BS-AG_BLKS_RES = %d ", s->bs_ag_blks_res);
+ if (s->t3212)
+ print(priv, "T3212 = %d sec.\n", s->t3212);
+ else
+ print(priv, "T3212 = disabled\n", s->t3212);
+
+ /* channel description */
+ if (s->h)
+ print(priv, "chan_nr = 0x%02x TSC = %d MAIO = %d HSN = %d\n",
+ s->chan_nr, s->tsc, s->maio, s->hsn);
+ else
+ print(priv, "chan_nr = 0x%02x TSC = %d ARFCN = %d\n",
+ s->chan_nr, s->tsc, s->arfcn);
+ print(priv, "\n");
+
+ return 0;
+}
+
+/*
+ * decoding
+ */
+
+int gsm48_decode_chan_h0(struct gsm48_chan_desc *cd, uint8_t *tsc,
+ uint16_t *arfcn)
+{
+ *tsc = cd->h0.tsc;
+ *arfcn = cd->h0.arfcn_low | (cd->h0.arfcn_high << 8);
+
+ return 0;
+}
+
+int gsm48_decode_chan_h1(struct gsm48_chan_desc *cd, uint8_t *tsc,
+ uint8_t *maio, uint8_t *hsn)
+{
+ *tsc = cd->h1.tsc;
+ *maio = cd->h1.maio_low | (cd->h1.maio_high << 2);
+ *hsn = cd->h1.hsn;
+
+ return 0;
+}
+
+/* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */
+static int decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd,
+ uint8_t len, uint8_t mask, uint8_t frqt)
+{
+#if 0
+ /* only Bit map 0 format for P-GSM */
+ if ((cd[0] & 0xc0 & mask) != 0x00 &&
+ (set->p_gsm && !set->e_gsm && !set->r_gsm && !set->dcs))
+ return 0;
+#endif
+
+ return gsm48_decode_freq_list(f, cd, len, mask, frqt);
+}
+
+/* decode "Cell Selection Parameters" (10.5.2.4) */
+static int gsm48_decode_cell_sel_param(struct gsm48_sysinfo *s,
+ struct gsm48_cell_sel_par *cs)
+{
+ s->ms_txpwr_max_cch = cs->ms_txpwr_max_ccch;
+ s->cell_resel_hyst_db = cs->cell_resel_hyst * 2;
+ s->rxlev_acc_min_db = cs->rxlev_acc_min - 110;
+ s->neci = cs->neci;
+ s->acs = cs->acs;
+
+ return 0;
+}
+
+/* decode "Cell Options (BCCH)" (10.5.2.3) */
+static int gsm48_decode_cellopt_bcch(struct gsm48_sysinfo *s,
+ struct gsm48_cell_options *co)
+{
+ s->bcch_radio_link_timeout = (co->radio_link_timeout + 1) * 4;
+ s->bcch_dtx = co->dtx;
+ s->bcch_pwrc = co->pwrc;
+
+ return 0;
+}
+
+/* decode "Cell Options (SACCH)" (10.5.2.3a) */
+static int gsm48_decode_cellopt_sacch(struct gsm48_sysinfo *s,
+ struct gsm48_cell_options *co)
+{
+ s->sacch_radio_link_timeout = (co->radio_link_timeout + 1) * 4;
+ s->sacch_dtx = co->dtx;
+ s->sacch_pwrc = co->pwrc;
+
+ return 0;
+}
+
+/* decode "Control Channel Description" (10.5.2.11) */
+static int gsm48_decode_ccd(struct gsm48_sysinfo *s,
+ struct gsm48_control_channel_descr *cc)
+{
+ s->ccch_conf = cc->ccch_conf;
+ s->bs_ag_blks_res = cc->bs_ag_blks_res;
+ s->att_allowed = cc->att;
+ s->pag_mf_periods = cc->bs_pa_mfrms + 2;
+ s->t3212 = cc->t3212 * 360; /* convert deci-hours to seconds */
+
+ return 0;
+}
+
+/* decode "Mobile Allocation" (10.5.2.21) */
+int gsm48_decode_mobile_alloc(struct gsm_sysinfo_freq *freq,
+ uint8_t *ma, uint8_t len, uint16_t *hopping, uint8_t *hopp_len, int si4)
+{
+ int i, j = 0;
+ uint16_t f[len << 3];
+
+ /* not more than 64 hopping indexes allowed in IE */
+ if (len > 8)
+ return -EINVAL;
+
+ /* tabula rasa */
+ *hopp_len = 0;
+ if (si4) {
+ for (i = 0; i < 1024; i++)
+ freq[i].mask &= ~FREQ_TYPE_HOPP;
+ }
+
+ /* generating list of all frequencies (1..1023,0) */
+ for (i = 1; i <= 1024; i++) {
+ if ((freq[i & 1023].mask & FREQ_TYPE_SERV)) {
+ LOGP(DRR, LOGL_INFO, "Serving cell ARFCN #%d: %d\n",
+ j, i & 1023);
+ f[j++] = i & 1023;
+ if (j == (len << 3))
+ break;
+ }
+ }
+
+ /* fill hopping table with frequency index given by IE
+ * and set hopping type bits
+ */
+ for (i = 0; i < (len << 3); i++) {
+ /* if bit is set, this frequency index is used for hopping */
+ if ((ma[len - 1 - (i >> 3)] & (1 << (i & 7)))) {
+ LOGP(DRR, LOGL_INFO, "Hopping ARFCN: %d (bit %d)\n",
+ i, f[i]);
+ /* index higher than entries in list ? */
+ if (i >= j) {
+ LOGP(DRR, LOGL_NOTICE, "Mobile Allocation "
+ "hopping index %d exceeds maximum "
+ "number of cell frequencies. (%d)\n",
+ i + 1, j);
+ break;
+ }
+ hopping[(*hopp_len)++] = f[i];
+ if (si4)
+ freq[f[i]].mask |= FREQ_TYPE_HOPP;
+ }
+ }
+
+ return 0;
+}
+
+/* Rach Control decode tables */
+static uint8_t gsm48_max_retrans[4] = {
+ 1, 2, 4, 7
+};
+static uint8_t gsm48_tx_integer[16] = {
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 25, 32, 50
+};
+
+/* decode "RACH Control Parameter" (10.5.2.29) */
+static int gsm48_decode_rach_ctl_param(struct gsm48_sysinfo *s,
+ struct gsm48_rach_control *rc)
+{
+ s->reest_denied = rc->re;
+ s->cell_barr = rc->cell_bar;
+ s->tx_integer = gsm48_tx_integer[rc->tx_integer];
+ s->max_retrans = gsm48_max_retrans[rc->max_trans];
+ s->class_barr = (rc->t2 << 8) | rc->t3;
+
+ return 0;
+}
+static int gsm48_decode_rach_ctl_neigh(struct gsm48_sysinfo *s,
+ struct gsm48_rach_control *rc)
+{
+ s->nb_reest_denied = rc->re;
+ s->nb_cell_barr = rc->cell_bar;
+ s->nb_tx_integer = gsm48_tx_integer[rc->tx_integer];
+ s->nb_max_retrans = gsm48_max_retrans[rc->max_trans];
+ s->nb_class_barr = (rc->t2 << 8) | rc->t3;
+
+ return 0;
+}
+
+/* decode "SI 1 Rest Octets" (10.5.2.32) */
+static int gsm48_decode_si1_rest(struct gsm48_sysinfo *s, uint8_t *si,
+ uint8_t len)
+{
+ struct bitvec bv;
+
+ memset(&bv, 0, sizeof(bv));
+ bv.data_len = len;
+ bv.data = si;
+
+ /* Optional Selection Parameters */
+ if (bitvec_get_bit_high(&bv) == H) {
+ s->nch = 1;
+ s->nch_position = bitvec_get_uint(&bv, 5);
+ } else
+ s->nch = 0;
+ if (bitvec_get_bit_high(&bv) == H)
+ s->band_ind = 1;
+ else
+ s->band_ind = 0;
+
+ return 0;
+}
+
+/* decode "SI 3 Rest Octets" (10.5.2.34) */
+static int gsm48_decode_si3_rest(struct gsm48_sysinfo *s, uint8_t *si,
+ uint8_t len)
+{
+ struct bitvec bv;
+
+ memset(&bv, 0, sizeof(bv));
+ bv.data_len = len;
+ bv.data = si;
+
+ /* Optional Selection Parameters */
+ if (bitvec_get_bit_high(&bv) == H) {
+ s->sp = 1;
+ s->sp_cbq = bitvec_get_uint(&bv, 1);
+ s->sp_cro = bitvec_get_uint(&bv, 6);
+ s->sp_to = bitvec_get_uint(&bv, 3);
+ s->sp_pt = bitvec_get_uint(&bv, 5);
+ } else
+ s->sp = 0;
+ /* Optional Power Offset */
+ if (bitvec_get_bit_high(&bv) == H) {
+ s->po = 1;
+ s->po_value = bitvec_get_uint(&bv, 2);
+ } else
+ s->po = 0;
+ /* System Onformation 2ter Indicator */
+ if (bitvec_get_bit_high(&bv) == H)
+ s->si2ter_ind = 1;
+ else
+ s->si2ter_ind = 0;
+ /* Early Classark Sending Control */
+ if (bitvec_get_bit_high(&bv) == H)
+ s->ecsm = 1;
+ else
+ s->ecsm = 0;
+ /* Scheduling if and where */
+ if (bitvec_get_bit_high(&bv) == H) {
+ s->sched = 1;
+ s->sched_where = bitvec_get_uint(&bv, 3);
+ } else
+ s->sched = 0;
+ /* GPRS Indicator */
+ if (bitvec_get_bit_high(&bv) == H) {
+ s->gprs = 1;
+ s->gprs_ra_colour = bitvec_get_uint(&bv, 3);
+ s->gprs_si13_pos = bitvec_get_uint(&bv, 1);
+ } else
+ s->gprs = 0;
+
+ return 0;
+}
+
+/* decode "SI 4 Rest Octets" (10.5.2.35) */
+static int gsm48_decode_si4_rest(struct gsm48_sysinfo *s, uint8_t *si,
+ uint8_t len)
+{
+ struct bitvec bv;
+
+ memset(&bv, 0, sizeof(bv));
+ bv.data_len = len;
+ bv.data = si;
+
+ /* Optional Selection Parameters */
+ if (bitvec_get_bit_high(&bv) == H) {
+ s->sp = 1;
+ s->sp_cbq = bitvec_get_uint(&bv, 1);
+ s->sp_cro = bitvec_get_uint(&bv, 6);
+ s->sp_to = bitvec_get_uint(&bv, 3);
+ s->sp_pt = bitvec_get_uint(&bv, 5);
+ } else
+ s->sp = 0;
+ /* Optional Power Offset */
+ if (bitvec_get_bit_high(&bv) == H) {
+ s->po = 1;
+ s->po_value = bitvec_get_uint(&bv, 3);
+ } else
+ s->po = 0;
+ /* GPRS Indicator */
+ if (bitvec_get_bit_high(&bv) == H) {
+ s->gprs = 1;
+ s->gprs_ra_colour = bitvec_get_uint(&bv, 3);
+ s->gprs_si13_pos = bitvec_get_uint(&bv, 1);
+ } else
+ s->gprs = 0;
+ // todo: more rest octet bits
+
+ return 0;
+}
+
+/* decode "SI 6 Rest Octets" (10.5.2.35a) */
+static int gsm48_decode_si6_rest(struct gsm48_sysinfo *s, uint8_t *si,
+ uint8_t len)
+{
+ return 0;
+}
+
+int gsm48_decode_sysinfo1(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_1 *si, int len)
+{
+ int payload_len = len - sizeof(*si);
+
+ memcpy(s->si1_msg, si, MIN(len, sizeof(s->si1_msg)));
+
+ /* Cell Channel Description */
+ decode_freq_list(s->freq, si->cell_channel_description,
+ sizeof(si->cell_channel_description), 0xce, FREQ_TYPE_SERV);
+ /* RACH Control Parameter */
+ gsm48_decode_rach_ctl_param(s, &si->rach_control);
+ /* SI 1 Rest Octets */
+ if (payload_len)
+ gsm48_decode_si1_rest(s, si->rest_octets, payload_len);
+
+ s->si1 = 1;
+
+ if (s->si4) {
+ LOGP(DRR, LOGL_NOTICE, "Now updating previously received "
+ "SYSTEM INFORMATION 4\n");
+ gsm48_decode_sysinfo4(s,
+ (struct gsm48_system_information_type_4 *) s->si4_msg,
+ sizeof(s->si4_msg));
+ }
+
+ return 0;
+}
+
+int gsm48_decode_sysinfo2(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_2 *si, int len)
+{
+ memcpy(s->si2_msg, si, MIN(len, sizeof(s->si2_msg)));
+
+ /* Neighbor Cell Description */
+ s->nb_ext_ind_si2 = (si->bcch_frequency_list[0] >> 6) & 1;
+ s->nb_ba_ind_si2 = (si->bcch_frequency_list[0] >> 5) & 1;
+ decode_freq_list(s->freq, si->bcch_frequency_list,
+ sizeof(si->bcch_frequency_list), 0xce, FREQ_TYPE_NCELL_2);
+ /* NCC Permitted */
+ s->nb_ncc_permitted_si2 = si->ncc_permitted;
+ /* RACH Control Parameter */
+ gsm48_decode_rach_ctl_neigh(s, &si->rach_control);
+
+ s->si2 = 1;
+
+ return 0;
+}
+
+int gsm48_decode_sysinfo2bis(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_2bis *si, int len)
+{
+ memcpy(s->si2b_msg, si, MIN(len, sizeof(s->si2b_msg)));
+
+ /* Neighbor Cell Description */
+ s->nb_ext_ind_si2bis = (si->bcch_frequency_list[0] >> 6) & 1;
+ s->nb_ba_ind_si2bis = (si->bcch_frequency_list[0] >> 5) & 1;
+ decode_freq_list(s->freq, si->bcch_frequency_list,
+ sizeof(si->bcch_frequency_list), 0xce, FREQ_TYPE_NCELL_2bis);
+ /* RACH Control Parameter */
+ gsm48_decode_rach_ctl_neigh(s, &si->rach_control);
+
+ s->si2bis = 1;
+
+ return 0;
+}
+
+int gsm48_decode_sysinfo2ter(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_2ter *si, int len)
+{
+ memcpy(s->si2t_msg, si, MIN(len, sizeof(s->si2t_msg)));
+
+ /* Neighbor Cell Description 2 */
+ s->nb_multi_rep_si2ter = (si->ext_bcch_frequency_list[0] >> 6) & 3;
+ s->nb_ba_ind_si2ter = (si->ext_bcch_frequency_list[0] >> 5) & 1;
+ decode_freq_list(s->freq, si->ext_bcch_frequency_list,
+ sizeof(si->ext_bcch_frequency_list), 0x8e,
+ FREQ_TYPE_NCELL_2ter);
+
+ s->si2ter = 1;
+
+ return 0;
+}
+
+int gsm48_decode_sysinfo3(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_3 *si, int len)
+{
+ int payload_len = len - sizeof(*si);
+
+ memcpy(s->si3_msg, si, MIN(len, sizeof(s->si3_msg)));
+
+ /* Cell Identity */
+ s->cell_id = ntohs(si->cell_identity);
+ /* LAI */
+ gsm48_decode_lai_hex(&si->lai, &s->mcc, &s->mnc, &s->lac);
+ /* Control Channel Description */
+ gsm48_decode_ccd(s, &si->control_channel_desc);
+ /* Cell Options (BCCH) */
+ gsm48_decode_cellopt_bcch(s, &si->cell_options);
+ /* Cell Selection Parameters */
+ gsm48_decode_cell_sel_param(s, &si->cell_sel_par);
+ /* RACH Control Parameter */
+ gsm48_decode_rach_ctl_param(s, &si->rach_control);
+ /* SI 3 Rest Octets */
+ if (payload_len >= 4)
+ gsm48_decode_si3_rest(s, si->rest_octets, payload_len);
+
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 3 (mcc %s mnc %s "
+ "lac 0x%04x)\n", gsm_print_mcc(s->mcc),
+ gsm_print_mnc(s->mnc), s->lac);
+
+ s->si3 = 1;
+
+ return 0;
+}
+
+int gsm48_decode_sysinfo4(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_4 *si, int len)
+{
+ int payload_len = len - sizeof(*si);
+
+ uint8_t *data = si->data;
+ struct gsm48_chan_desc *cd;
+
+ memcpy(s->si4_msg, si, MIN(len, sizeof(s->si4_msg)));
+
+ /* LAI */
+ gsm48_decode_lai_hex(&si->lai, &s->mcc, &s->mnc, &s->lac);
+ /* Cell Selection Parameters */
+ gsm48_decode_cell_sel_param(s, &si->cell_sel_par);
+ /* RACH Control Parameter */
+ gsm48_decode_rach_ctl_param(s, &si->rach_control);
+
+ /* CBCH Channel Description */
+ if (payload_len >= 1 && data[0] == GSM48_IE_CBCH_CHAN_DESC) {
+ if (payload_len < 4) {
+short_read:
+ LOGP(DRR, LOGL_NOTICE, "Short read!\n");
+ return -EIO;
+ }
+ cd = (struct gsm48_chan_desc *) (data + 1);
+ s->chan_nr = cd->chan_nr;
+ if (cd->h0.h) {
+ s->h = 1;
+ gsm48_decode_chan_h1(cd, &s->tsc, &s->maio, &s->hsn);
+ } else {
+ s->h = 0;
+ gsm48_decode_chan_h0(cd, &s->tsc, &s->arfcn);
+ }
+ payload_len -= 4;
+ data += 4;
+ }
+ /* CBCH Mobile Allocation */
+ if (payload_len >= 1 && data[0] == GSM48_IE_CBCH_MOB_AL) {
+ if (payload_len < 1 || payload_len < 2 + data[1])
+ goto short_read;
+ if (!s->si1) {
+ LOGP(DRR, LOGL_NOTICE, "Ignoring CBCH allocation of "
+ "SYSTEM INFORMATION 4 until SI 1 is "
+ "received.\n");
+ gsm48_decode_mobile_alloc(s->freq, data + 2, data[1],
+ s->hopping, &s->hopp_len, 1);
+ }
+ payload_len -= 2 + data[1];
+ data += 2 + data[1];
+ }
+ /* SI 4 Rest Octets */
+ if (payload_len > 0)
+ gsm48_decode_si4_rest(s, data, payload_len);
+
+ s->si4 = 1;
+
+ return 0;
+}
+
+int gsm48_decode_sysinfo5(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_5 *si, int len)
+{
+ memcpy(s->si5_msg, si, MIN(len, sizeof(s->si5_msg)));
+
+ /* Neighbor Cell Description */
+ s->nb_ext_ind_si5 = (si->bcch_frequency_list[0] >> 6) & 1;
+ s->nb_ba_ind_si5 = (si->bcch_frequency_list[0] >> 5) & 1;
+ decode_freq_list(s->freq, si->bcch_frequency_list,
+ sizeof(si->bcch_frequency_list), 0xce, FREQ_TYPE_REP_5);
+
+ s->si5 = 1;
+
+ return 0;
+}
+
+int gsm48_decode_sysinfo5bis(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_5bis *si, int len)
+{
+ memcpy(s->si5b_msg, si, MIN(len, sizeof(s->si5b_msg)));
+
+ /* Neighbor Cell Description */
+ s->nb_ext_ind_si5bis = (si->bcch_frequency_list[0] >> 6) & 1;
+ s->nb_ba_ind_si5bis = (si->bcch_frequency_list[0] >> 5) & 1;
+ decode_freq_list(s->freq, si->bcch_frequency_list,
+ sizeof(si->bcch_frequency_list), 0xce, FREQ_TYPE_REP_5bis);
+
+ s->si5bis = 1;
+
+ return 0;
+}
+
+int gsm48_decode_sysinfo5ter(struct gsm48_sysinfo *s,
+ struct gsm48_system_information_type_5ter *si, int len)
+{
+ memcpy(s->si5t_msg, si, MIN(len, sizeof(s->si5t_msg)));
+
+ /* Neighbor Cell Description */
+ s->nb_multi_rep_si5ter = (si->bcch_frequency_list[0] >> 6) & 3;
+ s->nb_ba_ind_si5ter = (si->bcch_frequency_list[0] >> 5) & 1;
+ decode_freq_list(s->freq, si->bcch_frequency_list,
+ sizeof(si->bcch_frequency_list), 0x8e, FREQ_TYPE_REP_5ter);