summaryrefslogtreecommitdiffstats
path: root/Src
diff options
context:
space:
mode:
authorroot2012-02-28 14:15:19 +0100
committerroot2012-02-28 14:15:19 +0100
commit1116885d96725ce064db04604e4d197a136b163c (patch)
tree22ba472d309f1ac66918f09cc63bb9be057cf579 /Src
parentcompiled version added (diff)
downloadimsi-catcher-detection-1116885d96725ce064db04604e4d197a136b163c.tar.gz
imsi-catcher-detection-1116885d96725ce064db04604e4d197a136b163c.tar.xz
imsi-catcher-detection-1116885d96725ce064db04604e4d197a136b163c.zip
updated codebase to latest version of osmocombb
Diffstat (limited to 'Src')
-rw-r--r--Src/eclipse/.metadata/.log845
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.cdt.core/.log1
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.cdt.core/CatcherDriver.1330426096136.pdombin0 -> 5419008 bytes
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.cdt.make.core/CatcherDriver.sc228
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.history/36/a07dff68fd6100111a83ded3e22caa93823
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.history/c9/f0b573ecfa6100111a83ded3e22caa93824
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.indexbin151 -> 151 bytes
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.root/6.treebin0 -> 84968 bytes
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resourcesbin764 -> 768 bytes
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs4
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/.workspace/2012/2/9/refactorings.history3
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/.workspace/2012/2/9/refactorings.index2
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.ltk.ui.refactoring/dialog_settings.xml7
-rw-r--r--Src/eclipse/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml6
-rw-r--r--Src/osmolib/include/l1ctl_proto.h3
-rw-r--r--Src/osmolib/src/.cproject209
-rw-r--r--Src/osmolib/src/.project77
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/host/calypso_pll/pll.pl0
-rwxr-xr-xSrc/osmolib/src/host/fb_tools/bdf_to_c.py294
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/host/gsmmap/git-version-gen0
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/common/Makefile.am2
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/common/logging.h2
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/common/networks.h2
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/common/osmocom_data.h2
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/common/sim.h10
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/Makefile.am5
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm411_sms.h33
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm480_ss.h9
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h7
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h13
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/mncc.h11
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/settings.h4
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/subscriber.h4
-rw-r--r--Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/transaction.h19
-rw-r--r--Src/osmolib/src/host/layer23/src/common/Makefile.am2
-rw-r--r--Src/osmolib/src/host/layer23/src/common/gps.c23
-rw-r--r--Src/osmolib/src/host/layer23/src/common/l1ctl.c2
-rw-r--r--Src/osmolib/src/host/layer23/src/common/l1ctl_lapdm_glue.c2
-rw-r--r--Src/osmolib/src/host/layer23/src/common/l1l2_interface.c3
-rw-r--r--Src/osmolib/src/host/layer23/src/common/logging.c11
-rw-r--r--Src/osmolib/src/host/layer23/src/common/main.c1
-rw-r--r--Src/osmolib/src/host/layer23/src/common/networks.c2
-rw-r--r--Src/osmolib/src/host/layer23/src/common/sap_interface.c3
-rw-r--r--Src/osmolib/src/host/layer23/src/common/sim.c21
-rw-r--r--Src/osmolib/src/host/layer23/src/misc/app_bcch_scan.c1
-rw-r--r--Src/osmolib/src/host/layer23/src/misc/app_cbch_sniff.c1
-rw-r--r--Src/osmolib/src/host/layer23/src/misc/app_ccch_scan.c34
-rw-r--r--Src/osmolib/src/host/layer23/src/misc/app_echo_test.c1
-rw-r--r--Src/osmolib/src/host/layer23/src/misc/bcch_scan.c3
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/host/layer23/src/misc/catcherbin951882 -> 1003279 bytes
-rw-r--r--Src/osmolib/src/host/layer23/src/misc/catcher.c13
-rw-r--r--Src/osmolib/src/host/layer23/src/misc/cell_log.c1
-rw-r--r--Src/osmolib/src/host/layer23/src/misc/rslms.c2
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/Makefile.am4
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/app_mobile.c9
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/gsm322.c12
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/gsm411_sms.c941
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/gsm480_ss.c1289
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/gsm48_cc.c41
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/gsm48_mm.c293
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/gsm48_rr.c590
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/main.c47
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/mnccms.c4
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/settings.c5
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/subscriber.c73
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/support.c2
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/transaction.c10
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/vty_interface.c148
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/host/osmocon/git-version-gen0
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/host/osmocon/memdump_convert.pl0
-rw-r--r--Src/osmolib/src/host/osmocon/osmocon.c10
-rw-r--r--Src/osmolib/src/host/osmocon/osmoload.c4
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/host/rita_pll/mtk_pll.pl0
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/host/rita_pll/rita_pll.pl0
-rw-r--r--Src/osmolib/src/shared/libosmocore/.gitignore26
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc16gen.h59
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc32gen.h59
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc64gen.h59
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc8gen.h59
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-host/src/crc16gen.c120
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-host/src/crc32gen.c120
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-host/src/crc64gen.c120
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-host/src/crc8gen.c120
-rwxr-xr-xSrc/osmolib/src/shared/libosmocore/build-host/tests/a5/a5_test225
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-host/tests/atconfig20
-rwxr-xr-xSrc/osmolib/src/shared/libosmocore/build-host/tests/auth/milenage_test225
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/shared/libosmocore/build-host/tests/bits/bitrev_test2
-rwxr-xr-xSrc/osmolib/src/shared/libosmocore/build-host/tests/conv/conv_test225
-rwxr-xr-xSrc/osmolib/src/shared/libosmocore/build-host/tests/gsm0808/gsm0808_test225
-rwxr-xr-xSrc/osmolib/src/shared/libosmocore/build-host/tests/lapd/lapd_test225
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/shared/libosmocore/build-host/utils/osmo-arfcn2
-rwxr-xr-xSrc/osmolib/src/shared/libosmocore/build-host/utils/osmo-auc-gen225
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc16gen.h59
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc32gen.h59
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc64gen.h59
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc8gen.h59
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-target/src/crc16gen.c120
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-target/src/crc32gen.c120
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-target/src/crc64gen.c120
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-target/src/crc8gen.c120
-rw-r--r--Src/osmolib/src/shared/libosmocore/build-target/tests/atconfig20
-rw-r--r--Src/osmolib/src/shared/libosmocore/configure.ac11
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/shared/libosmocore/debian/rules0
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/shared/libosmocore/git-version-gen0
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/Makefile.am11
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/conv.h67
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/crcXXgen.h.tpl59
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/gsmtap.h62
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/gsmtap_util.h9
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/linuxrbtree.h160
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/logging.h5
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/msgb.h26
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/prim.h3
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/timer.h6
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/timer_compat.h79
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/core/utils.h3
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/crypt/Makefile.am2
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/crypt/auth.h90
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/Makefile.am3
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/a5.h20
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/comp128.h2
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_smc.h62
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_smr.h45
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_utils.h36
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0808.h3
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h2
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/lapd_core.h171
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/lapdm.h60
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/Makefile.am2
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h6
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_11.h8
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_44_318.h153
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/sysinfo.h2
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/tlv.h42
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/vty/telnet_interface.h2
-rw-r--r--Src/osmolib/src/shared/libosmocore/include/osmocom/vty/vty.h4
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/Makefile.am15
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/backtrace.c4
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/conv.c174
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/crcXXgen.c.tpl120
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/Makefile.am14
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/a5.c114
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/auth_comp128v1.c47
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/auth_core.c121
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/auth_milenage.c109
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/comp128.c2
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_smc.c539
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_smr.c451
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_utils.c306
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/gsm0808.c183
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/gsm48.c2
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/lapd_core.c2170
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/lapdm.c1991
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-encblock.c38
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-internal-enc.c121
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-internal.c805
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes.h27
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes_i.h122
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes_wrap.h48
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/common.h20
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/crypto.h0
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/includes.h0
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/milenage.c329
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsm/milenage/milenage.h33
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/gsmtap_util.c49
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/logging.c12
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/logging_syslog.c2
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/rbtree.c383
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/serial.c24
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/socket.c2
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/timer.c178
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/utils.c6
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/vty/logging_vty.c25
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/vty/telnet_interface.c12
-rw-r--r--Src/osmolib/src/shared/libosmocore/src/vty/vty.c8
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/Makefile.am43
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/a5/Makefile.am6
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/a5/a5_test.c98
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/a5/a5_test.ok6
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/auth/Makefile.am8
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/auth/milenage_test.c78
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/auth/milenage_test.ok8
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/bits/Makefile.am1
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/bits/bitrev_test.ok24
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/conv/Makefile.am6
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/conv/conv_test.c486
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/conv/conv_test.ok55
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/gsm0808/Makefile.am6
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/gsm0808/gsm0808_test.c269
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/gsm0808/gsm0808_test.ok15
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/lapd/Makefile.am9
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/lapd/lapd_test.c319
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/lapd/lapd_test.ok20
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/msgfile/Makefile.am1
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/msgfile/msgfile_test.ok1
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/sms/Makefile.am1
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/sms/sms_test.ok2
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/smscb/Makefile.am1
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/smscb/smscb_test.ok4
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/testsuite.at73
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/timer/Makefile.am1
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/timer/timer_test.c182
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/timer/timer_test.ok2
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/ussd/Makefile.am1
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/ussd/ussd_test.c6
-rw-r--r--Src/osmolib/src/shared/libosmocore/tests/ussd/ussd_test.ok53
-rw-r--r--Src/osmolib/src/shared/libosmocore/utils/Makefile.am5
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/shared/libosmocore/utils/gen_website_doc_tree.sh0
-rw-r--r--Src/osmolib/src/shared/libosmocore/utils/osmo-auc-gen.c183
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/shared/update-libosmocore.sh0
-rw-r--r--Src/osmolib/src/target/firmware/Makefile28
-rw-r--r--Src/osmolib/src/target/firmware/abb/twl3025.c19
-rw-r--r--Src/osmolib/src/target/firmware/apps/chainload/main.c1
-rw-r--r--Src/osmolib/src/target/firmware/apps/compal_dsp_dump/main.c25
-rw-r--r--Src/osmolib/src/target/firmware/apps/hello_world/main.c41
-rw-r--r--Src/osmolib/src/target/firmware/apps/layer1/main.c48
-rw-r--r--Src/osmolib/src/target/firmware/apps/loader/main.c1
-rw-r--r--Src/osmolib/src/target/firmware/apps/rssi/main.c1544
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/target/firmware/apps/simtest/main.c75
-rw-r--r--Src/osmolib/src/target/firmware/board/compal/highram.lds4
-rw-r--r--Src/osmolib/src/target/firmware/board/compal/ram.lds4
-rw-r--r--Src/osmolib/src/target/firmware/board/compal_e86/init.c7
-rw-r--r--Src/osmolib/src/target/firmware/board/compal_e88/init.c6
-rw-r--r--Src/osmolib/src/target/firmware/board/compal_e99/init.c8
-rw-r--r--Src/osmolib/src/target/firmware/board/gta0x/init.c3
-rw-r--r--Src/osmolib/src/target/firmware/board/pirelli_dpl10/init.c42
-rw-r--r--Src/osmolib/src/target/firmware/board/se_j100/init.c7
-rw-r--r--Src/osmolib/src/target/firmware/calypso/backlight.c2
-rw-r--r--Src/osmolib/src/target/firmware/calypso/i2c.c6
-rw-r--r--Src/osmolib/src/target/firmware/calypso/keypad.c17
-rw-r--r--Src/osmolib/src/target/firmware/calypso/rtc.c5
-rw-r--r--Src/osmolib/src/target/firmware/calypso/sim.c717
-rw-r--r--Src/osmolib/src/target/firmware/comm/msgb.c1
-rw-r--r--Src/osmolib/src/target/firmware/comm/timer.c30
-rw-r--r--Src/osmolib/src/target/firmware/fb/4x6.c731
-rw-r--r--Src/osmolib/src/target/firmware/fb/5x8.c802
-rw-r--r--Src/osmolib/src/target/firmware/fb/c64.c1069
-rw-r--r--Src/osmolib/src/target/firmware/fb/fb_bw8.c311
-rw-r--r--Src/osmolib/src/target/firmware/fb/fb_dummy.c70
-rw-r--r--Src/osmolib/src/target/firmware/fb/fb_rgb332.c305
-rw-r--r--Src/osmolib/src/target/firmware/fb/fb_s6b33b1x.c193
-rw-r--r--Src/osmolib/src/target/firmware/fb/fb_ssd1783.c204
-rw-r--r--Src/osmolib/src/target/firmware/fb/fb_ssd1963.c196
-rw-r--r--Src/osmolib/src/target/firmware/fb/fb_st7558.c132
-rw-r--r--Src/osmolib/src/target/firmware/fb/fb_td014.c150
-rw-r--r--Src/osmolib/src/target/firmware/fb/font.c57
-rw-r--r--Src/osmolib/src/target/firmware/fb/framebuffer.c28
-rw-r--r--Src/osmolib/src/target/firmware/fb/helvB08.c833
-rw-r--r--Src/osmolib/src/target/firmware/fb/helvB14.c1195
-rw-r--r--Src/osmolib/src/target/firmware/fb/helvB24.c1871
-rw-r--r--Src/osmolib/src/target/firmware/fb/helvR08.c826
-rw-r--r--Src/osmolib/src/target/firmware/fb/helvR14.c1198
-rw-r--r--Src/osmolib/src/target/firmware/fb/helvR24.c1870
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/target/firmware/include/calypso/sim.h22
-rw-r--r--Src/osmolib/src/target/firmware/include/comm/timer.h23
-rw-r--r--Src/osmolib/src/target/firmware/include/fb/fb_bw8.h51
-rw-r--r--Src/osmolib/src/target/firmware/include/fb/fb_rgb332.h47
-rw-r--r--Src/osmolib/src/target/firmware/include/fb/font.h81
-rw-r--r--Src/osmolib/src/target/firmware/include/fb/framebuffer.h128
-rw-r--r--Src/osmolib/src/target/firmware/include/layer1/async.h3
-rw-r--r--Src/osmolib/src/target/firmware/include/layer1/l23_api.h3
-rw-r--r--Src/osmolib/src/target/firmware/include/layer1/sync.h1
-rw-r--r--Src/osmolib/src/target/firmware/include/rf/trf6151.h4
-rw-r--r--Src/osmolib/src/target/firmware/layer1/l23_api.c69
-rw-r--r--Src/osmolib/src/target/firmware/layer1/mframe_sched.c6
-rw-r--r--Src/osmolib/src/target/firmware/layer1/prim_fbsb.c2
-rw-r--r--Src/osmolib/src/target/firmware/layer1/prim_freq.c1
-rw-r--r--Src/osmolib/src/target/firmware/layer1/prim_pm.c9
-rw-r--r--Src/osmolib/src/target/firmware/layer1/prim_rach.c3
-rw-r--r--Src/osmolib/src/target/firmware/layer1/prim_rx_nb.c2
-rw-r--r--Src/osmolib/src/target/firmware/layer1/prim_tch.c4
-rw-r--r--Src/osmolib/src/target/firmware/layer1/prim_tx_nb.c2
-rw-r--r--Src/osmolib/src/target/firmware/layer1/tpu_window.c1
-rw-r--r--Src/osmolib/src/target/firmware/rf/mt6139.c4
-rw-r--r--Src/osmolib/src/target/firmware/rf/trf6151.c12
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/target_dsp/calypso/bin2cfile.py0
-rwxr-xr-x[-rw-r--r--]Src/osmolib/src/target_dsp/calypso/dump2coff.py0
277 files changed, 33944 insertions, 2920 deletions
diff --git a/Src/eclipse/.metadata/.log b/Src/eclipse/.metadata/.log
index fade1c1..5890662 100644
--- a/Src/eclipse/.metadata/.log
+++ b/Src/eclipse/.metadata/.log
@@ -1803,3 +1803,848 @@ org.eclipse.core.runtime.AssertionFailedException: unknown saveable: org.eclipse
!ENTRY org.eclipse.cdt.core 1 0 2012-02-28 11:48:24.985
!MESSAGE Indexed 'CatcherDriver' (187 sources, 288 headers) in 8.65 sec: 27,880 declarations; 107,743 references; 8 unresolved inclusions; 10 syntax errors; 4,423 unresolved names (3.16%)
+!SESSION 2012-02-28 12:47:07.521 -----------------------------------------------
+eclipse.buildId=I20110613-1736
+java.version=1.6.0_23
+java.vendor=Sun Microsystems Inc.
+BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_US
+Command-line arguments: -os linux -ws gtk -arch x86_64
+
+!ENTRY org.eclipse.core.resources 4 567 2012-02-28 12:47:26.620
+!MESSAGE Workspace restored, but some problems occurred.
+!SUBENTRY 1 org.eclipse.core.resources 4 567 2012-02-28 12:47:26.620
+!MESSAGE Could not read metadata for 'CatcherDriver'.
+!STACK 1
+org.eclipse.core.internal.resources.ResourceException: The project description file (.project) for 'CatcherDriver' is missing. This file contains important information about the project. The project will not function properly until this file is restored.
+ at org.eclipse.core.internal.localstore.FileSystemResourceManager.read(FileSystemResourceManager.java:851)
+ at org.eclipse.core.internal.resources.SaveManager.restoreMetaInfo(SaveManager.java:873)
+ at org.eclipse.core.internal.resources.SaveManager.restoreMetaInfo(SaveManager.java:853)
+ at org.eclipse.core.internal.resources.SaveManager.restore(SaveManager.java:702)
+ at org.eclipse.core.internal.resources.SaveManager.startup(SaveManager.java:1527)
+ at org.eclipse.core.internal.resources.Workspace.startup(Workspace.java:2503)
+ at org.eclipse.core.internal.resources.Workspace.open(Workspace.java:2251)
+ at org.eclipse.core.resources.ResourcesPlugin.start(ResourcesPlugin.java:439)
+ at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
+ at java.security.AccessController.doPrivileged(Native Method)
+ at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
+ at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
+ at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
+ at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:299)
+ at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:440)
+ at org.eclipse.osgi.internal.loader.BundleLoader.setLazyTrigger(BundleLoader.java:268)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:107)
+ at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:462)
+ at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:216)
+ at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:400)
+ at org.eclipse.osgi.internal.loader.SingleSourcePackage.loadClass(SingleSourcePackage.java:35)
+ at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:473)
+ at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:429)
+ at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417)
+ at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
+ at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
+!SUBENTRY 2 org.eclipse.core.resources 4 567 2012-02-28 12:47:26.621
+!MESSAGE The project description file (.project) for 'CatcherDriver' is missing. This file contains important information about the project. The project will not function properly until this file is restored.
+
+!ENTRY org.eclipse.core.filebuffers 4 2 2012-02-28 12:47:28.712
+!MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.core.filebuffers".
+!STACK 0
+java.lang.NullPointerException
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.createProjDescriptionForDescriptor(CConfigBasedDescriptorManager.java:374)
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.findDescriptor(CConfigBasedDescriptorManager.java:341)
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.getDescriptor(CConfigBasedDescriptorManager.java:238)
+ at org.eclipse.cdt.core.CCorePlugin.getCProjectDescription(CCorePlugin.java:640)
+ at org.eclipse.cdt.internal.ui.text.doctools.ProjectMap.load(ProjectMap.java:117)
+ at org.eclipse.cdt.internal.ui.text.doctools.ProjectMap.<init>(ProjectMap.java:58)
+ at org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager.getProjectMap(DocCommentOwnerManager.java:212)
+ at org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager.getCommentOwner(DocCommentOwnerManager.java:129)
+ at org.eclipse.cdt.internal.ui.text.CTextTools.getDocumentationCommentOwner(CTextTools.java:157)
+ at org.eclipse.cdt.internal.ui.text.CTextTools.setupCDocument(CTextTools.java:118)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentSetupParticipant.setup(CDocumentSetupParticipant.java:48)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBufferManager$1.run(ResourceTextFileBufferManager.java:151)
+ at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBufferManager.createEmptyDocument(ResourceTextFileBufferManager.java:166)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBuffer.initializeFileBufferContent(ResourceTextFileBuffer.java:289)
+ at org.eclipse.core.internal.filebuffers.ResourceFileBuffer.create(ResourceFileBuffer.java:245)
+ at org.eclipse.core.internal.filebuffers.TextFileBufferManager.connect(TextFileBufferManager.java:112)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.createFileInfo(TextFileDocumentProvider.java:559)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.createFileInfo(CDocumentProvider.java:856)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.connect(TextFileDocumentProvider.java:478)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.connect(CDocumentProvider.java:778)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.doSetInput(AbstractTextEditor.java:4213)
+ at org.eclipse.ui.texteditor.StatusTextEditor.doSetInput(StatusTextEditor.java:237)
+ at org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.doSetInput(AbstractDecoratedTextEditor.java:1451)
+ at org.eclipse.ui.editors.text.TextEditor.doSetInput(TextEditor.java:169)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.internalDoSetInput(CEditor.java:1380)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.doSetInput(CEditor.java:1345)
+ at org.eclipse.ui.texteditor.AbstractTextEditor$19.run(AbstractTextEditor.java:3200)
+ at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
+ at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
+ at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:759)
+ at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
+ at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:756)
+ at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2642)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.internalInit(AbstractTextEditor.java:3218)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.init(AbstractTextEditor.java:3245)
+ at org.eclipse.ui.internal.EditorManager.createSite(EditorManager.java:828)
+ at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:647)
+ at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)
+ at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)
+ at org.eclipse.ui.internal.EditorAreaHelper.setVisibleEditor(EditorAreaHelper.java:271)
+ at org.eclipse.ui.internal.EditorManager.setVisibleEditor(EditorManager.java:1459)
+ at org.eclipse.ui.internal.EditorManager$5.runWithException(EditorManager.java:972)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:803)
+ at org.eclipse.ui.internal.Workbench$33.runWithException(Workbench.java:1595)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
+ at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
+ at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
+ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
+ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
+ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
+
+!ENTRY org.eclipse.core.filebuffers 4 0 2012-02-28 12:47:28.715
+!MESSAGE A document setup participant failed to setup the document.
+!STACK 0
+java.lang.NullPointerException
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.createProjDescriptionForDescriptor(CConfigBasedDescriptorManager.java:374)
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.findDescriptor(CConfigBasedDescriptorManager.java:341)
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.getDescriptor(CConfigBasedDescriptorManager.java:238)
+ at org.eclipse.cdt.core.CCorePlugin.getCProjectDescription(CCorePlugin.java:640)
+ at org.eclipse.cdt.internal.ui.text.doctools.ProjectMap.load(ProjectMap.java:117)
+ at org.eclipse.cdt.internal.ui.text.doctools.ProjectMap.<init>(ProjectMap.java:58)
+ at org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager.getProjectMap(DocCommentOwnerManager.java:212)
+ at org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager.getCommentOwner(DocCommentOwnerManager.java:129)
+ at org.eclipse.cdt.internal.ui.text.CTextTools.getDocumentationCommentOwner(CTextTools.java:157)
+ at org.eclipse.cdt.internal.ui.text.CTextTools.setupCDocument(CTextTools.java:118)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentSetupParticipant.setup(CDocumentSetupParticipant.java:48)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBufferManager$1.run(ResourceTextFileBufferManager.java:151)
+ at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBufferManager.createEmptyDocument(ResourceTextFileBufferManager.java:166)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBuffer.initializeFileBufferContent(ResourceTextFileBuffer.java:289)
+ at org.eclipse.core.internal.filebuffers.ResourceFileBuffer.create(ResourceFileBuffer.java:245)
+ at org.eclipse.core.internal.filebuffers.TextFileBufferManager.connect(TextFileBufferManager.java:112)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.createFileInfo(TextFileDocumentProvider.java:559)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.createFileInfo(CDocumentProvider.java:856)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.connect(TextFileDocumentProvider.java:478)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.connect(CDocumentProvider.java:778)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.doSetInput(AbstractTextEditor.java:4213)
+ at org.eclipse.ui.texteditor.StatusTextEditor.doSetInput(StatusTextEditor.java:237)
+ at org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.doSetInput(AbstractDecoratedTextEditor.java:1451)
+ at org.eclipse.ui.editors.text.TextEditor.doSetInput(TextEditor.java:169)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.internalDoSetInput(CEditor.java:1380)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.doSetInput(CEditor.java:1345)
+ at org.eclipse.ui.texteditor.AbstractTextEditor$19.run(AbstractTextEditor.java:3200)
+ at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
+ at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
+ at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:759)
+ at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
+ at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:756)
+ at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2642)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.internalInit(AbstractTextEditor.java:3218)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.init(AbstractTextEditor.java:3245)
+ at org.eclipse.ui.internal.EditorManager.createSite(EditorManager.java:828)
+ at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:647)
+ at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)
+ at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)
+ at org.eclipse.ui.internal.EditorAreaHelper.setVisibleEditor(EditorAreaHelper.java:271)
+ at org.eclipse.ui.internal.EditorManager.setVisibleEditor(EditorManager.java:1459)
+ at org.eclipse.ui.internal.EditorManager$5.runWithException(EditorManager.java:972)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:803)
+ at org.eclipse.ui.internal.Workbench$33.runWithException(Workbench.java:1595)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
+ at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
+ at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
+ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
+ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
+ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
+
+!ENTRY org.eclipse.core.filebuffers 4 2 2012-02-28 12:47:28.716
+!MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.core.filebuffers".
+!STACK 0
+java.lang.NullPointerException
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.createProjDescriptionForDescriptor(CConfigBasedDescriptorManager.java:374)
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.findDescriptor(CConfigBasedDescriptorManager.java:341)
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.getDescriptor(CConfigBasedDescriptorManager.java:238)
+ at org.eclipse.cdt.core.CCorePlugin.getCProjectDescription(CCorePlugin.java:640)
+ at org.eclipse.cdt.internal.ui.text.doctools.ProjectMap.load(ProjectMap.java:117)
+ at org.eclipse.cdt.internal.ui.text.doctools.ProjectMap.<init>(ProjectMap.java:58)
+ at org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager.getProjectMap(DocCommentOwnerManager.java:212)
+ at org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager.getCommentOwner(DocCommentOwnerManager.java:129)
+ at org.eclipse.cdt.internal.ui.text.CTextTools.getDocumentationCommentOwner(CTextTools.java:157)
+ at org.eclipse.cdt.internal.ui.text.CTextTools.setupCDocument(CTextTools.java:118)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentSetupParticipant.setup(CDocumentSetupParticipant.java:48)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBufferManager$1.run(ResourceTextFileBufferManager.java:151)
+ at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBufferManager.createEmptyDocument(ResourceTextFileBufferManager.java:166)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBuffer.initializeFileBufferContent(ResourceTextFileBuffer.java:289)
+ at org.eclipse.core.internal.filebuffers.ResourceFileBuffer.create(ResourceFileBuffer.java:245)
+ at org.eclipse.core.internal.filebuffers.TextFileBufferManager.connect(TextFileBufferManager.java:112)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.createFileInfo(TextFileDocumentProvider.java:559)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.createFileInfo(CDocumentProvider.java:856)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.connect(TextFileDocumentProvider.java:478)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.connect(CDocumentProvider.java:778)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.doSetInput(AbstractTextEditor.java:4213)
+ at org.eclipse.ui.texteditor.StatusTextEditor.doSetInput(StatusTextEditor.java:237)
+ at org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.doSetInput(AbstractDecoratedTextEditor.java:1451)
+ at org.eclipse.ui.editors.text.TextEditor.doSetInput(TextEditor.java:169)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.internalDoSetInput(CEditor.java:1380)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.doSetInput(CEditor.java:1345)
+ at org.eclipse.ui.texteditor.AbstractTextEditor$19.run(AbstractTextEditor.java:3200)
+ at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
+ at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
+ at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:759)
+ at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
+ at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:756)
+ at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2642)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.internalInit(AbstractTextEditor.java:3218)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.init(AbstractTextEditor.java:3245)
+ at org.eclipse.ui.internal.EditorManager.createSite(EditorManager.java:828)
+ at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:647)
+ at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)
+ at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)
+ at org.eclipse.ui.internal.EditorAreaHelper.setVisibleEditor(EditorAreaHelper.java:271)
+ at org.eclipse.ui.internal.EditorManager.setVisibleEditor(EditorManager.java:1459)
+ at org.eclipse.ui.internal.EditorManager$5.runWithException(EditorManager.java:972)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:803)
+ at org.eclipse.ui.internal.Workbench$33.runWithException(Workbench.java:1595)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
+ at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
+ at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
+ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
+ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
+ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
+
+!ENTRY org.eclipse.core.filebuffers 4 0 2012-02-28 12:47:28.717
+!MESSAGE A document setup participant failed to setup the document.
+!STACK 0
+java.lang.NullPointerException
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.createProjDescriptionForDescriptor(CConfigBasedDescriptorManager.java:374)
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.findDescriptor(CConfigBasedDescriptorManager.java:341)
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.getDescriptor(CConfigBasedDescriptorManager.java:238)
+ at org.eclipse.cdt.core.CCorePlugin.getCProjectDescription(CCorePlugin.java:640)
+ at org.eclipse.cdt.internal.ui.text.doctools.ProjectMap.load(ProjectMap.java:117)
+ at org.eclipse.cdt.internal.ui.text.doctools.ProjectMap.<init>(ProjectMap.java:58)
+ at org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager.getProjectMap(DocCommentOwnerManager.java:212)
+ at org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager.getCommentOwner(DocCommentOwnerManager.java:129)
+ at org.eclipse.cdt.internal.ui.text.CTextTools.getDocumentationCommentOwner(CTextTools.java:157)
+ at org.eclipse.cdt.internal.ui.text.CTextTools.setupCDocument(CTextTools.java:118)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentSetupParticipant.setup(CDocumentSetupParticipant.java:48)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBufferManager$1.run(ResourceTextFileBufferManager.java:151)
+ at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBufferManager.createEmptyDocument(ResourceTextFileBufferManager.java:166)
+ at org.eclipse.core.internal.filebuffers.ResourceTextFileBuffer.initializeFileBufferContent(ResourceTextFileBuffer.java:289)
+ at org.eclipse.core.internal.filebuffers.ResourceFileBuffer.create(ResourceFileBuffer.java:245)
+ at org.eclipse.core.internal.filebuffers.TextFileBufferManager.connect(TextFileBufferManager.java:112)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.createFileInfo(TextFileDocumentProvider.java:559)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.createFileInfo(CDocumentProvider.java:856)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.connect(TextFileDocumentProvider.java:478)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.connect(CDocumentProvider.java:778)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.doSetInput(AbstractTextEditor.java:4213)
+ at org.eclipse.ui.texteditor.StatusTextEditor.doSetInput(StatusTextEditor.java:237)
+ at org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.doSetInput(AbstractDecoratedTextEditor.java:1451)
+ at org.eclipse.ui.editors.text.TextEditor.doSetInput(TextEditor.java:169)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.internalDoSetInput(CEditor.java:1380)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.doSetInput(CEditor.java:1345)
+ at org.eclipse.ui.texteditor.AbstractTextEditor$19.run(AbstractTextEditor.java:3200)
+ at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
+ at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
+ at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:759)
+ at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
+ at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:756)
+ at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2642)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.internalInit(AbstractTextEditor.java:3218)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.init(AbstractTextEditor.java:3245)
+ at org.eclipse.ui.internal.EditorManager.createSite(EditorManager.java:828)
+ at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:647)
+ at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)
+ at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)
+ at org.eclipse.ui.internal.EditorAreaHelper.setVisibleEditor(EditorAreaHelper.java:271)
+ at org.eclipse.ui.internal.EditorManager.setVisibleEditor(EditorManager.java:1459)
+ at org.eclipse.ui.internal.EditorManager$5.runWithException(EditorManager.java:972)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:803)
+ at org.eclipse.ui.internal.Workbench$33.runWithException(Workbench.java:1595)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
+ at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
+ at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
+ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
+ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
+ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
+
+!ENTRY org.eclipse.ui 4 0 2012-02-28 12:47:28.766
+!MESSAGE Unable to create editor ID org.eclipse.cdt.ui.editor.CEditor: Editor could not be initialized.
+!STACK 0
+java.lang.NullPointerException
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.createProjDescriptionForDescriptor(CConfigBasedDescriptorManager.java:374)
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.findDescriptor(CConfigBasedDescriptorManager.java:341)
+ at org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager.getDescriptor(CConfigBasedDescriptorManager.java:238)
+ at org.eclipse.cdt.core.CCorePlugin.getCProjectDescription(CCorePlugin.java:640)
+ at org.eclipse.cdt.internal.core.language.LanguageMappingStore.getProjectDescription(LanguageMappingStore.java:110)
+ at org.eclipse.cdt.internal.core.language.LanguageMappingStore.decodeMappings(LanguageMappingStore.java:75)
+ at org.eclipse.cdt.core.model.LanguageManager.getLanguageConfiguration(LanguageManager.java:447)
+ at org.eclipse.cdt.internal.core.language.LanguageMappingResolver.computeLanguage(LanguageMappingResolver.java:57)
+ at org.eclipse.cdt.core.model.LanguageManager.getLanguageForFile(LanguageManager.java:587)
+ at org.eclipse.cdt.internal.core.model.TranslationUnit.getLanguage(TranslationUnit.java:776)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.internalDoSetInput(CEditor.java:1392)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.doSetInput(CEditor.java:1345)
+ at org.eclipse.ui.texteditor.AbstractTextEditor$19.run(AbstractTextEditor.java:3200)
+ at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
+ at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
+ at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:759)
+ at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
+ at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:756)
+ at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2642)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.internalInit(AbstractTextEditor.java:3218)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.init(AbstractTextEditor.java:3245)
+ at org.eclipse.ui.internal.EditorManager.createSite(EditorManager.java:828)
+ at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:647)
+ at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)
+ at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)
+ at org.eclipse.ui.internal.EditorAreaHelper.setVisibleEditor(EditorAreaHelper.java:271)
+ at org.eclipse.ui.internal.EditorManager.setVisibleEditor(EditorManager.java:1459)
+ at org.eclipse.ui.internal.EditorManager$5.runWithException(EditorManager.java:972)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:803)
+ at org.eclipse.ui.internal.Workbench$33.runWithException(Workbench.java:1595)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
+ at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
+ at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
+ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
+ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
+ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
+
+!ENTRY org.eclipse.ui 2 2 2012-02-28 12:47:28.785
+!MESSAGE Ignored attempt to add saveable that was already registered
+!STACK 0
+org.eclipse.core.runtime.AssertionFailedException: unknown saveable: org.eclipse.ui.internal.DefaultSaveable@2c538cc2 from part: org.eclipse.ui.internal.ErrorEditorPart@2c538cc2
+ at org.eclipse.ui.internal.SaveablesList.logWarning(SaveablesList.java:187)
+ at org.eclipse.ui.internal.SaveablesList.addModel(SaveablesList.java:117)
+ at org.eclipse.ui.internal.SaveablesList.addModels(SaveablesList.java:289)
+ at org.eclipse.ui.internal.SaveablesList.postOpen(SaveablesList.java:695)
+ at org.eclipse.ui.internal.PartList.partOpened(PartList.java:234)
+ at org.eclipse.ui.internal.PartList.access$0(PartList.java:210)
+ at org.eclipse.ui.internal.PartList$1.propertyChanged(PartList.java:40)
+ at org.eclipse.ui.internal.WorkbenchPartReference.fireInternalPropertyChange(WorkbenchPartReference.java:375)
+ at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:610)
+ at org.eclipse.ui.internal.EditorAreaHelper.setVisibleEditor(EditorAreaHelper.java:271)
+ at org.eclipse.ui.internal.EditorManager.setVisibleEditor(EditorManager.java:1459)
+ at org.eclipse.ui.internal.EditorManager$5.runWithException(EditorManager.java:972)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:803)
+ at org.eclipse.ui.internal.Workbench$33.runWithException(Workbench.java:1595)
+ at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
+ at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
+ at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
+ at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3563)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3212)
+ at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
+ at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
+ at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
+ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
+ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
+ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
+
+!ENTRY org.eclipse.ui 4 0 2012-02-28 12:47:36.715
+!MESSAGE Unable to create editor ID org.eclipse.cdt.ui.editor.CEditor: The file does not exist.
+!STACK 1
+org.eclipse.core.runtime.CoreException: The file does not exist.
+ at org.eclipse.core.internal.filebuffers.ResourceFileBuffer.create(ResourceFileBuffer.java:237)
+ at org.eclipse.core.internal.filebuffers.TextFileBufferManager.connect(TextFileBufferManager.java:112)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.createFileInfo(TextFileDocumentProvider.java:559)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.createFileInfo(CDocumentProvider.java:856)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.connect(TextFileDocumentProvider.java:478)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.connect(CDocumentProvider.java:778)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.doSetInput(AbstractTextEditor.java:4213)
+ at org.eclipse.ui.texteditor.StatusTextEditor.doSetInput(StatusTextEditor.java:237)
+ at org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.doSetInput(AbstractDecoratedTextEditor.java:1451)
+ at org.eclipse.ui.editors.text.TextEditor.doSetInput(TextEditor.java:169)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.internalDoSetInput(CEditor.java:1380)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.doSetInput(CEditor.java:1345)
+ at org.eclipse.ui.texteditor.AbstractTextEditor$19.run(AbstractTextEditor.java:3200)
+ at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
+ at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
+ at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:759)
+ at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
+ at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:756)
+ at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2642)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.internalInit(AbstractTextEditor.java:3218)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.init(AbstractTextEditor.java:3245)
+ at org.eclipse.ui.internal.EditorManager.createSite(EditorManager.java:828)
+ at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:647)
+ at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)
+ at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)
+ at org.eclipse.ui.internal.PartPane.setVisible(PartPane.java:313)
+ at org.eclipse.ui.internal.presentations.PresentablePart.setVisible(PresentablePart.java:180)
+ at org.eclipse.ui.internal.presentations.util.PresentablePartFolder.select(PresentablePartFolder.java:270)
+ at org.eclipse.ui.internal.presentations.util.LeftToRightTabOrder.select(LeftToRightTabOrder.java:65)
+ at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation.selectPart(TabbedStackPresentation.java:473)
+ at org.eclipse.ui.internal.PartStack.refreshPresentationSelection(PartStack.java:1245)
+ at org.eclipse.ui.internal.PartStack.handleDeferredEvents(PartStack.java:1213)
+ at org.eclipse.ui.internal.LayoutPart.deferUpdates(LayoutPart.java:400)
+ at org.eclipse.ui.internal.PartSashContainer.handleDeferredEvents(PartSashContainer.java:1409)
+ at org.eclipse.ui.internal.LayoutPart.deferUpdates(LayoutPart.java:400)
+ at org.eclipse.ui.internal.WorkbenchPage.handleDeferredEvents(WorkbenchPage.java:1495)
+ at org.eclipse.ui.internal.WorkbenchPage.deferUpdates(WorkbenchPage.java:1485)
+ at org.eclipse.ui.internal.WorkbenchPage.closeEditors(WorkbenchPage.java:1459)
+ at org.eclipse.ui.internal.WorkbenchPage.closeEditor(WorkbenchPage.java:1523)
+ at org.eclipse.ui.internal.CloseEditorHandler.execute(CloseEditorHandler.java:47)
+ at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:293)
+ at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476)
+ at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
+ at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand(WorkbenchKeyboard.java:468)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:786)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:885)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings(WorkbenchKeyboard.java:567)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$3(WorkbenchKeyboard.java:508)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard$KeyDownFilter.handleEvent(WorkbenchKeyboard.java:123)
+ at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
+ at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1531)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1257)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1282)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1267)
+ at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1294)
+ at org.eclipse.swt.widgets.Widget.gtk_key_press_event(Widget.java:730)
+ at org.eclipse.swt.widgets.Control.gtk_key_press_event(Control.java:3019)
+ at org.eclipse.swt.widgets.Composite.gtk_key_press_event(Composite.java:734)
+ at org.eclipse.swt.widgets.Tree.gtk_key_press_event(Tree.java:2002)
+ at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:1743)
+ at org.eclipse.swt.widgets.Control.windowProc(Control.java:5016)
+ at org.eclipse.swt.widgets.Tree.windowProc(Tree.java:3530)
+ at org.eclipse.swt.widgets.Display.windowProc(Display.java:4408)
+ at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method)
+ at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(OS.java:8394)
+ at org.eclipse.swt.widgets.Display.eventProc(Display.java:1245)
+ at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method)
+ at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:2258)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3207)
+ at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2696)
+ at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2660)
+ at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
+ at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
+ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
+ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
+ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
+!SUBENTRY 1 org.eclipse.core.filebuffers 4 0 2012-02-28 12:47:36.716
+!MESSAGE The file does not exist.
+
+!ENTRY org.eclipse.ui 2 2 2012-02-28 12:47:36.729
+!MESSAGE Ignored attempt to add saveable that was already registered
+!STACK 0
+org.eclipse.core.runtime.AssertionFailedException: unknown saveable: org.eclipse.ui.internal.DefaultSaveable@19166179 from part: org.eclipse.ui.internal.ErrorEditorPart@19166179
+ at org.eclipse.ui.internal.SaveablesList.logWarning(SaveablesList.java:187)
+ at org.eclipse.ui.internal.SaveablesList.addModel(SaveablesList.java:117)
+ at org.eclipse.ui.internal.SaveablesList.addModels(SaveablesList.java:289)
+ at org.eclipse.ui.internal.SaveablesList.postOpen(SaveablesList.java:695)
+ at org.eclipse.ui.internal.PartList.partOpened(PartList.java:234)
+ at org.eclipse.ui.internal.PartList.access$0(PartList.java:210)
+ at org.eclipse.ui.internal.PartList$1.propertyChanged(PartList.java:40)
+ at org.eclipse.ui.internal.WorkbenchPartReference.fireInternalPropertyChange(WorkbenchPartReference.java:375)
+ at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:610)
+ at org.eclipse.ui.internal.PartPane.setVisible(PartPane.java:313)
+ at org.eclipse.ui.internal.presentations.PresentablePart.setVisible(PresentablePart.java:180)
+ at org.eclipse.ui.internal.presentations.util.PresentablePartFolder.select(PresentablePartFolder.java:270)
+ at org.eclipse.ui.internal.presentations.util.LeftToRightTabOrder.select(LeftToRightTabOrder.java:65)
+ at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation.selectPart(TabbedStackPresentation.java:473)
+ at org.eclipse.ui.internal.PartStack.refreshPresentationSelection(PartStack.java:1245)
+ at org.eclipse.ui.internal.PartStack.handleDeferredEvents(PartStack.java:1213)
+ at org.eclipse.ui.internal.LayoutPart.deferUpdates(LayoutPart.java:400)
+ at org.eclipse.ui.internal.PartSashContainer.handleDeferredEvents(PartSashContainer.java:1409)
+ at org.eclipse.ui.internal.LayoutPart.deferUpdates(LayoutPart.java:400)
+ at org.eclipse.ui.internal.WorkbenchPage.handleDeferredEvents(WorkbenchPage.java:1495)
+ at org.eclipse.ui.internal.WorkbenchPage.deferUpdates(WorkbenchPage.java:1485)
+ at org.eclipse.ui.internal.WorkbenchPage.closeEditors(WorkbenchPage.java:1459)
+ at org.eclipse.ui.internal.WorkbenchPage.closeEditor(WorkbenchPage.java:1523)
+ at org.eclipse.ui.internal.CloseEditorHandler.execute(CloseEditorHandler.java:47)
+ at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:293)
+ at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476)
+ at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
+ at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand(WorkbenchKeyboard.java:468)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:786)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:885)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings(WorkbenchKeyboard.java:567)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$3(WorkbenchKeyboard.java:508)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard$KeyDownFilter.handleEvent(WorkbenchKeyboard.java:123)
+ at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
+ at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1531)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1257)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1282)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1267)
+ at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1294)
+ at org.eclipse.swt.widgets.Widget.gtk_key_press_event(Widget.java:730)
+ at org.eclipse.swt.widgets.Control.gtk_key_press_event(Control.java:3019)
+ at org.eclipse.swt.widgets.Composite.gtk_key_press_event(Composite.java:734)
+ at org.eclipse.swt.widgets.Tree.gtk_key_press_event(Tree.java:2002)
+ at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:1743)
+ at org.eclipse.swt.widgets.Control.windowProc(Control.java:5016)
+ at org.eclipse.swt.widgets.Tree.windowProc(Tree.java:3530)
+ at org.eclipse.swt.widgets.Display.windowProc(Display.java:4408)
+ at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method)
+ at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(OS.java:8394)
+ at org.eclipse.swt.widgets.Display.eventProc(Display.java:1245)
+ at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method)
+ at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:2258)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3207)
+ at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2696)
+ at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2660)
+ at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
+ at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
+ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
+ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
+ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
+
+!ENTRY org.eclipse.ui 4 0 2012-02-28 12:47:37.016
+!MESSAGE Unable to create editor ID org.eclipse.cdt.ui.editor.CEditor: The file does not exist.
+!STACK 1
+org.eclipse.core.runtime.CoreException: The file does not exist.
+ at org.eclipse.core.internal.filebuffers.ResourceFileBuffer.create(ResourceFileBuffer.java:237)
+ at org.eclipse.core.internal.filebuffers.TextFileBufferManager.connect(TextFileBufferManager.java:112)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.createFileInfo(TextFileDocumentProvider.java:559)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.createFileInfo(CDocumentProvider.java:856)
+ at org.eclipse.ui.editors.text.TextFileDocumentProvider.connect(TextFileDocumentProvider.java:478)
+ at org.eclipse.cdt.internal.ui.editor.CDocumentProvider.connect(CDocumentProvider.java:778)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.doSetInput(AbstractTextEditor.java:4213)
+ at org.eclipse.ui.texteditor.StatusTextEditor.doSetInput(StatusTextEditor.java:237)
+ at org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.doSetInput(AbstractDecoratedTextEditor.java:1451)
+ at org.eclipse.ui.editors.text.TextEditor.doSetInput(TextEditor.java:169)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.internalDoSetInput(CEditor.java:1380)
+ at org.eclipse.cdt.internal.ui.editor.CEditor.doSetInput(CEditor.java:1345)
+ at org.eclipse.ui.texteditor.AbstractTextEditor$19.run(AbstractTextEditor.java:3200)
+ at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
+ at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
+ at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:759)
+ at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
+ at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:756)
+ at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2642)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.internalInit(AbstractTextEditor.java:3218)
+ at org.eclipse.ui.texteditor.AbstractTextEditor.init(AbstractTextEditor.java:3245)
+ at org.eclipse.ui.internal.EditorManager.createSite(EditorManager.java:828)
+ at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:647)
+ at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)
+ at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)
+ at org.eclipse.ui.internal.PartPane.setVisible(PartPane.java:313)
+ at org.eclipse.ui.internal.presentations.PresentablePart.setVisible(PresentablePart.java:180)
+ at org.eclipse.ui.internal.presentations.util.PresentablePartFolder.select(PresentablePartFolder.java:270)
+ at org.eclipse.ui.internal.presentations.util.LeftToRightTabOrder.select(LeftToRightTabOrder.java:65)
+ at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation.selectPart(TabbedStackPresentation.java:473)
+ at org.eclipse.ui.internal.PartStack.refreshPresentationSelection(PartStack.java:1245)
+ at org.eclipse.ui.internal.PartStack.handleDeferredEvents(PartStack.java:1213)
+ at org.eclipse.ui.internal.LayoutPart.deferUpdates(LayoutPart.java:400)
+ at org.eclipse.ui.internal.PartSashContainer.handleDeferredEvents(PartSashContainer.java:1409)
+ at org.eclipse.ui.internal.LayoutPart.deferUpdates(LayoutPart.java:400)
+ at org.eclipse.ui.internal.WorkbenchPage.handleDeferredEvents(WorkbenchPage.java:1495)
+ at org.eclipse.ui.internal.WorkbenchPage.deferUpdates(WorkbenchPage.java:1485)
+ at org.eclipse.ui.internal.WorkbenchPage.closeEditors(WorkbenchPage.java:1459)
+ at org.eclipse.ui.internal.WorkbenchPage.closeEditor(WorkbenchPage.java:1523)
+ at org.eclipse.ui.internal.CloseEditorHandler.execute(CloseEditorHandler.java:47)
+ at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:293)
+ at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476)
+ at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
+ at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand(WorkbenchKeyboard.java:468)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:786)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:885)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings(WorkbenchKeyboard.java:567)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$3(WorkbenchKeyboard.java:508)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard$KeyDownFilter.handleEvent(WorkbenchKeyboard.java:123)
+ at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
+ at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1531)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1257)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1282)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1267)
+ at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1294)
+ at org.eclipse.swt.widgets.Widget.gtk_key_press_event(Widget.java:730)
+ at org.eclipse.swt.widgets.Control.gtk_key_press_event(Control.java:3019)
+ at org.eclipse.swt.widgets.Composite.gtk_key_press_event(Composite.java:734)
+ at org.eclipse.swt.widgets.Tree.gtk_key_press_event(Tree.java:2002)
+ at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:1743)
+ at org.eclipse.swt.widgets.Control.windowProc(Control.java:5016)
+ at org.eclipse.swt.widgets.Tree.windowProc(Tree.java:3530)
+ at org.eclipse.swt.widgets.Display.windowProc(Display.java:4408)
+ at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method)
+ at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(OS.java:8394)
+ at org.eclipse.swt.widgets.Display.eventProc(Display.java:1245)
+ at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method)
+ at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:2258)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3207)
+ at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2696)
+ at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2660)
+ at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
+ at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
+ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
+ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
+ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
+!SUBENTRY 1 org.eclipse.core.filebuffers 4 0 2012-02-28 12:47:37.018
+!MESSAGE The file does not exist.
+
+!ENTRY org.eclipse.ui 2 2 2012-02-28 12:47:37.032
+!MESSAGE Ignored attempt to add saveable that was already registered
+!STACK 0
+org.eclipse.core.runtime.AssertionFailedException: unknown saveable: org.eclipse.ui.internal.DefaultSaveable@b53b098 from part: org.eclipse.ui.internal.ErrorEditorPart@b53b098
+ at org.eclipse.ui.internal.SaveablesList.logWarning(SaveablesList.java:187)
+ at org.eclipse.ui.internal.SaveablesList.addModel(SaveablesList.java:117)
+ at org.eclipse.ui.internal.SaveablesList.addModels(SaveablesList.java:289)
+ at org.eclipse.ui.internal.SaveablesList.postOpen(SaveablesList.java:695)
+ at org.eclipse.ui.internal.PartList.partOpened(PartList.java:234)
+ at org.eclipse.ui.internal.PartList.access$0(PartList.java:210)
+ at org.eclipse.ui.internal.PartList$1.propertyChanged(PartList.java:40)
+ at org.eclipse.ui.internal.WorkbenchPartReference.fireInternalPropertyChange(WorkbenchPartReference.java:375)
+ at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:610)
+ at org.eclipse.ui.internal.PartPane.setVisible(PartPane.java:313)
+ at org.eclipse.ui.internal.presentations.PresentablePart.setVisible(PresentablePart.java:180)
+ at org.eclipse.ui.internal.presentations.util.PresentablePartFolder.select(PresentablePartFolder.java:270)
+ at org.eclipse.ui.internal.presentations.util.LeftToRightTabOrder.select(LeftToRightTabOrder.java:65)
+ at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation.selectPart(TabbedStackPresentation.java:473)
+ at org.eclipse.ui.internal.PartStack.refreshPresentationSelection(PartStack.java:1245)
+ at org.eclipse.ui.internal.PartStack.handleDeferredEvents(PartStack.java:1213)
+ at org.eclipse.ui.internal.LayoutPart.deferUpdates(LayoutPart.java:400)
+ at org.eclipse.ui.internal.PartSashContainer.handleDeferredEvents(PartSashContainer.java:1409)
+ at org.eclipse.ui.internal.LayoutPart.deferUpdates(LayoutPart.java:400)
+ at org.eclipse.ui.internal.WorkbenchPage.handleDeferredEvents(WorkbenchPage.java:1495)
+ at org.eclipse.ui.internal.WorkbenchPage.deferUpdates(WorkbenchPage.java:1485)
+ at org.eclipse.ui.internal.WorkbenchPage.closeEditors(WorkbenchPage.java:1459)
+ at org.eclipse.ui.internal.WorkbenchPage.closeEditor(WorkbenchPage.java:1523)
+ at org.eclipse.ui.internal.CloseEditorHandler.execute(CloseEditorHandler.java:47)
+ at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:293)
+ at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476)
+ at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
+ at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand(WorkbenchKeyboard.java:468)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:786)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:885)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings(WorkbenchKeyboard.java:567)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$3(WorkbenchKeyboard.java:508)
+ at org.eclipse.ui.internal.keys.WorkbenchKeyboard$KeyDownFilter.handleEvent(WorkbenchKeyboard.java:123)
+ at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
+ at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1531)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1257)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1282)
+ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1267)
+ at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1294)
+ at org.eclipse.swt.widgets.Widget.gtk_key_press_event(Widget.java:730)
+ at org.eclipse.swt.widgets.Control.gtk_key_press_event(Control.java:3019)
+ at org.eclipse.swt.widgets.Composite.gtk_key_press_event(Composite.java:734)
+ at org.eclipse.swt.widgets.Tree.gtk_key_press_event(Tree.java:2002)
+ at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:1743)
+ at org.eclipse.swt.widgets.Control.windowProc(Control.java:5016)
+ at org.eclipse.swt.widgets.Tree.windowProc(Tree.java:3530)
+ at org.eclipse.swt.widgets.Display.windowProc(Display.java:4408)
+ at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method)
+ at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(OS.java:8394)
+ at org.eclipse.swt.widgets.Display.eventProc(Display.java:1245)
+ at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method)
+ at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:2258)
+ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3207)
+ at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2696)
+ at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2660)
+ at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
+ at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
+ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
+ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
+ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
+ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
+ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
+ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
+ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
+ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
+ at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
+ at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.cdt.core/.log b/Src/eclipse/.metadata/.plugins/org.eclipse.cdt.core/.log
index 865b28a..e69fab0 100644
--- a/Src/eclipse/.metadata/.plugins/org.eclipse.cdt.core/.log
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.cdt.core/.log
@@ -3,3 +3,4 @@
*** SESSION Oct 09, 2011 14:26:25.89 -------------------------------------------
*** SESSION Oct 10, 2011 15:16:10.81 -------------------------------------------
*** SESSION Feb 28, 2012 11:47:32.08 -------------------------------------------
+*** SESSION Feb 28, 2012 12:34:33.29 -------------------------------------------
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.cdt.core/CatcherDriver.1330426096136.pdom b/Src/eclipse/.metadata/.plugins/org.eclipse.cdt.core/CatcherDriver.1330426096136.pdom
new file mode 100644
index 0000000..924efda
--- /dev/null
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.cdt.core/CatcherDriver.1330426096136.pdom
Binary files differ
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.cdt.make.core/CatcherDriver.sc b/Src/eclipse/.metadata/.plugins/org.eclipse.cdt.make.core/CatcherDriver.sc
new file mode 100644
index 0000000..32f3d38
--- /dev/null
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.cdt.make.core/CatcherDriver.sc
@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?scdStore version="2"?>
+
+<scannerInfo id="org.eclipse.cdt.make.core.discoveredScannerInfo">
+<instance id="0.91533971">
+<collector id="org.eclipse.cdt.make.core.PerProjectSICollector">
+<includePath path="/usr/lib/gcc/x86_64-linux-gnu/4.6.1/include"/>
+<includePath path="/usr/local/include"/>
+<includePath path="/usr/lib/gcc/x86_64-linux-gnu/4.6.1/include-fixed"/>
+<includePath path="/usr/include/x86_64-linux-gnu"/>
+<includePath path="/usr/include"/>
+<definedSymbol symbol="__STDC__=1"/>
+<definedSymbol symbol="__STDC_HOSTED__=1"/>
+<definedSymbol symbol="__GNUC__=4"/>
+<definedSymbol symbol="__GNUC_MINOR__=6"/>
+<definedSymbol symbol="__GNUC_PATCHLEVEL__=1"/>
+<definedSymbol symbol="__VERSION__=&quot;4.6.1&quot;"/>
+<definedSymbol symbol="__FINITE_MATH_ONLY__=0"/>
+<definedSymbol symbol="_LP64=1"/>
+<definedSymbol symbol="__LP64__=1"/>
+<definedSymbol symbol="__SIZEOF_INT__=4"/>
+<definedSymbol symbol="__SIZEOF_LONG__=8"/>
+<definedSymbol symbol="__SIZEOF_LONG_LONG__=8"/>
+<definedSymbol symbol="__SIZEOF_SHORT__=2"/>
+<definedSymbol symbol="__SIZEOF_FLOAT__=4"/>
+<definedSymbol symbol="__SIZEOF_DOUBLE__=8"/>
+<definedSymbol symbol="__SIZEOF_LONG_DOUBLE__=16"/>
+<definedSymbol symbol="__SIZEOF_SIZE_T__=8"/>
+<definedSymbol symbol="__CHAR_BIT__=8"/>
+<definedSymbol symbol="__BIGGEST_ALIGNMENT__=16"/>
+<definedSymbol symbol="__ORDER_LITTLE_ENDIAN__=1234"/>
+<definedSymbol symbol="__ORDER_BIG_ENDIAN__=4321"/>
+<definedSymbol symbol="__ORDER_PDP_ENDIAN__=3412"/>
+<definedSymbol symbol="__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__"/>
+<definedSymbol symbol="__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__"/>
+<definedSymbol symbol="__SIZEOF_POINTER__=8"/>
+<definedSymbol symbol="__SIZE_TYPE__=long unsigned int"/>
+<definedSymbol symbol="__PTRDIFF_TYPE__=long int"/>
+<definedSymbol symbol="__WCHAR_TYPE__=int"/>
+<definedSymbol symbol="__WINT_TYPE__=unsigned int"/>
+<definedSymbol symbol="__INTMAX_TYPE__=long int"/>
+<definedSymbol symbol="__UINTMAX_TYPE__=long unsigned int"/>
+<definedSymbol symbol="__CHAR16_TYPE__=short unsigned int"/>
+<definedSymbol symbol="__CHAR32_TYPE__=unsigned int"/>
+<definedSymbol symbol="__SIG_ATOMIC_TYPE__=int"/>
+<definedSymbol symbol="__INT8_TYPE__=signed char"/>
+<definedSymbol symbol="__INT16_TYPE__=short int"/>
+<definedSymbol symbol="__INT32_TYPE__=int"/>
+<definedSymbol symbol="__INT64_TYPE__=long int"/>
+<definedSymbol symbol="__UINT8_TYPE__=unsigned char"/>
+<definedSymbol symbol="__UINT16_TYPE__=short unsigned int"/>
+<definedSymbol symbol="__UINT32_TYPE__=unsigned int"/>
+<definedSymbol symbol="__UINT64_TYPE__=long unsigned int"/>
+<definedSymbol symbol="__INT_LEAST8_TYPE__=signed char"/>
+<definedSymbol symbol="__INT_LEAST16_TYPE__=short int"/>
+<definedSymbol symbol="__INT_LEAST32_TYPE__=int"/>
+<definedSymbol symbol="__INT_LEAST64_TYPE__=long int"/>
+<definedSymbol symbol="__UINT_LEAST8_TYPE__=unsigned char"/>
+<definedSymbol symbol="__UINT_LEAST16_TYPE__=short unsigned int"/>
+<definedSymbol symbol="__UINT_LEAST32_TYPE__=unsigned int"/>
+<definedSymbol symbol="__UINT_LEAST64_TYPE__=long unsigned int"/>
+<definedSymbol symbol="__INT_FAST8_TYPE__=signed char"/>
+<definedSymbol symbol="__INT_FAST16_TYPE__=long int"/>
+<definedSymbol symbol="__INT_FAST32_TYPE__=long int"/>
+<definedSymbol symbol="__INT_FAST64_TYPE__=long int"/>
+<definedSymbol symbol="__UINT_FAST8_TYPE__=unsigned char"/>
+<definedSymbol symbol="__UINT_FAST16_TYPE__=long unsigned int"/>
+<definedSymbol symbol="__UINT_FAST32_TYPE__=long unsigned int"/>
+<definedSymbol symbol="__UINT_FAST64_TYPE__=long unsigned int"/>
+<definedSymbol symbol="__INTPTR_TYPE__=long int"/>
+<definedSymbol symbol="__UINTPTR_TYPE__=long unsigned int"/>
+<definedSymbol symbol="__GXX_ABI_VERSION=1002"/>
+<definedSymbol symbol="__SCHAR_MAX__=127"/>
+<definedSymbol symbol="__SHRT_MAX__=32767"/>
+<definedSymbol symbol="__INT_MAX__=2147483647"/>
+<definedSymbol symbol="__LONG_MAX__=9223372036854775807L"/>
+<definedSymbol symbol="__LONG_LONG_MAX__=9223372036854775807LL"/>
+<definedSymbol symbol="__WCHAR_MAX__=2147483647"/>
+<definedSymbol symbol="__WCHAR_MIN__=(-__WCHAR_MAX__ - 1)"/>
+<definedSymbol symbol="__WINT_MAX__=4294967295U"/>
+<definedSymbol symbol="__WINT_MIN__=0U"/>
+<definedSymbol symbol="__PTRDIFF_MAX__=9223372036854775807L"/>
+<definedSymbol symbol="__SIZE_MAX__=18446744073709551615UL"/>
+<definedSymbol symbol="__INTMAX_MAX__=9223372036854775807L"/>
+<definedSymbol symbol="__INTMAX_C(c)=c ## L"/>
+<definedSymbol symbol="__UINTMAX_MAX__=18446744073709551615UL"/>
+<definedSymbol symbol="__UINTMAX_C(c)=c ## UL"/>
+<definedSymbol symbol="__SIG_ATOMIC_MAX__=2147483647"/>
+<definedSymbol symbol="__SIG_ATOMIC_MIN__=(-__SIG_ATOMIC_MAX__ - 1)"/>
+<definedSymbol symbol="__INT8_MAX__=127"/>
+<definedSymbol symbol="__INT16_MAX__=32767"/>
+<definedSymbol symbol="__INT32_MAX__=2147483647"/>
+<definedSymbol symbol="__INT64_MAX__=9223372036854775807L"/>
+<definedSymbol symbol="__UINT8_MAX__=255"/>
+<definedSymbol symbol="__UINT16_MAX__=65535"/>
+<definedSymbol symbol="__UINT32_MAX__=4294967295U"/>
+<definedSymbol symbol="__UINT64_MAX__=18446744073709551615UL"/>
+<definedSymbol symbol="__INT_LEAST8_MAX__=127"/>
+<definedSymbol symbol="__INT8_C(c)=c"/>
+<definedSymbol symbol="__INT_LEAST16_MAX__=32767"/>
+<definedSymbol symbol="__INT16_C(c)=c"/>
+<definedSymbol symbol="__INT_LEAST32_MAX__=2147483647"/>
+<definedSymbol symbol="__INT32_C(c)=c"/>
+<definedSymbol symbol="__INT_LEAST64_MAX__=9223372036854775807L"/>
+<definedSymbol symbol="__INT64_C(c)=c ## L"/>
+<definedSymbol symbol="__UINT_LEAST8_MAX__=255"/>
+<definedSymbol symbol="__UINT8_C(c)=c"/>
+<definedSymbol symbol="__UINT_LEAST16_MAX__=65535"/>
+<definedSymbol symbol="__UINT16_C(c)=c"/>
+<definedSymbol symbol="__UINT_LEAST32_MAX__=4294967295U"/>
+<definedSymbol symbol="__UINT32_C(c)=c ## U"/>
+<definedSymbol symbol="__UINT_LEAST64_MAX__=18446744073709551615UL"/>
+<definedSymbol symbol="__UINT64_C(c)=c ## UL"/>
+<definedSymbol symbol="__INT_FAST8_MAX__=127"/>
+<definedSymbol symbol="__INT_FAST16_MAX__=9223372036854775807L"/>
+<definedSymbol symbol="__INT_FAST32_MAX__=9223372036854775807L"/>
+<definedSymbol symbol="__INT_FAST64_MAX__=9223372036854775807L"/>
+<definedSymbol symbol="__UINT_FAST8_MAX__=255"/>
+<definedSymbol symbol="__UINT_FAST16_MAX__=18446744073709551615UL"/>
+<definedSymbol symbol="__UINT_FAST32_MAX__=18446744073709551615UL"/>
+<definedSymbol symbol="__UINT_FAST64_MAX__=18446744073709551615UL"/>
+<definedSymbol symbol="__INTPTR_MAX__=9223372036854775807L"/>
+<definedSymbol symbol="__UINTPTR_MAX__=18446744073709551615UL"/>
+<definedSymbol symbol="__FLT_EVAL_METHOD__=0"/>
+<definedSymbol symbol="__DEC_EVAL_METHOD__=2"/>
+<definedSymbol symbol="__FLT_RADIX__=2"/>
+<definedSymbol symbol="__FLT_MANT_DIG__=24"/>
+<definedSymbol symbol="__FLT_DIG__=6"/>
+<definedSymbol symbol="__FLT_MIN_EXP__=(-125)"/>
+<definedSymbol symbol="__FLT_MIN_10_EXP__=(-37)"/>
+<definedSymbol symbol="__FLT_MAX_EXP__=128"/>
+<definedSymbol symbol="__FLT_MAX_10_EXP__=38"/>
+<definedSymbol symbol="__FLT_DECIMAL_DIG__=9"/>
+<definedSymbol symbol="__FLT_MAX__=3.40282346638528859812e+38F"/>
+<definedSymbol symbol="__FLT_MIN__=1.17549435082228750797e-38F"/>
+<definedSymbol symbol="__FLT_EPSILON__=1.19209289550781250000e-7F"/>
+<definedSymbol symbol="__FLT_DENORM_MIN__=1.40129846432481707092e-45F"/>
+<definedSymbol symbol="__FLT_HAS_DENORM__=1"/>
+<definedSymbol symbol="__FLT_HAS_INFINITY__=1"/>
+<definedSymbol symbol="__FLT_HAS_QUIET_NAN__=1"/>
+<definedSymbol symbol="__DBL_MANT_DIG__=53"/>
+<definedSymbol symbol="__DBL_DIG__=15"/>
+<definedSymbol symbol="__DBL_MIN_EXP__=(-1021)"/>
+<definedSymbol symbol="__DBL_MIN_10_EXP__=(-307)"/>
+<definedSymbol symbol="__DBL_MAX_EXP__=1024"/>
+<definedSymbol symbol="__DBL_MAX_10_EXP__=308"/>
+<definedSymbol symbol="__DBL_DECIMAL_DIG__=17"/>
+<definedSymbol symbol="__DBL_MAX__=((double)1.79769313486231570815e+308L)"/>
+<definedSymbol symbol="__DBL_MIN__=((double)2.22507385850720138309e-308L)"/>
+<definedSymbol symbol="__DBL_EPSILON__=((double)2.22044604925031308085e-16L)"/>
+<definedSymbol symbol="__DBL_DENORM_MIN__=((double)4.94065645841246544177e-324L)"/>
+<definedSymbol symbol="__DBL_HAS_DENORM__=1"/>
+<definedSymbol symbol="__DBL_HAS_INFINITY__=1"/>
+<definedSymbol symbol="__DBL_HAS_QUIET_NAN__=1"/>
+<definedSymbol symbol="__LDBL_MANT_DIG__=64"/>
+<definedSymbol symbol="__LDBL_DIG__=18"/>
+<definedSymbol symbol="__LDBL_MIN_EXP__=(-16381)"/>
+<definedSymbol symbol="__LDBL_MIN_10_EXP__=(-4931)"/>
+<definedSymbol symbol="__LDBL_MAX_EXP__=16384"/>
+<definedSymbol symbol="__LDBL_MAX_10_EXP__=4932"/>
+<definedSymbol symbol="__DECIMAL_DIG__=21"/>
+<definedSymbol symbol="__LDBL_MAX__=1.18973149535723176502e+4932L"/>
+<definedSymbol symbol="__LDBL_MIN__=3.36210314311209350626e-4932L"/>
+<definedSymbol symbol="__LDBL_EPSILON__=1.08420217248550443401e-19L"/>
+<definedSymbol symbol="__LDBL_DENORM_MIN__=3.64519953188247460253e-4951L"/>
+<definedSymbol symbol="__LDBL_HAS_DENORM__=1"/>
+<definedSymbol symbol="__LDBL_HAS_INFINITY__=1"/>
+<definedSymbol symbol="__LDBL_HAS_QUIET_NAN__=1"/>
+<definedSymbol symbol="__DEC32_MANT_DIG__=7"/>
+<definedSymbol symbol="__DEC32_MIN_EXP__=(-94)"/>
+<definedSymbol symbol="__DEC32_MAX_EXP__=97"/>
+<definedSymbol symbol="__DEC32_MIN__=1E-95DF"/>
+<definedSymbol symbol="__DEC32_MAX__=9.999999E96DF"/>
+<definedSymbol symbol="__DEC32_EPSILON__=1E-6DF"/>
+<definedSymbol symbol="__DEC32_SUBNORMAL_MIN__=0.000001E-95DF"/>
+<definedSymbol symbol="__DEC64_MANT_DIG__=16"/>
+<definedSymbol symbol="__DEC64_MIN_EXP__=(-382)"/>
+<definedSymbol symbol="__DEC64_MAX_EXP__=385"/>
+<definedSymbol symbol="__DEC64_MIN__=1E-383DD"/>
+<definedSymbol symbol="__DEC64_MAX__=9.999999999999999E384DD"/>
+<definedSymbol symbol="__DEC64_EPSILON__=1E-15DD"/>
+<definedSymbol symbol="__DEC64_SUBNORMAL_MIN__=0.000000000000001E-383DD"/>
+<definedSymbol symbol="__DEC128_MANT_DIG__=34"/>
+<definedSymbol symbol="__DEC128_MIN_EXP__=(-6142)"/>
+<definedSymbol symbol="__DEC128_MAX_EXP__=6145"/>
+<definedSymbol symbol="__DEC128_MIN__=1E-6143DL"/>
+<definedSymbol symbol="__DEC128_MAX__=9.999999999999999999999999999999999E6144DL"/>
+<definedSymbol symbol="__DEC128_EPSILON__=1E-33DL"/>
+<definedSymbol symbol="__DEC128_SUBNORMAL_MIN__=0.000000000000000000000000000000001E-6143DL"/>
+<definedSymbol symbol="__REGISTER_PREFIX__="/>
+<definedSymbol symbol="__USER_LABEL_PREFIX__="/>
+<definedSymbol symbol="_FORTIFY_SOURCE=2"/>
+<definedSymbol symbol="__GNUC_GNU_INLINE__=1"/>
+<definedSymbol symbol="__NO_INLINE__=1"/>
+<definedSymbol symbol="__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1=1"/>
+<definedSymbol symbol="__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2=1"/>
+<definedSymbol symbol="__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4=1"/>
+<definedSymbol symbol="__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8=1"/>
+<definedSymbol symbol="__GCC_HAVE_DWARF2_CFI_ASM=1"/>
+<definedSymbol symbol="__PRAGMA_REDEFINE_EXTNAME=1"/>
+<definedSymbol symbol="__SSP__=1"/>
+<definedSymbol symbol="__SIZEOF_INT128__=16"/>
+<definedSymbol symbol="__SIZEOF_WCHAR_T__=4"/>
+<definedSymbol symbol="__SIZEOF_WINT_T__=4"/>
+<definedSymbol symbol="__SIZEOF_PTRDIFF_T__=8"/>
+<definedSymbol symbol="__amd64=1"/>
+<definedSymbol symbol="__amd64__=1"/>
+<definedSymbol symbol="__x86_64=1"/>
+<definedSymbol symbol="__x86_64__=1"/>
+<definedSymbol symbol="__k8=1"/>
+<definedSymbol symbol="__k8__=1"/>
+<definedSymbol symbol="__MMX__=1"/>
+<definedSymbol symbol="__SSE__=1"/>
+<definedSymbol symbol="__SSE2__=1"/>
+<definedSymbol symbol="__SSE_MATH__=1"/>
+<definedSymbol symbol="__SSE2_MATH__=1"/>
+<definedSymbol symbol="__gnu_linux__=1"/>
+<definedSymbol symbol="__linux=1"/>
+<definedSymbol symbol="__linux__=1"/>
+<definedSymbol symbol="linux=1"/>
+<definedSymbol symbol="__unix=1"/>
+<definedSymbol symbol="__unix__=1"/>
+<definedSymbol symbol="unix=1"/>
+<definedSymbol symbol="__ELF__=1"/>
+<definedSymbol symbol="__DECIMAL_BID_FORMAT__=1"/>
+</collector>
+</instance>
+</scannerInfo>
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.history/36/a07dff68fd6100111a83ded3e22caa93 b/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.history/36/a07dff68fd6100111a83ded3e22caa93
new file mode 100644
index 0000000..7050c59
--- /dev/null
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.history/36/a07dff68fd6100111a83ded3e22caa93
@@ -0,0 +1,823 @@
+/* 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.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+
+#include <l1ctl_proto.h>
+
+#include <osmocom/core/logging.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/signal.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/rsl.h>
+
+#include <osmocom/bb/common/l1ctl.h>
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/lapdm.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/networks.h>
+#include <osmocom/bb/common/gps.h>
+#include <osmocom/bb/misc/cell_log.h>
+#include "../../../gsmmap/geo.h"
+
+#define READ_WAIT 2, 0
+#define RACH_WAIT 0, 900000
+#define MIN_RXLEV -106
+#define MAX_DIST 2000
+
+enum {
+ SCAN_STATE_PM,
+ SCAN_STATE_SYNC,
+ SCAN_STATE_READ,
+ SCAN_STATE_RACH,
+};
+
+/* ranges of bands */
+static uint16_t band_range[][2] = {{0, 124}, {512, 885}, {955, 1023}, {0, 0}};
+
+#define INFO_FLG_PM 1
+#define INFO_FLG_SYNC 2
+#define INFO_FLG_SI1 4
+#define INFO_FLG_SI2 8
+#define INFO_FLG_SI2bis 16
+#define INFO_FLG_SI2ter 32
+#define INFO_FLG_SI3 64
+#define INFO_FLG_SI4 128
+
+static struct osmocom_ms *ms;
+static struct osmo_timer_list timer;
+
+static struct pm_info {
+ uint16_t flags;
+ int8_t rxlev;
+} pm[1024];
+
+static int started = 0;
+static int state;
+static int8_t min_rxlev = MIN_RXLEV;
+static int sync_count;
+static int pm_index, pm_gps_valid;
+static double pm_gps_x, pm_gps_y, pm_gps_z;
+static int arfcn;
+static int rach_count;
+static FILE *logfp = NULL;
+extern char *logname;
+extern int RACH_MAX;
+
+
+static struct gsm48_sysinfo sysinfo;
+
+static struct log_si {
+ uint16_t flags;
+ uint8_t bsic;
+ int8_t rxlev;
+ uint16_t mcc, mnc, lac, cellid;
+ uint8_t ta;
+ double latitude, longitude;
+} log_si;
+
+struct rach_ref {
+ uint8_t valid;
+ uint8_t cr;
+ uint8_t t1, t2, t3;
+} rach_ref;
+
+#define LOGFILE(fmt, args...) \
+ fprintf(logfp, fmt, ## args);
+#define LOGFLUSH() \
+ fflush(logfp);
+
+static void start_sync(void);
+static void start_rach(void);
+static void start_pm(void);
+
+static void log_gps(void)
+{
+ if (!g.enable || !g.valid)
+ return;
+ LOGFILE("position %.8f %.8f\n", g.longitude, g.latitude);
+}
+
+static void log_time(void)
+{
+ time_t now;
+
+ if (g.enable && g.valid)
+ now = g.gmt;
+ else
+ time(&now);
+ LOGFILE("time %lu\n", now);
+}
+
+static void log_frame(char *tag, uint8_t *data)
+{
+ int i;
+
+ LOGFILE("%s", tag);
+ for (i = 0; i < 23; i++)
+ LOGFILE(" %02x", *data++);
+ LOGFILE("\n");
+}
+
+static void log_pm(void)
+{
+ int count = 0, i;
+
+ LOGFILE("[power]\n");
+ log_time();
+ log_gps();
+ for (i = 0; i <= 1023; i++) {
+ if ((pm[i].flags & INFO_FLG_PM)) {
+ if (!count)
+ LOGFILE("arfcn %d", i);
+ LOGFILE(" %d", pm[i].rxlev);
+ count++;
+ if (count == 12) {
+ LOGFILE("\n");
+ count = 0;
+ }
+ } else {
+ if (count) {
+ LOGFILE("\n");
+ count = 0;
+ }
+ }
+ }
+ if (count)
+ LOGFILE("\n");
+
+ LOGFILE("\n");
+ LOGFLUSH();
+}
+
+static void log_sysinfo(void)
+{
+ struct rx_meas_stat *meas = &ms->meas;
+ struct gsm48_sysinfo *s = &sysinfo;
+ int8_t rxlev;
+ char ta_str[32] = "";
+
+ if (log_si.ta != 0xff)
+ sprintf(ta_str, " TA=%d", log_si.ta);
+
+ //LOGP(DSUM, LOGL_INFO, "Cell: ARFCN=%d MCC=%s MNC=%s (%s, %s)%s\n",
+ // arfcn, gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc),
+ // gsm_get_mcc(s->mcc), gsm_get_mnc(s->mcc, s->mnc), ta_str);
+
+ LOGFILE("[SysInfo]\n");
+ LOGFILE("country %s\n", gsm_get_mcc(s->mcc))
+ LOGFILE("provider %s\n", gsm_get_mnc(s->mcc, s->mnc))
+ LOGFILE("arfcn %d\n", s->arfcn);
+ //log_time();
+ //log_gps();
+ //LOGFILE("bsic %d,%d\n", s->bsic >> 3, s->bsic & 7);
+ rxlev = meas->rxlev / meas->frames - 110;
+ LOGFILE("rxlev %d\n", rxlev);
+ //if (s->si1)
+ // log_frame("si1", s->si1_msg);
+ if (s->si2)
+ log_frame("si2", s->si2_msg);
+ if (s->si2bis)
+ log_frame("si2bis", s->si2b_msg);
+ if (s->si2ter)
+ log_frame("si2ter", s->si2t_msg);
+ //if (s->si3)
+ // log_frame("si3", s->si3_msg);
+ //if (s->si4)
+ // log_frame("si4", s->si4_msg);
+ //if (log_si.ta != 0xff)
+ // LOGFILE("ta %d\n", log_si.ta);
+ LOGFILE("[EndInfo]\n");
+ LOGFILE("\n");
+ LOGFLUSH();
+}
+
+static void timeout_cb(void *arg)
+{
+ switch (state) {
+ case SCAN_STATE_READ:
+ LOGP(DRR, LOGL_INFO, "Timeout reading BCCH\n");
+ start_sync();
+ break;
+ case SCAN_STATE_RACH:
+ LOGP(DRR, LOGL_INFO, "Timeout on RACH\n");
+ rach_count++;
+ start_rach();
+ break;
+ }
+}
+
+static void stop_timer(void)
+{
+ if (osmo_timer_pending(&timer))
+ osmo_timer_del(&timer);
+}
+
+static void start_timer(int sec, int micro)
+{
+ stop_timer();
+ timer.cb = timeout_cb;
+ timer.data = ms;
+ osmo_timer_schedule(&timer, sec, micro);
+}
+
+static void start_rach(void)
+{
+ struct gsm48_sysinfo *s = &sysinfo;
+ uint8_t chan_req_val, chan_req_mask;
+ struct msgb *nmsg;
+ struct abis_rsl_cchan_hdr *ncch;
+
+ if (rach_count == RACH_MAX) {
+ log_sysinfo();
+ start_sync();
+ return;
+ }
+
+ state = SCAN_STATE_RACH;
+
+ if (s->neci) {
+ chan_req_mask = 0x0f;
+ chan_req_val = 0x01;
+ LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x "
+ "(OTHER with NECI)\n", chan_req_val);
+ } else {
+ chan_req_mask = 0x1f;
+ chan_req_val = 0xe0;
+ LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x (OTHER no NECI)\n",
+ chan_req_val);
+ }
+
+ rach_ref.valid = 0;
+ rach_ref.cr = random();
+ rach_ref.cr &= chan_req_mask;
+ rach_ref.cr |= chan_req_val;
+
+ nmsg = msgb_alloc_headroom(RSL_ALLOC_SIZE+RSL_ALLOC_HEADROOM,
+ RSL_ALLOC_HEADROOM, "GSM 04.06 RSL");
+ if (!nmsg)
+ return;
+ nmsg->l2h = nmsg->data;
+ ncch = (struct abis_rsl_cchan_hdr *) msgb_put(nmsg, sizeof(*ncch)
+ + 4 + 2 + 2);
+ rsl_init_cchan_hdr(ncch, RSL_MT_CHAN_RQD);
+ ncch->chan_nr = RSL_CHAN_RACH;
+ ncch->data[0] = RSL_IE_REQ_REFERENCE;
+ ncch->data[1] = rach_ref.cr;
+ ncch->data[2] = (s->ccch_conf == 1) << 7;
+ ncch->data[3] = 0;
+ ncch->data[4] = RSL_IE_ACCESS_DELAY;
+ ncch->data[5] = 0; /* no delay */
+ ncch->data[6] = RSL_IE_MS_POWER;
+ ncch->data[7] = 0; /* full power */
+
+ start_timer(RACH_WAIT);
+
+ lapdm_rslms_recvmsg(nmsg, &ms->lapdm_channel);
+}
+
+static void start_sync(void)
+{
+ int rxlev = -128;
+ int i, dist = 0;
+ char dist_str[32] = "";
+
+ arfcn = 0xffff;
+ for (i = 0; i <= 1023; i++) {
+ if ((pm[i].flags & INFO_FLG_PM)
+ && !(pm[i].flags & INFO_FLG_SYNC)) {
+ if (pm[i].rxlev > rxlev) {
+ rxlev = pm[i].rxlev;
+ arfcn = i;
+ }
+ }
+ }
+ /* if GPS becomes valid, like after exitting a tunnel */
+ if (!pm_gps_valid && g.valid) {
+ pm_gps_valid = 1;
+ geo2space(&pm_gps_x, &pm_gps_y, &pm_gps_z, g.longitude,
+ g.latitude);
+ }
+ if (pm_gps_valid && g.valid) {
+ double x, y, z;
+
+ geo2space(&x, &y, &z, g.longitude, g.latitude);
+ dist = distinspace(pm_gps_x, pm_gps_y, pm_gps_z, x, y, z);
+ sprintf(dist_str, " dist %d", (int)dist);
+ }
+ if (dist > MAX_DIST || arfcn == 0xffff || rxlev < min_rxlev) {
+ memset(pm, 0, sizeof(pm));
+ pm_index = 0;
+ sync_count = 0;
+ start_pm();
+ return;
+ }
+ pm[arfcn].flags |= INFO_FLG_SYNC;
+ //HACK: no use for us right now
+ LOGP(DSUM, LOGL_INFO, "Sync ARFCN %d (rxlev %d, %d syncs "
+ "left)%s\n", arfcn, pm[arfcn].rxlev, sync_count--, dist_str);
+ memset(&sysinfo, 0, sizeof(sysinfo));
+ sysinfo.arfcn = arfcn;
+ state = SCAN_STATE_SYNC;
+ l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
+ l1ctl_tx_fbsb_req(ms, arfcn, L1CTL_FBSB_F_FB01SB, 100, 0,
+ CCCH_MODE_NONE);
+}
+
+static void start_pm(void)
+{
+ uint16_t from, to;
+
+ state = SCAN_STATE_PM;
+ from = band_range[pm_index][0];
+ to = band_range[pm_index][1];
+
+ if (from == 0 && to == 0) {
+ LOGP(DSUM, LOGL_INFO, "Measurement done\n");
+ pm_gps_valid = g.enable && g.valid;
+ if (pm_gps_valid)
+ geo2space(&pm_gps_x, &pm_gps_y, &pm_gps_z,
+ g.longitude, g.latitude);
+ log_pm();
+ start_sync();
+ return;
+ }
+ LOGP(DSUM, LOGL_INFO, "Measure from %d to %d\n", from, to);
+ l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
+ l1ctl_tx_pm_req_range(ms, from, to);
+}
+
+static int signal_cb(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data)
+{
+ struct osmobb_meas_res *mr;
+ struct osmobb_fbsb_res *fr;
+ uint16_t index;
+
+ if (subsys != SS_L1CTL)
+ return 0;
+
+ switch (signal) {
+ case S_L1CTL_PM_RES:
+ mr = signal_data;
+ index = mr->band_arfcn & 0x3ff;
+ pm[index].flags |= INFO_FLG_PM;
+ pm[index].rxlev = mr->rx_lev - 110;
+ if (pm[index].rxlev >= min_rxlev)
+ sync_count++;
+// printf("rxlev %d = %d (sync_count %d)\n", index, pm[index].rxlev, sync_count);
+ break;
+ case S_L1CTL_PM_DONE:
+ pm_index++;
+ start_pm();
+ break;
+ case S_L1CTL_FBSB_RESP:
+ fr = signal_data;
+ sysinfo.bsic = fr->bsic;
+ state = SCAN_STATE_READ;
+ memset(&ms->meas, 0, sizeof(ms->meas));
+ memset(&log_si, 0, sizeof(log_si));
+ log_si.flags |= INFO_FLG_SYNC;
+ log_si.ta = 0xff; /* invalid */
+ start_timer(READ_WAIT);
+ LOGP(DRR, LOGL_INFO, "Synchronized, start reading\n");
+ break;
+ case S_L1CTL_FBSB_ERR:
+ LOGP(DRR, LOGL_INFO, "Sync failed\n");
+ start_sync();
+ break;
+ case S_L1CTL_RESET:
+ if (started)
+ break;
+ started = 1;
+ memset(pm, 0, sizeof(pm));
+ pm_index = 0;
+ sync_count = 0;
+ start_pm();
+ }
+ return 0;
+}
+
+static int ta_result(uint8_t ta)
+{
+ stop_timer();
+
+ if (ta == 0xff)
+ LOGP(DSUM, LOGL_INFO, "Got assignment reject\n");
+ else {
+ LOGP(DSUM, LOGL_DEBUG, "Got assignment TA = %d\n", ta);
+ log_si.ta = ta;
+ }
+
+ log_sysinfo();
+ start_sync();
+
+ return 0;
+}
+
+/* match request reference agains request */
+static int match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref)
+{
+ uint8_t ia_t1, ia_t2, ia_t3;
+
+ /* filter confirmed RACH requests only */
+ if (rach_ref.valid && ref->ra == rach_ref.cr) {
+ ia_t1 = ref->t1;
+ ia_t2 = ref->t2;
+ ia_t3 = (ref->t3_high << 3) | ref->t3_low;
+ if (ia_t1 == rach_ref.t1 && ia_t2 == rach_ref.t2
+ && ia_t3 == rach_ref.t3) {
+ LOGP(DRR, LOGL_INFO, "request %02x matches "
+ "(fn=%d,%d,%d)\n", ref->ra, ia_t1, ia_t2,
+ ia_t3);
+ return 1;
+ } else
+ LOGP(DRR, LOGL_INFO, "request %02x matches but not "
+ "frame number (IMM.ASS fn=%d,%d,%d != RACH "
+ "fn=%d,%d,%d)\n", ref->ra, ia_t1, ia_t2, ia_t3,
+ rach_ref.t1, rach_ref.t2, rach_ref.t3);
+ }
+
+ return 0;
+}
+
+/* 9.1.18 IMMEDIATE ASSIGNMENT is received */
+static int imm_ass(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_imm_ass *ia = msgb_l3(msg);
+
+ LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT:\n");
+
+ if (state != SCAN_STATE_RACH) {
+ LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
+ return 0;
+ }
+
+ /* request ref */
+ if (match_ra(ms, &ia->req_ref)) {
+ return ta_result(ia->timing_advance);
+ }
+ LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
+
+ return 0;
+}
+
+/* 9.1.19 IMMEDIATE ASSIGNMENT EXTENDED is received */
+static int imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_imm_ass_ext *ia = msgb_l3(msg);
+
+ LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT EXTENDED:\n");
+
+ if (state != SCAN_STATE_RACH) {
+ LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
+ return 0;
+ }
+
+ /* request ref 1 */
+ if (match_ra(ms, &ia->req_ref1)) {
+ return ta_result(ia->timing_advance1);
+ }
+ /* request ref 2 */
+ if (match_ra(ms, &ia->req_ref2)) {
+ return ta_result(ia->timing_advance2);
+ }
+ LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
+
+ return 0;
+}
+
+/* 9.1.20 IMMEDIATE ASSIGNMENT REJECT is received */
+static int imm_ass_rej(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_imm_ass_rej *ia = msgb_l3(msg);
+ int i;
+ struct gsm48_req_ref *req_ref;
+
+ LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT REJECT:\n");
+
+ if (state != SCAN_STATE_RACH) {
+ LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
+ return 0;
+ }
+
+ for (i = 0; i < 4; i++) {
+ /* request reference */
+ req_ref = (struct gsm48_req_ref *)
+ (((uint8_t *)&ia->req_ref1) + i * 4);
+ LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT REJECT "
+ "(ref 0x%02x)\n", req_ref->ra);
+ if (match_ra(ms, req_ref)) {
+ return ta_result(0xff);
+ }
+ }
+
+ return 0;
+}
+
+/* receive CCCH at RR layer */
+static int pch_agch(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_system_information_type_header *sih = msgb_l3(msg);
+
+ switch (sih->system_information) {
+ case GSM48_MT_RR_PAG_REQ_1:
+ case GSM48_MT_RR_PAG_REQ_2:
+ case GSM48_MT_RR_PAG_REQ_3:
+ return 0;
+ case GSM48_MT_RR_IMM_ASS:
+ return imm_ass(ms, msg);
+ case GSM48_MT_RR_IMM_ASS_EXT:
+ return imm_ass_ext(ms, msg);
+ case GSM48_MT_RR_IMM_ASS_REJ:
+ return imm_ass_rej(ms, msg);
+ default:
+ return -EINVAL;
+ }
+}
+
+/* check if sysinfo is complete, change to RACH state */
+static int new_sysinfo(void)
+{
+ struct gsm48_sysinfo *s = &sysinfo;
+
+ /* restart timer */
+ start_timer(READ_WAIT);
+
+ /* mandatory */
+ if (!s->si1 || !s->si2 || !s->si3 || !s->si4) {
+ LOGP(DRR, LOGL_INFO, "not all mandatory SI received\n");
+ return 0;
+ }
+
+ /* extended band */
+ if (s->nb_ext_ind_si2 && !s->si2bis) {
+ LOGP(DRR, LOGL_INFO, "extended ba, but si2bis not received\n");
+ return 0;
+ }
+
+ /* 2ter */
+ if (s->si2ter_ind && !s->si2ter) {
+ LOGP(DRR, LOGL_INFO, "si2ter_ind, but si2ter not received\n");
+ return 0;
+ }
+
+ LOGP(DRR, LOGL_INFO, "Sysinfo complete\n");
+
+ stop_timer();
+
+ rach_count = 0;
+ start_rach();
+
+ return 0;
+}
+
+/* receive BCCH at RR layer */
+static int bcch(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_sysinfo *s = &sysinfo;
+ struct gsm48_system_information_type_header *sih = msgb_l3(msg);
+ uint8_t ccch_mode;
+
+ if (msgb_l3len(msg) != 23) {
+ LOGP(DRR, LOGL_NOTICE, "Invalid BCCH message length\n");
+ return -EINVAL;
+ }
+ switch (sih->system_information) {
+ case GSM48_MT_RR_SYSINFO_1:
+ if (!memcmp(sih, s->si1_msg, sizeof(s->si1_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 1\n");
+ gsm48_decode_sysinfo1(s,
+ (struct gsm48_system_information_type_1 *) sih,
+ msgb_l3len(msg));
+ return new_sysinfo();
+ case GSM48_MT_RR_SYSINFO_2:
+ if (!memcmp(sih, s->si2_msg, sizeof(s->si2_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2\n");
+ gsm48_decode_sysinfo2(s,
+ (struct gsm48_system_information_type_2 *) sih,
+ msgb_l3len(msg));
+ return new_sysinfo();
+ case GSM48_MT_RR_SYSINFO_2bis:
+ if (!memcmp(sih, s->si2b_msg, sizeof(s->si2b_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2bis\n");
+ gsm48_decode_sysinfo2bis(s,
+ (struct gsm48_system_information_type_2bis *) sih,
+ msgb_l3len(msg));
+ return new_sysinfo();
+ case GSM48_MT_RR_SYSINFO_2ter:
+ if (!memcmp(sih, s->si2t_msg, sizeof(s->si2t_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2ter\n");
+ gsm48_decode_sysinfo2ter(s,
+ (struct gsm48_system_information_type_2ter *) sih,
+ msgb_l3len(msg));
+ return new_sysinfo();
+ case GSM48_MT_RR_SYSINFO_3:
+ if (!memcmp(sih, s->si3_msg, sizeof(s->si3_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 3\n");
+ gsm48_decode_sysinfo3(s,
+ (struct gsm48_system_information_type_3 *) sih,
+ msgb_l3len(msg));
+ ccch_mode = (s->ccch_conf == 1) ? CCCH_MODE_COMBINED :
+ CCCH_MODE_NON_COMBINED;
+ LOGP(DRR, LOGL_INFO, "Changing CCCH_MODE to %d\n", ccch_mode);
+ l1ctl_tx_ccch_mode_req(ms, ccch_mode);
+ return new_sysinfo();
+ case GSM48_MT_RR_SYSINFO_4:
+ if (!memcmp(sih, s->si4_msg, sizeof(s->si4_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 4\n");
+ gsm48_decode_sysinfo4(s,
+ (struct gsm48_system_information_type_4 *) sih,
+ msgb_l3len(msg));
+ return new_sysinfo();
+ default:
+ return -EINVAL;
+ }
+}
+
+static int unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ struct tlv_parsed tv;
+ uint8_t ch_type, ch_subch, ch_ts;
+
+ DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
+ rllh->chan_nr, rllh->link_id);
+
+ rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
+ if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
+ DEBUGP(DRSL, "UNIT_DATA_IND without L3 INFO ?!?\n");
+ return -EIO;
+ }
+ msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
+
+ if (state != SCAN_STATE_READ && state != SCAN_STATE_RACH) {
+ return -EINVAL;
+ }
+
+ rsl_dec_chan_nr(rllh->chan_nr, &ch_type, &ch_subch, &ch_ts);
+ switch (ch_type) {
+ case RSL_CHAN_PCH_AGCH:
+ return pch_agch(ms, msg);
+ case RSL_CHAN_BCCH:
+ return bcch(ms, msg);
+#if 0
+ case RSL_CHAN_Bm_ACCHs:
+ case RSL_CHAN_Lm_ACCHs:
+ case RSL_CHAN_SDCCH4_ACCH:
+ case RSL_CHAN_SDCCH8_ACCH:
+ return rx_acch(ms, msg);
+#endif
+ default:
+ LOGP(DRSL, LOGL_NOTICE, "RSL with chan_nr 0x%02x unknown.\n",
+ rllh->chan_nr);
+ return -EINVAL;
+ }
+}
+
+static int rcv_rll(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ int msg_type = rllh->c.msg_type;
+
+ if (msg_type == RSL_MT_UNIT_DATA_IND) {
+ unit_data_ind(ms, msg);
+ } else
+ LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
+
+ msgb_free(msg);
+
+ return 0;
+}
+
+int chan_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
+ struct gsm48_req_ref *ref = (struct gsm48_req_ref *) (ch->data + 1);
+
+ if (msgb_l2len(msg) < sizeof(*ch) + sizeof(*ref)) {
+ LOGP(DRR, LOGL_ERROR, "CHAN_CNF too slort\n");
+ return -EINVAL;
+ }
+
+ rach_ref.valid = 1;
+ rach_ref.t1 = ref->t1;
+ rach_ref.t2 = ref->t2;
+ rach_ref.t3 = ref->t3_low | (ref->t3_high << 3);
+
+ return 0;
+}
+
+static int rcv_cch(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
+ int msg_type = ch->c.msg_type;
+ int rc;
+
+ LOGP(DRSL, LOGL_INFO, "Received '%s' from layer1\n",
+ rsl_msg_name(msg_type));
+
+ if (state == SCAN_STATE_RACH && msg_type == RSL_MT_CHAN_CONF) {
+ rc = chan_conf(ms, msg);
+ msgb_free(msg);
+ return rc;
+ }
+
+ LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
+ msgb_free(msg);
+ return 0;
+}
+
+static int rcv_rsl(struct msgb *msg, struct lapdm_entity *le, void *l3ctx)
+{
+ struct osmocom_ms *ms = l3ctx;
+ struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
+ int rc = 0;
+
+ switch (rslh->msg_discr & 0xfe) {
+ case ABIS_RSL_MDISC_RLL:
+ rc = rcv_rll(ms, msg);
+ break;
+ case ABIS_RSL_MDISC_COM_CHAN:
+ rc = rcv_cch(ms, msg);
+ break;
+ default:
+ LOGP(DRSL, LOGL_NOTICE, "unknown RSLms msg_discr 0x%02x\n",
+ rslh->msg_discr);
+ msgb_free(msg);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+int scan_init(struct osmocom_ms *_ms)
+{
+ ms = _ms;
+ osmo_signal_register_handler(SS_L1CTL, &signal_cb, NULL);
+ memset(&timer, 0, sizeof(timer));
+ lapdm_channel_set_l3(&ms->lapdm_channel, &rcv_rsl, ms);
+ g.enable = 1;
+ osmo_gps_init();
+ if (osmo_gps_open())
+ g.enable = 0;
+
+ if (!strcmp(logname, "-"))
+ logfp = stdout;
+ else
+ logfp = fopen(logname, "a");
+ if (!logfp) {
+ fprintf(stderr, "Failed to open logfile '%s'\n", logname);
+ scan_exit();
+ return -errno;
+ }
+ LOGP(DSUM, LOGL_INFO, "Scanner initialized\n");
+
+ return 0;
+}
+
+int scan_exit(void)
+{
+ LOGP(DSUM, LOGL_INFO, "Scanner exit\n");
+ if (g.valid)
+ osmo_gps_close();
+ if (logfp)
+ fclose(logfp);
+ osmo_signal_unregister_handler(SS_L1CTL, &signal_cb, NULL);
+ stop_timer();
+
+ return 0;
+}
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.history/c9/f0b573ecfa6100111a83ded3e22caa93 b/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.history/c9/f0b573ecfa6100111a83ded3e22caa93
new file mode 100644
index 0000000..00ed944
--- /dev/null
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.history/c9/f0b573ecfa6100111a83ded3e22caa93
@@ -0,0 +1,824 @@
+/* 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.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+
+#include <l1ctl_proto.h>
+
+#include <osmocom/core/logging.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/signal.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/rsl.h>
+
+#include <osmocom/bb/common/l1ctl.h>
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/lapdm.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/networks.h>
+#include <osmocom/bb/common/gps.h>
+#include <osmocom/bb/misc/cell_log.h>
+#include "../../../gsmmap/geo.h"
+
+#define READ_WAIT 2, 0
+#define RACH_WAIT 0, 900000
+#define MIN_RXLEV -106
+#define MAX_DIST 2000
+
+enum {
+ SCAN_STATE_PM,
+ SCAN_STATE_SYNC,
+ SCAN_STATE_READ,
+ SCAN_STATE_RACH,
+};
+
+/* ranges of bands */
+static uint16_t band_range[][2] = {{0, 124}, {512, 885}, {955, 1023}, {0, 0}};
+
+#define INFO_FLG_PM 1
+#define INFO_FLG_SYNC 2
+#define INFO_FLG_SI1 4
+#define INFO_FLG_SI2 8
+#define INFO_FLG_SI2bis 16
+#define INFO_FLG_SI2ter 32
+#define INFO_FLG_SI3 64
+#define INFO_FLG_SI4 128
+
+static struct osmocom_ms *ms;
+static struct osmo_timer_list timer;
+
+static struct pm_info {
+ uint16_t flags;
+ int8_t rxlev;
+} pm[1024];
+
+static int started = 0;
+static int state;
+static int8_t min_rxlev = MIN_RXLEV;
+static int sync_count;
+static int pm_index, pm_gps_valid;
+static double pm_gps_x, pm_gps_y, pm_gps_z;
+static int arfcn;
+static int rach_count;
+static FILE *logfp = NULL;
+extern char *logname;
+extern int RACH_MAX;
+
+
+static struct gsm48_sysinfo sysinfo;
+
+static struct log_si {
+ uint16_t flags;
+ uint8_t bsic;
+ int8_t rxlev;
+ uint16_t mcc, mnc, lac, cellid;
+ uint8_t ta;
+ double latitude, longitude;
+} log_si;
+
+struct rach_ref {
+ uint8_t valid;
+ uint8_t cr;
+ uint8_t t1, t2, t3;
+} rach_ref;
+
+#define LOGFILE(fmt, args...) \
+ fprintf(logfp, fmt, ## args);
+#define LOGFLUSH() \
+ fflush(logfp);
+
+static void start_sync(void);
+static void start_rach(void);
+static void start_pm(void);
+
+static void log_gps(void)
+{
+ if (!g.enable || !g.valid)
+ return;
+ LOGFILE("position %.8f %.8f\n", g.longitude, g.latitude);
+}
+
+static void log_time(void)
+{
+ time_t now;
+
+ if (g.enable && g.valid)
+ now = g.gmt;
+ else
+ time(&now);
+ LOGFILE("time %lu\n", now);
+}
+
+static void log_frame(char *tag, uint8_t *data)
+{
+ int i;
+
+ LOGFILE("%s", tag);
+ for (i = 0; i < 23; i++)
+ LOGFILE(" %02x", *data++);
+ LOGFILE("\n");
+}
+
+static void log_pm(void)
+{
+ int count = 0, i;
+
+ LOGFILE("[power]\n");
+ log_time();
+ log_gps();
+ for (i = 0; i <= 1023; i++) {
+ if ((pm[i].flags & INFO_FLG_PM)) {
+ if (!count)
+ LOGFILE("arfcn %d", i);
+ LOGFILE(" %d", pm[i].rxlev);
+ count++;
+ if (count == 12) {
+ LOGFILE("\n");
+ count = 0;
+ }
+ } else {
+ if (count) {
+ LOGFILE("\n");
+ count = 0;
+ }
+ }
+ }
+ if (count)
+ LOGFILE("\n");
+
+ LOGFILE("\n");
+ LOGFLUSH();
+}
+
+static void log_sysinfo(void)
+{
+ struct rx_meas_stat *meas = &ms->meas;
+ struct gsm48_sysinfo *s = &sysinfo;
+ int8_t rxlev;
+ char ta_str[32] = "";
+
+ if (log_si.ta != 0xff)
+ sprintf(ta_str, " TA=%d", log_si.ta);
+
+ //LOGP(DSUM, LOGL_INFO, "Cell: ARFCN=%d MCC=%s MNC=%s (%s, %s)%s\n",
+ // arfcn, gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc),
+ // gsm_get_mcc(s->mcc), gsm_get_mnc(s->mcc, s->mnc), ta_str);
+
+ LOGFILE("[SysInfo]\n");
+ LOGFILE("country %s\n", gsm_get_mcc(s->mcc))
+ LOGFILE("provider %s\n", gsm_get_mnc(s->mcc, s->mnc))
+ LOGFILE("arfcn %d\n", s->arfcn);
+ //log_time();
+ //log_gps();
+ //LOGFILE("bsic %d,%d\n", s->bsic >> 3, s->bsic & 7);
+ rxlev = meas->rxlev / meas->frames - 110;
+ LOGFILE("rxlev %d\n", rxlev);
+ //if (s->si1)
+ // log_frame("si1", s->si1_msg);
+ if (s->si2)
+ log_frame("si2", s->si2_msg);
+ if (s->si2bis)
+ log_frame("si2bis", s->si2b_msg);
+ if (s->si2ter)
+ log_frame("si2ter", s->si2t_msg);
+ //if (s->si3)
+ // log_frame("si3", s->si3_msg);
+ //if (s->si4)
+ // log_frame("si4", s->si4_msg);
+ //if (log_si.ta != 0xff)
+ // LOGFILE("ta %d\n", log_si.ta);
+
+ LOGFILE("[EndInfo]\n");
+ LOGFILE("\n");
+ LOGFLUSH();
+}
+
+static void timeout_cb(void *arg)
+{
+ switch (state) {
+ case SCAN_STATE_READ:
+ LOGP(DRR, LOGL_INFO, "Timeout reading BCCH\n");
+ start_sync();
+ break;
+ case SCAN_STATE_RACH:
+ LOGP(DRR, LOGL_INFO, "Timeout on RACH\n");
+ rach_count++;
+ start_rach();
+ break;
+ }
+}
+
+static void stop_timer(void)
+{
+ if (osmo_timer_pending(&timer))
+ osmo_timer_del(&timer);
+}
+
+static void start_timer(int sec, int micro)
+{
+ stop_timer();
+ timer.cb = timeout_cb;
+ timer.data = ms;
+ osmo_timer_schedule(&timer, sec, micro);
+}
+
+static void start_rach(void)
+{
+ struct gsm48_sysinfo *s = &sysinfo;
+ uint8_t chan_req_val, chan_req_mask;
+ struct msgb *nmsg;
+ struct abis_rsl_cchan_hdr *ncch;
+
+ if (rach_count == RACH_MAX) {
+ log_sysinfo();
+ start_sync();
+ return;
+ }
+
+ state = SCAN_STATE_RACH;
+
+ if (s->neci) {
+ chan_req_mask = 0x0f;
+ chan_req_val = 0x01;
+ LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x "
+ "(OTHER with NECI)\n", chan_req_val);
+ } else {
+ chan_req_mask = 0x1f;
+ chan_req_val = 0xe0;
+ LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x (OTHER no NECI)\n",
+ chan_req_val);
+ }
+
+ rach_ref.valid = 0;
+ rach_ref.cr = random();
+ rach_ref.cr &= chan_req_mask;
+ rach_ref.cr |= chan_req_val;
+
+ nmsg = msgb_alloc_headroom(RSL_ALLOC_SIZE+RSL_ALLOC_HEADROOM,
+ RSL_ALLOC_HEADROOM, "GSM 04.06 RSL");
+ if (!nmsg)
+ return;
+ nmsg->l2h = nmsg->data;
+ ncch = (struct abis_rsl_cchan_hdr *) msgb_put(nmsg, sizeof(*ncch)
+ + 4 + 2 + 2);
+ rsl_init_cchan_hdr(ncch, RSL_MT_CHAN_RQD);
+ ncch->chan_nr = RSL_CHAN_RACH;
+ ncch->data[0] = RSL_IE_REQ_REFERENCE;
+ ncch->data[1] = rach_ref.cr;
+ ncch->data[2] = (s->ccch_conf == 1) << 7;
+ ncch->data[3] = 0;
+ ncch->data[4] = RSL_IE_ACCESS_DELAY;
+ ncch->data[5] = 0; /* no delay */
+ ncch->data[6] = RSL_IE_MS_POWER;
+ ncch->data[7] = 0; /* full power */
+
+ start_timer(RACH_WAIT);
+
+ lapdm_rslms_recvmsg(nmsg, &ms->lapdm_channel);
+}
+
+static void start_sync(void)
+{
+ int rxlev = -128;
+ int i, dist = 0;
+ char dist_str[32] = "";
+
+ arfcn = 0xffff;
+ for (i = 0; i <= 1023; i++) {
+ if ((pm[i].flags & INFO_FLG_PM)
+ && !(pm[i].flags & INFO_FLG_SYNC)) {
+ if (pm[i].rxlev > rxlev) {
+ rxlev = pm[i].rxlev;
+ arfcn = i;
+ }
+ }
+ }
+ /* if GPS becomes valid, like after exitting a tunnel */
+ if (!pm_gps_valid && g.valid) {
+ pm_gps_valid = 1;
+ geo2space(&pm_gps_x, &pm_gps_y, &pm_gps_z, g.longitude,
+ g.latitude);
+ }
+ if (pm_gps_valid && g.valid) {
+ double x, y, z;
+
+ geo2space(&x, &y, &z, g.longitude, g.latitude);
+ dist = distinspace(pm_gps_x, pm_gps_y, pm_gps_z, x, y, z);
+ sprintf(dist_str, " dist %d", (int)dist);
+ }
+ if (dist > MAX_DIST || arfcn == 0xffff || rxlev < min_rxlev) {
+ memset(pm, 0, sizeof(pm));
+ pm_index = 0;
+ sync_count = 0;
+ start_pm();
+ return;
+ }
+ pm[arfcn].flags |= INFO_FLG_SYNC;
+ //HACK: no use for us right now
+ LOGP(DSUM, LOGL_INFO, "Sync ARFCN %d (rxlev %d, %d syncs "
+ "left)%s\n", arfcn, pm[arfcn].rxlev, sync_count--, dist_str);
+ memset(&sysinfo, 0, sizeof(sysinfo));
+ sysinfo.arfcn = arfcn;
+ state = SCAN_STATE_SYNC;
+ l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
+ l1ctl_tx_fbsb_req(ms, arfcn, L1CTL_FBSB_F_FB01SB, 100, 0,
+ CCCH_MODE_NONE);
+}
+
+static void start_pm(void)
+{
+ uint16_t from, to;
+
+ state = SCAN_STATE_PM;
+ from = band_range[pm_index][0];
+ to = band_range[pm_index][1];
+
+ if (from == 0 && to == 0) {
+ LOGP(DSUM, LOGL_INFO, "Measurement done\n");
+ pm_gps_valid = g.enable && g.valid;
+ if (pm_gps_valid)
+ geo2space(&pm_gps_x, &pm_gps_y, &pm_gps_z,
+ g.longitude, g.latitude);
+ log_pm();
+ start_sync();
+ return;
+ }
+ LOGP(DSUM, LOGL_INFO, "Measure from %d to %d\n", from, to);
+ l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
+ l1ctl_tx_pm_req_range(ms, from, to);
+}
+
+static int signal_cb(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data)
+{
+ struct osmobb_meas_res *mr;
+ struct osmobb_fbsb_res *fr;
+ uint16_t index;
+
+ if (subsys != SS_L1CTL)
+ return 0;
+
+ switch (signal) {
+ case S_L1CTL_PM_RES:
+ mr = signal_data;
+ index = mr->band_arfcn & 0x3ff;
+ pm[index].flags |= INFO_FLG_PM;
+ pm[index].rxlev = mr->rx_lev - 110;
+ if (pm[index].rxlev >= min_rxlev)
+ sync_count++;
+// printf("rxlev %d = %d (sync_count %d)\n", index, pm[index].rxlev, sync_count);
+ break;
+ case S_L1CTL_PM_DONE:
+ pm_index++;
+ start_pm();
+ break;
+ case S_L1CTL_FBSB_RESP:
+ fr = signal_data;
+ sysinfo.bsic = fr->bsic;
+ state = SCAN_STATE_READ;
+ memset(&ms->meas, 0, sizeof(ms->meas));
+ memset(&log_si, 0, sizeof(log_si));
+ log_si.flags |= INFO_FLG_SYNC;
+ log_si.ta = 0xff; /* invalid */
+ start_timer(READ_WAIT);
+ LOGP(DRR, LOGL_INFO, "Synchronized, start reading\n");
+ break;
+ case S_L1CTL_FBSB_ERR:
+ LOGP(DRR, LOGL_INFO, "Sync failed\n");
+ start_sync();
+ break;
+ case S_L1CTL_RESET:
+ if (started)
+ break;
+ started = 1;
+ memset(pm, 0, sizeof(pm));
+ pm_index = 0;
+ sync_count = 0;
+ start_pm();
+ }
+ return 0;
+}
+
+static int ta_result(uint8_t ta)
+{
+ stop_timer();
+
+ if (ta == 0xff)
+ LOGP(DSUM, LOGL_INFO, "Got assignment reject\n");
+ else {
+ LOGP(DSUM, LOGL_DEBUG, "Got assignment TA = %d\n", ta);
+ log_si.ta = ta;
+ }
+
+ log_sysinfo();
+ start_sync();
+
+ return 0;
+}
+
+/* match request reference agains request */
+static int match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref)
+{
+ uint8_t ia_t1, ia_t2, ia_t3;
+
+ /* filter confirmed RACH requests only */
+ if (rach_ref.valid && ref->ra == rach_ref.cr) {
+ ia_t1 = ref->t1;
+ ia_t2 = ref->t2;
+ ia_t3 = (ref->t3_high << 3) | ref->t3_low;
+ if (ia_t1 == rach_ref.t1 && ia_t2 == rach_ref.t2
+ && ia_t3 == rach_ref.t3) {
+ LOGP(DRR, LOGL_INFO, "request %02x matches "
+ "(fn=%d,%d,%d)\n", ref->ra, ia_t1, ia_t2,
+ ia_t3);
+ return 1;
+ } else
+ LOGP(DRR, LOGL_INFO, "request %02x matches but not "
+ "frame number (IMM.ASS fn=%d,%d,%d != RACH "
+ "fn=%d,%d,%d)\n", ref->ra, ia_t1, ia_t2, ia_t3,
+ rach_ref.t1, rach_ref.t2, rach_ref.t3);
+ }
+
+ return 0;
+}
+
+/* 9.1.18 IMMEDIATE ASSIGNMENT is received */
+static int imm_ass(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_imm_ass *ia = msgb_l3(msg);
+
+ LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT:\n");
+
+ if (state != SCAN_STATE_RACH) {
+ LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
+ return 0;
+ }
+
+ /* request ref */
+ if (match_ra(ms, &ia->req_ref)) {
+ return ta_result(ia->timing_advance);
+ }
+ LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
+
+ return 0;
+}
+
+/* 9.1.19 IMMEDIATE ASSIGNMENT EXTENDED is received */
+static int imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_imm_ass_ext *ia = msgb_l3(msg);
+
+ LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT EXTENDED:\n");
+
+ if (state != SCAN_STATE_RACH) {
+ LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
+ return 0;
+ }
+
+ /* request ref 1 */
+ if (match_ra(ms, &ia->req_ref1)) {
+ return ta_result(ia->timing_advance1);
+ }
+ /* request ref 2 */
+ if (match_ra(ms, &ia->req_ref2)) {
+ return ta_result(ia->timing_advance2);
+ }
+ LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
+
+ return 0;
+}
+
+/* 9.1.20 IMMEDIATE ASSIGNMENT REJECT is received */
+static int imm_ass_rej(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_imm_ass_rej *ia = msgb_l3(msg);
+ int i;
+ struct gsm48_req_ref *req_ref;
+
+ LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT REJECT:\n");
+
+ if (state != SCAN_STATE_RACH) {
+ LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
+ return 0;
+ }
+
+ for (i = 0; i < 4; i++) {
+ /* request reference */
+ req_ref = (struct gsm48_req_ref *)
+ (((uint8_t *)&ia->req_ref1) + i * 4);
+ LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT REJECT "
+ "(ref 0x%02x)\n", req_ref->ra);
+ if (match_ra(ms, req_ref)) {
+ return ta_result(0xff);
+ }
+ }
+
+ return 0;
+}
+
+/* receive CCCH at RR layer */
+static int pch_agch(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_system_information_type_header *sih = msgb_l3(msg);
+
+ switch (sih->system_information) {
+ case GSM48_MT_RR_PAG_REQ_1:
+ case GSM48_MT_RR_PAG_REQ_2:
+ case GSM48_MT_RR_PAG_REQ_3:
+ return 0;
+ case GSM48_MT_RR_IMM_ASS:
+ return imm_ass(ms, msg);
+ case GSM48_MT_RR_IMM_ASS_EXT:
+ return imm_ass_ext(ms, msg);
+ case GSM48_MT_RR_IMM_ASS_REJ:
+ return imm_ass_rej(ms, msg);
+ default:
+ return -EINVAL;
+ }
+}
+
+/* check if sysinfo is complete, change to RACH state */
+static int new_sysinfo(void)
+{
+ struct gsm48_sysinfo *s = &sysinfo;
+
+ /* restart timer */
+ start_timer(READ_WAIT);
+
+ /* mandatory */
+ if (!s->si1 || !s->si2 || !s->si3 || !s->si4) {
+ LOGP(DRR, LOGL_INFO, "not all mandatory SI received\n");
+ return 0;
+ }
+
+ /* extended band */
+ if (s->nb_ext_ind_si2 && !s->si2bis) {
+ LOGP(DRR, LOGL_INFO, "extended ba, but si2bis not received\n");
+ return 0;
+ }
+
+ /* 2ter */
+ if (s->si2ter_ind && !s->si2ter) {
+ LOGP(DRR, LOGL_INFO, "si2ter_ind, but si2ter not received\n");
+ return 0;
+ }
+
+ LOGP(DRR, LOGL_INFO, "Sysinfo complete\n");
+
+ stop_timer();
+
+ rach_count = 0;
+ start_rach();
+
+ return 0;
+}
+
+/* receive BCCH at RR layer */
+static int bcch(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_sysinfo *s = &sysinfo;
+ struct gsm48_system_information_type_header *sih = msgb_l3(msg);
+ uint8_t ccch_mode;
+
+ if (msgb_l3len(msg) != 23) {
+ LOGP(DRR, LOGL_NOTICE, "Invalid BCCH message length\n");
+ return -EINVAL;
+ }
+ switch (sih->system_information) {
+ case GSM48_MT_RR_SYSINFO_1:
+ if (!memcmp(sih, s->si1_msg, sizeof(s->si1_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 1\n");
+ gsm48_decode_sysinfo1(s,
+ (struct gsm48_system_information_type_1 *) sih,
+ msgb_l3len(msg));
+ return new_sysinfo();
+ case GSM48_MT_RR_SYSINFO_2:
+ if (!memcmp(sih, s->si2_msg, sizeof(s->si2_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2\n");
+ gsm48_decode_sysinfo2(s,
+ (struct gsm48_system_information_type_2 *) sih,
+ msgb_l3len(msg));
+ return new_sysinfo();
+ case GSM48_MT_RR_SYSINFO_2bis:
+ if (!memcmp(sih, s->si2b_msg, sizeof(s->si2b_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2bis\n");
+ gsm48_decode_sysinfo2bis(s,
+ (struct gsm48_system_information_type_2bis *) sih,
+ msgb_l3len(msg));
+ return new_sysinfo();
+ case GSM48_MT_RR_SYSINFO_2ter:
+ if (!memcmp(sih, s->si2t_msg, sizeof(s->si2t_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2ter\n");
+ gsm48_decode_sysinfo2ter(s,
+ (struct gsm48_system_information_type_2ter *) sih,
+ msgb_l3len(msg));
+ return new_sysinfo();
+ case GSM48_MT_RR_SYSINFO_3:
+ if (!memcmp(sih, s->si3_msg, sizeof(s->si3_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 3\n");
+ gsm48_decode_sysinfo3(s,
+ (struct gsm48_system_information_type_3 *) sih,
+ msgb_l3len(msg));
+ ccch_mode = (s->ccch_conf == 1) ? CCCH_MODE_COMBINED :
+ CCCH_MODE_NON_COMBINED;
+ LOGP(DRR, LOGL_INFO, "Changing CCCH_MODE to %d\n", ccch_mode);
+ l1ctl_tx_ccch_mode_req(ms, ccch_mode);
+ return new_sysinfo();
+ case GSM48_MT_RR_SYSINFO_4:
+ if (!memcmp(sih, s->si4_msg, sizeof(s->si4_msg)))
+ return 0;
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 4\n");
+ gsm48_decode_sysinfo4(s,
+ (struct gsm48_system_information_type_4 *) sih,
+ msgb_l3len(msg));
+ return new_sysinfo();
+ default:
+ return -EINVAL;
+ }
+}
+
+static int unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ struct tlv_parsed tv;
+ uint8_t ch_type, ch_subch, ch_ts;
+
+ DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
+ rllh->chan_nr, rllh->link_id);
+
+ rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
+ if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
+ DEBUGP(DRSL, "UNIT_DATA_IND without L3 INFO ?!?\n");
+ return -EIO;
+ }
+ msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
+
+ if (state != SCAN_STATE_READ && state != SCAN_STATE_RACH) {
+ return -EINVAL;
+ }
+
+ rsl_dec_chan_nr(rllh->chan_nr, &ch_type, &ch_subch, &ch_ts);
+ switch (ch_type) {
+ case RSL_CHAN_PCH_AGCH:
+ return pch_agch(ms, msg);
+ case RSL_CHAN_BCCH:
+ return bcch(ms, msg);
+#if 0
+ case RSL_CHAN_Bm_ACCHs:
+ case RSL_CHAN_Lm_ACCHs:
+ case RSL_CHAN_SDCCH4_ACCH:
+ case RSL_CHAN_SDCCH8_ACCH:
+ return rx_acch(ms, msg);
+#endif
+ default:
+ LOGP(DRSL, LOGL_NOTICE, "RSL with chan_nr 0x%02x unknown.\n",
+ rllh->chan_nr);
+ return -EINVAL;
+ }
+}
+
+static int rcv_rll(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ int msg_type = rllh->c.msg_type;
+
+ if (msg_type == RSL_MT_UNIT_DATA_IND) {
+ unit_data_ind(ms, msg);
+ } else
+ LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
+
+ msgb_free(msg);
+
+ return 0;
+}
+
+int chan_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
+ struct gsm48_req_ref *ref = (struct gsm48_req_ref *) (ch->data + 1);
+
+ if (msgb_l2len(msg) < sizeof(*ch) + sizeof(*ref)) {
+ LOGP(DRR, LOGL_ERROR, "CHAN_CNF too slort\n");
+ return -EINVAL;
+ }
+
+ rach_ref.valid = 1;
+ rach_ref.t1 = ref->t1;
+ rach_ref.t2 = ref->t2;
+ rach_ref.t3 = ref->t3_low | (ref->t3_high << 3);
+
+ return 0;
+}
+
+static int rcv_cch(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
+ int msg_type = ch->c.msg_type;
+ int rc;
+
+ LOGP(DRSL, LOGL_INFO, "Received '%s' from layer1\n",
+ rsl_msg_name(msg_type));
+
+ if (state == SCAN_STATE_RACH && msg_type == RSL_MT_CHAN_CONF) {
+ rc = chan_conf(ms, msg);
+ msgb_free(msg);
+ return rc;
+ }
+
+ LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
+ msgb_free(msg);
+ return 0;
+}
+
+static int rcv_rsl(struct msgb *msg, struct lapdm_entity *le, void *l3ctx)
+{
+ struct osmocom_ms *ms = l3ctx;
+ struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
+ int rc = 0;
+
+ switch (rslh->msg_discr & 0xfe) {
+ case ABIS_RSL_MDISC_RLL:
+ rc = rcv_rll(ms, msg);
+ break;
+ case ABIS_RSL_MDISC_COM_CHAN:
+ rc = rcv_cch(ms, msg);
+ break;
+ default:
+ LOGP(DRSL, LOGL_NOTICE, "unknown RSLms msg_discr 0x%02x\n",
+ rslh->msg_discr);
+ msgb_free(msg);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+int scan_init(struct osmocom_ms *_ms)
+{
+ ms = _ms;
+ osmo_signal_register_handler(SS_L1CTL, &signal_cb, NULL);
+ memset(&timer, 0, sizeof(timer));
+ lapdm_channel_set_l3(&ms->lapdm_channel, &rcv_rsl, ms);
+ g.enable = 1;
+ osmo_gps_init();
+ if (osmo_gps_open())
+ g.enable = 0;
+
+ if (!strcmp(logname, "-"))
+ logfp = stdout;
+ else
+ logfp = fopen(logname, "a");
+ if (!logfp) {
+ fprintf(stderr, "Failed to open logfile '%s'\n", logname);
+ scan_exit();
+ return -errno;
+ }
+ LOGP(DSUM, LOGL_INFO, "Scanner initialized\n");
+
+ return 0;
+}
+
+int scan_exit(void)
+{
+ LOGP(DSUM, LOGL_INFO, "Scanner exit\n");
+ if (g.valid)
+ osmo_gps_close();
+ if (logfp)
+ fclose(logfp);
+ osmo_signal_unregister_handler(SS_L1CTL, &signal_cb, NULL);
+ stop_timer();
+
+ return 0;
+}
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index b/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index
index 627f3fd..77b19d8 100644
--- a/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index
Binary files differ
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.root/6.tree b/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.root/6.tree
new file mode 100644
index 0000000..19535d3
--- /dev/null
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.root/6.tree
Binary files differ
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources b/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources
index a98b0ee..2437e0c 100644
--- a/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources
Binary files differ
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs b/Src/eclipse/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs
index 94ae83d..33601d8 100644
--- a/Src/eclipse/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs
@@ -1,7 +1,7 @@
-#Tue Feb 28 12:14:41 CET 2012
+#Tue Feb 28 12:46:40 CET 2012
eclipse.preferences.version=1
TASKS_FILTERS_MIGRATE=true
tipsAndTricks=true
-platformState=1330425960816
+platformState=1330428858162
quickStart=true
PROBLEMS_FILTERS_MIGRATE=true
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/.workspace/2012/2/9/refactorings.history b/Src/eclipse/.metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/.workspace/2012/2/9/refactorings.history
new file mode 100644
index 0000000..9cf3766
--- /dev/null
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/.workspace/2012/2/9/refactorings.history
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<session version="1.0">&#x0A;<refactoring comment="Delete 2 resources" deleteContents="false" description="Delete 2 resources" element1="/CatcherLib" element2="/PyCatcher" flags="7" id="org.eclipse.ltk.core.refactoring.delete.resources" resources="2" stamp="1330426031197"/>&#x0A;<refactoring comment="Delete resource &apos;CatcherDriver&apos;" deleteContents="false" description="Delete resource &apos;CatcherDriver&apos;" element1="/CatcherDriver" flags="7" id="org.eclipse.ltk.core.refactoring.delete.resources" resources="1" stamp="1330429654807"/>
+</session> \ No newline at end of file
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/.workspace/2012/2/9/refactorings.index b/Src/eclipse/.metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/.workspace/2012/2/9/refactorings.index
new file mode 100644
index 0000000..4a8774b
--- /dev/null
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.ltk.core.refactoring/.refactorings/.workspace/2012/2/9/refactorings.index
@@ -0,0 +1,2 @@
+1330426031197 Delete 2 resources
+1330429654807 Delete resource 'CatcherDriver'
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.ltk.ui.refactoring/dialog_settings.xml b/Src/eclipse/.metadata/.plugins/org.eclipse.ltk.ui.refactoring/dialog_settings.xml
new file mode 100644
index 0000000..27eb404
--- /dev/null
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.ltk.ui.refactoring/dialog_settings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<section name="Workbench">
+ <section name="RefactoringWizard.preview">
+ <item value="400" key="height"/>
+ <item value="600" key="width"/>
+ </section>
+</section>
diff --git a/Src/eclipse/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml b/Src/eclipse/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml
index 50a2f47..8a7667a 100644
--- a/Src/eclipse/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml
+++ b/Src/eclipse/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<workbench progressCount="4" version="2.0">
+<workbench progressCount="17" version="2.0">
<workbenchAdvisor/>
<window height="1081" maximized="true" width="1922" x="1280" y="0">
<fastViewData fastViewLocation="1024"/>
@@ -41,7 +41,7 @@
</editorArea>
<editor activePart="true" focus="true" id="org.eclipse.cdt.ui.editor.CEditor" name="catcher.c" partName="catcher.c" path="/home/tom/Documents/imsi-catcher-detection/Src/osmolib/src/host/layer23/src/misc/catcher.c" title="catcher.c" tooltip="CatcherDriver/host/layer23/src/misc/catcher.c" workbook="DefaultEditorWorkbook">
<input factoryID="org.eclipse.ui.part.FileEditorInputFactory" path="/CatcherDriver/host/layer23/src/misc/catcher.c"/>
-<editorState selectionHorizontalPixel="0" selectionLength="0" selectionOffset="4332" selectionTopPixel="3084"/>
+<editorState selectionHorizontalPixel="0" selectionLength="0" selectionOffset="14686" selectionTopPixel="10657"/>
</editor>
<editor id="org.eclipse.cdt.ui.editor.CEditor" name="sysinfo.h" partName="sysinfo.h" path="/home/tom/Documents/imsi-catcher-detection/Src/osmolib/src/host/layer23/include/osmocom/bb/common/sysinfo.h" title="sysinfo.h" tooltip="CatcherDriver/host/layer23/include/osmocom/bb/common/sysinfo.h" workbook="DefaultEditorWorkbook">
<input factoryID="org.eclipse.ui.part.FileEditorInputFactory" path="/CatcherDriver/host/layer23/include/osmocom/bb/common/sysinfo.h"/>
@@ -92,8 +92,8 @@
<view id="org.eclipse.ui.views.ResourceNavigator" partName="Navigator">
<viewState LINK_NAVIGATOR_TO_EDITOR="0" sorter="1">
<filters>
-<filter element=".*" isEnabled="false"/>
<filter element="*.class" isEnabled="true"/>
+<filter element=".*" isEnabled="false"/>
</filters>
<expanded>
<element path="/CatcherDriver"/>
diff --git a/Src/osmolib/include/l1ctl_proto.h b/Src/osmolib/include/l1ctl_proto.h
index c1220d6..4b9540e 100644
--- a/Src/osmolib/include/l1ctl_proto.h
+++ b/Src/osmolib/include/l1ctl_proto.h
@@ -283,12 +283,15 @@ 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 */
diff --git a/Src/osmolib/src/.cproject b/Src/osmolib/src/.cproject
new file mode 100644
index 0000000..f23e408
--- /dev/null
+++ b/Src/osmolib/src/.cproject
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?>
+
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+<storageModule moduleId="org.eclipse.cdt.core.settings">
+<cconfiguration id="0.1568089738">
+<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.1568089738" moduleId="org.eclipse.cdt.core.settings" name="Default">
+<externalSettings/>
+<extensions>
+<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+<extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+</extensions>
+</storageModule>
+<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+<configuration artifactName="catcher" buildProperties="" description="" id="0.1568089738" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg">
+<folderInfo id="0.1568089738." name="/" resourcePath="">
+<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.356512209" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
+<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.356512209.15336239" name=""/>
+<builder id="org.eclipse.cdt.build.core.settings.default.builder.1829941210" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
+<tool id="org.eclipse.cdt.build.core.settings.holder.libs.1321586476" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
+<tool id="org.eclipse.cdt.build.core.settings.holder.187679752" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
+<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.10655658" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
+</tool>
+<tool id="org.eclipse.cdt.build.core.settings.holder.2059651325" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
+<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.2069892859" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
+</tool>
+<tool id="org.eclipse.cdt.build.core.settings.holder.7400946" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
+<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1717505204" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
+</tool>
+</toolChain>
+</folderInfo>
+</configuration>
+</storageModule>
+<storageModule moduleId="scannerConfiguration">
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="makefileGenerator">
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<scannerConfigBuildInfo instanceId="0.1568089738">
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="makefileGenerator">
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+</scannerConfigBuildInfo>
+</storageModule>
+<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+</cconfiguration>
+</storageModule>
+<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+<project id="catcher.null.2014221762" name="catcher"/>
+</storageModule>
+</cproject>
diff --git a/Src/osmolib/src/.project b/Src/osmolib/src/.project
new file mode 100644
index 0000000..2b3b054
--- /dev/null
+++ b/Src/osmolib/src/.project
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>catcher</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <triggers>clean,full,incremental,</triggers>
+ <arguments>
+ <dictionary>
+ <key>?name?</key>
+ <value></value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.append_environment</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.autoBuildTarget</key>
+ <value>all</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.buildArguments</key>
+ <value></value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.buildCommand</key>
+ <value>make</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
+ <value>clean</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.contents</key>
+ <value>org.eclipse.cdt.make.core.activeConfigSettings</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+ <value>false</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.enableFullBuild</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.fullBuildTarget</key>
+ <value>all</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.stopOnError</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+ <value>true</value>
+ </dictionary>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ </natures>
+</projectDescription>
diff --git a/Src/osmolib/src/host/calypso_pll/pll.pl b/Src/osmolib/src/host/calypso_pll/pll.pl
index 52c9131..52c9131 100644..100755
--- a/Src/osmolib/src/host/calypso_pll/pll.pl
+++ b/Src/osmolib/src/host/calypso_pll/pll.pl
diff --git a/Src/osmolib/src/host/fb_tools/bdf_to_c.py b/Src/osmolib/src/host/fb_tools/bdf_to_c.py
new file mode 100755
index 0000000..2a3a644
--- /dev/null
+++ b/Src/osmolib/src/host/fb_tools/bdf_to_c.py
@@ -0,0 +1,294 @@
+#!/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
+import string
+
+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/osmolib/src/host/gsmmap/git-version-gen b/Src/osmolib/src/host/gsmmap/git-version-gen
index 652fac6..652fac6 100644..100755
--- a/Src/osmolib/src/host/gsmmap/git-version-gen
+++ b/Src/osmolib/src/host/gsmmap/git-version-gen
diff --git a/Src/osmolib/src/host/layer23/include/osmocom/bb/common/Makefile.am b/Src/osmolib/src/host/layer23/include/osmocom/bb/common/Makefile.am
index 26e63cf..945c73d 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/common/Makefile.am
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/common/Makefile.am
@@ -1,2 +1,2 @@
-noinst_HEADERS = l1ctl.h l1l2_interface.h l23_app.h lapdm.h logging.h \
+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/osmolib/src/host/layer23/include/osmocom/bb/common/logging.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/common/logging.h
index 554b767..3efa57a 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/common/logging.h
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/common/logging.h
@@ -12,11 +12,11 @@ enum {
DNB,
DMM,
DCC,
+ DSS,
DSMS,
DMNCC,
DMEAS,
DPAG,
- DLAPDM,
DL1C,
DSAP,
DSUM,
diff --git a/Src/osmolib/src/host/layer23/include/osmocom/bb/common/networks.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/common/networks.h
index e681216..d34f316 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/common/networks.h
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/common/networks.h
@@ -10,7 +10,7 @@ struct gsm_networks {
};
int gsm_match_mcc(uint16_t mcc, char *imsi);
-int gsm_match_mnc(uint16_t mcc, uint8_t mnc, 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);
diff --git a/Src/osmolib/src/host/layer23/include/osmocom/bb/common/osmocom_data.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
index 8f15007..ab7c250 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
@@ -11,7 +11,7 @@ struct osmocom_ms;
#include <osmocom/bb/mobile/support.h>
#include <osmocom/bb/mobile/settings.h>
#include <osmocom/bb/mobile/subscriber.h>
-#include <osmocom/bb/common/lapdm.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>
diff --git a/Src/osmolib/src/host/layer23/include/osmocom/bb/common/sim.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/common/sim.h
index a676b92..95d2147 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/common/sim.h
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/common/sim.h
@@ -266,6 +266,16 @@ struct gsm1111_ef_adn {
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);
diff --git a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/Makefile.am b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/Makefile.am
index 65b7ce7..b58b952 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/Makefile.am
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/Makefile.am
@@ -1,2 +1,3 @@
-noinst_HEADERS = gsm322.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
+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/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm411_sms.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm411_sms.h
new file mode 100644
index 0000000..d14e6db
--- /dev/null
+++ b/Src/osmolib/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/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm480_ss.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm480_ss.h
new file mode 100644
index 0000000..ecd778e
--- /dev/null
+++ b/Src/osmolib/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/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
index afdcf02..fb62aae 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
@@ -58,6 +58,7 @@ 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 */
};
@@ -193,6 +194,9 @@ struct gsm48_mmlayer {
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 */
@@ -204,6 +208,7 @@ struct gsm48_mm_conn {
uint32_t ref; /* reference to trans */
uint8_t protocol;
uint8_t transaction_id;
+ uint8_t sapi;
int state;
};
@@ -221,7 +226,7 @@ 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 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[];
diff --git a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h
index 1af09f4..b7280fb 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h
@@ -54,6 +54,7 @@
/* GSM 04.08 RR-SAP header */
struct gsm48_rr_hdr {
uint32_t msg_type; /* RR-* primitive */
+ uint8_t sapi;
uint8_t cause;
};
@@ -63,6 +64,12 @@ struct gsm48_rr_hdr {
#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
@@ -79,7 +86,6 @@ struct gsm48_rr_cd {
uint8_t maio;
uint8_t hsn;
uint8_t chan_nr; /* type, slot, sub slot */
- uint8_t link_id;
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 */
@@ -133,6 +139,7 @@ struct gsm48_rrlayer {
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 */
@@ -175,6 +182,10 @@ struct gsm48_rrlayer {
/* audio flow */
uint8_t audio_mode;
+
+ /* sapi 3 */
+ uint8_t sapi3_state;
+ uint8_t sapi3_link_id;
};
const char *get_rr_name(int value);
diff --git a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/mncc.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/mncc.h
index 1d7f779..cad1883 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/mncc.h
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/mncc.h
@@ -130,11 +130,11 @@ struct gsm_call {
struct gsm_mncc {
/* context based information */
- u_int32_t msg_type;
- u_int32_t callref;
+ uint32_t msg_type;
+ uint32_t callref;
/* which fields are present */
- u_int32_t fields;
+ uint32_t fields;
/* data derived informations (MNCC_F_ based) */
struct gsm_mncc_bearer_cap bearer_cap;
@@ -161,12 +161,13 @@ struct gsm_mncc {
int emergency;
char imsi[16];
+ unsigned char lchan_type;
unsigned char lchan_mode;
};
struct gsm_data_frame {
- u_int32_t msg_type;
- u_int32_t callref;
+ uint32_t msg_type;
+ uint32_t callref;
unsigned char data[0];
};
diff --git a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/settings.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/settings.h
index cd1b800..6d44696 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/settings.h
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/settings.h
@@ -23,6 +23,9 @@ struct gsm_settings {
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;
@@ -84,6 +87,7 @@ struct gsm_settings {
/* radio */
uint16_t dsc_max;
+ uint8_t force_rekey;
/* dialing */
struct llist_head abbrev;
diff --git a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/subscriber.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
index cc0cfac..3e50e29 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
@@ -77,6 +77,9 @@ struct gsm_subscriber {
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);
@@ -102,6 +105,7 @@ int gsm_subscr_dump_forbidden_plmn(struct osmocom_ms *ms,
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/osmolib/src/host/layer23/include/osmocom/bb/mobile/transaction.h b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/transaction.h
index aa62f46..8c06d5d 100644
--- a/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/transaction.h
+++ b/Src/osmolib/src/host/layer23/include/osmocom/bb/mobile/transaction.h
@@ -2,6 +2,8 @@
#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 {
@@ -38,18 +40,21 @@ struct gsm_trans {
struct osmo_timer_list timer;
struct gsm_mncc msg; /* stores setup/disconnect/release message */
} cc;
-#if 0
struct {
- uint8_t link_id; /* RSL Link ID to be used for this trans */
- int is_mt; /* is this a MO (0) or MT (1) transfer */
- enum gsm411_cp_state cp_state;
- struct osmo_timer_list cp_timer;
+ /* 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 */
- enum gsm411_rp_state rp_state;
+ struct gsm411_smc_inst smc_inst;
+ struct gsm411_smr_inst smr_inst;
struct gsm_sms *sms;
} sms;
-#endif
};
};
diff --git a/Src/osmolib/src/host/layer23/src/common/Makefile.am b/Src/osmolib/src/host/layer23/src/common/Makefile.am
index aca2eb4..73a0fc9 100644
--- a/Src/osmolib/src/host/layer23/src/common/Makefile.am
+++ b/Src/osmolib/src/host/layer23/src/common/Makefile.am
@@ -2,5 +2,5 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS)
noinst_LIBRARIES = liblayer23.a
-liblayer23_a_SOURCES = l1ctl.c l1l2_interface.c sap_interface.c lapdm.c \
+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/osmolib/src/host/layer23/src/common/gps.c b/Src/osmolib/src/host/layer23/src/common/gps.c
index 38aae2c..e9aaa97 100644
--- a/Src/osmolib/src/host/layer23/src/common/gps.c
+++ b/Src/osmolib/src/host/layer23/src/common/gps.c
@@ -56,7 +56,12 @@ static struct osmo_fd gps_bfd;
#ifdef _HAVE_GPSD
-static struct gps_data_t* gdata;
+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)
{
@@ -69,9 +74,15 @@ int osmo_gpsd_cb(struct osmo_fd *bfd, unsigned int what)
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))
@@ -111,7 +122,14 @@ int osmo_gpsd_open(void)
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;
@@ -139,6 +157,9 @@ void osmo_gpsd_close(void)
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' */
}
diff --git a/Src/osmolib/src/host/layer23/src/common/l1ctl.c b/Src/osmolib/src/host/layer23/src/common/l1ctl.c
index e3ab4c9..f998ebc 100644
--- a/Src/osmolib/src/host/layer23/src/common/l1ctl.c
+++ b/Src/osmolib/src/host/layer23/src/common/l1ctl.c
@@ -44,7 +44,7 @@
#include <osmocom/bb/common/l1ctl.h>
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/l1l2_interface.h>
-#include <osmocom/bb/common/lapdm.h>
+#include <osmocom/gsm/lapdm.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/codec/codec.h>
diff --git a/Src/osmolib/src/host/layer23/src/common/l1ctl_lapdm_glue.c b/Src/osmolib/src/host/layer23/src/common/l1ctl_lapdm_glue.c
index db071a3..0b2a8ed 100644
--- a/Src/osmolib/src/host/layer23/src/common/l1ctl_lapdm_glue.c
+++ b/Src/osmolib/src/host/layer23/src/common/l1ctl_lapdm_glue.c
@@ -27,7 +27,7 @@
#include <osmocom/gsm/prim.h>
#include <osmocom/bb/common/l1ctl.h>
-#include <osmocom/bb/common/lapdm.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)
diff --git a/Src/osmolib/src/host/layer23/src/common/l1l2_interface.c b/Src/osmolib/src/host/layer23/src/common/l1l2_interface.c
index abaa64f..d89995d 100644
--- a/Src/osmolib/src/host/layer23/src/common/l1l2_interface.c
+++ b/Src/osmolib/src/host/layer23/src/common/l1l2_interface.c
@@ -45,7 +45,7 @@
static int layer2_read(struct osmo_fd *fd)
{
struct msgb *msg;
- u_int16_t len;
+ uint16_t len;
int rc;
msg = msgb_alloc_headroom(GSM_L2_LENGTH+GSM_L2_HEADROOM, GSM_L2_HEADROOM, "Layer2");
@@ -150,6 +150,7 @@ int layer2_close(struct osmocom_ms *ms)
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;
}
diff --git a/Src/osmolib/src/host/layer23/src/common/logging.c b/Src/osmolib/src/host/layer23/src/common/logging.c
index 82ce914..d8fd076 100644
--- a/Src/osmolib/src/host/layer23/src/common/logging.c
+++ b/Src/osmolib/src/host/layer23/src/common/logging.c
@@ -68,6 +68,12 @@ static const struct log_info_cat default_categories[] = {
.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",
@@ -91,11 +97,6 @@ static const struct log_info_cat default_categories[] = {
.color = "\033[33m",
.enabled = 1, .loglevel = LOGL_DEBUG,
},
- [DLAPDM] = {
- .name = "DLAPDM",
- .description = "LAPDm Layer2",
- .enabled = 1, .loglevel = LOGL_NOTICE,
- },
[DL1C] = {
.name = "DL1C",
.description = "Layer 1 Control",
diff --git a/Src/osmolib/src/host/layer23/src/common/main.c b/Src/osmolib/src/host/layer23/src/common/main.c
index 751f95e..eb47b26 100644
--- a/Src/osmolib/src/host/layer23/src/common/main.c
+++ b/Src/osmolib/src/host/layer23/src/common/main.c
@@ -26,7 +26,6 @@
#include <osmocom/bb/common/l1l2_interface.h>
#include <osmocom/bb/common/sap_interface.h>
#include <osmocom/bb/misc/layer3.h>
-#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/l23_app.h>
diff --git a/Src/osmolib/src/host/layer23/src/common/networks.c b/Src/osmolib/src/host/layer23/src/common/networks.c
index 63221f0..40b70a1 100644
--- a/Src/osmolib/src/host/layer23/src/common/networks.c
+++ b/Src/osmolib/src/host/layer23/src/common/networks.c
@@ -1787,7 +1787,7 @@ int gsm_match_mcc(uint16_t mcc, char *imsi)
}
/* GSM 03.22 Annex A */
-int gsm_match_mnc(uint16_t mcc, uint8_t mnc, char *imsi)
+int gsm_match_mnc(uint16_t mcc, uint16_t mnc, char *imsi)
{
uint16_t sim_mnc;
diff --git a/Src/osmolib/src/host/layer23/src/common/sap_interface.c b/Src/osmolib/src/host/layer23/src/common/sap_interface.c
index fd5cdc3..1dad748 100644
--- a/Src/osmolib/src/host/layer23/src/common/sap_interface.c
+++ b/Src/osmolib/src/host/layer23/src/common/sap_interface.c
@@ -45,7 +45,7 @@
static int sap_read(struct osmo_fd *fd)
{
struct msgb *msg;
- u_int16_t len;
+ uint16_t len;
int rc;
struct osmocom_ms *ms = (struct osmocom_ms *) fd->data;
@@ -150,6 +150,7 @@ int sap_close(struct osmocom_ms *ms)
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;
}
diff --git a/Src/osmolib/src/host/layer23/src/common/sim.c b/Src/osmolib/src/host/layer23/src/common/sim.c
index 3aca693..8c89cf0 100644
--- a/Src/osmolib/src/host/layer23/src/common/sim.c
+++ b/Src/osmolib/src/host/layer23/src/common/sim.c
@@ -1045,8 +1045,25 @@ int sim_apdu_resp(struct osmocom_ms *ms, struct msgb *msg)
ntohs(ef->file_id), sim->file);
goto sim_error;
}
- /* get length of file */
- ef_len = ntohs(ef->file_size);
+ /* 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) {
diff --git a/Src/osmolib/src/host/layer23/src/misc/app_bcch_scan.c b/Src/osmolib/src/host/layer23/src/misc/app_bcch_scan.c
index 4c31f1a..7b21ed7 100644
--- a/Src/osmolib/src/host/layer23/src/misc/app_bcch_scan.c
+++ b/Src/osmolib/src/host/layer23/src/misc/app_bcch_scan.c
@@ -23,7 +23,6 @@
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/l1ctl.h>
-#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/l23_app.h>
#include <osmocom/bb/misc/layer3.h>
diff --git a/Src/osmolib/src/host/layer23/src/misc/app_cbch_sniff.c b/Src/osmolib/src/host/layer23/src/misc/app_cbch_sniff.c
index fb043db..2f45e48 100644
--- a/Src/osmolib/src/host/layer23/src/misc/app_cbch_sniff.c
+++ b/Src/osmolib/src/host/layer23/src/misc/app_cbch_sniff.c
@@ -24,7 +24,6 @@
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/l1ctl.h>
-#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/l23_app.h>
#include <osmocom/bb/misc/layer3.h>
diff --git a/Src/osmolib/src/host/layer23/src/misc/app_ccch_scan.c b/Src/osmolib/src/host/layer23/src/misc/app_ccch_scan.c
index 2f60505..d301b7b 100644
--- a/Src/osmolib/src/host/layer23/src/misc/app_ccch_scan.c
+++ b/Src/osmolib/src/host/layer23/src/misc/app_ccch_scan.c
@@ -33,7 +33,6 @@
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/bb/common/logging.h>
-#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/misc/rslms.h>
#include <osmocom/bb/misc/layer3.h>
#include <osmocom/bb/common/osmocom_data.h>
@@ -162,7 +161,8 @@ static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data)
case GSM48_MT_RR_SYSINFO_5ter:
break;
default:
- fprintf(stderr, "\tUnknown SI");
+ LOGP(DRR, LOGL_ERROR, "Unknown SI: %d\n",
+ si_hdr->system_information);
break;
};
}
@@ -352,7 +352,7 @@ static int gsm48_rx_paging_p2(struct msgb *msg, struct osmocom_ms *ms)
chan_need(pag->cneed1), pag->tmsi1);
LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to TMSI M(0x%x) \n",
pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed1), pag->tmsi2);
+ chan_need(pag->cneed2), pag->tmsi2);
/* no optional element */
if (msgb_l3len(msg) < sizeof(*pag) + 3)
@@ -380,6 +380,32 @@ static int gsm48_rx_paging_p2(struct msgb *msg, struct osmocom_ms *ms)
return 0;
}
+static int gsm48_rx_paging_p3(struct msgb *msg, struct osmocom_ms *ms)
+{
+ struct gsm48_paging3 *pag;
+
+ if (msgb_l3len(msg) < sizeof(*pag)) {
+ LOGP(DRR, LOGL_ERROR, "Paging3 message is too small.\n");
+ return -1;
+ }
+
+ pag = msgb_l3(msg);
+ LOGP(DRR, LOGL_NOTICE, "Paging1: %s chan %s to TMSI M(0x%x) \n",
+ pag_print_mode(pag->pag_mode),
+ chan_need(pag->cneed1), pag->tmsi1);
+ LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to TMSI M(0x%x) \n",
+ pag_print_mode(pag->pag_mode),
+ chan_need(pag->cneed2), pag->tmsi2);
+ LOGP(DRR, LOGL_NOTICE, "Paging3: %s chan %s to TMSI M(0x%x) \n",
+ pag_print_mode(pag->pag_mode),
+ "n/a ", pag->tmsi3);
+ LOGP(DRR, LOGL_NOTICE, "Paging4: %s chan %s to TMSI M(0x%x) \n",
+ pag_print_mode(pag->pag_mode),
+ "n/a ", pag->tmsi4);
+
+ return 0;
+}
+
int gsm48_rx_ccch(struct msgb *msg, struct osmocom_ms *ms)
{
struct gsm48_system_information_type_header *sih = msgb_l3(msg);
@@ -396,7 +422,7 @@ int gsm48_rx_ccch(struct msgb *msg, struct osmocom_ms *ms)
gsm48_rx_paging_p2(msg, ms);
break;
case GSM48_MT_RR_PAG_REQ_3:
- LOGP(DRR, LOGL_ERROR, "PAGING of type 3 is not implemented.\n");
+ gsm48_rx_paging_p3(msg, ms);
break;
case GSM48_MT_RR_IMM_ASS:
gsm48_rx_imm_ass(msg, ms);
diff --git a/Src/osmolib/src/host/layer23/src/misc/app_echo_test.c b/Src/osmolib/src/host/layer23/src/misc/app_echo_test.c
index 3d937d2..3a0ee0f 100644
--- a/Src/osmolib/src/host/layer23/src/misc/app_echo_test.c
+++ b/Src/osmolib/src/host/layer23/src/misc/app_echo_test.c
@@ -23,7 +23,6 @@
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/l1ctl.h>
-#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/l23_app.h>
#include <osmocom/bb/misc/layer3.h>
diff --git a/Src/osmolib/src/host/layer23/src/misc/bcch_scan.c b/Src/osmolib/src/host/layer23/src/misc/bcch_scan.c
index ddd0eea..4636c9a 100644
--- a/Src/osmolib/src/host/layer23/src/misc/bcch_scan.c
+++ b/Src/osmolib/src/host/layer23/src/misc/bcch_scan.c
@@ -40,7 +40,6 @@
#include <osmocom/bb/common/l1ctl.h>
#include <osmocom/bb/common/osmocom_data.h>
-#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/common/logging.h>
/* somewhere in 05.08 */
@@ -275,7 +274,7 @@ static int bscan_sig_cb(unsigned int subsys, unsigned int signal,
rc = get_next_arfcn(&fps);
if (rc < 0) {
fps.state = BSCAN_S_DONE;
- return;
+ return 0;
}
_cinfo_start_arfcn(rc);
break;
diff --git a/Src/osmolib/src/host/layer23/src/misc/catcher b/Src/osmolib/src/host/layer23/src/misc/catcher
index 647207e..ef3d795 100644..100755
--- a/Src/osmolib/src/host/layer23/src/misc/catcher
+++ b/Src/osmolib/src/host/layer23/src/misc/catcher
Binary files differ
diff --git a/Src/osmolib/src/host/layer23/src/misc/catcher.c b/Src/osmolib/src/host/layer23/src/misc/catcher.c
index b97be3d..03bf442 100644
--- a/Src/osmolib/src/host/layer23/src/misc/catcher.c
+++ b/Src/osmolib/src/host/layer23/src/misc/catcher.c
@@ -39,7 +39,6 @@
#include <osmocom/bb/common/l1ctl.h>
#include <osmocom/bb/common/osmocom_data.h>
-#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/networks.h>
#include <osmocom/bb/common/gps.h>
@@ -190,14 +189,16 @@ static void log_sysinfo(void)
// arfcn, gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc),
// gsm_get_mcc(s->mcc), gsm_get_mnc(s->mcc, s->mnc), ta_str);
LOGFILE("[SysInfo]\n");
- LOGFILE("country %s\n", gsm_get_mcc(s->mcc))
- LOGFILE("provider %s\n", gsm_get_mnc(s->mcc, s->mnc))
- LOGFILE("arfcn %d\n", s->arfcn);
+ LOGFILE("Country: %s\n", gsm_get_mcc(s->mcc));
+ LOGFILE("Provider: %s\n", gsm_get_mnc(s->mcc, s->mnc));
+ LOGFILE("ARFCN: %d\n", s->arfcn);
+ LOGFILE("Cell_ID: %d\n", s->cell_id);
+ LOGFILE("LAC: %d\n", s->lac);
//log_time();
//log_gps();
- //LOGFILE("bsic %d,%d\n", s->bsic >> 3, s->bsic & 7);
+ LOGFILE("BSIC: %d,%d\n", s->bsic >> 3, s->bsic & 7);
rxlev = meas->rxlev / meas->frames - 110;
- LOGFILE("rxlev %d\n", rxlev);
+ LOGFILE("rxlev: %d\n", rxlev);
//if (s->si1)
// log_frame("si1", s->si1_msg);
if (s->si2)
diff --git a/Src/osmolib/src/host/layer23/src/misc/cell_log.c b/Src/osmolib/src/host/layer23/src/misc/cell_log.c
index 1a9c33c..aa964f4 100644
--- a/Src/osmolib/src/host/layer23/src/misc/cell_log.c
+++ b/Src/osmolib/src/host/layer23/src/misc/cell_log.c
@@ -39,7 +39,6 @@
#include <osmocom/bb/common/l1ctl.h>
#include <osmocom/bb/common/osmocom_data.h>
-#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/networks.h>
#include <osmocom/bb/common/gps.h>
diff --git a/Src/osmolib/src/host/layer23/src/misc/rslms.c b/Src/osmolib/src/host/layer23/src/misc/rslms.c
index 68956f9..455e663 100644
--- a/Src/osmolib/src/host/layer23/src/misc/rslms.c
+++ b/Src/osmolib/src/host/layer23/src/misc/rslms.c
@@ -30,7 +30,7 @@
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/bb/common/logging.h>
-#include <osmocom/bb/common/lapdm.h>
+#include <osmocom/gsm/lapdm.h>
#include <osmocom/bb/misc/rslms.h>
#include <osmocom/bb/misc/layer3.h>
#include <osmocom/bb/common/osmocom_data.h>
diff --git a/Src/osmolib/src/host/layer23/src/mobile/Makefile.am b/Src/osmolib/src/host/layer23/src/mobile/Makefile.am
index 4cff9ef..f3365af 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/Makefile.am
+++ b/Src/osmolib/src/host/layer23/src/mobile/Makefile.am
@@ -3,8 +3,8 @@ AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS)
LDADD = ../common/liblayer23.a $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS)
noinst_LIBRARIES = libmobile.a
-libmobile_a_SOURCES = gsm322.c gsm48_cc.c gsm48_mm.c gsm48_rr.c \
- mnccms.c settings.c subscriber.c support.c \
+libmobile_a_SOURCES = gsm322.c gsm480_ss.c gsm411_sms.c gsm48_cc.c gsm48_mm.c \
+ gsm48_rr.c mnccms.c settings.c subscriber.c support.c \
transaction.c vty_interface.c voice.c mncc_sock.c
bin_PROGRAMS = mobile
diff --git a/Src/osmolib/src/host/layer23/src/mobile/app_mobile.c b/Src/osmolib/src/host/layer23/src/mobile/app_mobile.c
index ada9480..da388b2 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/app_mobile.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/app_mobile.c
@@ -28,10 +28,11 @@
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/l1l2_interface.h>
#include <osmocom/bb/common/l1ctl.h>
-#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/gps.h>
#include <osmocom/bb/mobile/gsm48_rr.h>
+#include <osmocom/bb/mobile/gsm480_ss.h>
+#include <osmocom/bb/mobile/gsm411_sms.h>
#include <osmocom/bb/mobile/vty.h>
#include <osmocom/bb/mobile/app_mobile.h>
#include <osmocom/bb/mobile/mncc.h>
@@ -145,6 +146,8 @@ int mobile_exit(struct osmocom_ms *ms, int force)
gsm48_rr_exit(ms);
gsm_subscr_exit(ms);
gsm48_cc_exit(ms);
+ gsm480_ss_exit(ms);
+ gsm411_sms_exit(ms);
gsm_sim_exit(ms);
lapdm_channel_exit(&ms->lapdm_channel);
@@ -168,6 +171,8 @@ int mobile_init(struct osmocom_ms *ms)
gsm_sim_init(ms);
gsm48_cc_init(ms);
+ gsm480_ss_init(ms);
+ gsm411_sms_init(ms);
gsm_voice_init(ms);
gsm_subscr_init(ms);
gsm48_rr_init(ms);
@@ -334,6 +339,8 @@ int l23_app_exit(void)
osmo_gps_close();
+ telnet_exit();
+
return 0;
}
diff --git a/Src/osmolib/src/host/layer23/src/mobile/gsm322.c b/Src/osmolib/src/host/layer23/src/mobile/gsm322.c
index 9384743..ce5e1e1 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/gsm322.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/gsm322.c
@@ -1840,10 +1840,11 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int index, uint16_t mcc,
/* loop through all scanned frequencies and select cell.
* if an index is given (arfci), we just check this cell only */
- if (index >= 0)
+ if (index >= 0) {
start = end = index;
- else
+ } else {
start = 0; end = 1023+299;
+ }
for (i = start; i <= end; i++) {
cs->list[i].flags &= ~GSM322_CS_FLAG_TEMP_AA;
s = cs->list[i].sysinfo;
@@ -3024,9 +3025,10 @@ int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
cs = &ms->cellsel;
LOGP(DCS, LOGL_INFO, "Loss of CCCH.\n");
if (cs->selected && cs->sel_arfcn == cs->arfcn) {
- LOGP(DCS, LOGL_INFO, "Unselect cell due to loss\n");
- /* unset selected cell */
- gsm322_unselect_cell(cs);
+ /* do not unselect cell */
+ LOGP(DCS, LOGL_INFO, "Keep cell selected after loss, "
+ "so we can use the Neighbour cell information "
+ "for cell re-selection.\n");
}
stop_cs_timer(cs);
gsm322_cs_loss(cs);
diff --git a/Src/osmolib/src/host/layer23/src/mobile/gsm411_sms.c b/Src/osmolib/src/host/layer23/src/mobile/gsm411_sms.c
new file mode 100644
index 0000000..4347e86
--- /dev/null
+++ b/Src/osmolib/src/host/layer23/src/mobile/gsm411_sms.c
@@ -0,0 +1,941 @@
+/*
+ * Code based on work of:
+ * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
+ * (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ *
+ * (C) 2011 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/mobile/mncc.h>
+#include <osmocom/bb/mobile/transaction.h>
+#include <osmocom/bb/mobile/gsm411_sms.h>
+#include <osmocom/gsm/gsm0411_utils.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/bb/mobile/vty.h>
+
+#define UM_SAPI_SMS 3
+
+extern void *l23_ctx;
+static uint32_t new_callref = 0x40000001;
+
+static int gsm411_rl_recv(struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg);
+static int gsm411_mn_recv(struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg);
+static int gsm411_mm_send(struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg, int cp_msg_type);
+static int gsm411_mn_send(struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg);
+/*
+ * init / exit
+ */
+
+int gsm411_sms_init(struct osmocom_ms *ms)
+{
+ LOGP(DLSMS, LOGL_INFO, "init SMS\n");
+
+ return 0;
+}
+
+int gsm411_sms_exit(struct osmocom_ms *ms)
+{
+ struct gsm_trans *trans, *trans2;
+
+ LOGP(DLSMS, LOGL_INFO, "exit SMS processes for %s\n", ms->name);
+
+ llist_for_each_entry_safe(trans, trans2, &ms->trans_list, entry) {
+ if (trans->protocol == GSM48_PDISC_SMS) {
+ LOGP(DLSMS, LOGL_NOTICE, "Free pendig "
+ "SMS-transaction.\n");
+ trans_free(trans);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * SMS content
+ */
+
+struct gsm_sms *sms_alloc(void)
+{
+ return talloc_zero(l23_ctx, struct gsm_sms);
+}
+
+void sms_free(struct gsm_sms *sms)
+{
+ talloc_free(sms);
+}
+
+struct gsm_sms *sms_from_text(const char *receiver, int dcs, const char *text)
+{
+ struct gsm_sms *sms = sms_alloc();
+
+ if (!sms)
+ return NULL;
+
+ strncpy(sms->text, text, sizeof(sms->text)-1);
+
+ /* FIXME: don't use ID 1 static */
+ sms->reply_path_req = 0;
+ sms->status_rep_req = 0;
+ sms->ud_hdr_ind = 0;
+ sms->protocol_id = 0; /* implicit */
+ sms->data_coding_scheme = dcs;
+ strncpy(sms->address, receiver, sizeof(sms->address)-1);
+ /* Generate user_data */
+ sms->user_data_len = gsm_7bit_encode(sms->user_data, sms->text);
+
+ return sms;
+}
+
+static int gsm411_sms_report(struct osmocom_ms *ms, struct gsm_sms *sms,
+ uint8_t cause)
+{
+ vty_notify(ms, NULL);
+ if (!cause)
+ vty_notify(ms, "SMS to %s successfull\n", sms->address);
+ else
+ vty_notify(ms, "SMS to %s failed: %s\n", sms->address,
+ get_value_string(gsm411_rp_cause_strs, cause));
+
+ return 0;
+}
+/*
+ * transaction
+ */
+
+/* SMS Specific transaction release.
+ * gets called by trans_free, DO NOT CALL YOURSELF!
+ */
+void _gsm411_sms_trans_free(struct gsm_trans *trans)
+{
+ gsm411_smr_clear(&trans->sms.smr_inst);
+ gsm411_smc_clear(&trans->sms.smc_inst);
+
+ if (trans->sms.sms) {
+ LOGP(DLSMS, LOGL_ERROR, "Transaction contains SMS.\n");
+ gsm411_sms_report(trans->ms, trans->sms.sms,
+ GSM411_RP_CAUSE_MO_SMS_REJECTED);
+ sms_free(trans->sms.sms);
+ trans->sms.sms = NULL;
+ }
+}
+
+/* release MM connection, free transaction */
+static int gsm411_trans_free(struct gsm_trans *trans)
+{
+ struct msgb *nmsg;
+
+ /* release MM connection */
+ nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSMS_REL_REQ, trans->callref,
+ trans->transaction_id, trans->sms.sapi);
+ if (!nmsg)
+ return -ENOMEM;
+ LOGP(DLSMS, LOGL_INFO, "Sending MMSMS_REL_REQ\n");
+ gsm48_mmxx_downmsg(trans->ms, nmsg);
+
+ trans->callref = 0;
+ trans_free(trans);
+
+ return 0;
+}
+
+/*
+ * receive SMS
+ */
+
+/* now here comes our SMS */
+static int gsm340_rx_sms_deliver(struct osmocom_ms *ms, struct msgb *msg,
+ struct gsm_sms *gsms)
+{
+ const char osmocomsms[] = ".osmocom/bb/sms.txt";
+ int len;
+ const char *home;
+ char *sms_file;
+ char vty_text[sizeof(gsms->text)], *p;
+ FILE *fp;
+
+ /* remove linefeeds and show at VTY */
+ strcpy(vty_text, gsms->text);
+ for (p = vty_text; *p; p++) {
+ if (*p == '\n' || *p == '\r')
+ *p = ' ';
+ }
+ vty_notify(ms, NULL);
+ vty_notify(ms, "SMS from %s: '%s'\n", gsms->address, vty_text);
+
+ home = getenv("HOME");
+ if (!home) {
+fail:
+ fprintf(stderr, "Can't deliver SMS, be sure to create '%s' in "
+ "your home directory.\n", osmocomsms);
+ return GSM411_RP_CAUSE_MT_MEM_EXCEEDED;
+ }
+ len = strlen(home) + 1 + sizeof(osmocomsms);
+ sms_file = talloc_size(l23_ctx, len);
+ if (!sms_file)
+ goto fail;
+ snprintf(sms_file, len, "%s/%s", home, osmocomsms);
+
+ fp = fopen(sms_file, "a");
+ if (!fp)
+ goto fail;
+ fprintf(fp, "[SMS from %s]\n%s\n", gsms->address, gsms->text);
+ fclose(fp);
+
+ talloc_free(sms_file);
+
+ return 0;
+}
+
+/* process an incoming TPDU (called from RP-DATA)
+ * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
+static int gsm340_rx_tpdu(struct gsm_trans *trans, struct msgb *msg)
+{
+ uint8_t *smsp = msgb_sms(msg);
+ struct gsm_sms *gsms;
+ unsigned int sms_alphabet;
+ uint8_t sms_mti, sms_mms;
+ uint8_t oa_len_bytes;
+ uint8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
+ int rc = 0;
+
+ gsms = sms_alloc();
+
+ /* invert those fields where 0 means active/present */
+ sms_mti = *smsp & 0x03;
+ sms_mms = !!(*smsp & 0x04);
+ gsms->status_rep_req = (*smsp & 0x20);
+ gsms->ud_hdr_ind = (*smsp & 0x40);
+ gsms->reply_path_req = (*smsp & 0x80);
+ smsp++;
+
+ /* length in bytes of the originate address */
+ oa_len_bytes = 2 + *smsp/2 + *smsp%2;
+ if (oa_len_bytes > 12) {
+ LOGP(DLSMS, LOGL_ERROR, "Originate Address > 12 bytes ?!?\n");
+ rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
+ goto out;
+ }
+ memset(address_lv, 0, sizeof(address_lv));
+ memcpy(address_lv, smsp, oa_len_bytes);
+ /* mangle first byte to reflect length in bytes, not digits */
+ address_lv[0] = oa_len_bytes - 1;
+ /* convert to real number */
+ if (((smsp[1] & 0x70) >> 4) == 1)
+ strcpy(gsms->address, "+");
+ else if (((smsp[1] & 0x70) >> 4) == 2)
+ strcpy(gsms->address, "0");
+ else
+ gsms->address[0] = '\0';
+ gsm48_decode_bcd_number(gsms->address + strlen(gsms->address),
+ sizeof(gsms->address) - strlen(gsms->address), address_lv, 1);
+ smsp += oa_len_bytes;
+
+ gsms->protocol_id = *smsp++;
+ gsms->data_coding_scheme = *smsp++;
+
+ sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
+ if (sms_alphabet == 0xffffffff) {
+ sms_free(gsms);
+ return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
+ }
+
+ /* get timestamp */
+ gsms->time = gsm340_scts(smsp);
+ smsp += 7;
+
+ /* user data */
+ gsms->user_data_len = *smsp++;
+ if (gsms->user_data_len) {
+ memcpy(gsms->user_data, smsp, gsms->user_data_len);
+
+ switch (sms_alphabet) {
+ case DCS_7BIT_DEFAULT:
+ gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
+ break;
+ case DCS_8BIT_DATA:
+ case DCS_UCS2:
+ case DCS_NONE:
+ break;
+ }
+ }
+
+ LOGP(DLSMS, LOGL_INFO, "RX SMS: MTI: 0x%02x, "
+ "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, OA: %s, "
+ "UserDataLength: 0x%02x, UserData: \"%s\"\n",
+ sms_mti, gsms->msg_ref,
+ gsms->protocol_id, gsms->data_coding_scheme, gsms->address,
+ gsms->user_data_len,
+ sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
+ osmo_hexdump(gsms->user_data,
+ gsms->user_data_len));
+
+ switch (sms_mti) {
+ case GSM340_SMS_DELIVER_SC2MS:
+ /* MS is receiving an SMS */
+ rc = gsm340_rx_sms_deliver(trans->ms, msg, gsms);
+ break;
+ case GSM340_SMS_STATUS_REP_SC2MS:
+ case GSM340_SMS_SUBMIT_REP_SC2MS:
+ LOGP(DLSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
+ rc = GSM411_RP_CAUSE_IE_NOTEXIST;
+ break;
+ default:
+ LOGP(DLSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
+ rc = GSM411_RP_CAUSE_IE_NOTEXIST;
+ break;
+ }
+
+out:
+ sms_free(gsms);
+
+ return rc;
+}
+
+static int gsm411_send_rp_ack(struct gsm_trans *trans, uint8_t msg_ref)
+{
+ struct msgb *msg = gsm411_msgb_alloc();
+
+ LOGP(DLSMS, LOGL_INFO, "TX: SMS RP ACK\n");
+
+ gsm411_push_rp_header(msg, GSM411_MT_RP_ACK_MO, msg_ref);
+ return gsm411_smr_send(&trans->sms.smr_inst, GSM411_SM_RL_REPORT_REQ,
+ msg);
+}
+
+static int gsm411_send_rp_error(struct gsm_trans *trans,
+ uint8_t msg_ref, uint8_t cause)
+{
+ struct msgb *msg = gsm411_msgb_alloc();
+
+ msgb_tv_put(msg, 1, cause);
+
+ LOGP(DLSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
+ get_value_string(gsm411_rp_cause_strs, cause));
+
+ gsm411_push_rp_header(msg, GSM411_MT_RP_ERROR_MO, msg_ref);
+ return gsm411_smr_send(&trans->sms.smr_inst, GSM411_SM_RL_REPORT_REQ,
+ msg);
+}
+
+/* Receive a 04.11 TPDU inside RP-DATA / user data */
+static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
+ struct gsm411_rp_hdr *rph,
+ uint8_t src_len, uint8_t *src,
+ uint8_t dst_len, uint8_t *dst,
+ uint8_t tpdu_len, uint8_t *tpdu)
+{
+ int rc = 0;
+
+ if (dst_len && dst)
+ LOGP(DLSMS, LOGL_ERROR, "RP-DATA (MT) with DST ?!?\n");
+
+ if (!src_len || !src || !tpdu_len || !tpdu) {
+ LOGP(DLSMS, LOGL_ERROR,
+ "RP-DATA (MO) without DST or TPDU ?!?\n");
+ gsm411_send_rp_error(trans, rph->msg_ref,
+ GSM411_RP_CAUSE_INV_MAND_INF);
+ return -EIO;
+ }
+ msg->l4h = tpdu;
+
+ LOGP(DLSMS, LOGL_INFO, "DST(%u,%s)\n", src_len,
+ osmo_hexdump(src, src_len));
+ LOGP(DLSMS, LOGL_INFO, "TPDU(%u,%s)\n", msg->tail-msg->l4h,
+ osmo_hexdump(msg->l4h, msg->tail-msg->l4h));
+
+ rc = gsm340_rx_tpdu(trans, msg);
+ if (rc == 0)
+ return gsm411_send_rp_ack(trans, rph->msg_ref);
+ else if (rc > 0)
+ return gsm411_send_rp_error(trans, rph->msg_ref, rc);
+ else
+ return rc;
+}
+
+/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
+static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
+ struct gsm411_rp_hdr *rph)
+{
+ uint8_t src_len, dst_len, rpud_len;
+ uint8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
+
+ /* in the MO case, this should always be zero length */
+ src_len = rph->data[0];
+ if (src_len)
+ src = &rph->data[1];
+
+ dst_len = rph->data[1+src_len];
+ if (dst_len)
+ dst = &rph->data[1+src_len+1];
+
+ rpud_len = rph->data[1+src_len+1+dst_len];
+ if (rpud_len)
+ rp_ud = &rph->data[1+src_len+1+dst_len+1];
+
+ LOGP(DLSMS, LOGL_INFO, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
+ src_len, dst_len, rpud_len);
+ return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
+ rpud_len, rp_ud);
+}
+
+/* receive RL DATA */
+static int gsm411_rx_rl_data(struct msgb *msg, struct gsm48_hdr *gh,
+ struct gsm_trans *trans)
+{
+ struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
+ uint8_t msg_type = rp_data->msg_type & 0x07;
+ int rc = 0;
+
+ switch (msg_type) {
+ case GSM411_MT_RP_DATA_MT:
+ LOGP(DLSMS, LOGL_INFO, "RX SMS RP-DATA (MT)\n");
+ rc = gsm411_rx_rp_data(msg, trans, rp_data);
+ break;
+ default:
+ LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
+ gsm411_trans_free(trans);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+/*
+ * send SMS
+ */
+
+/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
+static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
+ struct gsm411_rp_hdr *rph)
+{
+ struct osmocom_ms *ms = trans->ms;
+ struct gsm_sms *sms = trans->sms.sms;
+
+ /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
+ * successfully received a SMS. We can now safely mark it as
+ * transmitted */
+
+ if (!sms) {
+ LOGP(DLSMS, LOGL_ERROR, "RX RP-ACK but no sms in "
+ "transaction?!?\n");
+ return gsm411_send_rp_error(trans, rph->msg_ref,
+ GSM411_RP_CAUSE_PROTOCOL_ERR);
+ }
+
+ gsm411_sms_report(ms, sms, 0);
+
+ sms_free(sms);
+ trans->sms.sms = NULL;
+
+ return 0;
+}
+
+static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
+ struct gsm411_rp_hdr *rph)
+{
+ struct osmocom_ms *ms = trans->ms;
+ struct gsm_sms *sms = trans->sms.sms;
+ uint8_t cause_len = rph->data[0];
+ uint8_t cause = rph->data[1];
+
+ /* Error in response to MT RP_DATA, i.e. the MS did not
+ * successfully receive the SMS. We need to investigate
+ * the cause and take action depending on it */
+
+ LOGP(DLSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
+ trans->ms->name, cause_len, cause,
+ get_value_string(gsm411_rp_cause_strs, cause));
+
+ if (!sms) {
+ LOGP(DLSMS, LOGL_ERROR,
+ "RX RP-ERR, but no sms in transaction?!?\n");
+ return -EINVAL;
+#if 0
+ return gsm411_send_rp_error(trans, rph->msg_ref,
+ GSM411_RP_CAUSE_PROTOCOL_ERR);
+#endif
+ }
+
+ gsm411_sms_report(ms, sms, cause);
+
+ sms_free(sms);
+ trans->sms.sms = NULL;
+
+ return 0;
+}
+
+/* receive RL REPORT */
+static int gsm411_rx_rl_report(struct msgb *msg, struct gsm48_hdr *gh,
+ struct gsm_trans *trans)
+{
+ struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
+ uint8_t msg_type = rp_data->msg_type & 0x07;
+ int rc = 0;
+
+ switch (msg_type) {
+ case GSM411_MT_RP_ACK_MT:
+ LOGP(DLSMS, LOGL_INFO, "RX SMS RP-ACK (MT)\n");
+ rc = gsm411_rx_rp_ack(msg, trans, rp_data);
+ break;
+ case GSM411_MT_RP_ERROR_MT:
+ LOGP(DLSMS, LOGL_INFO, "RX SMS RP-ERROR (MT)\n");
+ rc = gsm411_rx_rp_error(msg, trans, rp_data);
+ break;
+ default:
+ LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
+ gsm411_trans_free(trans);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+/* generate a msgb containing a TPDU derived from struct gsm_sms,
+ * returns total size of TPDU */
+static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
+{
+ uint8_t *smsp;
+ uint8_t da[12]; /* max len per 03.40 */
+ uint8_t da_len = 0;
+ uint8_t octet_len;
+ unsigned int old_msg_len = msg->len;
+ uint8_t sms_vpf = GSM340_TP_VPF_NONE;
+ uint8_t sms_vp;
+
+ /* generate first octet with masked bits */
+ smsp = msgb_put(msg, 1);
+ /* TP-MTI (message type indicator) */
+ *smsp = GSM340_SMS_SUBMIT_MS2SC;
+ /* TP-RD */
+ if (0 /* FIXME */)
+ *smsp |= 0x04;
+ /* TP-VPF */
+ *smsp |= (sms_vpf << 3);
+ /* TP-SRI(deliver)/SRR(submit) */
+ if (sms->status_rep_req)
+ *smsp |= 0x20;
+ /* TP-UDHI (indicating TP-UD contains a header) */
+ if (sms->ud_hdr_ind)
+ *smsp |= 0x40;
+ /* TP-RP */
+ if (sms->reply_path_req)
+ *smsp |= 0x80;
+
+ /* generate message ref */
+ smsp = msgb_put(msg, 1);
+ *smsp = sms->msg_ref;
+
+ /* generate destination address */
+ if (sms->address[0] == '+')
+ da_len = gsm340_gen_oa(da, sizeof(da), 0x1, 0x1,
+ sms->address + 1);
+ else
+ da_len = gsm340_gen_oa(da, sizeof(da), 0x0, 0x1, sms->address);
+ smsp = msgb_put(msg, da_len);
+ memcpy(smsp, da, da_len);
+
+ /* generate TP-PID */
+ smsp = msgb_put(msg, 1);
+ *smsp = sms->protocol_id;
+
+ /* generate TP-DCS */
+ smsp = msgb_put(msg, 1);
+ *smsp = sms->data_coding_scheme;
+
+ /* generate TP-VP */
+ switch (sms_vpf) {
+ case GSM340_TP_VPF_NONE:
+ sms_vp = 0;
+ break;
+ default:
+ fprintf(stderr, "VPF unsupported, please fix!\n");
+ exit(0);
+ }
+ smsp = msgb_put(msg, sms_vp);
+
+ /* generate TP-UDL */
+ smsp = msgb_put(msg, 1);
+ *smsp = sms->user_data_len;
+
+ /* generate TP-UD */
+ switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
+ case DCS_7BIT_DEFAULT:
+ octet_len = sms->user_data_len*7/8;
+ if (sms->user_data_len*7%8 != 0)
+ octet_len++;
+ /* Warning, user_data_len indicates the amount of septets
+ * (characters), we need amount of octets occupied */
+ smsp = msgb_put(msg, octet_len);
+ memcpy(smsp, sms->user_data, octet_len);
+ break;
+ case DCS_UCS2:
+ case DCS_8BIT_DATA:
+ smsp = msgb_put(msg, sms->user_data_len);
+ memcpy(smsp, sms->user_data, sms->user_data_len);
+ break;
+ default:
+ LOGP(DLSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: "
+ "0x%02X\n", sms->data_coding_scheme);
+ break;
+ }
+
+ return msg->len - old_msg_len;
+}
+
+/* Take a SMS in gsm_sms structure and send it. */
+static int gsm411_tx_sms_submit(struct osmocom_ms *ms, const char *sms_sca,
+ struct gsm_sms *sms)
+{
+ struct msgb *msg;
+ struct gsm_trans *trans;
+ uint8_t *data, *rp_ud_len;
+ uint8_t msg_ref = 42;
+ int rc;
+ uint8_t transaction_id;
+ uint8_t sca[11]; /* max len per 03.40 */
+
+ LOGP(DLSMS, LOGL_INFO, "..._sms_submit()\n");
+
+ /* no running, no transaction */
+ if (!ms->started || ms->shutdown) {
+ LOGP(DLSMS, LOGL_ERROR, "Phone is down\n");
+ gsm411_sms_report(ms, sms, GSM411_RP_CAUSE_MO_TEMP_FAIL);
+ sms_free(sms);
+ return -EIO;
+ }
+
+ /* allocate transaction with dummy reference */
+ transaction_id = trans_assign_trans_id(ms, GSM48_PDISC_SMS, 0);
+ if (transaction_id < 0) {
+ LOGP(DLSMS, LOGL_ERROR, "No transaction ID available\n");
+ gsm411_sms_report(ms, sms, GSM411_RP_CAUSE_MO_CONGESTION);
+ sms_free(sms);
+ return -ENOMEM;
+ }
+ trans = trans_alloc(ms, GSM48_PDISC_SMS, transaction_id, new_callref++);
+ if (!trans) {
+ LOGP(DLSMS, LOGL_ERROR, "No memory for trans\n");
+ gsm411_sms_report(ms, sms, GSM411_RP_CAUSE_MO_TEMP_FAIL);
+ sms_free(sms);
+ return -ENOMEM;
+ }
+ gsm411_smc_init(&trans->sms.smc_inst, 0, gsm411_mn_recv,
+ gsm411_mm_send);
+ gsm411_smr_init(&trans->sms.smr_inst, 0, gsm411_rl_recv,
+ gsm411_mn_send);
+ trans->sms.sms = sms;
+ trans->sms.sapi = UM_SAPI_SMS;
+
+ msg = gsm411_msgb_alloc();
+
+ /* no orig Address */
+ data = (uint8_t *)msgb_put(msg, 1);
+ data[0] = 0x00; /* originator length == 0 */
+
+ /* Destination Address */
+ sca[1] = 0x80; /* no extension */
+ sca[1] |= ((sms_sca[0] == '+') ? 0x01 : 0x00) << 4; /* type */
+ sca[1] |= 0x1; /* plan*/
+
+ rc = gsm48_encode_bcd_number(sca, sizeof(sca), 1,
+ sms_sca + (sms_sca[0] == '+'));
+ if (rc < 0) {
+error:
+ gsm411_sms_report(ms, sms, GSM411_RP_CAUSE_SEMANT_INC_MSG);
+ gsm411_trans_free(trans);
+ msgb_free(msg);
+ return rc;
+ }
+ data = msgb_put(msg, rc);
+ memcpy(data, sca, rc);
+
+ /* obtain a pointer for the rp_ud_len, so we can fill it later */
+ rp_ud_len = (uint8_t *)msgb_put(msg, 1);
+
+ /* generate the 03.40 TPDU */
+ rc = gsm340_gen_tpdu(msg, sms);
+ if (rc < 0)
+ goto error;
+ *rp_ud_len = rc;
+
+ LOGP(DLSMS, LOGL_INFO, "TX: SMS DELIVER\n");
+
+ gsm411_push_rp_header(msg, GSM411_MT_RP_DATA_MO, msg_ref);
+ return gsm411_smr_send(&trans->sms.smr_inst, GSM411_SM_RL_DATA_REQ,
+ msg);
+}
+
+/* create and send SMS */
+int sms_send(struct osmocom_ms *ms, const char *sms_sca, const char *number,
+ const char *text)
+{
+ struct gsm_sms *sms = sms_from_text(number, 0, text);
+
+ if (!sms)
+ return -ENOMEM;
+
+ return gsm411_tx_sms_submit(ms, sms_sca, sms);
+}
+
+/*
+ * message flow between layers
+ */
+
+/* push MMSMS header and send to MM */
+static int gsm411_to_mm(struct msgb *msg, struct gsm_trans *trans,
+ int msg_type)
+{
+ struct gsm48_mmxx_hdr *mmh;
+
+ /* push RR header */
+ msgb_push(msg, sizeof(struct gsm48_mmxx_hdr));
+ mmh = (struct gsm48_mmxx_hdr *)msg->data;
+ mmh->msg_type = msg_type;
+ mmh->ref = trans->callref;
+ mmh->transaction_id = trans->transaction_id;
+ mmh->sapi = trans->sms.sapi;
+ mmh->emergency = 0;
+
+ /* send message to MM */
+ LOGP(DLSMS, LOGL_INFO, "Sending '%s' to MM (callref=%x, "
+ "transaction_id=%d, sapi=%d)\n", get_mmxx_name(msg_type),
+ trans->callref, trans->transaction_id, trans->sms.sapi);
+ return gsm48_mmxx_downmsg(trans->ms, msg);
+}
+
+/* mm_send: receive MMSMS sap message from SMC */
+static int gsm411_mm_send(struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg, int cp_msg_type)
+{
+ struct gsm_trans *trans =
+ container_of(inst, struct gsm_trans, sms.smc_inst);
+ int rc = 0;
+
+ switch (msg_type) {
+ case GSM411_MMSMS_EST_REQ:
+ gsm411_to_mm(msg, trans, msg_type);
+ break;
+ case GSM411_MMSMS_DATA_REQ:
+ gsm411_push_cp_header(msg, trans->protocol,
+ trans->transaction_id, cp_msg_type);
+ msg->l3h = msg->data;
+ LOGP(DLSMS, LOGL_INFO, "sending CP message (trans=%x)\n",
+ trans->transaction_id);
+ rc = gsm411_to_mm(msg, trans, msg_type);
+ break;
+ case GSM411_MMSMS_REL_REQ:
+ LOGP(DLSMS, LOGL_INFO, "Got MMSMS_REL_REQ, destroying "
+ "transaction.\n");
+ gsm411_to_mm(msg, trans, msg_type);
+ gsm411_trans_free(trans);
+ break;
+ default:
+ msgb_free(msg);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+/* mm_send: receive MNSMS sap message from SMR */
+static int gsm411_mn_send(struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg)
+{
+ struct gsm_trans *trans =
+ container_of(inst, struct gsm_trans, sms.smr_inst);
+
+ /* forward to SMC */
+ return gsm411_smc_send(&trans->sms.smc_inst, msg_type, msg);
+}
+
+/* receive SM-RL sap message from SMR
+ * NOTE: Message is freed by sender
+ */
+static int gsm411_rl_recv(struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg)
+{
+ struct gsm_trans *trans =
+ container_of(inst, struct gsm_trans, sms.smr_inst);
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ int rc = 0;
+
+ switch (msg_type) {
+ case GSM411_SM_RL_DATA_IND:
+ rc = gsm411_rx_rl_data(msg, gh, trans);
+ break;
+ case GSM411_SM_RL_REPORT_IND:
+ if (!gh)
+ LOGP(DLSMS, LOGL_INFO, "Release transaction on empty "
+ "report.\n");
+ else {
+ LOGP(DLSMS, LOGL_INFO, "Release transaction on RL "
+ "report.\n");
+ rc = gsm411_rx_rl_report(msg, gh, trans);
+ }
+ break;
+ default:
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+/* receive MNSMS sap message from SMC
+ * NOTE: Message is freed by sender
+ */
+static int gsm411_mn_recv(struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg)
+{
+ struct gsm_trans *trans =
+ container_of(inst, struct gsm_trans, sms.smc_inst);
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ int rc = 0;
+
+ switch (msg_type) {
+ case GSM411_MNSMS_EST_IND:
+ case GSM411_MNSMS_DATA_IND:
+ LOGP(DLSMS, LOGL_INFO, "MNSMS-DATA/EST-IND\n");
+ rc = gsm411_smr_recv(&trans->sms.smr_inst, msg_type, msg);
+ break;
+ case GSM411_MNSMS_ERROR_IND:
+ if (gh)
+ LOGP(DLSMS, LOGL_INFO, "MNSMS-ERROR-IND, cause %d "
+ "(%s)\n", gh->data[0],
+ get_value_string(gsm411_cp_cause_strs,
+ gh->data[0]));
+ else
+ LOGP(DLSMS, LOGL_INFO, "MNSMS-ERROR-IND, no cause\n");
+ rc = gsm411_smr_recv(&trans->sms.smr_inst, msg_type, msg);
+ break;
+ default:
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+/* receive est/data message from MM layer */
+static int gsm411_mmsms_ind(int mmsms_msg, struct gsm_trans *trans,
+ struct msgb *msg)
+{
+ struct osmocom_ms *ms = trans->ms;
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ int msg_type = gh->msg_type & 0xbf;
+ uint8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4;
+ /* flip */
+
+ /* pull the MMSMS header */
+ msgb_pull(msg, sizeof(struct gsm48_mmxx_hdr));
+
+ LOGP(DLSMS, LOGL_INFO, "(ms %s) Received est/data '%u'\n", ms->name,
+ msg_type);
+
+ /* 5.4: For MO, if a CP-DATA is received for a new
+ * transaction, equals reception of an implicit
+ * last CP-ACK for previous transaction */
+ if (trans->sms.smc_inst.cp_state == GSM411_CPS_IDLE
+ && msg_type == GSM411_MT_CP_DATA) {
+ int i;
+ struct gsm_trans *ptrans;
+
+ /* Scan through all remote initiated transactions */
+ for (i=8; i<15; i++) {
+ if (i == transaction_id)
+ continue;
+
+ ptrans = trans_find_by_id(ms, GSM48_PDISC_SMS, i);
+ if (!ptrans)
+ continue;
+
+ LOGP(DLSMS, LOGL_INFO, "Implicit CP-ACK for "
+ "trans_id=%x\n", i);
+
+ /* Finish it for good */
+ gsm411_trans_free(ptrans);
+ }
+ }
+ return gsm411_smc_recv(&trans->sms.smc_inst, mmsms_msg, msg, msg_type);
+}
+
+/* receive message from MM layer */
+int gsm411_rcv_sms(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
+ int msg_type = mmh->msg_type;
+ int sapi = mmh->sapi;
+ struct gsm_trans *trans;
+ int rc = 0;
+
+ trans = trans_find_by_callref(ms, mmh->ref);
+ if (!trans) {
+ LOGP(DLSMS, LOGL_INFO, " -> (new transaction sapi=%d)\n", sapi);
+ trans = trans_alloc(ms, GSM48_PDISC_SMS, mmh->transaction_id,
+ mmh->ref);
+ if (!trans)
+ return -ENOMEM;
+ gsm411_smc_init(&trans->sms.smc_inst, 0, gsm411_mn_recv,
+ gsm411_mm_send);
+ gsm411_smr_init(&trans->sms.smr_inst, 0, gsm411_rl_recv,
+ gsm411_mn_send);
+ trans->sms.sapi = mmh->sapi;
+ }
+
+ LOGP(DLSMS, LOGL_INFO, "(ms %s) Received '%s' from MM\n", ms->name,
+ get_mmxx_name(msg_type));
+
+ switch (msg_type) {
+ case GSM48_MMSMS_EST_CNF:
+ rc = gsm411_smc_recv(&trans->sms.smc_inst, GSM411_MMSMS_EST_CNF,
+ msg, 0);
+ break;
+ case GSM48_MMSMS_EST_IND:
+ case GSM48_MMSMS_DATA_IND:
+ rc = gsm411_mmsms_ind(msg_type, trans, msg);
+ break;
+ case GSM48_MMSMS_REL_IND:
+ case GSM48_MMSMS_ERR_IND:
+ LOGP(DLSMS, LOGL_INFO, "MM connection released.\n");
+ trans_free(trans);
+ break;
+ default:
+ LOGP(DLSMS, LOGL_NOTICE, "Message unhandled.\n");
+ rc = -ENOTSUP;
+ }
+
+ return rc;
+}
+
diff --git a/Src/osmolib/src/host/layer23/src/mobile/gsm480_ss.c b/Src/osmolib/src/host/layer23/src/mobile/gsm480_ss.c
new file mode 100644
index 0000000..fda6288
--- /dev/null
+++ b/Src/osmolib/src/host/layer23/src/mobile/gsm480_ss.c
@@ -0,0 +1,1289 @@
+/*
+ * (C) 2011 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/mobile/mncc.h>
+#include <osmocom/bb/mobile/transaction.h>
+#include <osmocom/bb/mobile/gsm480_ss.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/bb/mobile/vty.h>
+#include <osmocom/gsm/protocol/gsm_04_80.h>
+#include <osmocom/gsm/gsm48.h>
+
+static uint32_t new_callref = 0x80000001;
+
+static int gsm480_to_mm(struct msgb *msg, struct gsm_trans *trans,
+ int msg_type);
+static const struct value_string gsm480_err_names[] = {
+ { GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER,
+ "UNKNOWN SUBSCRIBER" },
+ { GSM0480_ERR_CODE_ILLEGAL_SUBSCRIBER,
+ "ILLEGAL SUBSCRIBER" },
+ { GSM0480_ERR_CODE_BEARER_SERVICE_NOT_PROVISIONED,
+ "BEARER SERVICE NOT PROVISIONED" },
+ { GSM0480_ERR_CODE_TELESERVICE_NOT_PROVISIONED,
+ "TELESERVICE NOT PROVISIONED" },
+ { GSM0480_ERR_CODE_ILLEGAL_EQUIPMENT,
+ "ILLEGAL EQUIPMENT" },
+ { GSM0480_ERR_CODE_CALL_BARRED,
+ "CALL BARRED" },
+ { GSM0480_ERR_CODE_ILLEGAL_SS_OPERATION,
+ "ILLEGAL SS OPERATION" },
+ { GSM0480_ERR_CODE_SS_ERROR_STATUS,
+ "SS ERROR STATUS" },
+ { GSM0480_ERR_CODE_SS_NOT_AVAILABLE,
+ "SS NOT AVAILABLE" },
+ { GSM0480_ERR_CODE_SS_SUBSCRIPTION_VIOLATION,
+ "SS SUBSCRIPTION VIOLATION" },
+ { GSM0480_ERR_CODE_SS_INCOMPATIBILITY,
+ "SS INCOMPATIBILITY" },
+ { GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED,
+ "FACILITY NOT SUPPORTED" },
+ { GSM0480_ERR_CODE_ABSENT_SUBSCRIBER,
+ "ABSENT SUBSCRIBER" },
+ { GSM0480_ERR_CODE_SYSTEM_FAILURE,
+ "SYSTEM FAILURE" },
+ { GSM0480_ERR_CODE_DATA_MISSING,
+ "DATA MISSING" },
+ { GSM0480_ERR_CODE_UNEXPECTED_DATA_VALUE,
+ "UNEXPECTED DATA VALUE" },
+ { GSM0480_ERR_CODE_PW_REGISTRATION_FAILURE,
+ "PW REGISTRATION FAILURE" },
+ { GSM0480_ERR_CODE_NEGATIVE_PW_CHECK,
+ "NEGATIVE PW CHECK" },
+ { GSM0480_ERR_CODE_NUM_PW_ATTEMPTS_VIOLATION,
+ "NUM PW ATTEMPTS VIOLATION" },
+ { GSM0480_ERR_CODE_UNKNOWN_ALPHABET,
+ "UNKNOWN ALPHABET" },
+ { GSM0480_ERR_CODE_USSD_BUSY,
+ "USSD BUSY" },
+ { GSM0480_ERR_CODE_MAX_MPTY_PARTICIPANTS,
+ "MAX MPTY PARTICIPANTS" },
+ { GSM0480_ERR_CODE_RESOURCES_NOT_AVAILABLE,
+ "RESOURCES NOT AVAILABLE" },
+ {0, NULL }
+};
+
+/* taken from Wireshark */
+static const struct value_string Teleservice_vals[] = {
+ {0x00, "allTeleservices" },
+ {0x10, "allSpeechTransmissionServices" },
+ {0x11, "telephony" },
+ {0x12, "emergencyCalls" },
+ {0x20, "allShortMessageServices" },
+ {0x21, "shortMessageMT-PP" },
+ {0x22, "shortMessageMO-PP" },
+ {0x60, "allFacsimileTransmissionServices" },
+ {0x61, "facsimileGroup3AndAlterSpeech" },
+ {0x62, "automaticFacsimileGroup3" },
+ {0x63, "facsimileGroup4" },
+
+ {0x70, "allDataTeleservices" },
+ {0x80, "allTeleservices-ExeptSMS" },
+
+ {0x90, "allVoiceGroupCallServices" },
+ {0x91, "voiceGroupCall" },
+ {0x92, "voiceBroadcastCall" },
+
+ {0xd0, "allPLMN-specificTS" },
+ {0xd1, "plmn-specificTS-1" },
+ {0xd2, "plmn-specificTS-2" },
+ {0xd3, "plmn-specificTS-3" },
+ {0xd4, "plmn-specificTS-4" },
+ {0xd5, "plmn-specificTS-5" },
+ {0xd6, "plmn-specificTS-6" },
+ {0xd7, "plmn-specificTS-7" },
+ {0xd8, "plmn-specificTS-8" },
+ {0xd9, "plmn-specificTS-9" },
+ {0xda, "plmn-specificTS-A" },
+ {0xdb, "plmn-specificTS-B" },
+ {0xdc, "plmn-specificTS-C" },
+ {0xdd, "plmn-specificTS-D" },
+ {0xde, "plmn-specificTS-E" },
+ {0xdf, "plmn-specificTS-F" },
+ { 0, NULL }
+};
+
+/* taken from Wireshark */
+static const struct value_string Bearerservice_vals[] = {
+ {0x00, "allBearerServices" },
+ {0x10, "allDataCDA-Services" },
+ {0x11, "dataCDA-300bps" },
+ {0x12, "dataCDA-1200bps" },
+ {0x13, "dataCDA-1200-75bps" },
+ {0x14, "dataCDA-2400bps" },
+ {0x15, "dataCDA-4800bps" },
+ {0x16, "dataCDA-9600bps" },
+ {0x17, "general-dataCDA" },
+
+ {0x18, "allDataCDS-Services" },
+ {0x1A, "dataCDS-1200bps" },
+ {0x1C, "dataCDS-2400bps" },
+ {0x1D, "dataCDS-4800bps" },
+ {0x1E, "dataCDS-9600bps" },
+ {0x1F, "general-dataCDS" },
+
+ {0x20, "allPadAccessCA-Services" },
+ {0x21, "padAccessCA-300bps" },
+ {0x22, "padAccessCA-1200bps" },
+ {0x23, "padAccessCA-1200-75bps" },
+ {0x24, "padAccessCA-2400bps" },
+ {0x25, "padAccessCA-4800bps" },
+ {0x26, "padAccessCA-9600bps" },
+ {0x27, "general-padAccessCA" },
+
+ {0x28, "allDataPDS-Services" },
+ {0x2C, "dataPDS-2400bps" },
+ {0x2D, "dataPDS-4800bps" },
+ {0x2E, "dataPDS-9600bps" },
+ {0x2F, "general-dataPDS" },
+
+ {0x30, "allAlternateSpeech-DataCDA" },
+ {0x38, "allAlternateSpeech-DataCDS" },
+ {0x40, "allSpeechFollowedByDataCDA" },
+ {0x48, "allSpeechFollowedByDataCDS" },
+
+ {0x50, "allDataCircuitAsynchronous" },
+ {0x60, "allAsynchronousServices" },
+ {0x58, "allDataCircuitSynchronous" },
+ {0x68, "allSynchronousServices" },
+
+ {0xD0, "allPLMN-specificBS" },
+ {0xD1, "plmn-specificBS-1" },
+ {0xD2, "plmn-specificBS-2" },
+ {0xD3, "plmn-specificBS-3" },
+ {0xD4, "plmn-specificBS-4" },
+ {0xD5, "plmn-specificBS-5" },
+ {0xD6, "plmn-specificBS-6" },
+ {0xD7, "plmn-specificBS-7" },
+ {0xD8, "plmn-specificBS-8" },
+ {0xD9, "plmn-specificBS-9" },
+ {0xDA, "plmn-specificBS-A" },
+ {0xDB, "plmn-specificBS-B" },
+ {0xDC, "plmn-specificBS-C" },
+ {0xDD, "plmn-specificBS-D" },
+ {0xDE, "plmn-specificBS-E" },
+ {0xDF, "plmn-specificBS-F" },
+ { 0, NULL }
+};
+
+static int gsm480_ss_result(struct osmocom_ms *ms, const char *response,
+ uint8_t error)
+{
+ vty_notify(ms, NULL);
+ if (response) {
+ char text[256], *t = text, *s;
+
+ strncpy(text, response, sizeof(text) - 1);
+ text[sizeof(text) - 1] = '\0';
+ while ((s = strchr(text, '\r')))
+ *s = '\n';
+ while ((s = strsep(&t, "\n"))) {
+ vty_notify(ms, "Service response: %s\n", s);
+ }
+ } else if (error)
+ vty_notify(ms, "Service request failed: %s\n",
+ get_value_string(gsm480_err_names, error));
+ else
+ vty_notify(ms, "Service request failed.\n");
+
+ return 0;
+}
+
+enum {
+ GSM480_SS_ST_IDLE = 0,
+ GSM480_SS_ST_REGISTER,
+ GSM480_SS_ST_ACTIVE,
+};
+
+/*
+ * init / exit
+ */
+
+int gsm480_ss_init(struct osmocom_ms *ms)
+{
+ LOGP(DSS, LOGL_INFO, "init SS\n");
+
+ return 0;
+}
+
+int gsm480_ss_exit(struct osmocom_ms *ms)
+{
+ struct gsm_trans *trans, *trans2;
+
+ LOGP(DSS, LOGL_INFO, "exit SS processes for %s\n", ms->name);
+
+ llist_for_each_entry_safe(trans, trans2, &ms->trans_list, entry) {
+ if (trans->protocol == GSM48_PDISC_NC_SS) {
+ LOGP(DSS, LOGL_NOTICE, "Free pendig "
+ "SS-transaction.\n");
+ trans_free(trans);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * transaction
+ */
+
+/* SS Specific transaction release.
+ * gets called by trans_free, DO NOT CALL YOURSELF!
+ */
+void _gsm480_ss_trans_free(struct gsm_trans *trans)
+{
+ if (trans->ss.msg) {
+ LOGP(DSS, LOGL_INFO, "Free pending SS request\n");
+ msgb_free(trans->ss.msg);
+ trans->ss.msg = NULL;
+ }
+ vty_notify(trans->ms, NULL);
+ vty_notify(trans->ms, "Service connection terminated.\n");
+}
+
+/* release MM connection, free transaction */
+static int gsm480_trans_free(struct gsm_trans *trans)
+{
+ struct msgb *nmsg;
+
+ /* release MM connection */
+ nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSS_REL_REQ, trans->callref,
+ trans->transaction_id, 0);
+ if (!nmsg)
+ return -ENOMEM;
+ LOGP(DSS, LOGL_INFO, "Sending MMSS_REL_REQ\n");
+ gsm48_mmxx_downmsg(trans->ms, nmsg);
+
+ trans->callref = 0;
+ trans_free(trans);
+
+ return 0;
+}
+
+/*
+ * endcoding
+ */
+
+#define GSM480_ALLOC_SIZE 512+128
+#define GSM480_ALLOC_HEADROOM 128
+
+struct msgb *gsm480_msgb_alloc(void)
+{
+ return msgb_alloc_headroom(GSM480_ALLOC_SIZE, GSM480_ALLOC_HEADROOM,
+ "GSM 04.80");
+}
+
+static inline unsigned char *msgb_wrap_with_L(struct msgb *msgb)
+{
+ uint8_t *data = msgb_push(msgb, 1);
+
+ data[0] = msgb->len - 1;
+ return data;
+}
+
+/* support function taken from OpenBSC */
+static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag)
+{
+ uint8_t *data = msgb_push(msgb, 2);
+
+ data[0] = tag;
+ data[1] = msgb->len - 2;
+ return data;
+}
+
+static inline void msgb_wrap_with_TL_asn(struct msgb *msg, uint8_t tag)
+{
+ int len = msg->len;
+ uint8_t *data = msgb_push(msg, (len >= 128) ? 3 : 2);
+
+ *data++ = tag;
+ if (len >= 128)
+ *data++ = 0x81;
+ *data = len;
+ return;
+}
+
+/* support function taken from OpenBSC */
+static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag,
+uint8_t value)
+{
+ uint8_t *data = msgb_push(msgb, 3);
+
+ data[0] = tag;
+ data[1] = 1;
+ data[2] = value;
+ return data;
+}
+
+static const char *ss_code_by_char(const char *code, uint8_t *ss_code)
+{
+ if (!strncmp(code, "21", 2)) {
+ *ss_code = 33;
+ return code + 2;
+ }
+ if (!strncmp(code, "67", 2)) {
+ *ss_code = 41;
+ return code + 2;
+ }
+ if (!strncmp(code, "61", 2)) {
+ *ss_code = 42;
+ return code + 2;
+ }
+ if (!strncmp(code, "62", 2)) {
+ *ss_code = 43;
+ return code + 2;
+ }
+ if (!strncmp(code, "002", 3)) {
+ *ss_code = 32;
+ return code + 3;
+ }
+ if (!strncmp(code, "004", 3)) {
+ *ss_code = 40;
+ return code + 3;
+ }
+
+ return NULL;
+}
+
+static const char *decode_ss_code(uint8_t ss_code)
+{
+ static char unknown[16];
+
+ switch (ss_code) {
+ case 33:
+ return "CFU";
+ case 41:
+ return "CFB";
+ case 42:
+ return "CFNR";
+ case 43:
+ return "CF Not Reachable";
+ case 32:
+ return "All CF";
+ case 40:
+ return "All conditional CF";
+ default:
+ sprintf(unknown, "Unknown %d", ss_code);
+ return unknown;
+ }
+}
+
+static int gsm480_tx_release_compl(struct gsm_trans *trans, uint8_t cause)
+{
+ struct msgb *msg;
+ struct gsm48_hdr *gh;
+
+ msg = gsm480_msgb_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_NC_SS | (trans->transaction_id << 4);
+ gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
+
+ if (cause) {
+ uint8_t *tlv = msgb_put(msg, 4);
+ *tlv = GSM48_IE_CAUSE;
+ *tlv = 2;
+ *tlv = 0x80 | cause;
+ *tlv = 0x80 | GSM48_CAUSE_LOC_USER;
+ }
+ return gsm480_to_mm(msg, trans, GSM48_MMSS_DATA_REQ);
+}
+
+static int return_imei(struct osmocom_ms *ms)
+{
+ char text[32];
+ struct gsm_settings *set = &ms->settings;
+
+ sprintf(text, "IMEI: %s SV: %s", set->imei,
+ set->imeisv + strlen(set->imei));
+ gsm480_ss_result(ms, text, 0);
+
+ return 0;
+}
+
+/* prepend invoke-id, facility IE and facility message */
+static int gsm480_tx_invoke(struct gsm_trans *trans, struct msgb *msg,
+ uint8_t msg_type)
+{
+ struct gsm48_hdr *gh;
+
+ /* Pre-pend the invoke ID */
+ msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, trans->ss.invoke_id);
+
+ /* Wrap this up as invoke vomponent */
+ if (msg_type == GSM0480_MTYPE_FACILITY)
+ msgb_wrap_with_TL_asn(msg, GSM0480_CTYPE_RETURN_RESULT);
+ else
+ msgb_wrap_with_TL_asn(msg, GSM0480_CTYPE_INVOKE);
+
+ /* Wrap this up as facility IE */
+ if (msg_type == GSM0480_MTYPE_FACILITY)
+ msgb_wrap_with_L(msg);
+ else
+ msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
+
+ /* FIXME: If phase 2, we need SSVERSION to be added */
+
+ /* Push L3 header */
+ gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_NC_SS | (trans->transaction_id << 4);
+ gh->msg_type = msg_type;
+
+ if (msg_type == GSM0480_MTYPE_FACILITY) {
+ /* directly transmit data on established connection */
+ return gsm480_to_mm(msg, trans, GSM48_MMSS_DATA_REQ);
+ } else {
+ /* store header until our MM connection is established */
+ trans->ss.msg = msg;
+
+ /* request establishment */
+ msg = gsm480_msgb_alloc();
+ if (!msg) {
+ trans_free(trans);
+ return -ENOMEM;
+ }
+ return gsm480_to_mm(msg, trans, GSM48_MMSS_EST_REQ);
+ }
+}
+
+static int gsm480_tx_cf(struct gsm_trans *trans, uint8_t msg_type,
+ uint8_t op_code, uint8_t ss_code, const char *dest)
+{
+ struct msgb *msg;
+
+ /* allocate message */
+ msg = gsm480_msgb_alloc();
+ if (!msg) {
+ trans_free(trans);
+ return -ENOMEM;
+ }
+
+ if (dest) {
+ uint8_t tlv[32];
+ int rc;
+
+ /* Forwarding To address */
+ tlv[0] = 0x84;
+ tlv[2] = 0x80; /* no extension */
+ tlv[2] |= ((dest[0] == '+') ? 0x01 : 0x00) << 4; /* type */
+ tlv[2] |= 0x1; /* plan*/
+ rc = gsm48_encode_bcd_number(tlv + 1, sizeof(tlv) - 1, 1,
+ dest + (dest[0] == '+'));
+ if (rc < 0) {
+ msgb_free(msg);
+ trans_free(trans);
+ return -EINVAL;
+ }
+ memcpy(msgb_put(msg, rc + 1), tlv, rc + 1);
+ }
+
+ /* Encode ss-Code */
+ msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, ss_code);
+
+ /* Then wrap these as a Sequence */
+ msgb_wrap_with_TL_asn(msg, GSM_0480_SEQUENCE_TAG);
+
+ /* Pre-pend the operation code */
+ msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, op_code);
+
+ return gsm480_tx_invoke(trans, msg, msg_type);
+}
+
+static int gsm480_tx_ussd(struct gsm_trans *trans, uint8_t msg_type,
+ const char *text)
+{
+ struct msgb *msg;
+ int length;
+
+ /* allocate message */
+ msg = gsm480_msgb_alloc();
+ if (!msg) {
+ trans_free(trans);
+ return -ENOMEM;
+ }
+
+ /* Encode service request */
+ length = gsm_7bit_encode(msg->data, text);
+ msgb_put(msg, length);
+
+ /* Then wrap it as an Octet String */
+ msgb_wrap_with_TL_asn(msg, ASN1_OCTET_STRING_TAG);
+
+ /* Pre-pend the DCS octet string */
+ msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, 0x0F);
+
+ /* Then wrap these as a Sequence */
+ msgb_wrap_with_TL_asn(msg, GSM_0480_SEQUENCE_TAG);
+
+ if (msg_type == GSM0480_MTYPE_FACILITY) {
+ /* Pre-pend the operation code */
+ msgb_push_TLV1(msg, GSM0480_OPERATION_CODE,
+ GSM0480_OP_CODE_USS_REQUEST);
+
+ /* Then wrap these as a Sequence */
+ msgb_wrap_with_TL_asn(msg, GSM_0480_SEQUENCE_TAG);
+ } else {
+ /* Pre-pend the operation code */
+ msgb_push_TLV1(msg, GSM0480_OPERATION_CODE,
+ GSM0480_OP_CODE_PROCESS_USS_REQ);
+ }
+
+ return gsm480_tx_invoke(trans, msg, msg_type);
+}
+
+/* create and send service code */
+int ss_send(struct osmocom_ms *ms, const char *code, int new_trans)
+{
+ struct gsm_trans *trans = NULL, *transt;
+ uint8_t transaction_id;
+
+ /* look for an old transaction */
+ if (!new_trans) {
+ llist_for_each_entry(transt, &ms->trans_list, entry) {
+ if (transt->protocol == GSM48_PDISC_NC_SS) {
+ trans = transt;
+ break;
+ }
+ }
+ }
+
+ /* if there is an old transaction, check if we can send data */
+ if (trans) {
+ if (trans->ss.state != GSM480_SS_ST_ACTIVE) {
+ LOGP(DSS, LOGL_INFO, "Pending trans not active.\n");
+ gsm480_ss_result(trans->ms, "Current service pending",
+ 0);
+ return 0;
+ }
+ if (!strcmp(code, "hangup")) {
+ gsm480_tx_release_compl(trans, 0);
+ gsm480_trans_free(trans);
+ return 0;
+ }
+ LOGP(DSS, LOGL_INFO, "Existing transaction.\n");
+ return gsm480_tx_ussd(trans, GSM0480_MTYPE_FACILITY, code);
+ }
+
+ /* do nothing, if hangup is received */
+ if (!strcmp(code, "hangup"))
+ return 0;
+
+ /* internal codes */
+ if (!strcmp(code, "*#06#")) {
+ return return_imei(ms);
+ }
+
+ /* no running, no transaction */
+ if (!ms->started || ms->shutdown) {
+ gsm480_ss_result(ms, "<phone is down>", 0);
+ return -EIO;
+ }
+
+ /* allocate transaction with dummy reference */
+ transaction_id = trans_assign_trans_id(ms, GSM48_PDISC_NC_SS,
+ 0);
+ if (transaction_id < 0) {
+ LOGP(DSS, LOGL_ERROR, "No transaction ID available\n");
+ gsm480_ss_result(ms, NULL,
+ GSM0480_ERR_CODE_RESOURCES_NOT_AVAILABLE);
+ return -ENOMEM;
+ }
+ trans = trans_alloc(ms, GSM48_PDISC_NC_SS, transaction_id,
+ new_callref++);
+ if (!trans) {
+ LOGP(DSS, LOGL_ERROR, "No memory for trans\n");
+ gsm480_ss_result(ms, NULL,
+ GSM0480_ERR_CODE_RESOURCES_NOT_AVAILABLE);
+ return -ENOMEM;
+ }
+
+ /* go register sent state */
+ trans->ss.state = GSM480_SS_ST_REGISTER;
+
+ /* FIXME: generate invoke ID */
+ trans->ss.invoke_id = 5;
+
+ /* interrogate */
+ if (code[0] == '*' && code[1] == '#' && code[strlen(code) - 1] == '#') {
+ uint8_t ss_code = 0;
+
+ ss_code_by_char(code + 2, &ss_code);
+ if (code)
+ return gsm480_tx_cf(trans, GSM0480_MTYPE_REGISTER,
+ GSM0480_OP_CODE_INTERROGATE_SS, ss_code, NULL);
+ } else
+ /* register / activate */
+ if (code[0] == '*' && code[strlen(code) - 1] == '#') {
+ uint8_t ss_code = 0;
+ const char *to;
+ char dest[32];
+
+ /* double star */
+ if (code[1] == '*')
+ code++;
+
+ to = ss_code_by_char(code + 1, &ss_code);
+
+ /* register */
+ if (code && to && to[0] == '*') {
+ strncpy(dest, to + 1, sizeof(dest) - 1);
+ dest[sizeof(dest) - 1] = '\0';
+ dest[strlen(dest) - 1] = '\0';
+ return gsm480_tx_cf(trans, GSM0480_MTYPE_REGISTER,
+ GSM0480_OP_CODE_REGISTER_SS, ss_code, dest);
+ }
+ /* activate */
+ if (code && to && to[0] == '#') {
+ return gsm480_tx_cf(trans, GSM0480_MTYPE_REGISTER,
+ GSM0480_OP_CODE_ACTIVATE_SS, ss_code, NULL);
+ }
+ } else
+ /* erasure */
+ if (code[0] == '#' && code[1] == '#' && code[strlen(code) - 1] == '#') {
+ uint8_t ss_code = 0;
+
+ ss_code_by_char(code + 2, &ss_code);
+
+ if (code)
+ return gsm480_tx_cf(trans, GSM0480_MTYPE_REGISTER,
+ GSM0480_OP_CODE_ERASE_SS, ss_code, NULL);
+ } else
+ /* deactivate */
+ if (code[0] == '#' && code[strlen(code) - 1] == '#') {
+ uint8_t ss_code = 0;
+
+ ss_code_by_char(code + 1, &ss_code);
+
+ if (code)
+ return gsm480_tx_cf(trans, GSM0480_MTYPE_REGISTER,
+ GSM0480_OP_CODE_DEACTIVATE_SS, ss_code, NULL);
+ }
+
+ /* other codes */
+ return gsm480_tx_ussd(trans, GSM0480_MTYPE_REGISTER, code);
+}
+
+/*
+ * decoding
+ */
+
+static int parse_tag_asn1(const uint8_t *data, int len,
+ const uint8_t **tag_data, int *tag_len)
+{
+ /* at least 2 bytes (tag + len) */
+ if (len < 2)
+ return -1;
+
+ /* extended length */
+ if (data[1] == 0x81) {
+ /* at least 2 bytes (tag + 0x81 + len) */
+ if (len < 3)
+ return -1;
+ *tag_len = data[2];
+ *tag_data = data + 3;
+ len -= 3;
+ } else {
+ *tag_len = data[1];
+ *tag_data = data + 2;
+ len -= 2;
+ }
+
+ /* check for buffer overflow */
+ if (len < *tag_len)
+ return -1;
+
+ /* return length */
+ return len;
+}
+
+static int gsm480_rx_ussd(struct gsm_trans *trans, const uint8_t *data,
+ int len)
+{
+ int num_chars;
+ char text[256];
+ int i;
+ const uint8_t *tag_data;
+ int tag_len;
+
+ /* sequence tag */
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 0) {
+ LOGP(DSS, LOGL_NOTICE, "2. Sequence tag too short\n");
+ return -EINVAL;
+ }
+ if (data[0] != GSM_0480_SEQUENCE_TAG) {
+ LOGP(DSS, LOGL_NOTICE, "Expecting 2. Sequence Tag\n");
+ return -EINVAL;
+ }
+ len = tag_len;
+ data = tag_data;
+
+ /* DSC */
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 1) {
+ LOGP(DSS, LOGL_NOTICE, "DSC tag too short\n");
+ return -EINVAL;
+ }
+ if (data[0] != ASN1_OCTET_STRING_TAG || tag_len != 1) {
+ LOGP(DSS, LOGL_NOTICE, "Expecting DSC tag\n");
+ return -EINVAL;
+ }
+ if (tag_data[0] != 0x0f) {
+ LOGP(DSS, LOGL_NOTICE, "DSC not 0x0f\n");
+ return -EINVAL;
+ }
+ len -= tag_data - data + tag_len;
+ data = tag_data + tag_len;
+
+ /* text */
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 0) {
+ LOGP(DSS, LOGL_NOTICE, "Text tag too short\n");
+ return -EINVAL;
+ }
+ if (data[0] != ASN1_OCTET_STRING_TAG) {
+ LOGP(DSS, LOGL_NOTICE, "Expecting text tag\n");
+ return -EINVAL;
+ }
+ num_chars = tag_len * 8 / 7;
+ /* Prevent a mobile-originated buffer-overrun! */
+ if (num_chars > sizeof(text) - 1)
+ num_chars = sizeof(text) - 1;
+ text[sizeof(text) - 1] = '\0';
+ gsm_7bit_decode(text, tag_data, num_chars);
+
+ for (i = 0; text[i]; i++) {
+ if (text[i] == '\r')
+ text[i] = '\n';
+ }
+ /* remove last CR, if exists */
+ if (text[0] && text[strlen(text) - 1] == '\n')
+ text[strlen(text) - 1] = '\0';
+ gsm480_ss_result(trans->ms, text, 0);
+
+ return 0;
+}
+
+static int gsm480_rx_cf(struct gsm_trans *trans, const uint8_t *data,
+ int len)
+{
+ struct osmocom_ms *ms = trans->ms;
+ const uint8_t *tag_data, *data2;
+ int tag_len, len2;
+ char number[32];
+
+ LOGP(DSS, LOGL_INFO, "call forwarding reply: len %d data %s\n", len,
+ osmo_hexdump(data, len));
+
+ vty_notify(ms, NULL);
+
+ /* forwarding feature list */
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 0) {
+ LOGP(DSS, LOGL_NOTICE, "Tag too short\n");
+ return -EINVAL;
+ }
+ if (data[0] == 0x80) {
+ if ((tag_data[0] & 0x01))
+ vty_notify(ms, "Status: activated\n");
+ else
+ vty_notify(ms, "Status: deactivated\n");
+ return 0;
+ }
+
+ switch(data[0]) {
+ case 0xa3:
+ len = tag_len;
+ data = tag_data;
+ break;
+ case 0xa0: /* forwarding info */
+ len = tag_len;
+ data = tag_data;
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 1) {
+ LOGP(DSS, LOGL_NOTICE, "Tag too short\n");
+ return -EINVAL;
+ }
+ /* check for SS code */
+ if (data[0] != 0x04)
+ break;
+ vty_notify(ms, "Reply for %s\n", decode_ss_code(tag_data[0]));
+ len -= tag_data - data + tag_len;
+ data = tag_data + tag_len;
+ /* sequence tag */
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 0) {
+ LOGP(DSS, LOGL_NOTICE, "Tag too short\n");
+ return -EINVAL;
+ }
+ if (data[0] != GSM_0480_SEQUENCE_TAG) {
+ LOGP(DSS, LOGL_NOTICE, "Expecting sequence tag\n");
+ return -EINVAL;
+ }
+ len = tag_len;
+ data = tag_data;
+ break;
+ default:
+ vty_notify(ms, "Call Forwarding reply unsupported.\n");
+ return 0;
+ }
+
+ while (len) {
+ /* sequence tag */
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 0) {
+ LOGP(DSS, LOGL_NOTICE, "Tag too short\n");
+ return -EINVAL;
+ }
+ if (data[0] != GSM_0480_SEQUENCE_TAG) {
+ len -= tag_data - data + tag_len;
+ data = tag_data + tag_len;
+ LOGP(DSS, LOGL_NOTICE, "Skipping tag 0x%x\n", data[0]);
+ continue;
+ }
+ len -= tag_data - data + tag_len;
+ data = tag_data + tag_len;
+ len2 = tag_len;
+ data2 = tag_data;
+
+ while (len2) {
+ /* tags in sequence */
+ if (parse_tag_asn1(data2, len2, &tag_data, &tag_len)
+ < 1) {
+ LOGP(DSS, LOGL_NOTICE, "Tag too short\n");
+ return -EINVAL;
+ }
+ LOGP(DSS, LOGL_INFO, "Tag: len %d data %s\n", tag_len,
+ osmo_hexdump(tag_data, tag_len));
+ switch (data2[0]) {
+ case 0x82:
+ vty_notify(ms, "Bearer Service: %s\n",
+ get_value_string(Bearerservice_vals,
+ tag_data[0]));
+ break;
+ case 0x83:
+ vty_notify(ms, "Teleservice: %s\n",
+ get_value_string(Teleservice_vals,
+ tag_data[0]));
+ break;
+ case 0x84:
+ if ((tag_data[0] & 0x01))
+ vty_notify(ms, "Status: activated\n");
+ else
+ vty_notify(ms, "Status: deactivated\n");
+ break;
+ case 0x85:
+ if (((tag_data[0] & 0x70) >> 4) == 1)
+ strcpy(number, "+");
+ else if (((tag_data[0] & 0x70) >> 4) == 1)
+ strcpy(number, "+");
+ else
+ number[0] = '\0';
+ gsm48_decode_bcd_number(number + strlen(number),
+ sizeof(number) - strlen(number),
+ tag_data - 1, 1);
+ vty_notify(ms, "Destination: %s\n", number);
+ break;
+ }
+ len2 -= tag_data - data2 + tag_len;
+ data2 = tag_data + tag_len;
+ }
+ }
+
+ return 0;
+}
+
+static int gsm480_rx_result(struct gsm_trans *trans, const uint8_t *data,
+ int len, int msg_type)
+{
+ const uint8_t *tag_data;
+ int tag_len;
+ int rc = 0;
+
+ LOGP(DSS, LOGL_INFO, "Result received (len %d)\n", len);
+
+ if (len && data[0] == 0x8d) {
+ LOGP(DSS, LOGL_NOTICE, "Skipping mysterious 0x8d\n");
+ len--;
+ data++;
+ }
+
+ /* invoke ID */
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 1) {
+ LOGP(DSS, LOGL_NOTICE, "Invoke ID too short\n");
+ return -EINVAL;
+ }
+ if (data[0] != GSM0480_COMPIDTAG_INVOKE_ID || tag_len != 1) {
+ LOGP(DSS, LOGL_NOTICE, "Expecting invoke ID\n");
+ return -EINVAL;
+ }
+
+ if (msg_type == GSM0480_CTYPE_RETURN_RESULT) {
+ if (trans->ss.invoke_id != data[2]) {
+ LOGP(DSS, LOGL_NOTICE, "Invoke ID mismatch\n");
+ }
+ }
+ /* Store invoke ID, in case we wan't to send a result. */
+ trans->ss.invoke_id = tag_data[0];
+ len -= tag_data - data + tag_len;
+ data = tag_data + tag_len;
+
+ if (!len) {
+ gsm480_ss_result(trans->ms, "<no result>", 0);
+ return 0;
+ }
+
+ /* sequence tag */
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 0) {
+ LOGP(DSS, LOGL_NOTICE, "Sequence tag too short\n");
+ return -EINVAL;
+ }
+ if (data[0] != GSM_0480_SEQUENCE_TAG) {
+ LOGP(DSS, LOGL_NOTICE, "Expecting Sequence Tag, trying "
+ "Operation Tag\n");
+ goto operation;
+ }
+ len = tag_len;
+ data = tag_data;
+
+ /* operation */
+operation:
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 1) {
+ LOGP(DSS, LOGL_NOTICE, "Operation too short\n");
+ return -EINVAL;
+ }
+ if (data[0] != GSM0480_OPERATION_CODE || tag_len != 1) {
+ LOGP(DSS, LOGL_NOTICE, "Expecting Operation Code\n");
+ return -EINVAL;
+ }
+ len -= tag_data - data + tag_len;
+ data = tag_data + tag_len;
+
+ switch (tag_data[0]) {
+ case GSM0480_OP_CODE_PROCESS_USS_REQ:
+ case GSM0480_OP_CODE_USS_REQUEST:
+ rc = gsm480_rx_ussd(trans, data, len);
+ break;
+ case GSM0480_OP_CODE_INTERROGATE_SS:
+ case GSM0480_OP_CODE_REGISTER_SS:
+ case GSM0480_OP_CODE_ACTIVATE_SS:
+ case GSM0480_OP_CODE_DEACTIVATE_SS:
+ case GSM0480_OP_CODE_ERASE_SS:
+ rc = gsm480_rx_cf(trans, data, len);
+ break;
+ default:
+ LOGP(DSS, LOGL_NOTICE, "Operation code not USS\n");
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+/* facility from BSC */
+static int gsm480_rx_fac_ie(struct gsm_trans *trans, const uint8_t *data,
+ int len)
+{
+ int rc = 0;
+ const uint8_t *tag_data;
+ int tag_len;
+
+ LOGP(DSS, LOGL_INFO, "Facility received (len %d)\n", len);
+
+ if (parse_tag_asn1(data, len, &tag_data, &tag_len) < 0) {
+ LOGP(DSS, LOGL_NOTICE, "Facility too short\n");
+ return -EINVAL;
+ }
+
+ switch (data[0]) {
+ case GSM0480_CTYPE_INVOKE:
+ case GSM0480_CTYPE_RETURN_RESULT:
+ rc = gsm480_rx_result(trans, tag_data, tag_len, data[0]);
+ break;
+ case GSM0480_CTYPE_RETURN_ERROR:
+ // FIXME: return error code
+ gsm480_ss_result(trans->ms, "<error received>", 0);
+ break;
+ case GSM0480_CTYPE_REJECT:
+ gsm480_ss_result(trans->ms, "<service rejected>", 0);
+ break;
+ default:
+ LOGP(DSS, LOGL_NOTICE, "CTYPE unknown\n");
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+static int gsm480_rx_cause_ie(struct gsm_trans *trans, const uint8_t *data,
+ int len)
+{
+ uint8_t value;
+
+ LOGP(DSS, LOGL_INFO, "Cause received (len %d)\n", len);
+
+ if (len < 2) {
+ LOGP(DSS, LOGL_NOTICE, "Cause too short\n");
+ return -EINVAL;
+ }
+ if (!(data[1] & 0x80)) {
+ if (len < 3) {
+ LOGP(DSS, LOGL_NOTICE, "Cause too short\n");
+ return -EINVAL;
+ }
+ value = data[3] & 0x7f;
+ } else
+ value = data[2] & 0x7f;
+
+ LOGP(DSS, LOGL_INFO, "Received Cause %d\n", value);
+
+ /* this is an error */
+ return -EINVAL;
+}
+
+/* release complete from BSC */
+static int gsm480_rx_release_comp(struct gsm_trans *trans, struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
+ struct tlv_parsed tp;
+ int rc = 0;
+
+ tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
+ if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
+ rc = gsm480_rx_fac_ie(trans, TLVP_VAL(&tp, GSM48_IE_FACILITY),
+ *(TLVP_VAL(&tp, GSM48_IE_FACILITY)-1));
+ } else {
+ /* facility optional */
+ LOGP(DSS, LOGL_INFO, "No facility IE received\n");
+ if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
+ rc = gsm480_rx_cause_ie(trans,
+ TLVP_VAL(&tp, GSM48_IE_CAUSE),
+ *(TLVP_VAL(&tp, GSM48_IE_CAUSE)-1));
+ }
+ }
+
+ if (rc < 0)
+ gsm480_ss_result(trans->ms, NULL, 0);
+ if (rc > 0)
+ gsm480_ss_result(trans->ms, NULL, rc);
+
+ /* remote releases */
+ gsm480_trans_free(trans);
+
+ return rc;
+}
+
+/* facility from BSC */
+static int gsm480_rx_facility(struct gsm_trans *trans, struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
+ struct tlv_parsed tp;
+ int rc = 0;
+
+ /* go register state */
+ trans->ss.state = GSM480_SS_ST_ACTIVE;
+
+ tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len,
+ GSM48_IE_FACILITY, 0);
+ if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
+ rc = gsm480_rx_fac_ie(trans, TLVP_VAL(&tp, GSM48_IE_FACILITY),
+ *(TLVP_VAL(&tp, GSM48_IE_FACILITY)-1));
+ } else {
+ LOGP(DSS, LOGL_INFO, "No facility IE received\n");
+ /* release 3.7.5 */
+ gsm480_tx_release_compl(trans, 96);
+ /* local releases */
+ gsm480_trans_free(trans);
+ }
+
+ if (rc < 0)
+ gsm480_ss_result(trans->ms, NULL, 0);
+ if (rc > 0)
+ gsm480_ss_result(trans->ms, NULL, rc);
+
+ return rc;
+}
+
+/* regisster from BSC */
+static int gsm480_rx_register(struct gsm_trans *trans, struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
+ struct tlv_parsed tp;
+ int rc = 0;
+
+ /* go register state */
+ trans->ss.state = GSM480_SS_ST_ACTIVE;
+
+ tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
+ if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
+ rc = gsm480_rx_fac_ie(trans, TLVP_VAL(&tp, GSM48_IE_FACILITY),
+ *(TLVP_VAL(&tp, GSM48_IE_FACILITY)-1));
+ } else {
+ /* facility optional */
+ LOGP(DSS, LOGL_INFO, "No facility IE received\n");
+ /* release 3.7.5 */
+ gsm480_tx_release_compl(trans, 96);
+ /* local releases */
+ gsm480_trans_free(trans);
+ }
+
+ if (rc < 0)
+ gsm480_ss_result(trans->ms, NULL, 0);
+ if (rc > 0)
+ gsm480_ss_result(trans->ms, NULL, rc);
+
+ return rc;
+}
+
+/*
+ * message handling
+ */
+
+/* push MMSS header and send to MM */
+static int gsm480_to_mm(struct msgb *msg, struct gsm_trans *trans,
+ int msg_type)
+{
+ struct gsm48_mmxx_hdr *mmh;
+
+ /* set l3H */
+ msg->l3h = msg->data;
+
+ /* push RR header */
+ msgb_push(msg, sizeof(struct gsm48_mmxx_hdr));
+ mmh = (struct gsm48_mmxx_hdr *)msg->data;
+ mmh->msg_type = msg_type;
+ mmh->ref = trans->callref;
+ mmh->transaction_id = trans->transaction_id;
+ mmh->sapi = 0;
+ mmh->emergency = 0;
+
+ /* send message to MM */
+ LOGP(DSS, LOGL_INFO, "Sending '%s' to MM (callref=%x, "
+ "transaction_id=%d)\n", get_mmxx_name(msg_type), trans->callref,
+ trans->transaction_id);
+ return gsm48_mmxx_downmsg(trans->ms, msg);
+}
+
+/* receive est confirm from MM layer */
+static int gsm480_mmss_est(int mmss_msg, struct gsm_trans *trans,
+ struct msgb *msg)
+{
+ struct osmocom_ms *ms = trans->ms;
+ struct msgb *temp;
+
+ LOGP(DSS, LOGL_INFO, "(ms %s) Received confirm, sending pending SS\n",
+ ms->name);
+
+ /* remove transaction, if no SS message */
+ if (!trans->ss.msg) {
+ LOGP(DSS, LOGL_ERROR, "(ms %s) No pending SS!\n", ms->name);
+ gsm480_trans_free(trans);
+ return -EINVAL;
+ }
+
+ /* detach message and then send */
+ temp = trans->ss.msg;
+ trans->ss.msg = NULL;
+ return gsm480_to_mm(temp, trans, GSM48_MMSS_DATA_REQ);
+}
+
+/* receive data indication from MM layer */
+static int gsm480_mmss_ind(int mmss_msg, struct gsm_trans *trans,
+ struct msgb *msg)
+{
+ struct osmocom_ms *ms = trans->ms;
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ int msg_type = gh->msg_type & 0xbf;
+ int rc = 0;
+
+ /* pull the MMSS header */
+ msgb_pull(msg, sizeof(struct gsm48_mmxx_hdr));
+
+ LOGP(DSS, LOGL_INFO, "(ms %s) Received est/data '%u'\n", ms->name,
+ msg_type);
+
+ switch (msg_type) {
+ case GSM0480_MTYPE_RELEASE_COMPLETE:
+ rc = gsm480_rx_release_comp(trans, msg);
+ break;
+ case GSM0480_MTYPE_FACILITY:
+ rc = gsm480_rx_facility(trans, msg);
+ break;
+ case GSM0480_MTYPE_REGISTER:
+ rc = gsm480_rx_register(trans, msg);
+ break;
+ default:
+ LOGP(DSS, LOGL_NOTICE, "Message unhandled.\n");
+ /* release 3.7.4 */
+ gsm480_tx_release_compl(trans, 97);
+ gsm480_trans_free(trans);
+ rc = -ENOTSUP;
+ }
+ return 0;
+}
+
+/* receive message from MM layer */
+int gsm480_rcv_ss(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
+ int msg_type = mmh->msg_type;
+ struct gsm_trans *trans;
+ int rc = 0;
+
+ trans = trans_find_by_callref(ms, mmh->ref);
+ if (!trans) {
+ LOGP(DSS, LOGL_INFO, " -> (new transaction)\n");
+ trans = trans_alloc(ms, GSM48_PDISC_NC_SS, mmh->transaction_id,
+ mmh->ref);
+ if (!trans)
+ return -ENOMEM;
+ }
+
+ LOGP(DSS, LOGL_INFO, "(ms %s) Received '%s' from MM\n", ms->name,
+ get_mmxx_name(msg_type));
+
+ switch (msg_type) {
+ case GSM48_MMSS_EST_CNF:
+ rc = gsm480_mmss_est(msg_type, trans, msg);
+ break;
+ case GSM48_MMSS_EST_IND:
+ case GSM48_MMSS_DATA_IND:
+ rc = gsm480_mmss_ind(msg_type, trans, msg);
+ break;
+ case GSM48_MMSS_REL_IND:
+ case GSM48_MMSS_ERR_IND:
+ LOGP(DSS, LOGL_INFO, "MM connection released.\n");
+ trans_free(trans);
+ break;
+ default:
+ LOGP(DSS, LOGL_NOTICE, "Message unhandled.\n");
+ rc = -ENOTSUP;
+ }
+
+ return rc;
+}
+
diff --git a/Src/osmolib/src/host/layer23/src/mobile/gsm48_cc.c b/Src/osmolib/src/host/layer23/src/mobile/gsm48_cc.c
index 2e97819..38dfab0 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/gsm48_cc.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/gsm48_cc.c
@@ -43,7 +43,7 @@ extern void *l23_ctx;
static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
static int gsm48_rel_null_free(struct gsm_trans *trans);
int mncc_release_ind(struct osmocom_ms *ms, struct gsm_trans *trans,
- u_int32_t callref, int location, int value);
+ uint32_t callref, int location, int value);
static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg);
@@ -173,6 +173,7 @@ static int gsm48_cc_to_mm(struct msgb *msg, struct gsm_trans *trans,
mmh->msg_type = msg_type;
mmh->ref = trans->callref;
mmh->transaction_id = trans->transaction_id;
+ mmh->sapi = 0;
mmh->emergency = emergency;
/* send message to MM */
@@ -215,7 +216,7 @@ int mncc_dequeue(struct osmocom_ms *ms)
struct gsm_mncc *mncc;
struct msgb *msg;
int work = 0;
-
+
while ((msg = msgb_dequeue(&cc->mncc_upqueue))) {
mncc = (struct gsm_mncc *)msg->data;
if (ms->mncc_entity.mncc_recv)
@@ -223,7 +224,7 @@ int mncc_dequeue(struct osmocom_ms *ms)
work = 1; /* work done */
msgb_free(msg);
}
-
+
return work;
}
@@ -392,7 +393,7 @@ static int gsm48_rel_null_free(struct gsm_trans *trans)
/* release MM connection */
nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_REL_REQ, trans->callref,
- trans->transaction_id);
+ trans->transaction_id, 0);
if (!nmsg)
return -ENOMEM;
LOGP(DCC, LOGL_INFO, "Sending MMCC_REL_REQ\n");
@@ -416,7 +417,7 @@ void mncc_set_cause(struct gsm_mncc *data, int loc, int val)
/* send release indication to upper layer */
int mncc_release_ind(struct osmocom_ms *ms, struct gsm_trans *trans,
- u_int32_t callref, int location, int value)
+ uint32_t callref, int location, int value)
{
struct gsm_mncc rel;
@@ -497,7 +498,7 @@ static int gsm48_cc_init_mm(struct gsm_trans *trans, void *arg)
/* establish MM connection */
nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_EST_REQ, trans->callref,
- trans->transaction_id);
+ trans->transaction_id, 0);
if (!nmsg)
return -ENOMEM;
nmmh = (struct gsm48_mmxx_hdr *) nmsg->data;
@@ -514,7 +515,7 @@ static int gsm48_cc_abort_mm(struct gsm_trans *trans, void *arg)
/* abort MM connection */
nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_REL_REQ, trans->callref,
- trans->transaction_id);
+ trans->transaction_id, 0);
if (!nmsg)
return -ENOMEM;
LOGP(DCC, LOGL_INFO, "Sending MMCC_REL_REQ\n");
@@ -556,7 +557,7 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans)
trans_free(trans);
return rc;
}
-
+
/* Get free transaction_id */
transaction_id = trans_assign_trans_id(trans->ms, GSM48_PDISC_CC, 0);
if (transaction_id < 0) {
@@ -712,7 +713,7 @@ static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
struct tlv_parsed tp;
struct gsm_mncc alerting;
-
+
LOGP(DCC, LOGL_INFO, "received ALERTING\n");
gsm48_stop_cc_timer(trans);
@@ -945,7 +946,7 @@ static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
gsm48_encode_ssversion(nmsg, &alerting->ssversion);
new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
-
+
return gsm48_cc_to_mm(nmsg, trans, GSM48_MMCC_DATA_REQ);
}
@@ -993,7 +994,7 @@ static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
gsm48_stop_cc_timer(trans);
new_cc_state(trans, GSM_CSTATE_ACTIVE);
-
+
memset(&connect_ack, 0, sizeof(struct gsm_mncc));
connect_ack.callref = trans->callref;
return mncc_recvmsg(trans->ms, trans, MNCC_SETUP_COMPL_IND,
@@ -1846,7 +1847,7 @@ static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
/* state trasitions for MNCC messages (upper layer) */
static struct downstate {
- u_int32_t states;
+ uint32_t states;
int type;
int (*rout) (struct gsm_trans *trans, void *arg);
} downstatelist[] = {
@@ -1991,12 +1992,12 @@ int mncc_tx_to_cc(void *inst, int msg_type, void *arg)
if ((msg_type == downstatelist[i].type)
&& ((1 << trans->cc.state) & downstatelist[i].states))
break;
- if (i == DOWNSLLEN) {
- LOGP(DCC, LOGL_NOTICE, "Message %d unhandled at state "
- "%d\n", msg_type, trans->cc.state);
- return 0;
- }
-
+ if (i == DOWNSLLEN) {
+ LOGP(DCC, LOGL_NOTICE, "Message %d unhandled at state %d\n",
+ msg_type, trans->cc.state);
+ return 0;
+ }
+
rc = downstatelist[i].rout(trans, arg);
return rc;
@@ -2004,7 +2005,7 @@ int mncc_tx_to_cc(void *inst, int msg_type, void *arg)
/* state trasitions for call control messages (lower layer) */
static struct datastate {
- u_int32_t states;
+ uint32_t states;
int type;
int (*rout) (struct gsm_trans *trans, struct msgb *msg);
} datastatelist[] = {
@@ -2021,7 +2022,7 @@ static struct datastate {
GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
{SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC) |
- SBIT(GSM_CSTATE_CALL_DELIVERED), /* 5.2.1.6 */
+ SBIT(GSM_CSTATE_CALL_DELIVERED), /* 5.2.1.6 */
GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
/* mobile terminating call establishment */
diff --git a/Src/osmolib/src/host/layer23/src/mobile/gsm48_mm.c b/Src/osmolib/src/host/layer23/src/mobile/gsm48_mm.c
index ff936e3..a8f699d 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/gsm48_mm.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/gsm48_mm.c
@@ -36,6 +36,8 @@
#include <osmocom/bb/common/networks.h>
#include <osmocom/bb/common/l1ctl.h>
#include <osmocom/bb/mobile/gsm48_cc.h>
+#include <osmocom/bb/mobile/gsm480_ss.h>
+#include <osmocom/bb/mobile/gsm411_sms.h>
#include <osmocom/bb/mobile/app_mobile.h>
#include <osmocom/bb/mobile/vty.h>
@@ -661,7 +663,7 @@ const char *get_mmr_name(int value)
/* allocate GSM 04.08 message (MMxx-SAP) */
struct msgb *gsm48_mmxx_msgb_alloc(int msg_type, uint32_t ref,
- uint8_t transaction_id)
+ uint8_t transaction_id, uint8_t sapi)
{
struct msgb *msg;
struct gsm48_mmxx_hdr *mmh;
@@ -675,6 +677,7 @@ struct msgb *gsm48_mmxx_msgb_alloc(int msg_type, uint32_t ref,
mmh->msg_type = msg_type;
mmh->ref = ref;
mmh->transaction_id = transaction_id;
+ mmh->sapi = sapi;
return msg;
}
@@ -748,26 +751,24 @@ int gsm48_mmxx_dequeue(struct osmocom_ms *ms)
struct msgb *msg;
struct gsm48_mmxx_hdr *mmh;
int work = 0;
-
+
while ((msg = msgb_dequeue(&mm->mmxx_upqueue))) {
mmh = (struct gsm48_mmxx_hdr *) msg->data;
switch (mmh->msg_type & GSM48_MMXX_MASK) {
case GSM48_MMCC_CLASS:
gsm48_rcv_cc(ms, msg);
break;
-#if 0
case GSM48_MMSS_CLASS:
- gsm48_rcv_ss(ms, msg);
+ gsm480_rcv_ss(ms, msg);
break;
case GSM48_MMSMS_CLASS:
- gsm48_rcv_sms(ms, msg);
+ gsm411_rcv_sms(ms, msg);
break;
-#endif
}
msgb_free(msg);
work = 1; /* work done */
}
-
+
return work;
}
@@ -778,14 +779,14 @@ int gsm48_mmr_dequeue(struct osmocom_ms *ms)
struct msgb *msg;
struct gsm48_mmr *mmr;
int work = 0;
-
+
while ((msg = msgb_dequeue(&mm->mmr_downqueue))) {
mmr = (struct gsm48_mmr *) msg->data;
gsm48_rcv_mmr(ms, msg);
msgb_free(msg);
work = 1; /* work done */
}
-
+
return work;
}
@@ -795,13 +796,13 @@ int gsm48_rr_dequeue(struct osmocom_ms *ms)
struct gsm48_mmlayer *mm = &ms->mmlayer;
struct msgb *msg;
int work = 0;
-
+
while ((msg = msgb_dequeue(&mm->rr_upqueue))) {
/* msg is freed there */
gsm48_rcv_rr(ms, msg);
work = 1; /* work done */
}
-
+
return work;
}
@@ -812,20 +813,20 @@ int gsm48_mmevent_dequeue(struct osmocom_ms *ms)
struct gsm48_mm_event *mme;
struct msgb *msg;
int work = 0;
-
+
while ((msg = msgb_dequeue(&mm->event_queue))) {
mme = (struct gsm48_mm_event *) msg->data;
gsm48_mm_ev(ms, mme->msg_type, msg);
msgb_free(msg);
work = 1; /* work done */
}
-
+
return work;
}
/* push RR header and send to RR */
-static int gsm48_mm_to_rr(struct osmocom_ms *ms, struct msgb *msg,
- int msg_type, uint8_t cause)
+static int gsm48_mm_to_rr(struct osmocom_ms *ms, struct msgb *msg, int msg_type,
+ uint8_t sapi, uint8_t cause)
{
struct gsm48_rr_hdr *rrh;
@@ -833,6 +834,7 @@ static int gsm48_mm_to_rr(struct osmocom_ms *ms, struct msgb *msg,
msgb_push(msg, sizeof(struct gsm48_rr_hdr));
rrh = (struct gsm48_rr_hdr *) msg->data;
rrh->msg_type = msg_type;
+ rrh->sapi = sapi;
rrh->cause = cause;
/* send message to RR */
@@ -927,7 +929,7 @@ static void new_mm_state(struct gsm48_mmlayer *mm, int state, int substate)
switch (substate) {
case GSM48_MM_SST_NORMAL_SERVICE:
vty_notify(ms, NULL);
- vty_notify(ms, "On Network, normal service: %s, %s\n",
+ vty_notify(ms, "On Network, normal service: %s, %s\n",
gsm_get_mcc(plmn->mcc),
gsm_get_mnc(plmn->mcc, plmn->mnc));
break;
@@ -1117,8 +1119,9 @@ static int gsm48_mm_return_idle(struct osmocom_ms *ms, struct msgb *msg)
return 0;
}
- /* selected cell equals the registered LAI */
- if (subscr->lac /* valid */
+ /* if we are attached and selected cell equals the registered LAI */
+ if (subscr->imsi_attached
+ && subscr->lac /* valid */
&& cs->sel_mcc == subscr->mcc
&& cs->sel_mnc == subscr->mnc
&& cs->sel_lac == subscr->lac) {
@@ -1336,7 +1339,7 @@ int gsm48_mm_exit(struct osmocom_ms *ms)
/* flush lists */
while (!llist_empty(&mm->mm_conn)) {
- conn = llist_entry(mm->mm_conn.next,
+ conn = llist_entry(mm->mm_conn.next,
struct gsm48_mm_conn, list);
mm_conn_free(conn);
}
@@ -1348,7 +1351,7 @@ int gsm48_mm_exit(struct osmocom_ms *ms)
msgb_free(msg);
while ((msg = msgb_dequeue(&mm->event_queue)))
msgb_free(msg);
-
+
/* stop timers */
stop_mm_t3210(mm);
stop_mm_t3211(mm);
@@ -1413,7 +1416,7 @@ struct gsm48_mm_conn *mm_conn_by_ref(struct gsm48_mmlayer *mm,
/* create MM connection instance */
static struct gsm48_mm_conn* mm_conn_new(struct gsm48_mmlayer *mm,
- int proto, uint8_t transaction_id, uint32_t ref)
+ int proto, uint8_t transaction_id, uint8_t sapi, uint32_t ref)
{
struct gsm48_mm_conn *conn = talloc_zero(l23_ctx, struct gsm48_mm_conn);
@@ -1421,12 +1424,13 @@ static struct gsm48_mm_conn* mm_conn_new(struct gsm48_mmlayer *mm,
return NULL;
LOGP(DMM, LOGL_INFO, "New MM Connection (proto 0x%02x trans_id %d "
- "ref %d)\n", proto, transaction_id, ref);
+ "sapi %d ref %x)\n", proto, transaction_id, sapi, ref);
conn->mm = mm;
conn->state = GSM48_MMXX_ST_IDLE;
conn->transaction_id = transaction_id;
conn->protocol = proto;
+ conn->sapi = sapi;
conn->ref = ref;
llist_add(&conn->list, &mm->mm_conn);
@@ -1448,22 +1452,27 @@ void mm_conn_free(struct gsm48_mm_conn *conn)
/* support function to release pending/all ongoing MM connections */
static int gsm48_mm_release_mm_conn(struct osmocom_ms *ms, int abort_any,
- uint8_t cause, int error)
+ uint8_t cause, int error, uint8_t sapi)
{
struct gsm48_mmlayer *mm = &ms->mmlayer;
struct gsm48_mm_conn *conn, *conn2;
struct msgb *nmsg;
struct gsm48_mmxx_hdr *nmmh;
+ /* Note: For SAPI 0 all connections are released */
+
if (abort_any)
- LOGP(DMM, LOGL_INFO, "Release any MM Connection\n");
+ LOGP(DMM, LOGL_INFO, "Release any MM Connection "
+ "(sapi = %d)\n", sapi);
else
- LOGP(DMM, LOGL_INFO, "Release pending MM Connections\n");
+ LOGP(DMM, LOGL_INFO, "Release pending MM Connections "
+ "(sapi = %d)\n", sapi);
/* release MM connection(s) */
llist_for_each_entry_safe(conn, conn2, &mm->mm_conn, list) {
/* abort any OR the pending connection */
- if (abort_any || conn->state == GSM48_MMXX_ST_CONN_PEND) {
+ if ((abort_any || conn->state == GSM48_MMXX_ST_CONN_PEND)
+ && (sapi == conn->sapi || sapi == 0)) {
/* send MMxx-REL-IND */
nmsg = NULL;
switch(conn->protocol) {
@@ -1471,19 +1480,22 @@ static int gsm48_mm_release_mm_conn(struct osmocom_ms *ms, int abort_any,
nmsg = gsm48_mmxx_msgb_alloc(
error ? GSM48_MMCC_ERR_IND
: GSM48_MMCC_REL_IND, conn->ref,
- conn->transaction_id);
+ conn->transaction_id,
+ conn->sapi);
break;
case GSM48_PDISC_NC_SS:
nmsg = gsm48_mmxx_msgb_alloc(
error ? GSM48_MMSS_ERR_IND
: GSM48_MMSS_REL_IND, conn->ref,
- conn->transaction_id);
+ conn->transaction_id,
+ conn->sapi);
break;
case GSM48_PDISC_SMS:
nmsg = gsm48_mmxx_msgb_alloc(
error ? GSM48_MMSMS_ERR_IND
: GSM48_MMSMS_REL_IND, conn->ref,
- conn->transaction_id);
+ conn->transaction_id,
+ conn->sapi);
break;
}
if (!nmsg) {
@@ -1525,7 +1537,7 @@ static int gsm48_mm_tx_mm_status(struct osmocom_ms *ms, uint8_t cause)
*reject_cause = cause;
/* push RR header and send down */
- return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0);
+ return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0);
}
/* 4.3.1.2 sending TMSI REALLOCATION COMPLETE message */
@@ -1545,7 +1557,7 @@ static int gsm48_mm_tx_tmsi_reall_cpl(struct osmocom_ms *ms)
ngh->msg_type = GSM48_MT_MM_TMSI_REALL_COMPL;
/* push RR header and send down */
- return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0);
+ return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0);
}
/* 4.3.1 TMSI REALLOCATION COMMAND is received */
@@ -1661,7 +1673,7 @@ static int gsm48_mm_tx_auth_rsp(struct osmocom_ms *ms, struct msgb *msg)
memcpy(sres, mme->sres, 4);
/* push RR header and send down */
- return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0);
+ return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0);
}
/* 4.3.2.5 AUTHENTICATION REJECT is received */
@@ -1766,7 +1778,7 @@ static int gsm48_mm_tx_id_rsp(struct osmocom_ms *ms, uint8_t mi_type)
gsm48_encode_mi(buf, nmsg, ms, mi_type);
/* push RR header and send down */
- return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0);
+ return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0);
}
/* 4.3.4.1 sending IMSI DETACH INDICATION message */
@@ -1814,7 +1826,7 @@ static int gsm48_mm_tx_imsi_detach(struct osmocom_ms *ms, int rr_prim)
/* push RR header and send down */
mm->est_cause = RR_EST_CAUSE_OTHER_SDCCH;
- return gsm48_mm_to_rr(ms, nmsg, rr_prim, mm->est_cause);
+ return gsm48_mm_to_rr(ms, nmsg, rr_prim, 0, mm->est_cause);
}
/* detach has ended */
@@ -1829,7 +1841,6 @@ static int gsm48_mm_imsi_detach_end(struct osmocom_ms *ms, struct msgb *msg)
/* stop IMSI detach timer (if running) */
stop_mm_t3220(mm);
-
/* SIM invalid */
subscr->sim_valid = 0;
@@ -1856,6 +1867,24 @@ static int gsm48_mm_imsi_detach_end(struct osmocom_ms *ms, struct msgb *msg)
return gsm48_mm_return_idle(ms, NULL);
}
+/* abort radio connection */
+static int gsm48_mm_imsi_detach_abort(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct msgb *nmsg;
+ struct gsm48_rr_hdr *nrrh;
+
+ /* abort RR if timer fired */
+ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_ABORT_REQ);
+ if (!nmsg)
+ return -ENOMEM;
+ nrrh = (struct gsm48_rr_hdr *) nmsg->data;
+ nrrh->cause = GSM48_RR_CAUSE_NORMAL;
+ gsm48_rr_downmsg(ms, nmsg);
+
+ /* imsi detach has ended now */
+ return gsm48_mm_imsi_detach_end(ms, msg);
+}
+
/* start an IMSI detach in MM IDLE */
static int gsm48_mm_imsi_detach_start(struct osmocom_ms *ms, struct msgb *msg)
{
@@ -1891,7 +1920,7 @@ static int gsm48_mm_imsi_detach_sent(struct osmocom_ms *ms, struct msgb *msg)
return 0;
}
-
+
/* release MM connection and proceed with IMSI detach */
static int gsm48_mm_imsi_detach_release(struct osmocom_ms *ms, struct msgb *msg)
{
@@ -1903,7 +1932,7 @@ static int gsm48_mm_imsi_detach_release(struct osmocom_ms *ms, struct msgb *msg)
stop_mm_t3230(mm);
/* release all connections */
- gsm48_mm_release_mm_conn(ms, 1, 16, 0);
+ gsm48_mm_release_mm_conn(ms, 1, 16, 0, 0);
/* wait for release of RR */
if (!s->att_allowed || !subscr->imsi_attached) {
@@ -1972,10 +2001,10 @@ static int gsm48_mm_rx_abort(struct osmocom_ms *ms, struct msgb *msg)
/* stop MM connection timer */
stop_mm_t3230(mm);
- gsm48_mm_release_mm_conn(ms, 1, 16, 0);
+ gsm48_mm_release_mm_conn(ms, 1, 16, 0, 0);
}
- if (reject_cause == GSM48_REJECT_ILLEGAL_ME) {
+ if (reject_cause == GSM48_REJECT_ILLEGAL_ME) {
/* SIM invalid */
subscr->sim_valid = 0;
@@ -2038,7 +2067,7 @@ static int gsm48_mm_sysinfo(struct osmocom_ms *ms, struct msgb *msg)
struct gsm48_mmlayer *mm = &ms->mmlayer;
struct gsm48_sysinfo *s = &ms->cellsel.sel_si;
- /* t3212 not changed in these states */
+ /* t3212 not changed in these states */
if (mm->state == GSM48_MM_ST_MM_IDLE
&& (mm->substate == GSM48_MM_SST_NO_CELL_AVAIL
|| mm->substate == GSM48_MM_SST_LIMITED_SERVICE
@@ -2074,7 +2103,7 @@ static int gsm48_mm_sysinfo(struct osmocom_ms *ms, struct msgb *msg)
}
mm->t3212_value = s->t3212;
}
-
+
return 0;
}
@@ -2095,7 +2124,7 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
struct gsm_settings *set = &ms->settings;
struct msgb *nmsg;
int msg_type;
-
+
/* (re)start only if we still require location update */
if (!mm->lupd_pending) {
LOGP(DMM, LOGL_INFO, "No loc. upd. pending.\n");
@@ -2315,7 +2344,7 @@ static int gsm48_mm_tx_loc_upd_req(struct osmocom_ms *ms)
/* location updating type */
nlu->type = mm->lupd_type;
/* cipering key */
- nlu->key_seq = subscr->key_seq;
+ nlu->key_seq = gsm_subscr_get_key_seq(ms, subscr);
/* LAI (last SIM stored LAI)
*
* NOTE: The TMSI is only valid within a LAI!
@@ -2343,7 +2372,7 @@ static int gsm48_mm_tx_loc_upd_req(struct osmocom_ms *ms)
/* push RR header and send down */
mm->est_cause = RR_EST_CAUSE_LOC_UPD;
- return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_EST_REQ, mm->est_cause);
+ return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_EST_REQ, 0, mm->est_cause);
}
/* 4.4.4.1 RR is esablised during location update */
@@ -2511,7 +2540,7 @@ static int gsm48_mm_rx_loc_upd_rej(struct osmocom_ms *ms, struct msgb *msg)
start_mm_t3240(mm);
new_mm_state(mm, GSM48_MM_ST_LOC_UPD_REJ, 0);
-
+
return 0;
}
@@ -2522,7 +2551,7 @@ static int gsm48_mm_rel_loc_upd_rej(struct osmocom_ms *ms, struct msgb *msg)
struct gsm_subscriber *subscr = &ms->subscr;
struct msgb *nmsg;
struct gsm322_msg *ngm;
-
+
LOGP(DMM, LOGL_INFO, "Loc. upd. rejected (cause %d)\n",
mm->lupd_rej_cause);
@@ -2777,7 +2806,7 @@ static int gsm48_mm_tx_cm_serv_req(struct osmocom_ms *ms, int rr_prim,
/* type and key */
nsr->cm_service_type = cm_serv;
- nsr->cipher_key_seq = subscr->key_seq;
+ nsr->cipher_key_seq = gsm_subscr_get_key_seq(ms, subscr);
/* classmark 2 */
cm2lv[0] = sizeof(struct gsm48_classmark2);
gsm48_rr_enc_cm2(ms, (struct gsm48_classmark2 *)(cm2lv + 1),
@@ -2807,7 +2836,7 @@ static int gsm48_mm_tx_cm_serv_req(struct osmocom_ms *ms, int rr_prim,
/* prio is optional for eMLPP */
/* push RR header and send down */
- return gsm48_mm_to_rr(ms, nmsg, rr_prim, mm->est_cause);
+ return gsm48_mm_to_rr(ms, nmsg, rr_prim, 0, mm->est_cause);
}
/* cm service abort message from upper layer
@@ -2829,7 +2858,7 @@ static int gsm48_mm_tx_cm_service_abort(struct osmocom_ms *ms)
ngh->msg_type = GSM48_MT_MM_CM_SERV_ABORT;
/* push RR header and send down */
- return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0);
+ return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0);
}
/* cm service acknowledge is received from lower layer */
@@ -2900,7 +2929,7 @@ static int gsm48_mm_rx_cm_service_rej(struct osmocom_ms *ms, struct msgb *msg)
}
/* release MM connection(s) */
- gsm48_mm_release_mm_conn(ms, abort_any, 16, 0);
+ gsm48_mm_release_mm_conn(ms, abort_any, 16, 0, 0);
/* state depends on the existance of remaining MM connections */
if (llist_empty(&mm->mm_conn))
@@ -2930,6 +2959,7 @@ static int gsm48_mm_init_mm(struct osmocom_ms *ms, struct msgb *msg,
struct msgb *nmsg;
struct gsm48_mmxx_hdr *nmmh;
struct gsm48_mm_conn *conn, *conn_found = NULL;
+ uint8_t sapi = mmh->sapi;
/* reset loc. upd. counter on CM service request */
mm->lupd_attempt = 0;
@@ -2947,20 +2977,24 @@ static int gsm48_mm_init_mm(struct osmocom_ms *ms, struct msgb *msg,
LOGP(DMM, LOGL_INFO, "Init MM Connection, but already have "
"pending MM Connection.\n");
cause = 17;
+ /* use sapi from connection. if no connection, use sapi from
+ * message.
+ */
+ sapi = conn_found->sapi;
reject:
nmsg = NULL;
switch(msg_type) {
case GSM48_MMCC_EST_REQ:
nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_REL_IND,
- mmh->ref, mmh->transaction_id);
+ mmh->ref, mmh->transaction_id, sapi);
break;
case GSM48_MMSS_EST_REQ:
nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSS_REL_IND,
- mmh->ref, mmh->transaction_id);
+ mmh->ref, mmh->transaction_id, sapi);
break;
case GSM48_MMSMS_EST_REQ:
nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSMS_REL_IND,
- mmh->ref, mmh->transaction_id);
+ mmh->ref, mmh->transaction_id, sapi);
break;
}
if (!nmsg)
@@ -3039,7 +3073,7 @@ static int gsm48_mm_init_mm(struct osmocom_ms *ms, struct msgb *msg,
}
/* create MM connection instance */
- conn = mm_conn_new(mm, proto, mmh->transaction_id, mmh->ref);
+ conn = mm_conn_new(mm, proto, mmh->transaction_id, mmh->sapi, mmh->ref);
if (!conn)
return -ENOMEM;
@@ -3166,6 +3200,7 @@ static int gsm48_mm_init_mm_reject(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
int msg_type = mmh->msg_type;
+ int sapi = mmh->sapi;
struct msgb *nmsg;
struct gsm48_mmxx_hdr *nmmh;
@@ -3174,15 +3209,15 @@ static int gsm48_mm_init_mm_reject(struct osmocom_ms *ms, struct msgb *msg)
switch(msg_type) {
case GSM48_MMCC_EST_REQ:
nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_REL_IND, mmh->ref,
- mmh->transaction_id);
+ mmh->transaction_id, sapi);
break;
case GSM48_MMSS_EST_REQ:
nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSS_REL_IND, mmh->ref,
- mmh->transaction_id);
+ mmh->transaction_id, sapi);
break;
case GSM48_MMSMS_EST_REQ:
nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSMS_REL_IND, mmh->ref,
- mmh->transaction_id);
+ mmh->transaction_id, sapi);
break;
}
if (!nmsg)
@@ -3198,7 +3233,7 @@ static int gsm48_mm_init_mm_reject(struct osmocom_ms *ms, struct msgb *msg)
*
* this function is called:
* - when ciphering command is received
- * - when cm service is accepted
+ * - when cm service is accepted
*/
static int gsm48_mm_conn_go_dedic(struct osmocom_ms *ms)
{
@@ -3228,22 +3263,33 @@ static int gsm48_mm_conn_go_dedic(struct osmocom_ms *ms)
nmsg = NULL;
switch(conn_found->protocol) {
case GSM48_PDISC_CC:
- nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_EST_CNF, conn->ref,
- conn->transaction_id);
+ nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_EST_CNF,
+ conn_found->ref, conn_found->transaction_id,
+ conn_found->sapi);
break;
case GSM48_PDISC_NC_SS:
- nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSS_EST_CNF, conn->ref,
- conn->transaction_id);
+ nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSS_EST_CNF,
+ conn_found->ref, conn_found->transaction_id,
+ conn_found->sapi);
break;
case GSM48_PDISC_SMS:
- nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSMS_EST_CNF, conn->ref,
- conn->transaction_id);
+ if (!mm->sapi3_link) {
+ LOGP(DMM, LOGL_INFO, "Sapi 3 link down, requesting "
+ "link, waiting for confirm.\n");
+ nmsg = gsm48_l3_msgb_alloc();
+ if (!nmsg)
+ return -ENOMEM;
+ return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_EST_REQ,
+ conn_found->sapi, 0);
+ }
+ nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSMS_EST_CNF,
+ conn_found->ref, conn_found->transaction_id,
+ conn_found->sapi);
break;
}
if (!nmsg)
return -ENOMEM;
nmmh = (struct gsm48_mmxx_hdr *)nmsg->data;
- nmmh->cause = 17;
gsm48_mmxx_upmsg(ms, nmsg);
return 0;
@@ -3287,13 +3333,12 @@ static int gsm48_mm_sync_ind_active(struct osmocom_ms *ms, struct msgb *msg)
switch(conn->protocol) {
case GSM48_PDISC_CC:
nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_SYNC_IND,
- conn->ref, conn->transaction_id);
+ conn->ref, conn->transaction_id, conn->sapi);
break;
}
if (!nmsg)
continue; /* skip if not of CC type */
nmmh = (struct gsm48_mmxx_hdr *)nmsg->data;
- nmmh->cause = 17;
/* copy L3 message */
nmsg->l3h = msgb_put(nmsg, msgb_l3len(msg));
memcpy(nmsg->l3h, msg->l3h, msgb_l3len(msg));
@@ -3331,7 +3376,7 @@ static int gsm48_mm_abort_mm_con(struct osmocom_ms *ms, struct msgb *msg)
stop_mm_t3230(mm);
/* release all connections */
- gsm48_mm_release_mm_conn(ms, 1, cause, 1);
+ gsm48_mm_release_mm_conn(ms, 1, cause, 1, 0);
/* return to MM IDLE */
return gsm48_mm_return_idle(ms, NULL);
@@ -3343,7 +3388,7 @@ static int gsm48_mm_timeout_mm_con(struct osmocom_ms *ms, struct msgb *msg)
struct gsm48_mmlayer *mm = &ms->mmlayer;
/* release pending connection */
- gsm48_mm_release_mm_conn(ms, 0, 102, 0);
+ gsm48_mm_release_mm_conn(ms, 0, 102, 0, 0);
/* state depends on the existance of remaining MM connections */
if (llist_empty(&mm->mm_conn)) {
@@ -3397,12 +3442,15 @@ static int gsm48_mm_data(struct osmocom_ms *ms, struct msgb *msg)
/* mirror message with REL_IND + cause */
return gsm48_mmxx_upmsg(ms, msg);
}
-
+
+ /* set SAPI, if upper layer does not do it correctly */
+ mmh->sapi = conn->sapi;
+
/* pull MM header */
msgb_pull(msg, sizeof(struct gsm48_mmxx_hdr));
/* push RR header and send down */
- return gsm48_mm_to_rr(ms, msg, GSM48_RR_DATA_REQ, 0);
+ return gsm48_mm_to_rr(ms, msg, GSM48_RR_DATA_REQ, conn->sapi, 0);
}
/* release of MM connection (active state) */
@@ -3526,6 +3574,50 @@ static int gsm48_mm_rel_other(struct osmocom_ms *ms, struct msgb *msg)
}
/*
+ * sapi 3
+ */
+
+static int gsm48_rcv_rr_sapi3(struct osmocom_ms *ms, struct msgb *msg,
+ int msg_type, uint8_t sapi)
+{
+ struct gsm48_mmlayer *mm = &ms->mmlayer;
+ struct gsm48_mm_conn *conn;
+
+ switch (msg_type) {
+ case GSM48_RR_EST_CNF:
+ LOGP(DMM, LOGL_INFO, "SAPI 3 link up, confirming conns.\n");
+ mm->sapi3_link = 1;
+ /* indicate establishment to sapi 3 connections */
+ llist_for_each_entry(conn, &mm->mm_conn, list) {
+ if (conn->sapi == sapi
+ && conn->state == GSM48_MMXX_ST_DEDICATED) {
+ struct gsm48_mmxx_hdr *nmmh;
+ struct msgb *nmsg;
+
+ nmsg = gsm48_mmxx_msgb_alloc(
+ GSM48_MMSMS_EST_CNF, conn->ref,
+ conn->transaction_id, conn->sapi);
+ if (!nmsg)
+ return -ENOMEM;
+ nmmh = (struct gsm48_mmxx_hdr *)nmsg->data;
+ gsm48_mmxx_upmsg(ms, nmsg);
+ }
+ }
+ break;
+ case GSM48_RR_DATA_IND:
+ return gsm48_mm_data_ind(ms, msg);
+ case GSM48_RR_REL_IND:
+ LOGP(DMM, LOGL_INFO, "SAPI 3 link down, releasing conns.\n");
+ mm->sapi3_link = 0;
+ gsm48_mm_release_mm_conn(ms, 1, 16, 0, sapi);
+ break;
+ }
+ msgb_free(msg);
+
+ return 0;
+}
+
+/*
* state machines
*/
@@ -3802,11 +3894,15 @@ static int gsm48_rcv_rr(struct osmocom_ms *ms, struct msgb *msg)
struct gsm48_mmlayer *mm = &ms->mmlayer;
struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *)msg->data;
int msg_type = rrh->msg_type;
+ int sapi = rrh->sapi;
int i, rc;
- LOGP(DMM, LOGL_INFO, "(ms %s) Received '%s' from RR in state %s\n",
- ms->name, get_rr_name(msg_type),
- gsm48_mm_state_names[mm->state]);
+ LOGP(DMM, LOGL_INFO, "(ms %s) Received '%s' from RR in state %s "
+ "(sapi %d)\n", ms->name, get_rr_name(msg_type),
+ gsm48_mm_state_names[mm->state], sapi);
+
+ if (sapi)
+ return gsm48_rcv_rr_sapi3(ms, msg, msg_type, sapi);
/* find function for current state and message */
for (i = 0; i < RRDATASLLEN; i++)
@@ -3820,7 +3916,7 @@ static int gsm48_rcv_rr(struct osmocom_ms *ms, struct msgb *msg)
}
rc = rrdatastatelist[i].rout(ms, msg);
-
+
if (rrdatastatelist[i].rout != gsm48_mm_data_ind)
msgb_free(msg);
@@ -3870,6 +3966,8 @@ static struct mmdatastate {
static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_mmlayer *mm = &ms->mmlayer;
+ struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *)msg->data;
+ int sapi = rrh->sapi;
struct gsm48_hdr *gh = msgb_l3(msg);
uint8_t pdisc = gh->proto_discr & 0x0f;
uint8_t msg_type = gh->msg_type & 0xbf;
@@ -3880,12 +3978,15 @@ static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
int i, rc;
/* 9.2.19 */
- if (msg_type == GSM48_MT_MM_NULL)
+ if (msg_type == GSM48_MT_MM_NULL) {
+ msgb_free(msg);
return 0;
+ }
if (mm->state == GSM48_MM_ST_IMSI_DETACH_INIT) {
LOGP(DMM, LOGL_NOTICE, "DATA IND ignored during IMSI "
"detach.\n");
+ msgb_free(msg);
return 0;
}
/* pull the RR header */
@@ -3897,7 +3998,6 @@ static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
rr_prim = GSM48_MMCC_DATA_IND;
rr_est = GSM48_MMCC_EST_IND;
break;
-#if 0
case GSM48_PDISC_NC_SS:
rr_prim = GSM48_MMSS_DATA_IND;
rr_est = GSM48_MMSS_EST_IND;
@@ -3906,7 +4006,6 @@ static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
rr_prim = GSM48_MMSMS_DATA_IND;
rr_est = GSM48_MMSMS_EST_IND;
break;
-#endif
}
if (rr_prim != -1) {
uint8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4;
@@ -3918,18 +4017,22 @@ static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
/* create MM connection instance */
if (!conn) {
- conn = mm_conn_new(mm, pdisc, transaction_id,
+ conn = mm_conn_new(mm, pdisc, transaction_id, sapi,
mm_conn_new_ref++);
rr_prim = rr_est;
}
- if (!conn)
+ if (!conn) {
+ msgb_free(msg);
return -ENOMEM;
+ }
/* push new header */
msgb_push(msg, sizeof(struct gsm48_mmxx_hdr));
mmh = (struct gsm48_mmxx_hdr *)msg->data;
mmh->msg_type = rr_prim;
mmh->ref = conn->ref;
+ mmh->transaction_id = conn->transaction_id;
+ mmh->sapi = conn->sapi;
/* go MM CONN ACTIVE state */
if (mm->state == GSM48_MM_ST_WAIT_NETWORK_CMD
@@ -3950,24 +4053,35 @@ static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
skip_ind = (gh->proto_discr & 0xf0) >> 4;
/* ignore if skip indicator is not B'0000' */
- if (skip_ind)
+ if (skip_ind) {
+ msgb_free(msg);
return 0;
+ }
break; /* follow the selection proceedure below */
case GSM48_PDISC_CC:
- return gsm48_rcv_cc(ms, msg);
+ rc = gsm48_rcv_cc(ms, msg);
+ msgb_free(msg);
+ return rc;
-#if 0
case GSM48_PDISC_NC_SS:
- return gsm48_rcv_ss(ms, msg);
+ rc = gsm480_rcv_ss(ms, msg);
+ msgb_free(msg);
+ return rc;
case GSM48_PDISC_SMS:
- return gsm48_rcv_sms(ms, msg);
-#endif
+ rc = gsm411_rcv_sms(ms, msg);
+ msgb_free(msg);
+ return rc;
+ case 0x0f: /* test TS 04.14 */
+ LOGP(DMM, LOGL_NOTICE, "Test protocol 0x%02x according to "
+ "TS 04.14 is not supported.\n", pdisc);
+ goto status;
default:
LOGP(DMM, LOGL_NOTICE, "Protocol type 0x%02x unsupported.\n",
pdisc);
+status:
msgb_free(msg);
return gsm48_mm_tx_mm_status(ms,
GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED);
@@ -4136,8 +4250,8 @@ static struct eventstate {
{ALL_STATES, ALL_STATES,
GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_delay},
- {GSM48_MM_ST_IMSI_DETACH_INIT, ALL_STATES,
- GSM48_MM_EVENT_TIMEOUT_T3220, gsm48_mm_imsi_detach_end},
+ {SBIT(GSM48_MM_ST_IMSI_DETACH_INIT), ALL_STATES,
+ GSM48_MM_EVENT_TIMEOUT_T3220, gsm48_mm_imsi_detach_abort},
/* location update in other cases */
{SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES,
@@ -4166,7 +4280,8 @@ static struct eventstate {
GSM48_MM_EVENT_TIMEOUT_T3240, gsm48_mm_abort_rr},
/* T3230 timed out */
- {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
+ {SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN) |
+ SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
GSM48_MM_EVENT_TIMEOUT_T3230, gsm48_mm_timeout_mm_con},
/* SIM reports SRES */
diff --git a/Src/osmolib/src/host/layer23/src/mobile/gsm48_rr.c b/Src/osmolib/src/host/layer23/src/mobile/gsm48_rr.c
index c1e386a..b6083af 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/gsm48_rr.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/gsm48_rr.c
@@ -145,7 +145,7 @@ static int gsm48_decode_ba_range(const uint8_t *ba, uint8_t ba_len,
*/
uint16_t lower, higher;
int i, n, required_octets;
-
+
/* find out how much ba ranges will be decoded */
n = *ba++;
ba_len --;
@@ -351,7 +351,7 @@ const char *gsm48_rr_state_names[] = {
static void new_rr_state(struct gsm48_rrlayer *rr, int state)
{
- if (state < 0 || state >=
+ if (state < 0 || state >=
(sizeof(gsm48_rr_state_names) / sizeof(char *)))
return;
@@ -422,6 +422,26 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state)
}
}
+const char *gsm48_sapi3_state_names[] = {
+ "idle",
+ "wait establishment",
+ "established",
+ "wait release",
+};
+
+static void new_sapi3_state(struct gsm48_rrlayer *rr, int state)
+{
+ if (state < 0 || state >=
+ (sizeof(gsm48_sapi3_state_names) / sizeof(char *)))
+ return;
+
+ LOGP(DRR, LOGL_INFO, "new SAPI 3 link state %s -> %s\n",
+ gsm48_sapi3_state_names[rr->sapi3_state],
+ gsm48_sapi3_state_names[state]);
+
+ rr->sapi3_state = state;
+}
+
/*
* messages
*/
@@ -504,7 +524,7 @@ int gsm48_rr_upmsg(struct osmocom_ms *ms, struct msgb *msg)
/* push rsl header and send (RSL-SAP) */
static int gsm48_send_rsl(struct osmocom_ms *ms, uint8_t msg_type,
- struct msgb *msg)
+ struct msgb *msg, uint8_t link_id)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
@@ -512,20 +532,19 @@ static int gsm48_send_rsl(struct osmocom_ms *ms, uint8_t msg_type,
LOGP(DRR, LOGL_ERROR, "FIX l3h\n");
return -EINVAL;
}
- rsl_rll_push_l3(msg, msg_type, rr->cd_now.chan_nr,
- rr->cd_now.link_id, 1);
+ rsl_rll_push_l3(msg, msg_type, rr->cd_now.chan_nr, link_id, 1);
return lapdm_rslms_recvmsg(msg, &ms->lapdm_channel);
}
-/* push rsl header + release mode and send (RSL-SAP) */
-static int gsm48_send_rsl_rel(struct osmocom_ms *ms, uint8_t msg_type,
- struct msgb *msg)
+/* push rsl header without L3 info and send (RSL-SAP) */
+static int gsm48_send_rsl_nol3(struct osmocom_ms *ms, uint8_t msg_type,
+ struct msgb *msg, uint8_t link_id)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
rsl_rll_push_hdr(msg, msg_type, rr->cd_now.chan_nr,
- rr->cd_now.link_id, 1);
+ link_id, 1);
return lapdm_rslms_recvmsg(msg, &ms->lapdm_channel);
}
@@ -547,13 +566,13 @@ int gsm48_rsl_dequeue(struct osmocom_ms *ms)
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct msgb *msg;
int work = 0;
-
+
while ((msg = msgb_dequeue(&rr->rsl_upqueue))) {
/* msg is freed there */
gsm48_rcv_rsl(ms, msg);
work = 1; /* work done */
}
-
+
return work;
}
@@ -571,6 +590,43 @@ int gsm48_rr_stop_monitor(struct osmocom_ms *ms)
return 0;
}
+/* release L3 link in both directions in case of main link release */
+static int gsm48_release_sapi3_link(struct osmocom_ms *ms)
+{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm48_rr_hdr *nrrh;
+ struct msgb *nmsg;
+ uint8_t *mode;
+
+ if (rr->sapi3_state == GSM48_RR_SAPI3ST_IDLE)
+ return 0;
+
+ LOGP(DRR, LOGL_INFO, "Main signallin link is down, so release SAPI 3 "
+ "link locally.\n");
+
+ new_sapi3_state(rr, GSM48_RR_SAPI3ST_IDLE);
+
+ /* disconnect the SAPI 3 signalling link */
+ nmsg = gsm48_l3_msgb_alloc();
+ if (!nmsg)
+ return -ENOMEM;
+ mode = msgb_put(nmsg, 2);
+ mode[0] = RSL_IE_RELEASE_MODE;
+ mode[1] = 1; /* local release */
+ gsm48_send_rsl_nol3(ms, RSL_MT_REL_REQ, nmsg, rr->sapi3_link_id);
+
+ /* send inication to upper layer */
+ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
+ if (!nmsg)
+ return -ENOMEM;
+ nrrh = (struct gsm48_rr_hdr *)nmsg->data;
+ nrrh->cause = RR_REL_CAUSE_NORMAL;
+ nrrh->sapi = rr->sapi3_link_id & 7;
+ gsm48_rr_upmsg(ms, nmsg);
+
+ return 0;
+}
+
/*
* timers handling
*/
@@ -598,7 +654,7 @@ static void timeout_rr_meas(void *arg)
snr = (meas->snr + meas->frames / 2) / meas->frames;
sprintf(text, "MON: f=%d lev=%s snr=%2d ber=%3d "
"LAI=%s %s %04x ID=%04x", cs->sel_arfcn,
- gsm_print_rxlev(rxlev), berr, snr,
+ gsm_print_rxlev(rxlev), berr, snr,
gsm_print_mcc(cs->sel_mcc),
gsm_print_mnc(cs->sel_mnc), cs->sel_lac, cs->sel_id);
if (rr->state == GSM48_RR_ST_DEDICATED) {
@@ -646,7 +702,11 @@ static void timeout_rr_t_starting(void *arg)
nmsg = gsm48_l3_msgb_alloc();
if (!nmsg)
return;
- gsm48_send_rsl(rr->ms, RSL_MT_SUSP_REQ, nmsg);
+ gsm48_send_rsl(rr->ms, RSL_MT_SUSP_REQ, nmsg, 0);
+
+ /* release SAPI 3 link, if exits
+ * FIXME: suspend and resume afterward */
+ gsm48_release_sapi3_link(rr->ms);
}
/* special timer to ensure that UA is sent before disconnecting channel */
@@ -679,7 +739,10 @@ static void timeout_rr_t3110(void *arg)
mode = msgb_put(nmsg, 2);
mode[0] = RSL_IE_RELEASE_MODE;
mode[1] = 1; /* local release */
- gsm48_send_rsl_rel(ms, RSL_MT_REL_REQ, nmsg);
+ gsm48_send_rsl_nol3(ms, RSL_MT_REL_REQ, nmsg, 0);
+
+ /* release SAPI 3 link, if exits */
+ gsm48_release_sapi3_link(ms);
return;
}
@@ -857,7 +920,7 @@ static int gsm48_rr_tx_rr_status(struct osmocom_ms *ms, uint8_t cause)
/* rr cause */
st->rr_cause = cause;
- return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg, 0);
}
/*
@@ -892,7 +955,7 @@ static int gsm48_rr_tx_cip_mode_cpl(struct osmocom_ms *ms, uint8_t cr)
memcpy(tlv, buf, 2 + buf[1]);
}
- gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+ gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg, 0);
/* send RR_SYNC_IND(ciphering) */
nmsg = gsm48_rr_msgb_alloc(GSM48_RR_SYNC_IND);
@@ -1224,7 +1287,7 @@ static int gsm48_rr_tx_cm_change(struct osmocom_ms *ms)
memcpy(tlv, cm3, 2 + cm3[1]);
}
- return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg, 0);
}
/* receiving classmark enquiry */
@@ -1239,7 +1302,8 @@ static int gsm48_rr_rx_cm_enq(struct osmocom_ms *ms, struct msgb *msg)
*/
/* start random access */
-static int gsm48_rr_chan_req(struct osmocom_ms *ms, int cause, int paging)
+static int gsm48_rr_chan_req(struct osmocom_ms *ms, int cause, int paging,
+ int paging_mi_type)
{
struct gsm_settings *set = &ms->settings;
struct gsm48_rrlayer *rr = &ms->rrlayer;
@@ -1450,6 +1514,9 @@ rel_ind:
* after location updating */
rr->est_cause = cause;
+ /* store paging mobile identity type, if we respond to paging */
+ rr->paging_mi_type = paging_mi_type;
+
/* if channel is already active somehow */
if (cs->ccch_state == GSM322_CCCH_ST_DATA)
return gsm48_rr_tx_rand_acc(ms, NULL);
@@ -2037,7 +2104,7 @@ static int gsm48_rr_chan2cause[4] = {
};
/* given LV of mobile identity is checked agains ms */
-static int gsm_match_mi(struct osmocom_ms *ms, uint8_t *mi)
+static uint8_t gsm_match_mi(struct osmocom_ms *ms, uint8_t *mi)
{
struct gsm322_cellsel *cs = &ms->cellsel;
char imsi[16];
@@ -2059,7 +2126,7 @@ static int gsm_match_mi(struct osmocom_ms *ms, uint8_t *mi)
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n",
ntohl(tmsi));
- return 1;
+ return mi_type;
} else
LOGP(DPAG, LOGL_INFO, " TMSI %08x (not for us)\n",
ntohl(tmsi));
@@ -2069,7 +2136,7 @@ static int gsm_match_mi(struct osmocom_ms *ms, uint8_t *mi)
if (!strcmp(imsi, ms->subscr.imsi)) {
LOGP(DPAG, LOGL_INFO, " IMSI %s matches\n", imsi);
- return 1;
+ return mi_type;
} else
LOGP(DPAG, LOGL_INFO, " IMSI %s (not for us)\n", imsi);
break;
@@ -2089,7 +2156,7 @@ static int gsm48_rr_rx_pag_req_1(struct osmocom_ms *ms, struct msgb *msg)
struct gsm48_paging1 *pa = msgb_l3(msg);
int payload_len = msgb_l3len(msg) - sizeof(*pa);
int chan_1, chan_2;
- uint8_t *mi;
+ uint8_t *mi, mi_type;
/* empty paging request */
if (payload_len >= 2 && (pa->data[1] & GSM_MI_TYPE_MASK) == 0)
@@ -2121,8 +2188,9 @@ static int gsm48_rr_rx_pag_req_1(struct osmocom_ms *ms, struct msgb *msg)
mi = pa->data;
if (payload_len < mi[0] + 1)
goto short_read;
- if (gsm_match_mi(ms, mi) > 0)
- return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
+ if ((mi_type = gsm_match_mi(ms, mi)) > 0)
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1,
+ mi_type);
/* second MI */
payload_len -= mi[0] + 1;
mi = pa->data + mi[0] + 1;
@@ -2132,8 +2200,9 @@ static int gsm48_rr_rx_pag_req_1(struct osmocom_ms *ms, struct msgb *msg)
return 0;
if (payload_len < mi[1] + 2)
goto short_read;
- if (gsm_match_mi(ms, mi + 1) > 0)
- return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
+ if ((mi_type = gsm_match_mi(ms, mi + 1)) > 0)
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1,
+ mi_type);
return 0;
}
@@ -2145,7 +2214,7 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm48_paging2 *pa = msgb_l3(msg);
int payload_len = msgb_l3len(msg) - sizeof(*pa);
- uint8_t *mi;
+ uint8_t *mi, mi_type;
int chan_1, chan_2, chan_3;
/* 3.3.1.1.2: ignore paging while not camping on a cell */
@@ -2176,7 +2245,8 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi1));
- return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1,
+ GSM_MI_TYPE_TMSI);
} else
LOGP(DPAG, LOGL_INFO, " TMSI %08x (not for us)\n",
ntohl(pa->tmsi1));
@@ -2186,7 +2256,8 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi2));
- return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1,
+ GSM_MI_TYPE_TMSI);
} else
LOGP(DPAG, LOGL_INFO, " TMSI %08x (not for us)\n",
ntohl(pa->tmsi2));
@@ -2199,8 +2270,9 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
if (payload_len < mi[1] + 2 + 1) /* must include "channel needed" */
goto short_read;
chan_3 = mi[mi[1] + 2] & 0x03; /* channel needed */
- if (gsm_match_mi(ms, mi + 1) > 0)
- return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1);
+ if ((mi_type = gsm_match_mi(ms, mi + 1)) > 0)
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1,
+ mi_type);
return 0;
}
@@ -2243,7 +2315,8 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi1));
- return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1,
+ GSM_MI_TYPE_TMSI);
} else
LOGP(DPAG, LOGL_INFO, " TMSI %08x (not for us)\n",
ntohl(pa->tmsi1));
@@ -2253,7 +2326,8 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi2));
- return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1,
+ GSM_MI_TYPE_TMSI);
} else
LOGP(DPAG, LOGL_INFO, " TMSI %08x (not for us)\n",
ntohl(pa->tmsi2));
@@ -2263,7 +2337,8 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi3));
- return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1,
+ GSM_MI_TYPE_TMSI);
} else
LOGP(DPAG, LOGL_INFO, " TMSI %08x (not for us)\n",
ntohl(pa->tmsi3));
@@ -2273,7 +2348,8 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi4));
- return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_4], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_4], 1,
+ GSM_MI_TYPE_TMSI);
} else
LOGP(DPAG, LOGL_INFO, " TMSI %08x (not for us)\n",
ntohl(pa->tmsi4));
@@ -2415,7 +2491,7 @@ static int gsm48_rr_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg)
/* timing advance */
rr->cd_now.ind_ta = ia->timing_advance;
/* mobile allocation */
- memcpy(&rr->cd_now.mob_alloc_lv, &ia->mob_alloc_len,
+ memcpy(&rr->cd_now.mob_alloc_lv, &ia->mob_alloc_len,
ia->mob_alloc_len + 1);
rr->wait_assign = 2;
/* reset scheduler */
@@ -2850,7 +2926,10 @@ int gsm48_rr_los(struct osmocom_ms *ms)
mode[0] = RSL_IE_RELEASE_MODE;
mode[1] = 1; /* local release */
/* start release */
- return gsm48_send_rsl_rel(ms, RSL_MT_REL_REQ, nmsg);
+ gsm48_send_rsl_nol3(ms, RSL_MT_REL_REQ, nmsg, 0);
+ /* release SAPI 3 link, if exits */
+ gsm48_release_sapi3_link(ms);
+ return 0;
case GSM48_RR_ST_REL_PEND:
LOGP(DRR, LOGL_INFO, "LOS during RR release procedure, release "
"locally\n");
@@ -2991,7 +3070,7 @@ static int gsm48_rr_render_ma(struct osmocom_ms *ms, struct gsm48_rr_cd *cd,
/* decode mobile allocation */
if (cd->mob_alloc_lv[0]) {
struct gsm_sysinfo_freq *freq = s->freq;
-
+
LOGP(DRR, LOGL_INFO, "decoding mobile allocation\n");
if (cd->cell_desc_lv[0]) {
@@ -3172,7 +3251,7 @@ static int gsm48_rr_dl_est(struct osmocom_ms *ms)
gh->msg_type = GSM48_MT_RR_PAG_RESP;
pr = (struct gsm48_pag_rsp *) msgb_put(nmsg, sizeof(*pr));
/* key sequence */
- pr->key_seq = subscr->key_seq;
+ pr->key_seq = gsm_subscr_get_key_seq(ms, subscr);
/* classmark 2 */
pr->cm2_len = sizeof(pr->cm2);
gsm48_rr_enc_cm2(ms, &pr->cm2, rr->cd_now.arfcn);
@@ -3180,7 +3259,8 @@ static int gsm48_rr_dl_est(struct osmocom_ms *ms)
if (ms->subscr.tmsi != 0xffffffff
&& ms->subscr.mcc == cs->sel_mcc
&& ms->subscr.mnc == cs->sel_mnc
- && ms->subscr.lac == cs->sel_lac) {
+ && ms->subscr.lac == cs->sel_lac
+ && rr->paging_mi_type == GSM_MI_TYPE_TMSI) {
gsm48_generate_mid_from_tmsi(mi, subscr->tmsi);
LOGP(DRR, LOGL_INFO, "sending paging response with "
"TMSI\n");
@@ -3216,7 +3296,7 @@ static int gsm48_rr_dl_est(struct osmocom_ms *ms)
#endif
/* start establishmnet */
- return gsm48_send_rsl(ms, RSL_MT_EST_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_EST_REQ, nmsg, 0);
}
/* the link is established */
@@ -3237,7 +3317,7 @@ static int gsm48_rr_estab_cnf(struct osmocom_ms *ms, struct msgb *msg)
mode[0] = RSL_IE_RELEASE_MODE;
mode[1] = 0; /* normal release */
/* start release */
- return gsm48_send_rsl_rel(ms, RSL_MT_REL_REQ, nmsg);
+ return gsm48_send_rsl_nol3(ms, RSL_MT_REL_REQ, nmsg, 0);
}
/* 3.3.1.1.4 */
@@ -3286,6 +3366,9 @@ static int gsm48_rr_rel_ind(struct osmocom_ms *ms, struct msgb *msg)
/* pending release */
new_rr_state(rr, GSM48_RR_ST_REL_PEND);
+ /* also release SAPI 3 link, if exists */
+ gsm48_release_sapi3_link(ms);
+
return 0;
}
@@ -3308,7 +3391,7 @@ static int gsm48_rr_rx_chan_rel(struct osmocom_ms *ms, struct msgb *msg)
}
tlv_parse(&tp, &gsm48_rr_att_tlvdef, cr->data, payload_len, 0, 0);
- LOGP(DRR, LOGL_INFO, "channel release request with cause 0x%02x)\n",
+ LOGP(DRR, LOGL_INFO, "channel release request with cause 0x%02x\n",
cr->rr_cause);
/* BA range */
@@ -3334,7 +3417,11 @@ static int gsm48_rr_rx_chan_rel(struct osmocom_ms *ms, struct msgb *msg)
mode = msgb_put(nmsg, 2);
mode[0] = RSL_IE_RELEASE_MODE;
mode[1] = 0; /* normal release */
- return gsm48_send_rsl_rel(ms, RSL_MT_REL_REQ, nmsg);
+ gsm48_send_rsl_nol3(ms, RSL_MT_REL_REQ, nmsg, 0);
+
+ /* release SAPI 3 link, if exits */
+ gsm48_release_sapi3_link(ms);
+ return 0;
}
/*
@@ -3411,7 +3498,7 @@ static int gsm48_rr_rx_frq_redef(struct osmocom_ms *ms, struct msgb *msg)
}
/* mobile allocation */
- memcpy(rr->cd_now.mob_alloc_lv, &fr->mob_alloc_len,
+ memcpy(rr->cd_now.mob_alloc_lv, &fr->mob_alloc_len,
fr->mob_alloc_len + 1);
/* starting time */
@@ -3469,7 +3556,7 @@ static int gsm48_rr_tx_chan_modify_ack(struct osmocom_ms *ms,
/* mode */
cm->mode = mode;
- return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg, 0);
}
/* 9.1.5 CHANNEL MODE MODIFY is received */
@@ -3547,7 +3634,7 @@ static int gsm48_rr_tx_ass_cpl(struct osmocom_ms *ms, uint8_t cause)
/* RR_CAUSE */
ac->rr_cause = cause;
- return gsm48_send_rsl(ms, RSL_MT_RES_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_RES_REQ, nmsg, 0);
}
/* 9.1.4 sending ASSIGNMENT FAILURE */
@@ -3572,7 +3659,7 @@ static int gsm48_rr_tx_ass_fail(struct osmocom_ms *ms, uint8_t cause,
/* RR_CAUSE */
af->rr_cause = cause;
- return gsm48_send_rsl(ms, rsl_prim, nmsg);
+ return gsm48_send_rsl(ms, rsl_prim, nmsg, 0);
}
/* 9.1.2 ASSIGNMENT COMMAND is received */
@@ -3663,8 +3750,8 @@ static int gsm48_rr_rx_ass_cmd(struct osmocom_ms *ms, struct msgb *msg)
cda->start_tm.fn = (ms->meas.last_fn + TEST_STARTING_TIMER) % 42432;
LOGP(DRR, LOGL_INFO, " TESTING: starting time ahead\n");
#else
- if (TLVP_PRESENT(&tp, GSM48_IE_START_TIME)) {
- gsm48_decode_start_time(cda, (struct gsm48_start_time *)
+ if (TLVP_PRESENT(&tp, GSM48_IE_START_TIME)) {
+ gsm48_decode_start_time(cda, (struct gsm48_start_time *)
TLVP_VAL(&tp, GSM48_IE_START_TIME));
/* 9.1.2.5 "... before time IE is not present..." */
if (!before_time) {
@@ -3882,7 +3969,11 @@ static int gsm48_rr_rx_ass_cmd(struct osmocom_ms *ms, struct msgb *msg)
nmsg = gsm48_l3_msgb_alloc();
if (!nmsg)
return -ENOMEM;
- gsm48_send_rsl(ms, RSL_MT_SUSP_REQ, nmsg);
+ gsm48_send_rsl(ms, RSL_MT_SUSP_REQ, nmsg, 0);
+
+ /* release SAPI 3 link, if exits
+ * FIXME: suspend and resume afterward */
+ gsm48_release_sapi3_link(ms);
return 0;
}
@@ -3910,7 +4001,7 @@ static int gsm48_rr_tx_hando_cpl(struct osmocom_ms *ms, uint8_t cause)
// FIXME: mobile observed time
- return gsm48_send_rsl(ms, RSL_MT_RES_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_RES_REQ, nmsg, 0);
}
/* 9.1.4 sending HANDOVER FAILURE */
@@ -3935,7 +4026,7 @@ static int gsm48_rr_tx_hando_fail(struct osmocom_ms *ms, uint8_t cause,
/* RR_CAUSE */
hf->rr_cause = cause;
- return gsm48_send_rsl(ms, rsl_prim, nmsg);
+ return gsm48_send_rsl(ms, rsl_prim, nmsg, 0);
}
/* receiving HANDOVER COMMAND message (9.1.15) */
@@ -3984,8 +4075,8 @@ static int gsm48_rr_rx_hando_cmd(struct osmocom_ms *ms, struct msgb *msg)
tlv_parse(&tp, &gsm48_rr_att_tlvdef, ho->data, payload_len, 0, 0);
/* sync ind */
- if (TLVP_PRESENT(&tp, GSM48_IE_SYNC_IND)) {
- gsm48_decode_sync_ind(rr, (struct gsm48_sync_ind *)
+ if (TLVP_PRESENT(&tp, GSM48_IE_SYNC_IND)) {
+ gsm48_decode_sync_ind(rr, (struct gsm48_sync_ind *)
TLVP_VAL(&tp, GSM48_IE_SYNC_IND));
LOGP(DRR, LOGL_INFO, " (sync_ind=%d rot=%d nci=%d)\n",
rr->hando_sync_ind, rr->hando_rot, rr->hando_nci);
@@ -4043,8 +4134,8 @@ static int gsm48_rr_rx_hando_cmd(struct osmocom_ms *ms, struct msgb *msg)
cda->start_tm.fn = (ms->meas.last_fn + TEST_STARTING_TIMER) % 42432;
LOGP(DRR, LOGL_INFO, " TESTING: starting time ahead\n");
#else
- if (TLVP_PRESENT(&tp, GSM48_IE_START_TIME)) {
- gsm48_decode_start_time(cda, (struct gsm48_start_time *)
+ if (TLVP_PRESENT(&tp, GSM48_IE_START_TIME)) {
+ gsm48_decode_start_time(cda, (struct gsm48_start_time *)
TLVP_VAL(&tp, GSM48_IE_START_TIME));
/* 9.1.2.5 "... before time IE is not present..." */
if (!before_time) {
@@ -4268,7 +4359,11 @@ static int gsm48_rr_rx_hando_cmd(struct osmocom_ms *ms, struct msgb *msg)
nmsg = gsm48_l3_msgb_alloc();
if (!nmsg)
return -ENOMEM;
- gsm48_send_rsl(ms, RSL_MT_SUSP_REQ, nmsg);
+ gsm48_send_rsl(ms, RSL_MT_SUSP_REQ, nmsg, 0);
+
+ /* release SAPI 3 link, if exits
+ * FIXME: suspend and resume afterward */
+ gsm48_release_sapi3_link(ms);
return 0;
}
@@ -4280,8 +4375,16 @@ static int gsm48_rr_dequeue_down(struct osmocom_ms *ms)
struct msgb *msg;
while((msg = msgb_dequeue(&rr->downqueue))) {
+ struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *) msg->data;
+ uint8_t sapi = rrh->sapi;
+
LOGP(DRR, LOGL_INFO, "Sending queued message.\n");
- gsm48_send_rsl(ms, RSL_MT_DATA_REQ, msg);
+ if (sapi && rr->sapi3_state != GSM48_RR_SAPI3ST_ESTAB) {
+ LOGP(DRR, LOGL_INFO, "Dropping SAPI 3 msg, no link!\n");
+ msgb_free(msg);
+ return 0;
+ }
+ gsm48_send_rsl(ms, RSL_MT_DATA_REQ, msg, 0);
}
return 0;
@@ -4370,7 +4473,7 @@ static int gsm48_rr_susp_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
}
/*
- * radio ressource requests
+ * radio ressource requests
*/
/* establish request for dedicated mode */
@@ -4475,19 +4578,21 @@ static int gsm48_rr_est_req(struct osmocom_ms *ms, struct msgb *msg)
msgb_l3(msg), msgb_l3len(msg));
/* request channel */
- return gsm48_rr_chan_req(ms, rrh->cause, 0);
+ return gsm48_rr_chan_req(ms, rrh->cause, 0, 0);
}
/* 3.4.2 transfer data in dedicated mode */
static int gsm48_rr_data_req(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *) msg->data;
+ uint8_t sapi = rrh->sapi;
if (rr->state != GSM48_RR_ST_DEDICATED) {
msgb_free(msg);
return -EINVAL;
}
-
+
/* pull RR header */
msgb_pull(msg, sizeof(struct gsm48_rr_hdr));
@@ -4502,8 +4607,15 @@ static int gsm48_rr_data_req(struct osmocom_ms *ms, struct msgb *msg)
return 0;
}
+ if (sapi && rr->sapi3_state != GSM48_RR_SAPI3ST_ESTAB) {
+ LOGP(DRR, LOGL_INFO, "Dropping SAPI 3 msg, no link!\n");
+ msgb_free(msg);
+ return 0;
+ }
+
/* forward message */
- return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, msg);
+ return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, msg,
+ sapi ? rr->sapi3_link_id : 0);
}
/*
@@ -4684,7 +4796,7 @@ static int gsm48_rr_unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
struct tlv_parsed tv;
uint8_t ch_type, ch_subch, ch_ts;
-
+
DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
rllh->chan_nr, rllh->link_id);
@@ -4765,7 +4877,11 @@ static int gsm48_rr_abort_req(struct osmocom_ms *ms, struct msgb *msg)
mode = msgb_put(nmsg, 2);
mode[0] = RSL_IE_RELEASE_MODE;
mode[1] = 0; /* normal release */
- return gsm48_send_rsl_rel(ms, RSL_MT_REL_REQ, nmsg);
+ gsm48_send_rsl_nol3(ms, RSL_MT_REL_REQ, nmsg, 0);
+
+ /* release SAPI 3 link, if exits */
+ gsm48_release_sapi3_link(ms);
+ return 0;
}
LOGP(DRR, LOGL_INFO, "Abort in connection pending state, return to "
@@ -4853,6 +4969,7 @@ static int gsm48_rr_mdl_error_ind(struct osmocom_ms *ms, struct msgb *msg)
struct gsm48_rr_hdr *nrrh;
uint8_t *mode;
uint8_t cause = rllh->data[2];
+ uint8_t link_id = rllh->link_id;
switch (cause) {
case RLL_CAUSE_SEQ_ERR:
@@ -4865,14 +4982,14 @@ static int gsm48_rr_mdl_error_ind(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DRR, LOGL_NOTICE, "MDL-Error (cause %d) aborting\n", cause);
- /* disconnect the main signalling link */
+ /* disconnect the (main) signalling link */
nmsg = gsm48_l3_msgb_alloc();
if (!nmsg)
return -ENOMEM;
mode = msgb_put(nmsg, 2);
mode[0] = RSL_IE_RELEASE_MODE;
mode[1] = 1; /* local release */
- gsm48_send_rsl_rel(ms, RSL_MT_REL_REQ, nmsg);
+ gsm48_send_rsl_nol3(ms, RSL_MT_REL_REQ, nmsg, link_id);
/* in case of modify/hando: wait for confirm */
if (rr->modify_state)
@@ -4884,13 +5001,191 @@ static int gsm48_rr_mdl_error_ind(struct osmocom_ms *ms, struct msgb *msg)
return -ENOMEM;
nrrh = (struct gsm48_rr_hdr *)nmsg->data;
nrrh->cause = RR_REL_CAUSE_LINK_FAILURE;
+ nrrh->sapi = link_id & 7;
gsm48_rr_upmsg(ms, nmsg);
- /* return idle */
- new_rr_state(rr, GSM48_RR_ST_IDLE);
+ /* only for main signalling link */
+ if ((link_id & 7) == 0) {
+ /* return idle */
+ new_rr_state(rr, GSM48_RR_ST_IDLE);
+ /* release SAPI 3 link, if exits */
+ gsm48_release_sapi3_link(ms);
+ } else {
+ new_sapi3_state(rr, GSM48_RR_SAPI3ST_IDLE);
+ LOGP(DSUM, LOGL_INFO, "Radio link SAPI3 failed\n");
+ }
return 0;
}
+static int gsm48_rr_estab_ind_sapi3(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ uint8_t link_id = rllh->link_id;
+ struct msgb *nmsg;
+ struct gsm48_rr_hdr *nrrh;
+
+ if (rr->state != GSM48_RR_ST_DEDICATED) {
+ /* disconnect sapi 3 link */
+ gsm48_release_sapi3_link(ms);
+ return -EINVAL;
+ }
+
+ new_sapi3_state(rr, GSM48_RR_SAPI3ST_ESTAB);
+ rr->sapi3_link_id = link_id; /* set link ID */
+
+ LOGP(DSUM, LOGL_INFO, "Radio link SAPI3 is established\n");
+
+ /* send inication to upper layer */
+ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_EST_IND);
+ if (!nmsg)
+ return -ENOMEM;
+ nrrh = (struct gsm48_rr_hdr *)nmsg->data;
+ nrrh->sapi = link_id & 7;
+
+ return gsm48_rr_upmsg(ms, nmsg);
+}
+
+static int gsm48_rr_estab_cnf_sapi3(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ uint8_t link_id = rllh->link_id;
+ struct msgb *nmsg;
+ struct gsm48_rr_hdr *nrrh;
+
+ if (rr->state != GSM48_RR_ST_DEDICATED) {
+ gsm48_release_sapi3_link(ms);
+ return -EINVAL;
+ }
+
+ new_sapi3_state(rr, GSM48_RR_SAPI3ST_ESTAB);
+ rr->sapi3_link_id = link_id; /* set link ID, just to be sure */
+
+ LOGP(DSUM, LOGL_INFO, "Radio link SAPI3 is established\n");
+
+ /* send inication to upper layer */
+ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_EST_CNF);
+ if (!nmsg)
+ return -ENOMEM;
+ nrrh = (struct gsm48_rr_hdr *)nmsg->data;
+ nrrh->sapi = link_id & 7;
+
+ return gsm48_rr_upmsg(ms, nmsg);
+}
+
+/* 3.4.2 data from layer 2 to RR and upper layer (sapi 3)*/
+static int gsm48_rr_data_ind_sapi3(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ uint8_t sapi = rllh->link_id & 7;
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ struct gsm48_rr_hdr *rrh;
+ uint8_t pdisc = gh->proto_discr & 0x0f;
+
+ if (pdisc == GSM48_PDISC_RR) {
+ msgb_free(msg);
+ return -EINVAL;
+ }
+
+ /* pull off RSL header up to L3 message */
+ msgb_pull(msg, (long)msgb_l3(msg) - (long)msg->data);
+
+ /* push RR header */
+ msgb_push(msg, sizeof(struct gsm48_rr_hdr));
+ rrh = (struct gsm48_rr_hdr *)msg->data;
+ rrh->msg_type = GSM48_RR_DATA_IND;
+ rrh->sapi = sapi;
+
+ return gsm48_rr_upmsg(ms, msg);
+}
+
+static int gsm48_rr_rel_ind_sapi3(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ uint8_t link_id = rllh->link_id;
+ struct msgb *nmsg;
+ struct gsm48_rr_hdr *nrrh;
+
+ new_sapi3_state(rr, GSM48_RR_SAPI3ST_IDLE);
+
+ LOGP(DSUM, LOGL_INFO, "Radio link SAPI3 is released\n");
+
+ /* send inication to upper layer */
+ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
+ if (!nmsg)
+ return -ENOMEM;
+ nrrh = (struct gsm48_rr_hdr *)nmsg->data;
+ nrrh->cause = RR_REL_CAUSE_NORMAL;
+ nrrh->sapi = link_id & 7;
+
+ return gsm48_rr_upmsg(ms, nmsg);
+}
+
+/* request SAPI 3 establishment */
+static int gsm48_rr_est_req_sapi3(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+ uint8_t ch_type, ch_subch, ch_ts;
+ struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *) msg->data;
+ uint8_t sapi = rrh->sapi;
+ struct msgb *nmsg;
+
+ if (rr->state != GSM48_RR_ST_DEDICATED) {
+ struct gsm48_rr_hdr *nrrh;
+
+ /* send inication to upper layer */
+ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
+ if (!nmsg)
+ return -ENOMEM;
+ nrrh = (struct gsm48_rr_hdr *)nmsg->data;
+ nrrh->cause = RR_REL_CAUSE_NORMAL;
+ nrrh->sapi = sapi;
+ return gsm48_rr_upmsg(ms, nmsg);
+ }
+
+ rsl_dec_chan_nr(rr->cd_now.chan_nr, &ch_type, &ch_subch, &ch_ts);
+ if (ch_type != RSL_CHAN_Bm_ACCHs
+ && ch_type != RSL_CHAN_Lm_ACCHs) {
+ LOGP(DRR, LOGL_INFO, "Requesting DCCH link, because no TCH "
+ "(sapi %d)\n", sapi);
+ rr->sapi3_link_id = 0x00 | sapi; /* SAPI 3, DCCH */
+ } else {
+ LOGP(DRR, LOGL_INFO, "Requesting ACCH link, because TCH "
+ "(sapi %d)\n", sapi);
+ rr->sapi3_link_id = 0x40 | sapi; /* SAPI 3, ACCH */
+ }
+
+ /* already established */
+ new_sapi3_state(rr, GSM48_RR_SAPI3ST_WAIT_EST);
+
+ /* send message */
+ nmsg = gsm48_l3_msgb_alloc();
+ if (!nmsg)
+ return -ENOMEM;
+ return gsm48_send_rsl_nol3(ms, RSL_MT_EST_REQ, nmsg, rr->sapi3_link_id);
+}
+
+static int gsm48_rr_est_req_estab_sapi3(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *) msg->data;
+ uint8_t sapi = rrh->sapi;
+ struct msgb *nmsg;
+ struct gsm48_rr_hdr *nrrh;
+
+ LOGP(DRR, LOGL_INFO, "Radio link SAPI3 already established\n");
+
+ /* send inication to upper layer */
+ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_EST_CNF);
+ if (!nmsg)
+ return -ENOMEM;
+ nrrh = (struct gsm48_rr_hdr *)nmsg->data;
+ nrrh->sapi = sapi;
+
+ return gsm48_rr_upmsg(ms, nmsg);
+}
+
/*
* state machines
*/
@@ -4901,6 +5196,8 @@ static struct dldatastate {
int type;
int (*rout) (struct osmocom_ms *ms, struct msgb *msg);
} dldatastatelist[] = {
+ /* SAPI 0 on DCCH */
+
/* data transfer */
{SBIT(GSM48_RR_ST_IDLE) |
SBIT(GSM48_RR_ST_CONN_PEND) |
@@ -4950,35 +5247,79 @@ static struct dldatastate {
#define DLDATASLLEN \
(sizeof(dldatastatelist) / sizeof(struct dldatastate))
+static struct dldatastate dldatastatelists3[] = {
+ /* SAPI 3 on DCCH */
+
+ /* establish */
+ {SBIT(GSM48_RR_SAPI3ST_IDLE),
+ RSL_MT_EST_IND, gsm48_rr_estab_ind_sapi3},
+
+ /* establish */
+ {SBIT(GSM48_RR_SAPI3ST_IDLE) | SBIT(GSM48_RR_SAPI3ST_WAIT_EST),
+ RSL_MT_EST_CONF, gsm48_rr_estab_cnf_sapi3},
+
+ /* data transfer */
+ {SBIT(GSM48_RR_SAPI3ST_ESTAB),
+ RSL_MT_DATA_IND, gsm48_rr_data_ind_sapi3},
+
+ /* release */
+ {SBIT(GSM48_RR_SAPI3ST_WAIT_EST) | SBIT(GSM48_RR_SAPI3ST_ESTAB),
+ RSL_MT_REL_IND, gsm48_rr_rel_ind_sapi3},
+
+ {ALL_STATES,
+ RSL_MT_ERROR_IND, gsm48_rr_mdl_error_ind},
+};
+
+#define DLDATASLLENS3 \
+ (sizeof(dldatastatelists3) / sizeof(struct dldatastate))
+
static int gsm48_rcv_rll(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
int msg_type = rllh->c.msg_type;
+ int link_id = rllh->link_id;
int i;
int rc;
- if (msg_type != RSL_MT_UNIT_DATA_IND) {
- LOGP(DRSL, LOGL_INFO, "(ms %s) Received '%s' from L2 in state "
- "%s\n", ms->name, rsl_msg_name(msg_type),
- gsm48_rr_state_names[rr->state]);
- }
+ LOGP(DRSL, LOGL_INFO, "(ms %s) Received '%s' from L2 in state "
+ "%s (link_id 0x%x)\n", ms->name, rsl_msg_name(msg_type),
+ gsm48_rr_state_names[rr->state], link_id);
/* find function for current state and message */
- for (i = 0; i < DLDATASLLEN; i++)
- if ((msg_type == dldatastatelist[i].type)
- && ((1 << rr->state) & dldatastatelist[i].states))
- break;
- if (i == DLDATASLLEN) {
- LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
- msgb_free(msg);
- return 0;
- }
+ if (!(link_id & 7)) {
+ /* SAPI 0 */
+ for (i = 0; i < DLDATASLLEN; i++)
+ if ((msg_type == dldatastatelist[i].type)
+ && ((1 << rr->state) & dldatastatelist[i].states))
+ break;
+ if (i == DLDATASLLEN) {
+ LOGP(DRSL, LOGL_NOTICE, "RSLms message '%s' "
+ "unhandled\n", rsl_msg_name(msg_type));
+ msgb_free(msg);
+ return 0;
+ }
+
+ rc = dldatastatelist[i].rout(ms, msg);
+ } else {
+ /* SAPI 3 */
+ for (i = 0; i < DLDATASLLENS3; i++)
+ if ((msg_type == dldatastatelists3[i].type)
+ && ((1 << rr->sapi3_state) &
+ dldatastatelists3[i].states))
+ break;
+ if (i == DLDATASLLENS3) {
+ LOGP(DRSL, LOGL_NOTICE, "RSLms message '%s' "
+ "unhandled\n", rsl_msg_name(msg_type));
+ msgb_free(msg);
+ return 0;
+ }
- rc = dldatastatelist[i].rout(ms, msg);
+ rc = dldatastatelists3[i].rout(ms, msg);
+ }
/* free msgb unless it is forwarded */
- if (dldatastatelist[i].rout != gsm48_rr_data_ind)
+ if (msg_type != RSL_MT_DATA_IND)
msgb_free(msg);
return rc;
@@ -5033,12 +5374,14 @@ static int gsm48_rcv_rsl(struct osmocom_ms *ms, struct msgb *msg)
return rc;
}
-/* state trasitions for RR-SAP messages from up */
+/* state trasitions for RR-SAP messages from up (main link) */
static struct rrdownstate {
uint32_t states;
int type;
int (*rout) (struct osmocom_ms *ms, struct msgb *msg);
} rrdownstatelist[] = {
+ /* SAPI 0 */
+
/* NOTE: If not IDLE, it is rejected there. */
{ALL_STATES, /* 3.3.1.1 */
GSM48_RR_EST_REQ, gsm48_rr_est_req},
@@ -5054,33 +5397,69 @@ static struct rrdownstate {
#define RRDOWNSLLEN \
(sizeof(rrdownstatelist) / sizeof(struct rrdownstate))
+/* state trasitions for RR-SAP messages from up with (SAPI 3) */
+static struct rrdownstate rrdownstatelists3[] = {
+ /* SAPI 3 */
+
+ {SBIT(GSM48_RR_SAPI3ST_IDLE),
+ GSM48_RR_EST_REQ, gsm48_rr_est_req_sapi3},
+
+ {SBIT(GSM48_RR_SAPI3ST_ESTAB),
+ GSM48_RR_EST_REQ, gsm48_rr_est_req_estab_sapi3},
+
+ {SBIT(GSM48_RR_SAPI3ST_ESTAB),
+ GSM48_RR_DATA_REQ, gsm48_rr_data_req}, /* handles SAPI 3 too */
+};
+
+#define RRDOWNSLLENS3 \
+ (sizeof(rrdownstatelists3) / sizeof(struct rrdownstate))
+
int gsm48_rr_downmsg(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *) msg->data;
int msg_type = rrh->msg_type;
+ int sapi = rrh->sapi;
int i;
int rc;
- LOGP(DRR, LOGL_INFO, "(ms %s) Message '%s' received in state %s\n",
- ms->name, get_rr_name(msg_type),
- gsm48_rr_state_names[rr->state]);
+ LOGP(DRR, LOGL_INFO, "(ms %s) Message '%s' received in state %s "
+ "(sapi %d)\n", ms->name, get_rr_name(msg_type),
+ gsm48_rr_state_names[rr->state], sapi);
- /* find function for current state and message */
- for (i = 0; i < RRDOWNSLLEN; i++)
- if ((msg_type == rrdownstatelist[i].type)
- && ((1 << rr->state) & rrdownstatelist[i].states))
- break;
- if (i == RRDOWNSLLEN) {
- LOGP(DRR, LOGL_NOTICE, "Message unhandled at this state.\n");
- msgb_free(msg);
- return 0;
- }
+ if (!sapi) {
+ /* SAPI 0: find function for current state and message */
+ for (i = 0; i < RRDOWNSLLEN; i++)
+ if ((msg_type == rrdownstatelist[i].type)
+ && ((1 << rr->state) & rrdownstatelist[i].states))
+ break;
+ if (i == RRDOWNSLLEN) {
+ LOGP(DRR, LOGL_NOTICE, "Message unhandled at this "
+ "state.\n");
+ msgb_free(msg);
+ return 0;
+ }
- rc = rrdownstatelist[i].rout(ms, msg);
+ rc = rrdownstatelist[i].rout(ms, msg);
+ } else {
+ /* SAPI 3: find function for current state and message */
+ for (i = 0; i < RRDOWNSLLENS3; i++)
+ if ((msg_type == rrdownstatelists3[i].type)
+ && ((1 << rr->sapi3_state)
+ & rrdownstatelists3[i].states))
+ break;
+ if (i == RRDOWNSLLENS3) {
+ LOGP(DRR, LOGL_NOTICE, "Message unhandled at this "
+ "state.\n");
+ msgb_free(msg);
+ return 0;
+ }
- /* free msgb uless it is forwarded */
- if (rrdownstatelist[i].rout != gsm48_rr_data_req)
+ rc = rrdownstatelists3[i].rout(ms, msg);
+ }
+
+ /* free msgb unless it is forwarded */
+ if (msg_type != GSM48_RR_DATA_REQ)
msgb_free(msg);
return rc;
@@ -5166,7 +5545,7 @@ static void timeout_rr_t3124(void *arg)
nmsg = gsm48_l3_msgb_alloc();
if (!nmsg)
return -ENOMEM;
- return gsm48_send_rsl(ms, RSL_MT_REEST_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_REEST_REQ, nmsg, 0);
todo
}
@@ -5179,7 +5558,7 @@ static int gsm48_rr_tx_hando_access(struct osmocom_ms *ms)
return -ENOMEM;
*msgb_put(nmsg, 1) = rr->hando_ref;
todo burst
- return gsm48_send_rsl(ms, RSL_MT_RAND_ACC_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_RAND_ACC_REQ, nmsg, 0);
}
/* send next channel request in dedicated state */
@@ -5239,8 +5618,7 @@ int gsm48_rr_tx_voice(struct osmocom_ms *ms, struct msgb *msg)
return -ENOTSUP;
}
- return l1ctl_tx_traffic_req(ms, msg, rr->cd_now.chan_nr,
- rr->cd_now.link_id);
+ return l1ctl_tx_traffic_req(ms, msg, rr->cd_now.chan_nr, 0);
}
int gsm48_rr_audio_mode(struct osmocom_ms *ms, uint8_t mode)
diff --git a/Src/osmolib/src/host/layer23/src/mobile/main.c b/Src/osmolib/src/host/layer23/src/mobile/main.c
index 6e743df..89c9b94 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/main.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/main.c
@@ -67,6 +67,9 @@ int mobile_work(struct osmocom_ms *ms);
int mobile_exit(struct osmocom_ms *ms, int force);
+const char *debug_default =
+ "DCS:DNB:DPLMN:DRR:DMM:DSIM:DCC:DMNCC:DSS:DLSMS:DPAG:DSUM";
+
const char *openbsc_copyright =
"Copyright (C) 2008-2010 ...\n"
"Contributions by ...\n\n"
@@ -87,7 +90,8 @@ static void print_help()
printf(" -i --gsmtap-ip The destination IP used for GSMTAP.\n");
printf(" -v --vty-port The VTY port number to telnet to. "
"(default %u)\n", vty_port);
- printf(" -d --debug Change debug flags.\n");
+ printf(" -d --debug Change debug flags. default: %s\n",
+ debug_default);
printf(" -D --daemonize Run as daemon\n");
printf(" -m --mncc-sock Disable built-in MNCC handler and "
"offer socket\n");
@@ -147,13 +151,30 @@ void sighandler(int sigset)
fprintf(stderr, "Signal %d received.\n", sigset);
- /* in case there is a lockup during exit */
- signal(SIGINT, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGPIPE, SIG_DFL);
-
- osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
+ switch (sigset) {
+ case SIGINT:
+ /* If another signal is received afterwards, the program
+ * is terminated without finishing shutdown process.
+ */
+ signal(SIGINT, SIG_DFL);
+ signal(SIGHUP, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGPIPE, SIG_DFL);
+ signal(SIGABRT, SIG_DFL);
+ signal(SIGUSR1, SIG_DFL);
+ signal(SIGUSR2, SIG_DFL);
+
+ osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
+ break;
+ case SIGABRT:
+ /* in case of abort, we want to obtain a talloc report
+ * and then return to the caller, who will abort the process
+ */
+ case SIGUSR1:
+ case SIGUSR2:
+ talloc_report_full(l23_ctx, stderr);
+ break;
+ }
}
int main(int argc, char **argv)
@@ -176,11 +197,12 @@ int main(int argc, char **argv)
log_set_all_filter(stderr_target, 1);
l23_ctx = talloc_named_const(NULL, 1, "layer2 context");
+ msgb_set_talloc_ctx(l23_ctx);
handle_options(argc, argv);
if (!debug_set)
- log_parse_category_mask(stderr_target, "DCS:DNB:DPLMN:DRR:DMM:DSIM:DCC:DMNCC:DPAG:DSUM");
+ log_parse_category_mask(stderr_target, debug_default);
log_set_log_level(stderr_target, LOGL_DEBUG);
if (gsmtap_ip) {
@@ -214,6 +236,9 @@ int main(int argc, char **argv)
signal(SIGHUP, sighandler);
signal(SIGTERM, sighandler);
signal(SIGPIPE, sighandler);
+ signal(SIGABRT, sighandler);
+ signal(SIGUSR1, sighandler);
+ signal(SIGUSR2, sighandler);
if (daemonize) {
printf("Running as daemon\n");
@@ -231,5 +256,9 @@ int main(int argc, char **argv)
l23_app_exit();
+ talloc_free(config_file);
+ talloc_free(config_dir);
+ talloc_report_full(l23_ctx, stderr);
+
return 0;
}
diff --git a/Src/osmolib/src/host/layer23/src/mobile/mnccms.c b/Src/osmolib/src/host/layer23/src/mobile/mnccms.c
index c6db1ab..9fdc45f 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/mnccms.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/mnccms.c
@@ -187,7 +187,7 @@ static void mncc_set_bearer(struct osmocom_ms *ms, int8_t speech_ver,
LOGP(DMNCC, LOGL_INFO, " support half rate v1\n");
}
/* if specific speech_ver is given (it must be supported) */
- } else
+ } else
mncc->bearer_cap.speech_ver[i++] = speech_ver;
mncc->bearer_cap.speech_ver[i] = -1; /* end of list */
mncc->bearer_cap.transfer = 0;
@@ -579,7 +579,7 @@ int mncc_call(struct osmocom_ms *ms, char *number)
setup.called.plan = 1; /* ISDN */
strncpy(setup.called.number, number,
sizeof(setup.called.number) - 1);
-
+
/* bearer capability (mandatory) */
mncc_set_bearer(ms, -1, &setup);
if (ms->settings.clir)
diff --git a/Src/osmolib/src/host/layer23/src/mobile/settings.c b/Src/osmolib/src/host/layer23/src/mobile/settings.c
index 592f8a8..e34db7e 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/settings.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/settings.c
@@ -47,8 +47,7 @@ int gsm_settings_init(struct osmocom_ms *ms)
sprintf(set->imeisv, "0000000000000000");
/* SIM type */
-#warning TODO: Enable after SIM reader is available in master branch.
-// set->sim_type = SIM_TYPE_READER;
+ set->sim_type = GSM_SIM_TYPE_READER;
/* test SIM */
strcpy(set->test_imsi, "001010000000000");
@@ -183,7 +182,7 @@ int gsm_random_imei(struct gsm_settings *set)
strcpy(set->imei + 15 - digits, rand + 15 - digits);
strncpy(set->imeisv, set->imei, 15);
-
+
return 0;
}
diff --git a/Src/osmolib/src/host/layer23/src/mobile/subscriber.c b/Src/osmolib/src/host/layer23/src/mobile/subscriber.c
index 6de742a..8ebb173 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/subscriber.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/subscriber.c
@@ -320,9 +320,9 @@ static int subscr_sim_msisdn(struct osmocom_ms *ms, uint8_t *data,
return 0;
/* number */
- if (adn->ton_npi == 1)
+ if (((adn->ton_npi & 0x70) >> 4) == 1)
strcpy(subscr->msisdn, "+");
- if (adn->ton_npi == 2)
+ if (((adn->ton_npi & 0x70) >> 4) == 2)
strcpy(subscr->msisdn, "0");
strncat(subscr->msisdn, sim_decode_bcd(adn->number, adn->len_bcd - 1),
sizeof(subscr->msisdn) - 2);
@@ -332,6 +332,36 @@ static int subscr_sim_msisdn(struct osmocom_ms *ms, uint8_t *data,
return 0;
}
+static int subscr_sim_smsp(struct osmocom_ms *ms, uint8_t *data,
+ uint8_t length)
+{
+ struct gsm_subscriber *subscr = &ms->subscr;
+ struct gsm1111_ef_smsp *smsp;
+
+ if (length < sizeof(*smsp))
+ return -EINVAL;
+ smsp = (struct gsm1111_ef_smsp *) (data + length - sizeof(*smsp));
+
+ /* empty */
+ subscr->sms_sca[0] = '\0';
+
+ /* TS-Service Centre Address */
+ if (!(smsp->par_ind & 0x02) && smsp->ts_sca[0] <= 11) {
+ if (((smsp->ts_sca[1] & 0x70) >> 4) == 1)
+ strcpy(subscr->sms_sca, "+");
+ if (((smsp->ts_sca[1] & 0x70) >> 4) == 2)
+ strcpy(subscr->sms_sca, "0");
+ gsm48_decode_bcd_number(subscr->sms_sca +
+ strlen(subscr->sms_sca), sizeof(subscr->sms_sca)
+ - strlen(subscr->sms_sca), smsp->ts_sca, 1);
+ }
+
+ LOGP(DMM, LOGL_INFO, "received SMSP from SIM (sca=%s)\n",
+ subscr->sms_sca);
+
+ return 0;
+}
+
static int subscr_sim_kc(struct osmocom_ms *ms, uint8_t *data,
uint8_t length)
{
@@ -497,20 +527,22 @@ static struct subscr_sim_file {
uint8_t mandatory;
uint16_t path[MAX_SIM_PATH_LENGTH];
uint16_t file;
+ uint8_t sim_job;
int (*func)(struct osmocom_ms *ms, uint8_t *data,
uint8_t length);
} subscr_sim_files[] = {
- { 1, { 0 }, 0x2fe2, subscr_sim_iccid },
- { 1, { 0x7f20, 0 }, 0x6f07, subscr_sim_imsi },
- { 1, { 0x7f20, 0 }, 0x6f7e, subscr_sim_loci },
- { 0, { 0x7f10, 0 }, 0x6f40, subscr_sim_msisdn },
- { 0, { 0x7f20, 0 }, 0x6f20, subscr_sim_kc },
- { 0, { 0x7f20, 0 }, 0x6f30, subscr_sim_plmnsel },
- { 0, { 0x7f20, 0 }, 0x6f31, subscr_sim_hpplmn },
- { 0, { 0x7f20, 0 }, 0x6f46, subscr_sim_spn },
- { 0, { 0x7f20, 0 }, 0x6f78, subscr_sim_acc },
- { 0, { 0x7f20, 0 }, 0x6f7b, subscr_sim_fplmn },
- { 0, { 0 }, 0, NULL }
+ { 1, { 0 }, 0x2fe2, SIM_JOB_READ_BINARY, subscr_sim_iccid },
+ { 1, { 0x7f20, 0 }, 0x6f07, SIM_JOB_READ_BINARY, subscr_sim_imsi },
+ { 1, { 0x7f20, 0 }, 0x6f7e, SIM_JOB_READ_BINARY, subscr_sim_loci },
+ { 0, { 0x7f20, 0 }, 0x6f20, SIM_JOB_READ_BINARY, subscr_sim_kc },
+ { 0, { 0x7f20, 0 }, 0x6f30, SIM_JOB_READ_BINARY, subscr_sim_plmnsel },
+ { 0, { 0x7f20, 0 }, 0x6f31, SIM_JOB_READ_BINARY, subscr_sim_hpplmn },
+ { 0, { 0x7f20, 0 }, 0x6f46, SIM_JOB_READ_BINARY, subscr_sim_spn },
+ { 0, { 0x7f20, 0 }, 0x6f78, SIM_JOB_READ_BINARY, subscr_sim_acc },
+ { 0, { 0x7f20, 0 }, 0x6f7b, SIM_JOB_READ_BINARY, subscr_sim_fplmn },
+ { 0, { 0x7f10, 0 }, 0x6f40, SIM_JOB_READ_RECORD, subscr_sim_msisdn },
+ { 0, { 0x7f10, 0 }, 0x6f42, SIM_JOB_READ_RECORD, subscr_sim_smsp },
+ { 0, { 0 }, 0, 0, NULL }
};
/* request file from SIM */
@@ -553,7 +585,7 @@ static int subscr_sim_request(struct osmocom_ms *ms)
/* trigger SIM reading */
nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_query,
- SIM_JOB_READ_BINARY);
+ sf->sim_job);
if (!nmsg)
return -ENOMEM;
nsh = (struct sim_hdr *) nmsg->data;
@@ -564,6 +596,8 @@ static int subscr_sim_request(struct osmocom_ms *ms)
}
nsh->path[i] = 0; /* end of path */
nsh->file = sf->file;
+ nsh->rec_no = 1;
+ nsh->rec_mode = 0x04;
LOGP(DMM, LOGL_INFO, "Requesting SIM file 0x%04x\n", nsh->file);
sim_job(ms, nmsg);
@@ -1110,6 +1144,14 @@ int gsm_subscr_is_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
return 0;
}
+int gsm_subscr_get_key_seq(struct osmocom_ms *ms, struct gsm_subscriber *subscr)
+{
+ if (ms->settings.force_rekey)
+ return 7;
+ else
+ return subscr->key_seq;
+}
+
int gsm_subscr_dump_forbidden_plmn(struct osmocom_ms *ms,
void (*print)(void *, const char *, ...), void *priv)
{
@@ -1148,6 +1190,9 @@ void gsm_subscr_dump(struct gsm_subscriber *subscr,
print(priv, " Service Provider Name: %s\n", subscr->sim_spn);
if (subscr->msisdn[0])
print(priv, " MSISDN: %s\n", subscr->msisdn);
+ if (subscr->sms_sca[0])
+ print(priv, " SMS Service Center Address: %s\n",
+ subscr->sms_sca);
print(priv, " Status: %s IMSI %s", subscr_ustate_names[subscr->ustate],
(subscr->imsi_attached) ? "attached" : "detached");
if (subscr->tmsi != 0xffffffff)
diff --git a/Src/osmolib/src/host/layer23/src/mobile/support.c b/Src/osmolib/src/host/layer23/src/mobile/support.c
index c4269ac..bfc6180 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/support.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/support.c
@@ -41,7 +41,7 @@ void gsm_support_init(struct osmocom_ms *ms)
/* support of VBS */
sup->vbs = 0; /* no */
/* support of SMS */
- sup->sms_ptp = 0; /* no */
+ sup->sms_ptp = 1; /* no */
/* screening indicator */
sup->ss_ind = 1; /* phase 2 error handling */
/* pseudo synchronised capability */
diff --git a/Src/osmolib/src/host/layer23/src/mobile/transaction.c b/Src/osmolib/src/host/layer23/src/mobile/transaction.c
index 4b66050..45bf2b4 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/transaction.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/transaction.c
@@ -33,6 +33,8 @@
extern void *l23_ctx;
void _gsm48_cc_trans_free(struct gsm_trans *trans);
+void _gsm480_ss_trans_free(struct gsm_trans *trans);
+void _gsm411_sms_trans_free(struct gsm_trans *trans);
struct gsm_trans *trans_find_by_id(struct osmocom_ms *ms,
uint8_t proto, uint8_t trans_id)
@@ -90,14 +92,12 @@ void trans_free(struct gsm_trans *trans)
case GSM48_PDISC_CC:
_gsm48_cc_trans_free(trans);
break;
-#if 0
- case GSM48_PDISC_SS:
- _gsm411_ss_trans_free(trans);
+ case GSM48_PDISC_NC_SS:
+ _gsm480_ss_trans_free(trans);
break;
case GSM48_PDISC_SMS:
_gsm411_sms_trans_free(trans);
break;
-#endif
}
DEBUGP(DCC, "ms %s frees transaction (mem %p)\n", trans->ms->name,
@@ -108,7 +108,7 @@ void trans_free(struct gsm_trans *trans)
talloc_free(trans);
}
-/* allocate an unused transaction ID
+/* allocate an unused transaction ID
* in the given protocol using the ti_flag specified */
int trans_assign_trans_id(struct osmocom_ms *ms,
uint8_t protocol, uint8_t ti_flag)
diff --git a/Src/osmolib/src/host/layer23/src/mobile/vty_interface.c b/Src/osmolib/src/host/layer23/src/mobile/vty_interface.c
index c0a7cef..dc9e09d 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/vty_interface.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/vty_interface.c
@@ -37,6 +37,8 @@
#include <osmocom/bb/mobile/transaction.h>
#include <osmocom/bb/mobile/vty.h>
#include <osmocom/bb/mobile/app_mobile.h>
+#include <osmocom/bb/mobile/gsm480_ss.h>
+#include <osmocom/bb/mobile/gsm411_sms.h>
#include <osmocom/vty/telnet_interface.h>
void *l23_ctx;
@@ -837,6 +839,84 @@ DEFUN(call_dtmf, call_dtmf_cmd, "call MS_NAME dtmf DIGITS",
return CMD_SUCCESS;
}
+DEFUN(sms, sms_cmd, "sms MS_NAME NUMBER .LINE",
+ "Send an SMS\nName of MS (see \"show ms\")\nPhone number to send SMS "
+ "(Use digits '0123456789*#abc', and '+' to dial international)\n"
+ "SMS text\n")
+{
+ struct osmocom_ms *ms;
+ struct gsm_settings *set;
+ struct gsm_settings_abbrev *abbrev;
+ char *number, *sms_sca = NULL;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+ set = &ms->settings;
+
+ if (!set->sms_ptp) {
+ vty_out(vty, "SMS not supported by this mobile, please enable "
+ "SMS support%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (ms->subscr.sms_sca[0])
+ sms_sca = ms->subscr.sms_sca;
+ else if (set->sms_sca[0])
+ sms_sca = set->sms_sca;
+
+ if (!sms_sca) {
+ vty_out(vty, "SMS sms-service-center not defined on SIM card, "
+ "please define one at settings.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ number = (char *)argv[1];
+ llist_for_each_entry(abbrev, &set->abbrev, list) {
+ if (!strcmp(number, abbrev->abbrev)) {
+ number = abbrev->number;
+ vty_out(vty, "Using number '%s'%s", number,
+ VTY_NEWLINE);
+ break;
+ }
+ }
+ if (vty_check_number(vty, number))
+ return CMD_WARNING;
+
+ sms_send(ms, sms_sca, number, argv_concat(argv, argc, 2));
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(service, service_cmd, "service MS_NAME (*#06#|*#21#|*#67#|*#61#|*#62#"
+ "|*#002#|*#004#|*xx*number#|*xx#|#xx#|##xx#|STRING|hangup)",
+ "Send a Supplementary Service request\nName of MS (see \"show ms\")\n"
+ "Query IMSI\n"
+ "Query Call Forwarding Unconditional (CFU)\n"
+ "Query Call Forwarding when Busy (CFB)\n"
+ "Query Call Forwarding when No Response (CFNR)\n"
+ "Query Call Forwarding when Not Reachable\n"
+ "Query all Call Forwardings\n"
+ "Query all conditional Call Forwardings\n"
+ "Set and activate Call Forwarding (xx = Service Code, see above)\n"
+ "Activate Call Forwarding (xx = Service Code, see above)\n"
+ "Deactivate Call Forwarding (xx = Service Code, see above)\n"
+ "Erase and deactivate Call Forwarding (xx = Service Code, see above)\n"
+ "Service string "
+ "(Example: '*100#' requests account balace on some networks.)\n"
+ "Hangup existing service connection")
+{
+ struct osmocom_ms *ms;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+
+ ss_send(ms, argv[1], 0);
+
+ return CMD_SUCCESS;
+}
+
DEFUN(test_reselection, test_reselection_cmd, "test re-selection NAME",
"Manually trigger cell re-selection\nName of MS (see \"show ms\")")
{
@@ -1208,12 +1288,21 @@ static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
else
if (!hide_default)
vty_out(vty, " no emergency-imsi%s", VTY_NEWLINE);
+ if (set->sms_sca[0])
+ vty_out(vty, " sms-service-center %s%s", set->sms_sca,
+ VTY_NEWLINE);
+ else
+ if (!hide_default)
+ vty_out(vty, " no sms-service-center%s", VTY_NEWLINE);
if (!hide_default || set->cw)
vty_out(vty, " %scall-waiting%s", (set->cw) ? "" : "no ",
VTY_NEWLINE);
if (!hide_default || set->auto_answer)
vty_out(vty, " %sauto-answer%s",
(set->auto_answer) ? "" : "no ", VTY_NEWLINE);
+ if (!hide_default || set->force_rekey)
+ vty_out(vty, " %sforce-rekey%s",
+ (set->force_rekey) ? "" : "no ", VTY_NEWLINE);
if (!hide_default || set->clip)
vty_out(vty, " %sclip%s", (set->clip) ? "" : "no ",
VTY_NEWLINE);
@@ -1569,6 +1658,37 @@ DEFUN(cfg_ms_no_emerg_imsi, cfg_ms_no_emerg_imsi_cmd, "no emergency-imsi",
return CMD_SUCCESS;
}
+DEFUN(cfg_ms_sms_sca, cfg_ms_sms_sca_cmd, "sms-service-center NUMBER",
+ "Use Service center address for outgoing SMS\nNumber of service center "
+ "(Use digits '0123456789*#abc', and '+' to dial international)")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+ const char *number = argv[0];
+
+ if ((strlen(number) > 20 && number[0] != '+') || strlen(number) > 21) {
+ vty_out(vty, "Number too long%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (vty_check_number(vty, number))
+ return CMD_WARNING;
+
+ strcpy(set->sms_sca, number);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_ms_no_sms_sca, cfg_ms_no_sms_sca_cmd, "no sms-service-center",
+ NO_STR "Use Service center address for outgoing SMS")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+
+ set->sms_sca[0] = '\0';
+
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_no_cw, cfg_ms_no_cw_cmd, "no call-waiting",
NO_STR "Disallow waiting calls")
{
@@ -1613,6 +1733,28 @@ DEFUN(cfg_auto_answer, cfg_ms_auto_answer_cmd, "auto-answer",
return CMD_SUCCESS;
}
+DEFUN(cfg_no_force_rekey, cfg_ms_no_force_rekey_cmd, "no force-rekey",
+ NO_STR "Disable key renew forcing after every event")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+
+ set->force_rekey = 0;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_force_rekey, cfg_ms_force_rekey_cmd, "force-rekey",
+ "Enable key renew forcing after every event")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+
+ set->force_rekey = 1;
+
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_clip, cfg_ms_clip_cmd, "clip",
"Force caller ID presentation")
{
@@ -2624,6 +2766,8 @@ int ms_vty_init(void)
install_element(ENABLE_NODE, &call_cmd);
install_element(ENABLE_NODE, &call_retr_cmd);
install_element(ENABLE_NODE, &call_dtmf_cmd);
+ install_element(ENABLE_NODE, &sms_cmd);
+ install_element(ENABLE_NODE, &service_cmd);
install_element(ENABLE_NODE, &test_reselection_cmd);
install_element(ENABLE_NODE, &delete_forbidden_plmn_cmd);
@@ -2657,10 +2801,14 @@ int ms_vty_init(void)
install_element(MS_NODE, &cfg_ms_imei_random_cmd);
install_element(MS_NODE, &cfg_ms_no_emerg_imsi_cmd);
install_element(MS_NODE, &cfg_ms_emerg_imsi_cmd);
+ install_element(MS_NODE, &cfg_ms_no_sms_sca_cmd);
+ install_element(MS_NODE, &cfg_ms_sms_sca_cmd);
install_element(MS_NODE, &cfg_ms_cw_cmd);
install_element(MS_NODE, &cfg_ms_no_cw_cmd);
install_element(MS_NODE, &cfg_ms_auto_answer_cmd);
install_element(MS_NODE, &cfg_ms_no_auto_answer_cmd);
+ install_element(MS_NODE, &cfg_ms_force_rekey_cmd);
+ install_element(MS_NODE, &cfg_ms_no_force_rekey_cmd);
install_element(MS_NODE, &cfg_ms_clip_cmd);
install_element(MS_NODE, &cfg_ms_clir_cmd);
install_element(MS_NODE, &cfg_ms_no_clip_cmd);
diff --git a/Src/osmolib/src/host/osmocon/git-version-gen b/Src/osmolib/src/host/osmocon/git-version-gen
index 652fac6..652fac6 100644..100755
--- a/Src/osmolib/src/host/osmocon/git-version-gen
+++ b/Src/osmolib/src/host/osmocon/git-version-gen
diff --git a/Src/osmolib/src/host/osmocon/memdump_convert.pl b/Src/osmolib/src/host/osmocon/memdump_convert.pl
index 3d18a0b..3d18a0b 100644..100755
--- a/Src/osmolib/src/host/osmocon/memdump_convert.pl
+++ b/Src/osmolib/src/host/osmocon/memdump_convert.pl
diff --git a/Src/osmolib/src/host/osmocon/osmocon.c b/Src/osmolib/src/host/osmocon/osmocon.c
index 189984f..66f2462 100644
--- a/Src/osmolib/src/host/osmocon/osmocon.c
+++ b/Src/osmolib/src/host/osmocon/osmocon.c
@@ -123,6 +123,7 @@ enum dnload_mode {
MODE_C155,
MODE_ROMLOAD,
MODE_MTK,
+ MODE_INVALID,
};
struct dnload {
@@ -267,7 +268,7 @@ int read_file(const char *filename)
}
rc = fstat(fd, &st);
- if (st.st_size > MAX_DNLOAD_SIZE) {
+ if ((st.st_size > MAX_DNLOAD_SIZE) && (dnload.mode != MODE_ROMLOAD)) {
fprintf(stderr, "The maximum file size is 64kBytes (%u bytes)\n",
MAX_DNLOAD_SIZE);
return -EFBIG;
@@ -1184,7 +1185,7 @@ static int parse_mode(const char *arg)
else if (!strcasecmp(arg, "mtk"))
return MODE_MTK;
- return -1;
+ return MODE_INVALID;
}
#define HELP_TEXT \
@@ -1236,7 +1237,8 @@ static int un_tool_read(struct osmo_fd *fd, unsigned int flags)
c += rc;
}
- length = ntohs(*(uint16_t*)buf);
+ memcpy(&length, buf, sizeof length);
+ length = ntohs(length);
c = 0;
while(c < length) {
@@ -1412,7 +1414,7 @@ int main(int argc, char **argv)
break;
case 'm':
dnload.mode = parse_mode(optarg);
- if (dnload.mode < 0)
+ if (dnload.mode == MODE_INVALID)
usage(argv[0]);
break;
case 's':
diff --git a/Src/osmolib/src/host/osmocon/osmoload.c b/Src/osmolib/src/host/osmocon/osmoload.c
index 8a0b21c..2d55839 100644
--- a/Src/osmolib/src/host/osmocon/osmoload.c
+++ b/Src/osmolib/src/host/osmocon/osmoload.c
@@ -186,7 +186,7 @@ static void osmoload_osmo_hexdump(const uint8_t *data, unsigned int len)
static void
loader_send_request(struct msgb *msg) {
int rc;
- u_int16_t len = htons(msg->len);
+ uint16_t len = htons(msg->len);
if(osmoload.print_requests) {
printf("Sending %d bytes:\n", msg->len);
@@ -453,7 +453,7 @@ loader_handle_reply(struct msgb *msg) {
static int
loader_read_cb(struct osmo_fd *fd, unsigned int flags) {
struct msgb *msg;
- u_int16_t len;
+ uint16_t len;
int rc;
msg = msgb_alloc(MSGB_MAX, "loader");
diff --git a/Src/osmolib/src/host/rita_pll/mtk_pll.pl b/Src/osmolib/src/host/rita_pll/mtk_pll.pl
index ff931c5..ff931c5 100644..100755
--- a/Src/osmolib/src/host/rita_pll/mtk_pll.pl
+++ b/Src/osmolib/src/host/rita_pll/mtk_pll.pl
diff --git a/Src/osmolib/src/host/rita_pll/rita_pll.pl b/Src/osmolib/src/host/rita_pll/rita_pll.pl
index b5b0944..b5b0944 100644..100755
--- a/Src/osmolib/src/host/rita_pll/rita_pll.pl
+++ b/Src/osmolib/src/host/rita_pll/rita_pll.pl
diff --git a/Src/osmolib/src/shared/libosmocore/.gitignore b/Src/osmolib/src/shared/libosmocore/.gitignore
index b4d657f..82e43e3 100644
--- a/Src/osmolib/src/shared/libosmocore/.gitignore
+++ b/Src/osmolib/src/shared/libosmocore/.gitignore
@@ -7,6 +7,8 @@ Makefile.in
*.la
*.pc
aclocal.m4
+acinclude.m4
+aminclude.am
m4/*.m4
autom4te.cache
config.h*
@@ -31,16 +33,40 @@ Doxyfile.codec
.tarball-version
.version
+#gnu autotest
+tests/package.m4
+tests/atconfig
+tests/atlocal
+tests/osmo-test
+tests/package.m4
+tests/testsuite
+tests/testsuite.dir/
+tests/testsuite.log
+
tests/sms/sms_test
tests/timer/timer_test
tests/msgfile/msgfile_test
tests/ussd/ussd_test
tests/smscb/smscb_test
+tests/bits/bitrev_test
+tests/a5/a5_test
+tests/auth/milenage_test
+tests/conv/conv_test
+tests/lapd/lapd_test
+tests/gsm0808/gsm0808_test
utils/osmo-arfcn
+utils/osmo-auc-gen
doc/codec
doc/core
doc/vty
doc/gsm
doc/html.tar
+
+src/crc*gen.c
+include/osmocom/core/crc*gen.h
+
+
+# vi files
+*.sw?
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc16gen.h b/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc16gen.h
new file mode 100644
index 0000000..09101d4
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc16gen.h
@@ -0,0 +1,59 @@
+/*
+ * crc16gen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 __OSMO_CRC16GEN_H__
+#define __OSMO_CRC16GEN_H__
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc16gen.h
+ * \file Osmocom generic CRC routines (for max 16 bits poly) header
+ */
+
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+
+/*! \brief structure describing a given CRC code of max 16 bits */
+struct osmo_crc16gen_code {
+ int bits; /*!< \brief Actual number of bits of the CRC */
+ uint16_t poly; /*!< \brief Polynom (normal representation, MSB omitted */
+ uint16_t init; /*!< \brief Initialization value of the CRC state */
+ uint16_t remainder; /*!< \brief Remainder of the CRC (final XOR) */
+};
+
+uint16_t osmo_crc16gen_compute_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len);
+int osmo_crc16gen_check_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits);
+void osmo_crc16gen_set_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits);
+
+
+/*! }@ */
+
+#endif /* __OSMO_CRC16GEN_H__ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc32gen.h b/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc32gen.h
new file mode 100644
index 0000000..fe84f6c
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc32gen.h
@@ -0,0 +1,59 @@
+/*
+ * crc32gen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 __OSMO_CRC32GEN_H__
+#define __OSMO_CRC32GEN_H__
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc32gen.h
+ * \file Osmocom generic CRC routines (for max 32 bits poly) header
+ */
+
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+
+/*! \brief structure describing a given CRC code of max 32 bits */
+struct osmo_crc32gen_code {
+ int bits; /*!< \brief Actual number of bits of the CRC */
+ uint32_t poly; /*!< \brief Polynom (normal representation, MSB omitted */
+ uint32_t init; /*!< \brief Initialization value of the CRC state */
+ uint32_t remainder; /*!< \brief Remainder of the CRC (final XOR) */
+};
+
+uint32_t osmo_crc32gen_compute_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len);
+int osmo_crc32gen_check_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits);
+void osmo_crc32gen_set_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits);
+
+
+/*! }@ */
+
+#endif /* __OSMO_CRC32GEN_H__ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc64gen.h b/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc64gen.h
new file mode 100644
index 0000000..9ffc056
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc64gen.h
@@ -0,0 +1,59 @@
+/*
+ * crc64gen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 __OSMO_CRC64GEN_H__
+#define __OSMO_CRC64GEN_H__
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc64gen.h
+ * \file Osmocom generic CRC routines (for max 64 bits poly) header
+ */
+
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+
+/*! \brief structure describing a given CRC code of max 64 bits */
+struct osmo_crc64gen_code {
+ int bits; /*!< \brief Actual number of bits of the CRC */
+ uint64_t poly; /*!< \brief Polynom (normal representation, MSB omitted */
+ uint64_t init; /*!< \brief Initialization value of the CRC state */
+ uint64_t remainder; /*!< \brief Remainder of the CRC (final XOR) */
+};
+
+uint64_t osmo_crc64gen_compute_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len);
+int osmo_crc64gen_check_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits);
+void osmo_crc64gen_set_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits);
+
+
+/*! }@ */
+
+#endif /* __OSMO_CRC64GEN_H__ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc8gen.h b/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc8gen.h
new file mode 100644
index 0000000..99e5164
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/include/osmocom/core/crc8gen.h
@@ -0,0 +1,59 @@
+/*
+ * crc8gen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 __OSMO_CRC8GEN_H__
+#define __OSMO_CRC8GEN_H__
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc8gen.h
+ * \file Osmocom generic CRC routines (for max 8 bits poly) header
+ */
+
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+
+/*! \brief structure describing a given CRC code of max 8 bits */
+struct osmo_crc8gen_code {
+ int bits; /*!< \brief Actual number of bits of the CRC */
+ uint8_t poly; /*!< \brief Polynom (normal representation, MSB omitted */
+ uint8_t init; /*!< \brief Initialization value of the CRC state */
+ uint8_t remainder; /*!< \brief Remainder of the CRC (final XOR) */
+};
+
+uint8_t osmo_crc8gen_compute_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len);
+int osmo_crc8gen_check_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits);
+void osmo_crc8gen_set_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits);
+
+
+/*! }@ */
+
+#endif /* __OSMO_CRC8GEN_H__ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/src/crc16gen.c b/Src/osmolib/src/shared/libosmocore/build-host/src/crc16gen.c
new file mode 100644
index 0000000..4d4b78f
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/src/crc16gen.c
@@ -0,0 +1,120 @@
+/*
+ * crc16gen.c
+ *
+ * Generic CRC routines (for max 16 bits poly)
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc16gen.c
+ * \file Osmocom generic CRC routines (for max 16 bits poly)
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/crc16gen.h>
+
+
+/*! \brief Compute the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \returns The CRC value
+ */
+uint16_t
+osmo_crc16gen_compute_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len)
+{
+ const uint16_t poly = code->poly;
+ uint16_t crc = code->init;
+ int i, n = code->bits-1;
+
+ for (i=0; i<len; i++) {
+ uint16_t bit = in[i] & 1;
+ crc ^= (bit << n);
+ if (crc & (1 << n)) {
+ crc <<= 1;
+ crc ^= poly;
+ } else {
+ crc <<= 1;
+ }
+ crc &= (1ULL << code->bits) - 1;
+ }
+
+ crc ^= code->remainder;
+
+ return crc;
+}
+
+
+/*! \brief Checks the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits with the alleged CRC
+ * \returns 0 if CRC matches. 1 in case of error.
+ *
+ * The crc_bits array must have a length of code->len
+ */
+int
+osmo_crc16gen_check_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits)
+{
+ uint16_t crc;
+ int i;
+
+ crc = osmo_crc16gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ if (crc_bits[i] ^ ((crc >> (code->bits-i-1)) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/*! \brief Computes and writes the CRC value of a given array of bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits to write the computed CRC to
+ *
+ * The crc_bits array must have a length of code->len
+ */
+void
+osmo_crc16gen_set_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits)
+{
+ uint16_t crc;
+ int i;
+
+ crc = osmo_crc16gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ crc_bits[i] = ((crc >> (code->bits-i-1)) & 1);
+}
+
+/*! }@ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/src/crc32gen.c b/Src/osmolib/src/shared/libosmocore/build-host/src/crc32gen.c
new file mode 100644
index 0000000..765ff4f
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/src/crc32gen.c
@@ -0,0 +1,120 @@
+/*
+ * crc32gen.c
+ *
+ * Generic CRC routines (for max 32 bits poly)
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc32gen.c
+ * \file Osmocom generic CRC routines (for max 32 bits poly)
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/crc32gen.h>
+
+
+/*! \brief Compute the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \returns The CRC value
+ */
+uint32_t
+osmo_crc32gen_compute_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len)
+{
+ const uint32_t poly = code->poly;
+ uint32_t crc = code->init;
+ int i, n = code->bits-1;
+
+ for (i=0; i<len; i++) {
+ uint32_t bit = in[i] & 1;
+ crc ^= (bit << n);
+ if (crc & (1 << n)) {
+ crc <<= 1;
+ crc ^= poly;
+ } else {
+ crc <<= 1;
+ }
+ crc &= (1ULL << code->bits) - 1;
+ }
+
+ crc ^= code->remainder;
+
+ return crc;
+}
+
+
+/*! \brief Checks the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits with the alleged CRC
+ * \returns 0 if CRC matches. 1 in case of error.
+ *
+ * The crc_bits array must have a length of code->len
+ */
+int
+osmo_crc32gen_check_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits)
+{
+ uint32_t crc;
+ int i;
+
+ crc = osmo_crc32gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ if (crc_bits[i] ^ ((crc >> (code->bits-i-1)) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/*! \brief Computes and writes the CRC value of a given array of bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits to write the computed CRC to
+ *
+ * The crc_bits array must have a length of code->len
+ */
+void
+osmo_crc32gen_set_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits)
+{
+ uint32_t crc;
+ int i;
+
+ crc = osmo_crc32gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ crc_bits[i] = ((crc >> (code->bits-i-1)) & 1);
+}
+
+/*! }@ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/src/crc64gen.c b/Src/osmolib/src/shared/libosmocore/build-host/src/crc64gen.c
new file mode 100644
index 0000000..8ce9dd6
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/src/crc64gen.c
@@ -0,0 +1,120 @@
+/*
+ * crc64gen.c
+ *
+ * Generic CRC routines (for max 64 bits poly)
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc64gen.c
+ * \file Osmocom generic CRC routines (for max 64 bits poly)
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/crc64gen.h>
+
+
+/*! \brief Compute the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \returns The CRC value
+ */
+uint64_t
+osmo_crc64gen_compute_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len)
+{
+ const uint64_t poly = code->poly;
+ uint64_t crc = code->init;
+ int i, n = code->bits-1;
+
+ for (i=0; i<len; i++) {
+ uint64_t bit = in[i] & 1;
+ crc ^= (bit << n);
+ if (crc & (1 << n)) {
+ crc <<= 1;
+ crc ^= poly;
+ } else {
+ crc <<= 1;
+ }
+ crc &= (1ULL << code->bits) - 1;
+ }
+
+ crc ^= code->remainder;
+
+ return crc;
+}
+
+
+/*! \brief Checks the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits with the alleged CRC
+ * \returns 0 if CRC matches. 1 in case of error.
+ *
+ * The crc_bits array must have a length of code->len
+ */
+int
+osmo_crc64gen_check_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits)
+{
+ uint64_t crc;
+ int i;
+
+ crc = osmo_crc64gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ if (crc_bits[i] ^ ((crc >> (code->bits-i-1)) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/*! \brief Computes and writes the CRC value of a given array of bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits to write the computed CRC to
+ *
+ * The crc_bits array must have a length of code->len
+ */
+void
+osmo_crc64gen_set_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits)
+{
+ uint64_t crc;
+ int i;
+
+ crc = osmo_crc64gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ crc_bits[i] = ((crc >> (code->bits-i-1)) & 1);
+}
+
+/*! }@ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/src/crc8gen.c b/Src/osmolib/src/shared/libosmocore/build-host/src/crc8gen.c
new file mode 100644
index 0000000..0756a10
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/src/crc8gen.c
@@ -0,0 +1,120 @@
+/*
+ * crc8gen.c
+ *
+ * Generic CRC routines (for max 8 bits poly)
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc8gen.c
+ * \file Osmocom generic CRC routines (for max 8 bits poly)
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/crc8gen.h>
+
+
+/*! \brief Compute the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \returns The CRC value
+ */
+uint8_t
+osmo_crc8gen_compute_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len)
+{
+ const uint8_t poly = code->poly;
+ uint8_t crc = code->init;
+ int i, n = code->bits-1;
+
+ for (i=0; i<len; i++) {
+ uint8_t bit = in[i] & 1;
+ crc ^= (bit << n);
+ if (crc & (1 << n)) {
+ crc <<= 1;
+ crc ^= poly;
+ } else {
+ crc <<= 1;
+ }
+ crc &= (1ULL << code->bits) - 1;
+ }
+
+ crc ^= code->remainder;
+
+ return crc;
+}
+
+
+/*! \brief Checks the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits with the alleged CRC
+ * \returns 0 if CRC matches. 1 in case of error.
+ *
+ * The crc_bits array must have a length of code->len
+ */
+int
+osmo_crc8gen_check_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits)
+{
+ uint8_t crc;
+ int i;
+
+ crc = osmo_crc8gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ if (crc_bits[i] ^ ((crc >> (code->bits-i-1)) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/*! \brief Computes and writes the CRC value of a given array of bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits to write the computed CRC to
+ *
+ * The crc_bits array must have a length of code->len
+ */
+void
+osmo_crc8gen_set_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits)
+{
+ uint8_t crc;
+ int i;
+
+ crc = osmo_crc8gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ crc_bits[i] = ((crc >> (code->bits-i-1)) & 1);
+}
+
+/*! }@ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/tests/a5/a5_test b/Src/osmolib/src/shared/libosmocore/build-host/tests/a5/a5_test
new file mode 100755
index 0000000..c169f80
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/tests/a5/a5_test
@@ -0,0 +1,225 @@
+#! /bin/bash
+
+# a5_test - temporary wrapper script for .libs/a5_test
+# Generated by libtool (GNU libtool) 2.4 Debian-2.4-2ubuntu1
+#
+# The a5_test program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/tests/a5; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin; export PATH; gcc -g -O2 -o \$progdir/\$file a5_test.o ../../src/.libs/libosmocore.so ../../src/gsm/.libs/libosmogsm.so -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/.libs -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/gsm/.libs)"
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='2.4'
+ notinst_deplibs=' ../../src/libosmocore.la ../../src/gsm/libosmogsm.la'
+else
+ # When we are sourced in execute mode, $file and $ECHO are already set.
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ file="$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+ ECHO="printf %s\\n"
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../../libtool value, followed by no.
+lt_option_debug=
+func_parse_lt_options ()
+{
+ lt_script_arg0=$0
+ shift
+ for lt_opt
+ do
+ case "$lt_opt" in
+ --lt-debug) lt_option_debug=1 ;;
+ --lt-dump-script)
+ lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'`
+ test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
+ lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'`
+ cat "$lt_dump_D/$lt_dump_F"
+ exit 0
+ ;;
+ --lt-*)
+ $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n "$lt_option_debug"; then
+ echo "a5_test:a5_test:${LINENO}: libtool wrapper (GNU libtool) 2.4 Debian-2.4-2ubuntu1" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=1;
+ for lt_arg
+ do
+ $ECHO "a5_test:a5_test:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg"
+ lt_dump_args_N=`expr $lt_dump_args_N + 1`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+ if test -n "$lt_option_debug"; then
+ $ECHO "a5_test:a5_test:${LINENO}: newargv[0]: $progdir/$program" 1>&2
+ func_lt_dump_args ${1+"$@"} 1>&2
+ fi
+ exec "$progdir/$program" ${1+"$@"}
+
+ $ECHO "$0: cannot exec $program $*" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ for lt_wr_arg
+ do
+ case $lt_wr_arg in
+ --lt-*) ;;
+ *) set x "$@" "$lt_wr_arg"; shift;;
+ esac
+ shift
+ done
+ func_exec_program_core ${1+"$@"}
+}
+
+ # Parse options
+ func_parse_lt_options "$0" ${1+"$@"}
+
+ # Find the directory that this script lives in.
+ thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+ test "x$thisdir" = "x$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+ while test -n "$file"; do
+ destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+
+ # If there was a directory component, then change thisdir.
+ if test "x$destdir" != "x$file"; then
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+ *) thisdir="$thisdir/$destdir" ;;
+ esac
+ fi
+
+ file=`$ECHO "$file" | /bin/sed 's%^.*/%%'`
+ file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+ if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+ # special case for '.'
+ if test "$thisdir" = "."; then
+ thisdir=`pwd`
+ fi
+ # remove .libs from thisdir
+ case "$thisdir" in
+ *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;;
+ .libs ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=`cd "$thisdir" && pwd`
+ test -n "$absdir" && thisdir="$absdir"
+
+ program=lt-'a5_test'
+ progdir="$thisdir/.libs"
+
+ if test ! -f "$progdir/$program" ||
+ { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
+ test "X$file" != "X$progdir/$program"; }; then
+
+ file="$$-$program"
+
+ if test ! -d "$progdir"; then
+ mkdir "$progdir"
+ else
+ rm -f "$progdir/$file"
+ fi
+
+ # relink executable if necessary
+ if test -n "$relink_command"; then
+ if relink_command_output=`eval $relink_command 2>&1`; then :
+ else
+ printf %s\n "$relink_command_output" >&2
+ rm -f "$progdir/$file"
+ exit 1
+ fi
+ fi
+
+ mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+ { rm -f "$progdir/$program";
+ mv -f "$progdir/$file" "$progdir/$program"; }
+ rm -f "$progdir/$file"
+ fi
+
+ if test -f "$progdir/$program"; then
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ # Run the actual program with our arguments.
+ func_exec_program ${1+"$@"}
+ fi
+ else
+ # The program doesn't exist.
+ $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+ $ECHO "This script is just a wrapper for $program." 1>&2
+ $ECHO "See the libtool documentation for more information." 1>&2
+ exit 1
+ fi
+fi
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/tests/atconfig b/Src/osmolib/src/shared/libosmocore/build-host/tests/atconfig
new file mode 100644
index 0000000..b8266f3
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/tests/atconfig
@@ -0,0 +1,20 @@
+# Configurable variable values for building test suites.
+# Generated by ./config.status.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# The test suite will define top_srcdir=/../.. etc.
+at_testdir='tests'
+abs_builddir='/home/tom/imsi-catcher-detection/Src/osmolib/src/shared/libosmocore/build-host/tests'
+at_srcdir='../../tests'
+abs_srcdir='/home/tom/imsi-catcher-detection/Src/osmolib/src/shared/libosmocore/build-host/../tests'
+at_top_srcdir='../..'
+abs_top_srcdir='/home/tom/imsi-catcher-detection/Src/osmolib/src/shared/libosmocore/build-host/..'
+at_top_build_prefix='../'
+abs_top_builddir='/home/tom/imsi-catcher-detection/Src/osmolib/src/shared/libosmocore/build-host'
+
+# Backward compatibility with Autotest <= 2.59b:
+at_top_builddir=$at_top_build_prefix
+
+AUTOTEST_PATH='tests'
+
+SHELL=${CONFIG_SHELL-'/bin/bash'}
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/tests/auth/milenage_test b/Src/osmolib/src/shared/libosmocore/build-host/tests/auth/milenage_test
new file mode 100755
index 0000000..b6bef92
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/tests/auth/milenage_test
@@ -0,0 +1,225 @@
+#! /bin/bash
+
+# milenage_test - temporary wrapper script for .libs/milenage_test
+# Generated by libtool (GNU libtool) 2.4 Debian-2.4-2ubuntu1
+#
+# The milenage_test program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/tests/auth; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin; export PATH; gcc -g -O2 -o \$progdir/\$file milenage_test.o ../../src/.libs/libosmocore.so ../../src/gsm/.libs/libosmogsm.so -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/.libs -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/gsm/.libs)"
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='2.4'
+ notinst_deplibs=' ../../src/libosmocore.la ../../src/gsm/libosmogsm.la'
+else
+ # When we are sourced in execute mode, $file and $ECHO are already set.
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ file="$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+ ECHO="printf %s\\n"
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../../libtool value, followed by no.
+lt_option_debug=
+func_parse_lt_options ()
+{
+ lt_script_arg0=$0
+ shift
+ for lt_opt
+ do
+ case "$lt_opt" in
+ --lt-debug) lt_option_debug=1 ;;
+ --lt-dump-script)
+ lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'`
+ test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
+ lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'`
+ cat "$lt_dump_D/$lt_dump_F"
+ exit 0
+ ;;
+ --lt-*)
+ $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n "$lt_option_debug"; then
+ echo "milenage_test:milenage_test:${LINENO}: libtool wrapper (GNU libtool) 2.4 Debian-2.4-2ubuntu1" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=1;
+ for lt_arg
+ do
+ $ECHO "milenage_test:milenage_test:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg"
+ lt_dump_args_N=`expr $lt_dump_args_N + 1`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+ if test -n "$lt_option_debug"; then
+ $ECHO "milenage_test:milenage_test:${LINENO}: newargv[0]: $progdir/$program" 1>&2
+ func_lt_dump_args ${1+"$@"} 1>&2
+ fi
+ exec "$progdir/$program" ${1+"$@"}
+
+ $ECHO "$0: cannot exec $program $*" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ for lt_wr_arg
+ do
+ case $lt_wr_arg in
+ --lt-*) ;;
+ *) set x "$@" "$lt_wr_arg"; shift;;
+ esac
+ shift
+ done
+ func_exec_program_core ${1+"$@"}
+}
+
+ # Parse options
+ func_parse_lt_options "$0" ${1+"$@"}
+
+ # Find the directory that this script lives in.
+ thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+ test "x$thisdir" = "x$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+ while test -n "$file"; do
+ destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+
+ # If there was a directory component, then change thisdir.
+ if test "x$destdir" != "x$file"; then
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+ *) thisdir="$thisdir/$destdir" ;;
+ esac
+ fi
+
+ file=`$ECHO "$file" | /bin/sed 's%^.*/%%'`
+ file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+ if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+ # special case for '.'
+ if test "$thisdir" = "."; then
+ thisdir=`pwd`
+ fi
+ # remove .libs from thisdir
+ case "$thisdir" in
+ *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;;
+ .libs ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=`cd "$thisdir" && pwd`
+ test -n "$absdir" && thisdir="$absdir"
+
+ program=lt-'milenage_test'
+ progdir="$thisdir/.libs"
+
+ if test ! -f "$progdir/$program" ||
+ { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
+ test "X$file" != "X$progdir/$program"; }; then
+
+ file="$$-$program"
+
+ if test ! -d "$progdir"; then
+ mkdir "$progdir"
+ else
+ rm -f "$progdir/$file"
+ fi
+
+ # relink executable if necessary
+ if test -n "$relink_command"; then
+ if relink_command_output=`eval $relink_command 2>&1`; then :
+ else
+ printf %s\n "$relink_command_output" >&2
+ rm -f "$progdir/$file"
+ exit 1
+ fi
+ fi
+
+ mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+ { rm -f "$progdir/$program";
+ mv -f "$progdir/$file" "$progdir/$program"; }
+ rm -f "$progdir/$file"
+ fi
+
+ if test -f "$progdir/$program"; then
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ # Run the actual program with our arguments.
+ func_exec_program ${1+"$@"}
+ fi
+ else
+ # The program doesn't exist.
+ $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+ $ECHO "This script is just a wrapper for $program." 1>&2
+ $ECHO "See the libtool documentation for more information." 1>&2
+ exit 1
+ fi
+fi
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/tests/bits/bitrev_test b/Src/osmolib/src/shared/libosmocore/build-host/tests/bits/bitrev_test
index b9f073e..9d063d1 100644..100755
--- a/Src/osmolib/src/shared/libosmocore/build-host/tests/bits/bitrev_test
+++ b/Src/osmolib/src/shared/libosmocore/build-host/tests/bits/bitrev_test
@@ -31,7 +31,7 @@ DUALCASE=1; export DUALCASE # for MKS sh
# if CDPATH is set.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-relink_command="(cd /home/tom/imsi-catcher-detection/Src/osmocom-bb/src/shared/libosmocore/build-host/tests/bits; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/home/tom/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/local/bin; export PATH; gcc -g -O2 -o \$progdir/\$file bitrev_test.o ../../src/.libs/libosmocore.so -Wl,-rpath -Wl,/home/tom/imsi-catcher-detection/Src/osmocom-bb/src/shared/libosmocore/build-host/src/.libs)"
+relink_command="(cd /home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/tests/bits; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin; export PATH; gcc -g -O2 -o \$progdir/\$file bitrev_test.o ../../src/.libs/libosmocore.so -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/.libs)"
# This environment variable determines our operation mode.
if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/tests/conv/conv_test b/Src/osmolib/src/shared/libosmocore/build-host/tests/conv/conv_test
new file mode 100755
index 0000000..d0ca113
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/tests/conv/conv_test
@@ -0,0 +1,225 @@
+#! /bin/bash
+
+# conv_test - temporary wrapper script for .libs/conv_test
+# Generated by libtool (GNU libtool) 2.4 Debian-2.4-2ubuntu1
+#
+# The conv_test program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/tests/conv; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin; export PATH; gcc -g -O2 -o \$progdir/\$file conv_test.o ../../src/.libs/libosmocore.so -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/.libs)"
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='2.4'
+ notinst_deplibs=' ../../src/libosmocore.la'
+else
+ # When we are sourced in execute mode, $file and $ECHO are already set.
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ file="$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+ ECHO="printf %s\\n"
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../../libtool value, followed by no.
+lt_option_debug=
+func_parse_lt_options ()
+{
+ lt_script_arg0=$0
+ shift
+ for lt_opt
+ do
+ case "$lt_opt" in
+ --lt-debug) lt_option_debug=1 ;;
+ --lt-dump-script)
+ lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'`
+ test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
+ lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'`
+ cat "$lt_dump_D/$lt_dump_F"
+ exit 0
+ ;;
+ --lt-*)
+ $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n "$lt_option_debug"; then
+ echo "conv_test:conv_test:${LINENO}: libtool wrapper (GNU libtool) 2.4 Debian-2.4-2ubuntu1" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=1;
+ for lt_arg
+ do
+ $ECHO "conv_test:conv_test:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg"
+ lt_dump_args_N=`expr $lt_dump_args_N + 1`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+ if test -n "$lt_option_debug"; then
+ $ECHO "conv_test:conv_test:${LINENO}: newargv[0]: $progdir/$program" 1>&2
+ func_lt_dump_args ${1+"$@"} 1>&2
+ fi
+ exec "$progdir/$program" ${1+"$@"}
+
+ $ECHO "$0: cannot exec $program $*" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ for lt_wr_arg
+ do
+ case $lt_wr_arg in
+ --lt-*) ;;
+ *) set x "$@" "$lt_wr_arg"; shift;;
+ esac
+ shift
+ done
+ func_exec_program_core ${1+"$@"}
+}
+
+ # Parse options
+ func_parse_lt_options "$0" ${1+"$@"}
+
+ # Find the directory that this script lives in.
+ thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+ test "x$thisdir" = "x$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+ while test -n "$file"; do
+ destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+
+ # If there was a directory component, then change thisdir.
+ if test "x$destdir" != "x$file"; then
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+ *) thisdir="$thisdir/$destdir" ;;
+ esac
+ fi
+
+ file=`$ECHO "$file" | /bin/sed 's%^.*/%%'`
+ file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+ if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+ # special case for '.'
+ if test "$thisdir" = "."; then
+ thisdir=`pwd`
+ fi
+ # remove .libs from thisdir
+ case "$thisdir" in
+ *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;;
+ .libs ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=`cd "$thisdir" && pwd`
+ test -n "$absdir" && thisdir="$absdir"
+
+ program=lt-'conv_test'
+ progdir="$thisdir/.libs"
+
+ if test ! -f "$progdir/$program" ||
+ { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
+ test "X$file" != "X$progdir/$program"; }; then
+
+ file="$$-$program"
+
+ if test ! -d "$progdir"; then
+ mkdir "$progdir"
+ else
+ rm -f "$progdir/$file"
+ fi
+
+ # relink executable if necessary
+ if test -n "$relink_command"; then
+ if relink_command_output=`eval $relink_command 2>&1`; then :
+ else
+ printf %s\n "$relink_command_output" >&2
+ rm -f "$progdir/$file"
+ exit 1
+ fi
+ fi
+
+ mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+ { rm -f "$progdir/$program";
+ mv -f "$progdir/$file" "$progdir/$program"; }
+ rm -f "$progdir/$file"
+ fi
+
+ if test -f "$progdir/$program"; then
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ # Run the actual program with our arguments.
+ func_exec_program ${1+"$@"}
+ fi
+ else
+ # The program doesn't exist.
+ $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+ $ECHO "This script is just a wrapper for $program." 1>&2
+ $ECHO "See the libtool documentation for more information." 1>&2
+ exit 1
+ fi
+fi
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/tests/gsm0808/gsm0808_test b/Src/osmolib/src/shared/libosmocore/build-host/tests/gsm0808/gsm0808_test
new file mode 100755
index 0000000..62f2291
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/tests/gsm0808/gsm0808_test
@@ -0,0 +1,225 @@
+#! /bin/bash
+
+# gsm0808_test - temporary wrapper script for .libs/gsm0808_test
+# Generated by libtool (GNU libtool) 2.4 Debian-2.4-2ubuntu1
+#
+# The gsm0808_test program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/tests/gsm0808; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin; export PATH; gcc -g -O2 -o \$progdir/\$file gsm0808_test.o ../../src/.libs/libosmocore.so ../../src/gsm/.libs/libosmogsm.so -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/.libs -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/gsm/.libs)"
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='2.4'
+ notinst_deplibs=' ../../src/libosmocore.la ../../src/gsm/libosmogsm.la'
+else
+ # When we are sourced in execute mode, $file and $ECHO are already set.
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ file="$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+ ECHO="printf %s\\n"
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../../libtool value, followed by no.
+lt_option_debug=
+func_parse_lt_options ()
+{
+ lt_script_arg0=$0
+ shift
+ for lt_opt
+ do
+ case "$lt_opt" in
+ --lt-debug) lt_option_debug=1 ;;
+ --lt-dump-script)
+ lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'`
+ test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
+ lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'`
+ cat "$lt_dump_D/$lt_dump_F"
+ exit 0
+ ;;
+ --lt-*)
+ $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n "$lt_option_debug"; then
+ echo "gsm0808_test:gsm0808_test:${LINENO}: libtool wrapper (GNU libtool) 2.4 Debian-2.4-2ubuntu1" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=1;
+ for lt_arg
+ do
+ $ECHO "gsm0808_test:gsm0808_test:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg"
+ lt_dump_args_N=`expr $lt_dump_args_N + 1`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+ if test -n "$lt_option_debug"; then
+ $ECHO "gsm0808_test:gsm0808_test:${LINENO}: newargv[0]: $progdir/$program" 1>&2
+ func_lt_dump_args ${1+"$@"} 1>&2
+ fi
+ exec "$progdir/$program" ${1+"$@"}
+
+ $ECHO "$0: cannot exec $program $*" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ for lt_wr_arg
+ do
+ case $lt_wr_arg in
+ --lt-*) ;;
+ *) set x "$@" "$lt_wr_arg"; shift;;
+ esac
+ shift
+ done
+ func_exec_program_core ${1+"$@"}
+}
+
+ # Parse options
+ func_parse_lt_options "$0" ${1+"$@"}
+
+ # Find the directory that this script lives in.
+ thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+ test "x$thisdir" = "x$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+ while test -n "$file"; do
+ destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+
+ # If there was a directory component, then change thisdir.
+ if test "x$destdir" != "x$file"; then
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+ *) thisdir="$thisdir/$destdir" ;;
+ esac
+ fi
+
+ file=`$ECHO "$file" | /bin/sed 's%^.*/%%'`
+ file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+ if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+ # special case for '.'
+ if test "$thisdir" = "."; then
+ thisdir=`pwd`
+ fi
+ # remove .libs from thisdir
+ case "$thisdir" in
+ *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;;
+ .libs ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=`cd "$thisdir" && pwd`
+ test -n "$absdir" && thisdir="$absdir"
+
+ program=lt-'gsm0808_test'
+ progdir="$thisdir/.libs"
+
+ if test ! -f "$progdir/$program" ||
+ { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
+ test "X$file" != "X$progdir/$program"; }; then
+
+ file="$$-$program"
+
+ if test ! -d "$progdir"; then
+ mkdir "$progdir"
+ else
+ rm -f "$progdir/$file"
+ fi
+
+ # relink executable if necessary
+ if test -n "$relink_command"; then
+ if relink_command_output=`eval $relink_command 2>&1`; then :
+ else
+ printf %s\n "$relink_command_output" >&2
+ rm -f "$progdir/$file"
+ exit 1
+ fi
+ fi
+
+ mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+ { rm -f "$progdir/$program";
+ mv -f "$progdir/$file" "$progdir/$program"; }
+ rm -f "$progdir/$file"
+ fi
+
+ if test -f "$progdir/$program"; then
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ # Run the actual program with our arguments.
+ func_exec_program ${1+"$@"}
+ fi
+ else
+ # The program doesn't exist.
+ $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+ $ECHO "This script is just a wrapper for $program." 1>&2
+ $ECHO "See the libtool documentation for more information." 1>&2
+ exit 1
+ fi
+fi
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/tests/lapd/lapd_test b/Src/osmolib/src/shared/libosmocore/build-host/tests/lapd/lapd_test
new file mode 100755
index 0000000..a4bb289
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/tests/lapd/lapd_test
@@ -0,0 +1,225 @@
+#! /bin/bash
+
+# lapd_test - temporary wrapper script for .libs/lapd_test
+# Generated by libtool (GNU libtool) 2.4 Debian-2.4-2ubuntu1
+#
+# The lapd_test program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/tests/lapd; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin; export PATH; gcc -g -O2 -o \$progdir/\$file lapd_test.o ../../src/.libs/libosmocore.so ../../src/gsm/.libs/libosmogsm.so -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/.libs -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/gsm/.libs)"
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='2.4'
+ notinst_deplibs=' ../../src/libosmocore.la ../../src/gsm/libosmogsm.la'
+else
+ # When we are sourced in execute mode, $file and $ECHO are already set.
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ file="$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+ ECHO="printf %s\\n"
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../../libtool value, followed by no.
+lt_option_debug=
+func_parse_lt_options ()
+{
+ lt_script_arg0=$0
+ shift
+ for lt_opt
+ do
+ case "$lt_opt" in
+ --lt-debug) lt_option_debug=1 ;;
+ --lt-dump-script)
+ lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'`
+ test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
+ lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'`
+ cat "$lt_dump_D/$lt_dump_F"
+ exit 0
+ ;;
+ --lt-*)
+ $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n "$lt_option_debug"; then
+ echo "lapd_test:lapd_test:${LINENO}: libtool wrapper (GNU libtool) 2.4 Debian-2.4-2ubuntu1" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=1;
+ for lt_arg
+ do
+ $ECHO "lapd_test:lapd_test:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg"
+ lt_dump_args_N=`expr $lt_dump_args_N + 1`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+ if test -n "$lt_option_debug"; then
+ $ECHO "lapd_test:lapd_test:${LINENO}: newargv[0]: $progdir/$program" 1>&2
+ func_lt_dump_args ${1+"$@"} 1>&2
+ fi
+ exec "$progdir/$program" ${1+"$@"}
+
+ $ECHO "$0: cannot exec $program $*" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ for lt_wr_arg
+ do
+ case $lt_wr_arg in
+ --lt-*) ;;
+ *) set x "$@" "$lt_wr_arg"; shift;;
+ esac
+ shift
+ done
+ func_exec_program_core ${1+"$@"}
+}
+
+ # Parse options
+ func_parse_lt_options "$0" ${1+"$@"}
+
+ # Find the directory that this script lives in.
+ thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+ test "x$thisdir" = "x$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+ while test -n "$file"; do
+ destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+
+ # If there was a directory component, then change thisdir.
+ if test "x$destdir" != "x$file"; then
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+ *) thisdir="$thisdir/$destdir" ;;
+ esac
+ fi
+
+ file=`$ECHO "$file" | /bin/sed 's%^.*/%%'`
+ file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+ if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+ # special case for '.'
+ if test "$thisdir" = "."; then
+ thisdir=`pwd`
+ fi
+ # remove .libs from thisdir
+ case "$thisdir" in
+ *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;;
+ .libs ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=`cd "$thisdir" && pwd`
+ test -n "$absdir" && thisdir="$absdir"
+
+ program=lt-'lapd_test'
+ progdir="$thisdir/.libs"
+
+ if test ! -f "$progdir/$program" ||
+ { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
+ test "X$file" != "X$progdir/$program"; }; then
+
+ file="$$-$program"
+
+ if test ! -d "$progdir"; then
+ mkdir "$progdir"
+ else
+ rm -f "$progdir/$file"
+ fi
+
+ # relink executable if necessary
+ if test -n "$relink_command"; then
+ if relink_command_output=`eval $relink_command 2>&1`; then :
+ else
+ printf %s\n "$relink_command_output" >&2
+ rm -f "$progdir/$file"
+ exit 1
+ fi
+ fi
+
+ mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+ { rm -f "$progdir/$program";
+ mv -f "$progdir/$file" "$progdir/$program"; }
+ rm -f "$progdir/$file"
+ fi
+
+ if test -f "$progdir/$program"; then
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ # Run the actual program with our arguments.
+ func_exec_program ${1+"$@"}
+ fi
+ else
+ # The program doesn't exist.
+ $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+ $ECHO "This script is just a wrapper for $program." 1>&2
+ $ECHO "See the libtool documentation for more information." 1>&2
+ exit 1
+ fi
+fi
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/utils/osmo-arfcn b/Src/osmolib/src/shared/libosmocore/build-host/utils/osmo-arfcn
index 30facd4..f4b3fc1 100644..100755
--- a/Src/osmolib/src/shared/libosmocore/build-host/utils/osmo-arfcn
+++ b/Src/osmolib/src/shared/libosmocore/build-host/utils/osmo-arfcn
@@ -31,7 +31,7 @@ DUALCASE=1; export DUALCASE # for MKS sh
# if CDPATH is set.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-relink_command="(cd /home/tom/imsi-catcher-detection/Src/osmocom-bb/src/shared/libosmocore/build-host/utils; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/home/tom/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/local/bin; export PATH; gcc -g -O2 -o \$progdir/\$file osmo-arfcn.o ../src/.libs/libosmocore.so ../src/gsm/.libs/libosmogsm.so -Wl,-rpath -Wl,/home/tom/imsi-catcher-detection/Src/osmocom-bb/src/shared/libosmocore/build-host/src/.libs -Wl,-rpath -Wl,/home/tom/imsi-catcher-detection/Src/osmocom-bb/src/shared/libosmocore/build-host/src/gsm/.libs)"
+relink_command="(cd /home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/utils; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin; export PATH; gcc -g -O2 -o \$progdir/\$file osmo-arfcn.o ../src/.libs/libosmocore.so ../src/gsm/.libs/libosmogsm.so -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/.libs -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/gsm/.libs)"
# This environment variable determines our operation mode.
if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
diff --git a/Src/osmolib/src/shared/libosmocore/build-host/utils/osmo-auc-gen b/Src/osmolib/src/shared/libosmocore/build-host/utils/osmo-auc-gen
new file mode 100755
index 0000000..69bb486
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-host/utils/osmo-auc-gen
@@ -0,0 +1,225 @@
+#! /bin/bash
+
+# osmo-auc-gen - temporary wrapper script for .libs/osmo-auc-gen
+# Generated by libtool (GNU libtool) 2.4 Debian-2.4-2ubuntu1
+#
+# The osmo-auc-gen program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/utils; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin; export PATH; gcc -g -O2 -o \$progdir/\$file osmo-auc-gen.o ../src/.libs/libosmocore.so ../src/gsm/.libs/libosmogsm.so -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/.libs -Wl,-rpath -Wl,/home/tom/test/osmocom-bb/src/shared/libosmocore/build-host/src/gsm/.libs)"
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='2.4'
+ notinst_deplibs=' ../src/libosmocore.la ../src/gsm/libosmogsm.la'
+else
+ # When we are sourced in execute mode, $file and $ECHO are already set.
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ file="$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+ ECHO="printf %s\\n"
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../libtool value, followed by no.
+lt_option_debug=
+func_parse_lt_options ()
+{
+ lt_script_arg0=$0
+ shift
+ for lt_opt
+ do
+ case "$lt_opt" in
+ --lt-debug) lt_option_debug=1 ;;
+ --lt-dump-script)
+ lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'`
+ test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
+ lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'`
+ cat "$lt_dump_D/$lt_dump_F"
+ exit 0
+ ;;
+ --lt-*)
+ $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n "$lt_option_debug"; then
+ echo "osmo-auc-gen:osmo-auc-gen:${LINENO}: libtool wrapper (GNU libtool) 2.4 Debian-2.4-2ubuntu1" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=1;
+ for lt_arg
+ do
+ $ECHO "osmo-auc-gen:osmo-auc-gen:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg"
+ lt_dump_args_N=`expr $lt_dump_args_N + 1`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+ if test -n "$lt_option_debug"; then
+ $ECHO "osmo-auc-gen:osmo-auc-gen:${LINENO}: newargv[0]: $progdir/$program" 1>&2
+ func_lt_dump_args ${1+"$@"} 1>&2
+ fi
+ exec "$progdir/$program" ${1+"$@"}
+
+ $ECHO "$0: cannot exec $program $*" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ for lt_wr_arg
+ do
+ case $lt_wr_arg in
+ --lt-*) ;;
+ *) set x "$@" "$lt_wr_arg"; shift;;
+ esac
+ shift
+ done
+ func_exec_program_core ${1+"$@"}
+}
+
+ # Parse options
+ func_parse_lt_options "$0" ${1+"$@"}
+
+ # Find the directory that this script lives in.
+ thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+ test "x$thisdir" = "x$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+ while test -n "$file"; do
+ destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+
+ # If there was a directory component, then change thisdir.
+ if test "x$destdir" != "x$file"; then
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+ *) thisdir="$thisdir/$destdir" ;;
+ esac
+ fi
+
+ file=`$ECHO "$file" | /bin/sed 's%^.*/%%'`
+ file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+ if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+ # special case for '.'
+ if test "$thisdir" = "."; then
+ thisdir=`pwd`
+ fi
+ # remove .libs from thisdir
+ case "$thisdir" in
+ *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;;
+ .libs ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=`cd "$thisdir" && pwd`
+ test -n "$absdir" && thisdir="$absdir"
+
+ program=lt-'osmo-auc-gen'
+ progdir="$thisdir/.libs"
+
+ if test ! -f "$progdir/$program" ||
+ { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
+ test "X$file" != "X$progdir/$program"; }; then
+
+ file="$$-$program"
+
+ if test ! -d "$progdir"; then
+ mkdir "$progdir"
+ else
+ rm -f "$progdir/$file"
+ fi
+
+ # relink executable if necessary
+ if test -n "$relink_command"; then
+ if relink_command_output=`eval $relink_command 2>&1`; then :
+ else
+ printf %s\n "$relink_command_output" >&2
+ rm -f "$progdir/$file"
+ exit 1
+ fi
+ fi
+
+ mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+ { rm -f "$progdir/$program";
+ mv -f "$progdir/$file" "$progdir/$program"; }
+ rm -f "$progdir/$file"
+ fi
+
+ if test -f "$progdir/$program"; then
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ # Run the actual program with our arguments.
+ func_exec_program ${1+"$@"}
+ fi
+ else
+ # The program doesn't exist.
+ $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+ $ECHO "This script is just a wrapper for $program." 1>&2
+ $ECHO "See the libtool documentation for more information." 1>&2
+ exit 1
+ fi
+fi
diff --git a/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc16gen.h b/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc16gen.h
new file mode 100644
index 0000000..09101d4
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc16gen.h
@@ -0,0 +1,59 @@
+/*
+ * crc16gen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 __OSMO_CRC16GEN_H__
+#define __OSMO_CRC16GEN_H__
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc16gen.h
+ * \file Osmocom generic CRC routines (for max 16 bits poly) header
+ */
+
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+
+/*! \brief structure describing a given CRC code of max 16 bits */
+struct osmo_crc16gen_code {
+ int bits; /*!< \brief Actual number of bits of the CRC */
+ uint16_t poly; /*!< \brief Polynom (normal representation, MSB omitted */
+ uint16_t init; /*!< \brief Initialization value of the CRC state */
+ uint16_t remainder; /*!< \brief Remainder of the CRC (final XOR) */
+};
+
+uint16_t osmo_crc16gen_compute_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len);
+int osmo_crc16gen_check_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits);
+void osmo_crc16gen_set_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits);
+
+
+/*! }@ */
+
+#endif /* __OSMO_CRC16GEN_H__ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc32gen.h b/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc32gen.h
new file mode 100644
index 0000000..fe84f6c
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc32gen.h
@@ -0,0 +1,59 @@
+/*
+ * crc32gen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 __OSMO_CRC32GEN_H__
+#define __OSMO_CRC32GEN_H__
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc32gen.h
+ * \file Osmocom generic CRC routines (for max 32 bits poly) header
+ */
+
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+
+/*! \brief structure describing a given CRC code of max 32 bits */
+struct osmo_crc32gen_code {
+ int bits; /*!< \brief Actual number of bits of the CRC */
+ uint32_t poly; /*!< \brief Polynom (normal representation, MSB omitted */
+ uint32_t init; /*!< \brief Initialization value of the CRC state */
+ uint32_t remainder; /*!< \brief Remainder of the CRC (final XOR) */
+};
+
+uint32_t osmo_crc32gen_compute_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len);
+int osmo_crc32gen_check_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits);
+void osmo_crc32gen_set_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits);
+
+
+/*! }@ */
+
+#endif /* __OSMO_CRC32GEN_H__ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc64gen.h b/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc64gen.h
new file mode 100644
index 0000000..9ffc056
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc64gen.h
@@ -0,0 +1,59 @@
+/*
+ * crc64gen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 __OSMO_CRC64GEN_H__
+#define __OSMO_CRC64GEN_H__
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc64gen.h
+ * \file Osmocom generic CRC routines (for max 64 bits poly) header
+ */
+
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+
+/*! \brief structure describing a given CRC code of max 64 bits */
+struct osmo_crc64gen_code {
+ int bits; /*!< \brief Actual number of bits of the CRC */
+ uint64_t poly; /*!< \brief Polynom (normal representation, MSB omitted */
+ uint64_t init; /*!< \brief Initialization value of the CRC state */
+ uint64_t remainder; /*!< \brief Remainder of the CRC (final XOR) */
+};
+
+uint64_t osmo_crc64gen_compute_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len);
+int osmo_crc64gen_check_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits);
+void osmo_crc64gen_set_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits);
+
+
+/*! }@ */
+
+#endif /* __OSMO_CRC64GEN_H__ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc8gen.h b/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc8gen.h
new file mode 100644
index 0000000..99e5164
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-target/include/osmocom/core/crc8gen.h
@@ -0,0 +1,59 @@
+/*
+ * crc8gen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 __OSMO_CRC8GEN_H__
+#define __OSMO_CRC8GEN_H__
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc8gen.h
+ * \file Osmocom generic CRC routines (for max 8 bits poly) header
+ */
+
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+
+/*! \brief structure describing a given CRC code of max 8 bits */
+struct osmo_crc8gen_code {
+ int bits; /*!< \brief Actual number of bits of the CRC */
+ uint8_t poly; /*!< \brief Polynom (normal representation, MSB omitted */
+ uint8_t init; /*!< \brief Initialization value of the CRC state */
+ uint8_t remainder; /*!< \brief Remainder of the CRC (final XOR) */
+};
+
+uint8_t osmo_crc8gen_compute_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len);
+int osmo_crc8gen_check_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits);
+void osmo_crc8gen_set_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits);
+
+
+/*! }@ */
+
+#endif /* __OSMO_CRC8GEN_H__ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-target/src/crc16gen.c b/Src/osmolib/src/shared/libosmocore/build-target/src/crc16gen.c
new file mode 100644
index 0000000..4d4b78f
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-target/src/crc16gen.c
@@ -0,0 +1,120 @@
+/*
+ * crc16gen.c
+ *
+ * Generic CRC routines (for max 16 bits poly)
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc16gen.c
+ * \file Osmocom generic CRC routines (for max 16 bits poly)
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/crc16gen.h>
+
+
+/*! \brief Compute the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \returns The CRC value
+ */
+uint16_t
+osmo_crc16gen_compute_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len)
+{
+ const uint16_t poly = code->poly;
+ uint16_t crc = code->init;
+ int i, n = code->bits-1;
+
+ for (i=0; i<len; i++) {
+ uint16_t bit = in[i] & 1;
+ crc ^= (bit << n);
+ if (crc & (1 << n)) {
+ crc <<= 1;
+ crc ^= poly;
+ } else {
+ crc <<= 1;
+ }
+ crc &= (1ULL << code->bits) - 1;
+ }
+
+ crc ^= code->remainder;
+
+ return crc;
+}
+
+
+/*! \brief Checks the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits with the alleged CRC
+ * \returns 0 if CRC matches. 1 in case of error.
+ *
+ * The crc_bits array must have a length of code->len
+ */
+int
+osmo_crc16gen_check_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits)
+{
+ uint16_t crc;
+ int i;
+
+ crc = osmo_crc16gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ if (crc_bits[i] ^ ((crc >> (code->bits-i-1)) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/*! \brief Computes and writes the CRC value of a given array of bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits to write the computed CRC to
+ *
+ * The crc_bits array must have a length of code->len
+ */
+void
+osmo_crc16gen_set_bits(const struct osmo_crc16gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits)
+{
+ uint16_t crc;
+ int i;
+
+ crc = osmo_crc16gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ crc_bits[i] = ((crc >> (code->bits-i-1)) & 1);
+}
+
+/*! }@ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-target/src/crc32gen.c b/Src/osmolib/src/shared/libosmocore/build-target/src/crc32gen.c
new file mode 100644
index 0000000..765ff4f
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-target/src/crc32gen.c
@@ -0,0 +1,120 @@
+/*
+ * crc32gen.c
+ *
+ * Generic CRC routines (for max 32 bits poly)
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc32gen.c
+ * \file Osmocom generic CRC routines (for max 32 bits poly)
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/crc32gen.h>
+
+
+/*! \brief Compute the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \returns The CRC value
+ */
+uint32_t
+osmo_crc32gen_compute_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len)
+{
+ const uint32_t poly = code->poly;
+ uint32_t crc = code->init;
+ int i, n = code->bits-1;
+
+ for (i=0; i<len; i++) {
+ uint32_t bit = in[i] & 1;
+ crc ^= (bit << n);
+ if (crc & (1 << n)) {
+ crc <<= 1;
+ crc ^= poly;
+ } else {
+ crc <<= 1;
+ }
+ crc &= (1ULL << code->bits) - 1;
+ }
+
+ crc ^= code->remainder;
+
+ return crc;
+}
+
+
+/*! \brief Checks the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits with the alleged CRC
+ * \returns 0 if CRC matches. 1 in case of error.
+ *
+ * The crc_bits array must have a length of code->len
+ */
+int
+osmo_crc32gen_check_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits)
+{
+ uint32_t crc;
+ int i;
+
+ crc = osmo_crc32gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ if (crc_bits[i] ^ ((crc >> (code->bits-i-1)) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/*! \brief Computes and writes the CRC value of a given array of bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits to write the computed CRC to
+ *
+ * The crc_bits array must have a length of code->len
+ */
+void
+osmo_crc32gen_set_bits(const struct osmo_crc32gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits)
+{
+ uint32_t crc;
+ int i;
+
+ crc = osmo_crc32gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ crc_bits[i] = ((crc >> (code->bits-i-1)) & 1);
+}
+
+/*! }@ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-target/src/crc64gen.c b/Src/osmolib/src/shared/libosmocore/build-target/src/crc64gen.c
new file mode 100644
index 0000000..8ce9dd6
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-target/src/crc64gen.c
@@ -0,0 +1,120 @@
+/*
+ * crc64gen.c
+ *
+ * Generic CRC routines (for max 64 bits poly)
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc64gen.c
+ * \file Osmocom generic CRC routines (for max 64 bits poly)
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/crc64gen.h>
+
+
+/*! \brief Compute the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \returns The CRC value
+ */
+uint64_t
+osmo_crc64gen_compute_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len)
+{
+ const uint64_t poly = code->poly;
+ uint64_t crc = code->init;
+ int i, n = code->bits-1;
+
+ for (i=0; i<len; i++) {
+ uint64_t bit = in[i] & 1;
+ crc ^= (bit << n);
+ if (crc & (1 << n)) {
+ crc <<= 1;
+ crc ^= poly;
+ } else {
+ crc <<= 1;
+ }
+ crc &= (1ULL << code->bits) - 1;
+ }
+
+ crc ^= code->remainder;
+
+ return crc;
+}
+
+
+/*! \brief Checks the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits with the alleged CRC
+ * \returns 0 if CRC matches. 1 in case of error.
+ *
+ * The crc_bits array must have a length of code->len
+ */
+int
+osmo_crc64gen_check_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits)
+{
+ uint64_t crc;
+ int i;
+
+ crc = osmo_crc64gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ if (crc_bits[i] ^ ((crc >> (code->bits-i-1)) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/*! \brief Computes and writes the CRC value of a given array of bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits to write the computed CRC to
+ *
+ * The crc_bits array must have a length of code->len
+ */
+void
+osmo_crc64gen_set_bits(const struct osmo_crc64gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits)
+{
+ uint64_t crc;
+ int i;
+
+ crc = osmo_crc64gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ crc_bits[i] = ((crc >> (code->bits-i-1)) & 1);
+}
+
+/*! }@ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-target/src/crc8gen.c b/Src/osmolib/src/shared/libosmocore/build-target/src/crc8gen.c
new file mode 100644
index 0000000..0756a10
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-target/src/crc8gen.c
@@ -0,0 +1,120 @@
+/*
+ * crc8gen.c
+ *
+ * Generic CRC routines (for max 8 bits poly)
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crc8gen.c
+ * \file Osmocom generic CRC routines (for max 8 bits poly)
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/crc8gen.h>
+
+
+/*! \brief Compute the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \returns The CRC value
+ */
+uint8_t
+osmo_crc8gen_compute_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len)
+{
+ const uint8_t poly = code->poly;
+ uint8_t crc = code->init;
+ int i, n = code->bits-1;
+
+ for (i=0; i<len; i++) {
+ uint8_t bit = in[i] & 1;
+ crc ^= (bit << n);
+ if (crc & (1 << n)) {
+ crc <<= 1;
+ crc ^= poly;
+ } else {
+ crc <<= 1;
+ }
+ crc &= (1ULL << code->bits) - 1;
+ }
+
+ crc ^= code->remainder;
+
+ return crc;
+}
+
+
+/*! \brief Checks the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits with the alleged CRC
+ * \returns 0 if CRC matches. 1 in case of error.
+ *
+ * The crc_bits array must have a length of code->len
+ */
+int
+osmo_crc8gen_check_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits)
+{
+ uint8_t crc;
+ int i;
+
+ crc = osmo_crc8gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ if (crc_bits[i] ^ ((crc >> (code->bits-i-1)) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/*! \brief Computes and writes the CRC value of a given array of bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits to write the computed CRC to
+ *
+ * The crc_bits array must have a length of code->len
+ */
+void
+osmo_crc8gen_set_bits(const struct osmo_crc8gen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits)
+{
+ uint8_t crc;
+ int i;
+
+ crc = osmo_crc8gen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ crc_bits[i] = ((crc >> (code->bits-i-1)) & 1);
+}
+
+/*! }@ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/build-target/tests/atconfig b/Src/osmolib/src/shared/libosmocore/build-target/tests/atconfig
new file mode 100644
index 0000000..4989dee
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/build-target/tests/atconfig
@@ -0,0 +1,20 @@
+# Configurable variable values for building test suites.
+# Generated by ./config.status.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# The test suite will define top_srcdir=/../.. etc.
+at_testdir='tests'
+abs_builddir='/home/tom/imsi-catcher-detection/Src/osmolib/src/shared/libosmocore/build-target/tests'
+at_srcdir='../../tests'
+abs_srcdir='/home/tom/imsi-catcher-detection/Src/osmolib/src/shared/libosmocore/build-target/../tests'
+at_top_srcdir='../..'
+abs_top_srcdir='/home/tom/imsi-catcher-detection/Src/osmolib/src/shared/libosmocore/build-target/..'
+at_top_build_prefix='../'
+abs_top_builddir='/home/tom/imsi-catcher-detection/Src/osmolib/src/shared/libosmocore/build-target'
+
+# Backward compatibility with Autotest <= 2.59b:
+at_top_builddir=$at_top_build_prefix
+
+AUTOTEST_PATH='tests'
+
+SHELL=${CONFIG_SHELL-'/bin/bash'}
diff --git a/Src/osmolib/src/shared/libosmocore/configure.ac b/Src/osmolib/src/shared/libosmocore/configure.ac
index 52ab850..ec79a92 100644
--- a/Src/osmolib/src/shared/libosmocore/configure.ac
+++ b/Src/osmolib/src/shared/libosmocore/configure.ac
@@ -3,6 +3,7 @@ AC_INIT([libosmocore],
[openbsc-devel@lists.openbsc.org])
AM_INIT_AUTOMAKE([dist-bzip2])
+AC_CONFIG_TESTDIR(tests)
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@@ -19,6 +20,10 @@ AC_CONFIG_MACRO_DIR([m4])
dnl checks for header files
AC_HEADER_STDC
AC_CHECK_HEADERS(execinfo.h sys/select.h sys/socket.h syslog.h ctype.h)
+# for src/conv.c
+AC_FUNC_ALLOCA
+AC_SEARCH_LIBS([dlopen], [dl dld], [LIBRARY_DL="$LIBS";LIBS=""])
+AC_SUBST(LIBRARY_DL)
AC_PATH_PROG(DOXYGEN,doxygen,false)
AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false)
@@ -134,6 +139,7 @@ then
AC_DEFINE([PANIC_INFLOOP],[1],[Use infinite loop on panic rather than fprintf/abort])
fi
+
AC_OUTPUT(
libosmocore.pc
libosmocodec.pc
@@ -158,6 +164,11 @@ AC_OUTPUT(
tests/ussd/Makefile
tests/smscb/Makefile
tests/bits/Makefile
+ tests/a5/Makefile
+ tests/auth/Makefile
+ tests/conv/Makefile
+ tests/lapd/Makefile
+ tests/gsm0808/Makefile
utils/Makefile
Doxyfile.core
Doxyfile.gsm
diff --git a/Src/osmolib/src/shared/libosmocore/debian/rules b/Src/osmolib/src/shared/libosmocore/debian/rules
index 15f78f2..15f78f2 100644..100755
--- a/Src/osmolib/src/shared/libosmocore/debian/rules
+++ b/Src/osmolib/src/shared/libosmocore/debian/rules
diff --git a/Src/osmolib/src/shared/libosmocore/git-version-gen b/Src/osmolib/src/shared/libosmocore/git-version-gen
index 42cf3d2..42cf3d2 100644..100755
--- a/Src/osmolib/src/shared/libosmocore/git-version-gen
+++ b/Src/osmolib/src/shared/libosmocore/git-version-gen
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/Makefile.am b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/Makefile.am
index f131269..1df111a 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/Makefile.am
@@ -2,8 +2,11 @@ osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h bits.h \
bitvec.h statistics.h utils.h socket.h \
gsmtap.h write_queue.h prim.h \
logging.h rate_ctr.h gsmtap_util.h \
- crc16.h panic.h process.h \
- backtrace.h conv.h application.h
+ crc16.h panic.h process.h linuxrbtree.h \
+ backtrace.h conv.h application.h \
+ crcgen.h crc8gen.h crc16gen.h crc32gen.h crc64gen.h
+
+noinst_HEADERS = timer_compat.h
if ENABLE_PLUGIN
osmocore_HEADERS += plugin.h
@@ -22,3 +25,7 @@ osmocore_HEADERS += serial.h
endif
osmocoredir = $(includedir)/osmocom/core
+
+crc%gen.h: crcXXgen.h.tpl
+ @echo " SED $< -> $@"
+ @sed -e's/XX/$*/g' $< > $@
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/conv.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/conv.h
index db3058c..e76a5c6 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/conv.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/conv.h
@@ -35,25 +35,52 @@
#include <osmocom/core/bits.h>
-/*! \brief structure describing a given convolutional code */
+/*! \brief possibe termination types
+ *
+ * The termination type will determine which state the encoder/decoder
+ * can start/end with. This is mostly taken care of in the high level API
+ * call. So if you use the low level API, you must take care of making the
+ * proper calls yourself.
+ */
+enum osmo_conv_term {
+ CONV_TERM_FLUSH = 0, /*!< \brief Flush encoder state */
+ CONV_TERM_TRUNCATION, /*!< \brief Direct truncation */
+ CONV_TERM_TAIL_BITING, /*!< \brief Tail biting */
+};
+
+/*! \brief structure describing a given convolutional code
+ *
+ * The only required fields are N,K and the next_output/next_state arrays. The
+ * other can be left to default value of zero depending on what the code does.
+ * If 'len' is left at 0 then only the low level API can be used.
+ */
struct osmo_conv_code {
- int N;
- int K;
- int len;
+ int N; /*!< \brief Inverse of code rate */
+ int K; /*!< \brief Constraint length */
+ int len; /*!< \brief # of data bits */
+
+ enum osmo_conv_term term; /*!< \brief Termination type */
- const uint8_t (*next_output)[2];
- const uint8_t (*next_state)[2];
+ const uint8_t (*next_output)[2];/*!< \brief Next output array */
+ const uint8_t (*next_state)[2]; /*!< \brief Next state array */
- const uint8_t *next_term_output;
- const uint8_t *next_term_state;
+ const uint8_t *next_term_output;/*!< \brief Flush termination output */
+ const uint8_t *next_term_state; /*!< \brief Flush termination state */
- const int *puncture;
+ const int *puncture; /*!< \brief Punctured bits indexes */
};
+/* Common */
+
+int osmo_conv_get_input_length(const struct osmo_conv_code *code, int len);
+int osmo_conv_get_output_length(const struct osmo_conv_code *code, int len);
+
+
/* Encoding */
/* Low level API */
+
/*! \brief convolutional encoder state */
struct osmo_conv_encoder {
const struct osmo_conv_code *code; /*!< \brief for which code? */
@@ -64,9 +91,11 @@ struct osmo_conv_encoder {
void osmo_conv_encode_init(struct osmo_conv_encoder *encoder,
const struct osmo_conv_code *code);
+void osmo_conv_encode_load_state(struct osmo_conv_encoder *encoder,
+ const ubit_t *input);
int osmo_conv_encode_raw(struct osmo_conv_encoder *encoder,
const ubit_t *input, ubit_t *output, int n);
-int osmo_conv_encode_finish(struct osmo_conv_encoder *encoder, ubit_t *output);
+int osmo_conv_encode_flush(struct osmo_conv_encoder *encoder, ubit_t *output);
/* All-in-one */
int osmo_conv_encode(const struct osmo_conv_code *code,
@@ -76,10 +105,10 @@ int osmo_conv_encode(const struct osmo_conv_code *code,
/* Decoding */
/* Low level API */
+
/*! \brief convolutional decoder state */
struct osmo_conv_decoder {
- /*! \brief description of convolutional code */
- const struct osmo_conv_code *code;
+ const struct osmo_conv_code *code; /*!< \brief for which code? */
int n_states; /*!< \brief number of states */
@@ -88,22 +117,24 @@ struct osmo_conv_decoder {
int o_idx; /*!< \brief output index */
int p_idx; /*!< \brief puncture index */
- unsigned int *ae; /*!< \brief accumulater error */
+ unsigned int *ae; /*!< \brief accumulated error */
unsigned int *ae_next; /*!< \brief next accumulated error (tmp in scan) */
uint8_t *state_history; /*!< \brief state history [len][n_states] */
};
void osmo_conv_decode_init(struct osmo_conv_decoder *decoder,
- const struct osmo_conv_code *code, int len);
-void osmo_conv_decode_reset(struct osmo_conv_decoder *decoder);
+ const struct osmo_conv_code *code,
+ int len, int start_state);
+void osmo_conv_decode_reset(struct osmo_conv_decoder *decoder, int start_state);
+void osmo_conv_decode_rewind(struct osmo_conv_decoder *decoder);
void osmo_conv_decode_deinit(struct osmo_conv_decoder *decoder);
int osmo_conv_decode_scan(struct osmo_conv_decoder *decoder,
const sbit_t *input, int n);
-int osmo_conv_decode_finish(struct osmo_conv_decoder *decoder,
- const sbit_t *input);
+int osmo_conv_decode_flush(struct osmo_conv_decoder *decoder,
+ const sbit_t *input);
int osmo_conv_decode_get_output(struct osmo_conv_decoder *decoder,
- ubit_t *output, int has_finish);
+ ubit_t *output, int has_flush, int end_state);
/* All-in-one */
int osmo_conv_decode(const struct osmo_conv_code *code,
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/crcXXgen.h.tpl b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/crcXXgen.h.tpl
new file mode 100644
index 0000000..b411276
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/crcXXgen.h.tpl
@@ -0,0 +1,59 @@
+/*
+ * crcXXgen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 __OSMO_CRCXXGEN_H__
+#define __OSMO_CRCXXGEN_H__
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crcXXgen.h
+ * \file Osmocom generic CRC routines (for max XX bits poly) header
+ */
+
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+
+/*! \brief structure describing a given CRC code of max XX bits */
+struct osmo_crcXXgen_code {
+ int bits; /*!< \brief Actual number of bits of the CRC */
+ uintXX_t poly; /*!< \brief Polynom (normal representation, MSB omitted */
+ uintXX_t init; /*!< \brief Initialization value of the CRC state */
+ uintXX_t remainder; /*!< \brief Remainder of the CRC (final XOR) */
+};
+
+uintXX_t osmo_crcXXgen_compute_bits(const struct osmo_crcXXgen_code *code,
+ const ubit_t *in, int len);
+int osmo_crcXXgen_check_bits(const struct osmo_crcXXgen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits);
+void osmo_crcXXgen_set_bits(const struct osmo_crcXXgen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits);
+
+
+/*! }@ */
+
+#endif /* __OSMO_CRCXXGEN_H__ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/gsmtap.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/gsmtap.h
index 236b25a..5dc869d 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/gsmtap.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/gsmtap.h
@@ -14,6 +14,21 @@
#include <stdint.h>
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* The GSMTAP format definition is maintained in libosmocore,
+ * specifically the latest version can always be obtained from
+ * http://cgit.osmocom.org/cgit/libosmocore/tree/include/osmocom/core/gsmtap.h
+ *
+ * If you want to introduce new protocol/burst/channel types or extend
+ * GSMTAP in any way, please contact the GSMTAP maintainer at either the
+ * public openbsc@lists.osmocom.org mailing list, or privately at
+ * Harald Welte <laforge@gnumonks.org>.
+ *
+ * Your cooperation ensures that all projects will use the same GSMTAP
+ * definitions and remain compatible with each other.
+ */
+
#define GSMTAP_VERSION 0x02
#define GSMTAP_TYPE_UM 0x01
@@ -22,6 +37,12 @@
#define GSMTAP_TYPE_SIM 0x04
#define GSMTAP_TYPE_TETRA_I1 0x05 /* tetra air interface */
#define GSMTAP_TYPE_TETRA_I1_BURST 0x06 /* tetra air interface */
+#define GSMTAP_TYPE_WMX_BURST 0x07 /* WiMAX burst */
+#define GSMTAP_TYPE_GB_LLC 0x08 /* GPRS Gb interface: LLC */
+#define GSMTAP_TYPE_GB_SNDCP 0x09 /* GPRS Gb interface: SNDCP */
+#define GSMTAP_TYPE_GMR1_UM 0x0a /* GMR-1 L2 packets */
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
/* sub-types for TYPE_UM_BURST */
#define GSMTAP_BURST_UNKNOWN 0x00
@@ -34,6 +55,15 @@
#define GSMTAP_BURST_DUMMY 0x07
#define GSMTAP_BURST_ACCESS 0x08
#define GSMTAP_BURST_NONE 0x09
+/* WiMAX bursts */
+#define GSMTAP_BURST_CDMA_CODE 0x10 /* WiMAX CDMA Code Attribute burst */
+#define GSMTAP_BURST_FCH 0x11 /* WiMAX FCH burst */
+#define GSMTAP_BURST_FFB 0x12 /* WiMAX Fast Feedback burst */
+#define GSMTAP_BURST_PDU 0x13 /* WiMAX PDU burst */
+#define GSMTAP_BURST_HACK 0x14 /* WiMAX HARQ ACK burst */
+#define GSMTAP_BURST_PHY_ATTRIBUTES 0x15 /* WiMAX PHY Attributes burst */
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
/* sub-types for TYPE_UM */
#define GSMTAP_CHANNEL_UNKNOWN 0x00
@@ -47,8 +77,15 @@
#define GSMTAP_CHANNEL_SDCCH8 0x08
#define GSMTAP_CHANNEL_TCH_F 0x09
#define GSMTAP_CHANNEL_TCH_H 0x0a
+#define GSMTAP_CHANNEL_PACCH 0x0b
+#define GSMTAP_CHANNEL_CBCH52 0x0c
+#define GSMTAP_CHANNEL_PDCH 0x0d
+#define GSMTAP_CHANNEL_PTCCH 0x0e
+#define GSMTAP_CHANNEL_CBCH51 0x0f
#define GSMTAP_CHANNEL_ACCH 0x80
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
/* sub-types for TYPE_TETRA_AIR */
#define GSMTAP_TETRA_BSCH 0x01
#define GSMTAP_TETRA_AACH 0x02
@@ -59,6 +96,30 @@
#define GSMTAP_TETRA_STCH 0x07
#define GSMTAP_TETRA_TCH_F 0x08
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_GMR1_UM */
+#define GSMTAP_GMR1_UNKNOWN 0x00
+#define GSMTAP_GMR1_BCCH 0x01
+#define GSMTAP_GMR1_CCCH 0x02 /* either AGCH or PCH */
+#define GSMTAP_GMR1_PCH 0x03
+#define GSMTAP_GMR1_AGCH 0x04
+#define GSMTAP_GMR1_BACH 0x05
+#define GSMTAP_GMR1_RACH 0x06
+#define GSMTAP_GMR1_CBCH 0x07
+#define GSMTAP_GMR1_SDCCH 0x08
+#define GSMTAP_GMR1_TACCH 0x09
+#define GSMTAP_GMR1_GBCH 0x0a
+
+#define GSMTAP_GMR1_SACCH 0x01 /* to be combined with _TCH{6,9} */
+#define GSMTAP_GMR1_FACCH 0x02 /* to be combines with _TCH{3,6,9} */
+#define GSMTAP_GMR1_DKAB 0x03 /* to be combined with _TCH3 */
+#define GSMTAP_GMR1_TCH3 0x10
+#define GSMTAP_GMR1_TCH6 0x14
+#define GSMTAP_GMR1_TCH9 0x18
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
/* flags for the ARFCN */
#define GSMTAP_ARFCN_F_PCS 0x8000
#define GSMTAP_ARFCN_F_UPLINK 0x4000
@@ -67,6 +128,7 @@
/* IANA-assigned well-known UDP port for GSMTAP messages */
#define GSMTAP_UDP_PORT 4729
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
struct gsmtap_hdr {
uint8_t version; /* version, set to 0x01 currently */
uint8_t hdr_len; /* length in number of 32bit words */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/gsmtap_util.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/gsmtap_util.h
index 36cbf53..5609381 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/gsmtap_util.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/gsmtap_util.h
@@ -12,6 +12,10 @@
uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t rsl_link_id);
+struct msgb *gsmtap_makemsg_ex(uint8_t type, uint16_t arfcn, uint8_t ts, uint8_t chan_type,
+ uint8_t ss, uint32_t fn, int8_t signal_dbm,
+ uint8_t snr, const uint8_t *data, unsigned int len);
+
struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type,
uint8_t ss, uint32_t fn, int8_t signal_dbm,
uint8_t snr, const uint8_t *data, unsigned int len);
@@ -40,6 +44,11 @@ int gsmtap_source_add_sink(struct gsmtap_inst *gti);
int gsmtap_sendmsg(struct gsmtap_inst *gti, struct msgb *msg);
+int gsmtap_send_ex(struct gsmtap_inst *gti, uint8_t type, uint16_t arfcn, uint8_t ts,
+ uint8_t chan_type, uint8_t ss, uint32_t fn,
+ int8_t signal_dbm, uint8_t snr, const uint8_t *data,
+ unsigned int len);
+
int gsmtap_send(struct gsmtap_inst *gti, uint16_t arfcn, uint8_t ts,
uint8_t chan_type, uint8_t ss, uint32_t fn,
int8_t signal_dbm, uint8_t snr, const uint8_t *data,
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/linuxrbtree.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/linuxrbtree.h
new file mode 100644
index 0000000..44e00a1
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/linuxrbtree.h
@@ -0,0 +1,160 @@
+/*
+ Red Black Trees
+ (C) 1999 Andrea Arcangeli <andrea@suse.de>
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ linux/include/linux/rbtree.h
+
+ To use rbtrees you'll have to implement your own insert and search cores.
+ This will avoid us to use callbacks and to drop drammatically performances.
+ I know it's not the cleaner way, but in C (not in C++) to get
+ performances and genericity...
+
+ Some example of insert and search follows here. The search is a plain
+ normal search over an ordered tree. The insert instead must be implemented
+ int two steps: as first thing the code must insert the element in
+ order as a red leaf in the tree, then the support library function
+ rb_insert_color() must be called. Such function will do the
+ not trivial work to rebalance the rbtree if necessary.
+
+-----------------------------------------------------------------------
+static inline struct page * rb_search_page_cache(struct inode * inode,
+ unsigned long offset)
+{
+ struct rb_node * n = inode->i_rb_page_cache.rb_node;
+ struct page * page;
+
+ while (n)
+ {
+ page = rb_entry(n, struct page, rb_page_cache);
+
+ if (offset < page->offset)
+ n = n->rb_left;
+ else if (offset > page->offset)
+ n = n->rb_right;
+ else
+ return page;
+ }
+ return NULL;
+}
+
+static inline struct page * __rb_insert_page_cache(struct inode * inode,
+ unsigned long offset,
+ struct rb_node * node)
+{
+ struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
+ struct rb_node * parent = NULL;
+ struct page * page;
+
+ while (*p)
+ {
+ parent = *p;
+ page = rb_entry(parent, struct page, rb_page_cache);
+
+ if (offset < page->offset)
+ p = &(*p)->rb_left;
+ else if (offset > page->offset)
+ p = &(*p)->rb_right;
+ else
+ return page;
+ }
+
+ rb_link_node(node, parent, p);
+
+ return NULL;
+}
+
+static inline struct page * rb_insert_page_cache(struct inode * inode,
+ unsigned long offset,
+ struct rb_node * node)
+{
+ struct page * ret;
+ if ((ret = __rb_insert_page_cache(inode, offset, node)))
+ goto out;
+ rb_insert_color(node, &inode->i_rb_page_cache);
+ out:
+ return ret;
+}
+-----------------------------------------------------------------------
+*/
+
+#ifndef _LINUX_RBTREE_H
+#define _LINUX_RBTREE_H
+
+#include <stdlib.h>
+
+struct rb_node
+{
+ unsigned long rb_parent_color;
+#define RB_RED 0
+#define RB_BLACK 1
+ struct rb_node *rb_right;
+ struct rb_node *rb_left;
+} __attribute__((aligned(sizeof(long))));
+ /* The alignment might seem pointless, but allegedly CRIS needs it */
+
+struct rb_root
+{
+ struct rb_node *rb_node;
+};
+
+
+#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
+#define rb_color(r) ((r)->rb_parent_color & 1)
+#define rb_is_red(r) (!rb_color(r))
+#define rb_is_black(r) rb_color(r)
+#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
+#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
+
+static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
+{
+ rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
+}
+static inline void rb_set_color(struct rb_node *rb, int color)
+{
+ rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
+}
+
+#define RB_ROOT { NULL, }
+#define rb_entry(ptr, type, member) container_of(ptr, type, member)
+
+#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
+#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
+#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
+
+extern void rb_insert_color(struct rb_node *, struct rb_root *);
+extern void rb_erase(struct rb_node *, struct rb_root *);
+
+/* Find logical next and previous nodes in a tree */
+extern struct rb_node *rb_next(const struct rb_node *);
+extern struct rb_node *rb_prev(const struct rb_node *);
+extern struct rb_node *rb_first(const struct rb_root *);
+extern struct rb_node *rb_last(const struct rb_root *);
+
+/* Fast replacement of a single node without remove/rebalance/add/rebalance */
+extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
+ struct rb_root *root);
+
+static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
+ struct rb_node ** rb_link)
+{
+ node->rb_parent_color = (unsigned long )parent;
+ node->rb_left = node->rb_right = NULL;
+
+ *rb_link = node;
+}
+
+#endif /* _LINUX_RBTREE_H */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/logging.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/logging.h
index 72e4c93..043a850 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/logging.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/logging.h
@@ -62,12 +62,13 @@ void logp(int subsys, char *file, int line, int cont, const char *format, ...) _
/* logging levels defined by the library itself */
#define DLGLOBAL -1
-#define DLLAPDM -2
+#define DLLAPD -2
#define DLINP -3
#define DLMUX -4
#define DLMI -5
#define DLMIB -6
-#define OSMO_NUM_DLIB 6
+#define DLSMS -7
+#define OSMO_NUM_DLIB 7
struct log_category {
uint8_t loglevel;
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/msgb.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/msgb.h
index 9f46e6c..e465ec2 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/msgb.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/msgb.h
@@ -312,6 +312,32 @@ static inline void msgb_reserve(struct msgb *msg, int len)
msg->tail += len;
}
+/*! \brief Trim the msgb to a given absolute length
+ * \param[in] msg message buffer
+ * \param[in] len new total length of buffer
+ * \returns 0 in case of success, negative in case of error
+ */
+static inline int msgb_trim(struct msgb *msg, int len)
+{
+ if (len > msg->data_len)
+ return -1;
+
+ msg->len = len;
+ msg->tail = msg->data + len;
+
+ return 0;
+}
+
+/*! \brief Trim the msgb to a given layer3 length
+ * \pram[in] msg message buffer
+ * \param[in] l3len new layer3 length
+ * \returns 0 in case of success, negative in case of error
+ */
+static inline int msgb_l3trim(struct msgb *msg, int l3len)
+{
+ return msgb_trim(msg, (msg->l3h - msg->data) + l3len);
+}
+
/*! \brief Allocate message buffer with specified headroom
* \param[in] size size in bytes, including headroom
* \param[in] headroom headroom in bytes
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/prim.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/prim.h
index 2e60c46..b1026fe 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/prim.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/prim.h
@@ -10,6 +10,9 @@
#include <stdint.h>
#include <osmocom/core/msgb.h>
+#define OSMO_PRIM(prim, op) ((prim << 8) | (op & 0xFF))
+#define OSMO_PRIM_HDR(oph) OSMO_PRIM((oph)->primitive, (oph)->operation)
+
/*! \brief primitive operation */
enum osmo_prim_operation {
PRIM_OP_REQUEST, /*!< \brief request */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/timer.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/timer.h
index 8f8c826..30f558b 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/timer.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/timer.h
@@ -32,6 +32,7 @@
#include <sys/time.h>
#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/linuxrbtree.h>
/**
* Timer management:
@@ -51,11 +52,10 @@
*/
/*! \brief A structure representing a single instance of a timer */
struct osmo_timer_list {
- struct llist_head entry; /*!< \brief linked list header */
+ struct rb_node node; /*!< \brief rb-tree node header */
+ struct llist_head list; /*!< \brief internal list header */
struct timeval timeout; /*!< \brief expiration time */
unsigned int active : 1; /*!< \brief is it active? */
- unsigned int handled : 1; /*!< \brief did we already handle it */
- unsigned int in_list : 1; /*!< \brief is it in the global list? */
void (*cb)(void*); /*!< \brief call-back called at timeout */
void *data; /*!< \brief user data for callback */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/timer_compat.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/timer_compat.h
new file mode 100644
index 0000000..209e84a
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/timer_compat.h
@@ -0,0 +1,79 @@
+/*
+ * (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ * 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.
+ *
+ */
+
+/*! \defgroup timer Osmocom timers
+ * @{
+ */
+
+/*! \file timer_compat.h
+ * \brief Compatibility header with some helpers
+ */
+
+#ifndef TIMER_COMPAT_H
+#define TIMER_COMPAT_H
+
+
+/* Convenience macros for operations on timevals.
+ NOTE: `timercmp' does not work for >= or <=. */
+
+#ifndef timerisset
+# define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
+#endif
+
+#ifndef timerclear
+# define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
+#endif
+
+#ifndef timercmp
+# define timercmp(a, b, CMP) \
+ (((a)->tv_sec == (b)->tv_sec) ? \
+ ((a)->tv_usec CMP (b)->tv_usec) : \
+ ((a)->tv_sec CMP (b)->tv_sec))
+#endif
+
+#ifndef timeradd
+# define timeradd(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
+ if ((result)->tv_usec >= 1000000) \
+ { \
+ ++(result)->tv_sec; \
+ (result)->tv_usec -= 1000000; \
+ } \
+ } while (0)
+#endif
+
+#ifndef timersub
+# define timersub(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((result)->tv_usec < 0) { \
+ --(result)->tv_sec; \
+ (result)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif
+
+
+/*! }@ */
+
+#endif /* TIMER_COMPAT_H */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/utils.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/utils.h
index 940c25f..f1843d9 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/core/utils.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/core/utils.h
@@ -34,7 +34,8 @@ int osmo_hexparse(const char *str, uint8_t *b, int max_len);
char *osmo_ubit_dump(const uint8_t *bits, unsigned int len);
char *osmo_hexdump(const unsigned char *buf, int len);
-char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len);
+char *osmo_hexdump_nospc(const unsigned char *buf, int len);
+char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len) __attribute__((__deprecated__));
#define osmo_static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/crypt/Makefile.am b/Src/osmolib/src/shared/libosmocore/include/osmocom/crypt/Makefile.am
index 7ce69fd..e4a6e53 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/crypt/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/crypt/Makefile.am
@@ -1,3 +1,3 @@
-osmocrypt_HEADERS = gprs_cipher.h
+osmocrypt_HEADERS = gprs_cipher.h auth.h
osmocryptdir = $(includedir)/osmocom/crypt
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/crypt/auth.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/crypt/auth.h
new file mode 100644
index 0000000..30e16e8
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/crypt/auth.h
@@ -0,0 +1,90 @@
+#ifndef _OSMOCRYPTO_AUTH_H
+#define _OSMOCRYPTO_AUTH_H
+
+#include <stdint.h>
+
+#include <osmocom/core/linuxlist.h>
+
+/*! \brief Authentication Type */
+enum osmo_sub_auth_type {
+ OSMO_AUTH_TYPE_NONE = 0x00,
+ OSMO_AUTH_TYPE_GSM = 0x01,
+ OSMO_AUTH_TYPE_UMTS = 0x02,
+};
+
+/*! \brief Authentication Algorithm */
+enum osmo_auth_algo {
+ OSMO_AUTH_ALG_NONE,
+ OSMO_AUTH_ALG_COMP128v1,
+ OSMO_AUTH_ALG_COMP128v2,
+ OSMO_AUTH_ALG_COMP128v3,
+ OSMO_AUTH_ALG_XOR,
+ OSMO_AUTH_ALG_MILENAGE,
+ _OSMO_AUTH_ALG_NUM,
+};
+
+/*! \brief permanent (secret) subscriber auth data */
+struct osmo_sub_auth_data {
+ enum osmo_sub_auth_type type;
+ enum osmo_auth_algo algo;
+ union {
+ struct {
+ uint8_t opc[16];
+ uint8_t k[16];
+ uint8_t amf[2];
+ uint64_t sqn;
+ } umts;
+ struct {
+ uint8_t ki[16];
+ } gsm;
+ } u;
+};
+
+/* data structure describing a computed auth vector, generated by AuC */
+struct osmo_auth_vector {
+ uint8_t rand[16];
+ uint8_t autn[16];
+ uint8_t ck[16];
+ uint8_t ik[16];
+ uint8_t res[16];
+ uint8_t res_len;
+ uint8_t kc[8];
+ uint8_t sres[4];
+ uint32_t auth_types; /*!< bitmask of OSMO_AUTH_TYPE_* */
+};
+
+/* \brief An implementation of an authentication algorithm */
+struct osmo_auth_impl {
+ struct llist_head list;
+ enum osmo_auth_algo algo;
+ const char *name;
+ unsigned int priority;
+
+ int (*gen_vec)(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data *aud,
+ const uint8_t *_rand);
+
+ int (*gen_vec_auts)(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data *aud,
+ const uint8_t *rand_auts, const uint8_t *auts,
+ const uint8_t *_rand);
+};
+
+int osmo_auth_gen_vec(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data *aud, const uint8_t *_rand);
+
+int osmo_auth_gen_vec_auts(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data *aud,
+ const uint8_t *rand_auts, const uint8_t *auts,
+ const uint8_t *_rand);
+
+int osmo_auth_register(struct osmo_auth_impl *impl);
+
+int osmo_auth_load(const char *path);
+
+int osmo_auth_supported(enum osmo_auth_algo algo);
+
+const char *osmo_auth_alg_name(enum osmo_auth_algo alg);
+enum osmo_auth_algo osmo_auth_alg_parse(const char *name);
+
+#endif /* _OSMOCRYPTO_AUTH_H */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/Makefile.am b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/Makefile.am
index 90f19bc..fc1abfe 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/Makefile.am
@@ -1,6 +1,7 @@
osmogsm_HEADERS = a5.h comp128.h gsm0808.h gsm48_ie.h mncc.h rxlev_stat.h \
gsm0480.h gsm48.h gsm_utils.h rsl.h tlv.h abis_nm.h \
- sysinfo.h prim.h gsm0502.h lapdm.h
+ sysinfo.h prim.h gsm0502.h lapd_core.h lapdm.h \
+ gsm0411_utils.h gsm0411_smc.h gsm0411_smr.h
SUBDIRS = protocol
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/a5.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/a5.h
index 2c630e5..7e6a17c 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/a5.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/a5.h
@@ -27,6 +27,18 @@
#include <osmocom/core/bits.h>
+/*! \defgroup a5 GSM A5 ciphering algorithm
+ * @{
+ */
+
+/*! \file gsm/a5.h
+ * \brief Osmocom GSM A5 ciphering algorithm header
+ */
+
+/*! \brief Converts a frame number into the 22 bit number used in A5/x
+ * \param[in] fn The true framenumber
+ * \return 22 bit word
+ */
static inline uint32_t
osmo_a5_fn_count(uint32_t fn)
{
@@ -42,8 +54,10 @@ osmo_a5_fn_count(uint32_t fn)
* - fn is the _real_ GSM frame number.
* (converted internally to fn_count)
*/
-void osmo_a5(int n, uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
-void osmo_a5_1(uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
-void osmo_a5_2(uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
+void osmo_a5(int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
+void osmo_a5_1(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
+void osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
+
+/*! }@ */
#endif /* __OSMO_A5_H__ */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/comp128.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/comp128.h
index c37808f..e4587d4 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/comp128.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/comp128.h
@@ -16,7 +16,7 @@
* sres : uint8_t [4]
* kc : uint8_t [8]
*/
-void comp128(uint8_t *ki, uint8_t *srand, uint8_t *sres, uint8_t *kc);
+void comp128(const uint8_t *ki, const uint8_t *srand, uint8_t *sres, uint8_t *kc);
#endif /* __COMP128_H__ */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_smc.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_smc.h
new file mode 100644
index 0000000..e1508a2
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_smc.h
@@ -0,0 +1,62 @@
+#ifndef _GSM0411_SMC_H
+#define _GSM0411_SMC_H
+
+#include <osmocom/gsm/protocol/gsm_04_11.h>
+
+#define GSM411_MMSMS_EST_REQ 0x310
+#define GSM411_MMSMS_EST_IND 0x312
+#define GSM411_MMSMS_EST_CNF 0x311
+#define GSM411_MMSMS_REL_REQ 0x320
+#define GSM411_MMSMS_REL_IND 0x322
+#define GSM411_MMSMS_DATA_REQ 0x330
+#define GSM411_MMSMS_DATA_IND 0x332
+#define GSM411_MMSMS_UNIT_DATA_REQ 0x340
+#define GSM411_MMSMS_UNIT_DATA_IND 0x342
+#define GSM411_MMSMS_ERR_IND 0x372
+
+#define GSM411_MNSMS_ABORT_REQ 0x101
+#define GSM411_MNSMS_DATA_REQ 0x102
+#define GSM411_MNSMS_DATA_IND 0x103
+#define GSM411_MNSMS_EST_REQ 0x104
+#define GSM411_MNSMS_EST_IND 0x105
+#define GSM411_MNSMS_ERROR_IND 0x106
+#define GSM411_MNSMS_REL_REQ 0x107
+
+struct gsm411_smc_inst {
+ int network; /* is this a MO (0) or MT (1) transfer */
+ int (*mn_recv) (struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg);
+ int (*mm_send) (struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg, int cp_msg_type);
+
+ enum gsm411_cp_state cp_state;
+ struct osmo_timer_list cp_timer;
+ struct msgb *cp_msg; /* store pending message */
+ int cp_rel; /* store pending release */
+ int cp_retx; /* retry counter */
+ int cp_max_retr; /* maximum retry */
+ int cp_tc1; /* timer value TC1* */
+
+};
+
+extern const struct value_string gsm411_cp_cause_strs[];
+
+/* init a new instance */
+void gsm411_smc_init(struct gsm411_smc_inst *inst, int network,
+ int (*mn_recv) (struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg),
+ int (*mm_send) (struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg, int cp_msg_type));
+
+/* clear instance */
+void gsm411_smc_clear(struct gsm411_smc_inst *inst);
+
+/* message from upper layer */
+int gsm411_smc_send(struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg);
+
+/* message from lower layer */
+int gsm411_smc_recv(struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg, int cp_msg_type);
+
+#endif /* _GSM0411_SMC_H */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_smr.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_smr.h
new file mode 100644
index 0000000..5ea8584
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_smr.h
@@ -0,0 +1,45 @@
+#ifndef _GSM0411_SMR_H
+#define _GSM0411_SMR_H
+
+#include <osmocom/gsm/protocol/gsm_04_11.h>
+
+#define GSM411_SM_RL_DATA_REQ 0x401
+#define GSM411_SM_RL_DATA_IND 0x402
+#define GSM411_SM_RL_MEM_AVAIL_REQ 0x403
+#define GSM411_SM_RL_MEM_AVAIL_IND 0x404
+#define GSM411_SM_RL_REPORT_REQ 0x405
+#define GSM411_SM_RL_REPORT_IND 0x406
+
+struct gsm411_smr_inst {
+ int network; /* is this a MO (0) or MT (1) transfer */
+ int (*rl_recv) (struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg);
+ int (*mn_send) (struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg);
+
+ enum gsm411_rp_state rp_state;
+ struct osmo_timer_list rp_timer;
+};
+
+extern const struct value_string gsm411_rp_cause_strs[];
+
+/* init a new instance */
+void gsm411_smr_init(struct gsm411_smr_inst *inst, int network,
+ int (*rl_recv) (struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg),
+ int (*mn_send) (struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg));
+
+/* clear instance */
+void gsm411_smr_clear(struct gsm411_smr_inst *inst);
+
+/* message from upper layer */
+int gsm411_smr_send(struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg);
+
+/* message from lower layer */
+int gsm411_smr_recv(struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg);
+
+#endif /* _GSM0411_SMR_H */
+
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_utils.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_utils.h
new file mode 100644
index 0000000..d29ca63
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0411_utils.h
@@ -0,0 +1,36 @@
+#ifndef _GSM0411_UTILS_H
+#define _GSM0411_UTILS_H
+
+/* Turn int into semi-octet representation: 98 => 0x89 */
+uint8_t gsm411_bcdify(uint8_t value);
+
+/* Turn semi-octet representation into int: 0x89 => 98 */
+uint8_t gsm411_unbcdify(uint8_t value);
+
+struct msgb *gsm411_msgb_alloc(void);
+
+/* Generate 03.40 TP-SCTS */
+void gsm340_gen_scts(uint8_t *scts, time_t time);
+
+/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
+time_t gsm340_scts(uint8_t *scts);
+
+/* decode validity period. return minutes */
+unsigned long gsm340_validity_period(uint8_t sms_vpf, uint8_t *sms_vp);
+
+/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
+enum sms_alphabet gsm338_get_sms_alphabet(uint8_t dcs);
+
+/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
+int gsm340_gen_oa(uint8_t *oa, unsigned int oa_len, uint8_t type,
+ uint8_t plan, const char *number);
+
+/* Prefix msg with a RP header */
+int gsm411_push_rp_header(struct msgb *msg, uint8_t rp_msg_type,
+ uint8_t rp_msg_ref);
+
+/* Prefix msg with a 04.08/04.11 CP header */
+int gsm411_push_cp_header(struct msgb *msg, uint8_t proto, uint8_t trans,
+ uint8_t msg_type);
+
+#endif /* _GSM0411_UTILS_H */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0808.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0808.h
index 38d88ef..5380dd9 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0808.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm0808.h
@@ -30,7 +30,8 @@ struct msgb *gsm0808_create_clear_command(uint8_t reason);
struct msgb *gsm0808_create_clear_complete(void);
struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);
struct msgb *gsm0808_create_cipher_reject(uint8_t cause);
-struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark, uint8_t length);
+struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,
+ const uint8_t *cm3, uint8_t cm3_len);
struct msgb *gsm0808_create_sapi_reject(uint8_t link_id);
struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause,
uint8_t chosen_channel, uint8_t encr_alg_id,
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h
index f4fce25..2e57642 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h
@@ -108,7 +108,7 @@ int gsm48_encode_more(struct msgb *msg);
struct gsm_sysinfo_freq {
/* if the frequency included in the sysinfo */
uint8_t mask;
-};
+} __attribute__ ((packed));
/* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */
int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd,
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/lapd_core.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/lapd_core.h
new file mode 100644
index 0000000..0f4e889
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/lapd_core.h
@@ -0,0 +1,171 @@
+#ifndef _OSMOCOM_LAPD_H
+#define _OSMOCOM_LAPD_H
+
+#include <stdint.h>
+
+#include <osmocom/core/timer.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/prim.h>
+
+/*! \defgroup lapd LAPD implementation common part
+ * @{
+ */
+
+/*! \file lapd.h */
+
+/* primitive related sutff */
+
+/*! \brief LAPD related primitives (L2<->L3 SAP)*/
+enum osmo_dl_prim {
+ PRIM_DL_UNIT_DATA, /*!< \brief DL-UNIT-DATA */
+ PRIM_DL_DATA, /*!< \brief DL-DATA */
+ PRIM_DL_EST, /*!< \brief DL-ESTABLISH */
+ PRIM_DL_REL, /*!< \brief DL-RLEEASE */
+ PRIM_DL_SUSP, /*!< \brief DL-SUSPEND */
+ PRIM_DL_RES, /*!< \brief DL-RESUME */
+ PRIM_DL_RECON, /*!< \brief DL-RECONNECT */
+ PRIM_MDL_ERROR, /*!< \brief MDL-ERROR */
+};
+
+/* Uses the same values as RLL, so no conversion for GSM is required. */
+#define MDL_CAUSE_T200_EXPIRED 0x01
+#define MDL_CAUSE_REEST_REQ 0x02
+#define MDL_CAUSE_UNSOL_UA_RESP 0x03
+#define MDL_CAUSE_UNSOL_DM_RESP 0x04
+#define MDL_CAUSE_UNSOL_DM_RESP_MF 0x05
+#define MDL_CAUSE_UNSOL_SPRV_RESP 0x06
+#define MDL_CAUSE_SEQ_ERR 0x07
+#define MDL_CAUSE_UFRM_INC_PARAM 0x08
+#define MDL_CAUSE_SFRM_INC_PARAM 0x09
+#define MDL_CAUSE_IFRM_INC_MBITS 0x0a
+#define MDL_CAUSE_IFRM_INC_LEN 0x0b
+#define MDL_CAUSE_FRM_UNIMPL 0x0c
+#define MDL_CAUSE_SABM_MF 0x0d
+#define MDL_CAUSE_SABM_INFO_NOTALL 0x0e
+#define MDL_CAUSE_FRMR 0x0f
+
+/*! \brief for MDL-ERROR.ind */
+struct mdl_error_ind_param {
+ uint8_t cause; /*!< \brief generic cause value */
+};
+
+/*! \brief for DL-REL.req */
+struct dl_rel_req_param {
+ uint8_t mode; /*!< \brief release mode */
+};
+
+/*! \brief primitive header for LAPD DL-SAP primitives */
+struct osmo_dlsap_prim {
+ struct osmo_prim_hdr oph; /*!< \brief generic primitive header */
+ union {
+ struct mdl_error_ind_param error_ind;
+ struct dl_rel_req_param rel_req;
+ } u; /*!< \brief request-specific data */
+};
+
+/*! \brief LAPD mode/role */
+enum lapd_mode {
+ LAPD_MODE_USER, /*!< \brief behave like user */
+ LAPD_MODE_NETWORK, /*!< \brief behave like network */
+};
+
+/*! \brief LAPD state (Figure B.2/Q.921)*/
+enum lapd_state {
+ LAPD_STATE_NULL = 0,
+ LAPD_STATE_TEI_UNASS,
+ LAPD_STATE_ASS_TEI_WAIT,
+ LAPD_STATE_EST_TEI_WAIT,
+ LAPD_STATE_IDLE,
+ LAPD_STATE_SABM_SENT,
+ LAPD_STATE_DISC_SENT,
+ LAPD_STATE_MF_EST,
+ LAPD_STATE_TIMER_RECOV,
+};
+
+/*! \brief LAPD message format (I / S / U) */
+enum lapd_format {
+ LAPD_FORM_UKN = 0,
+ LAPD_FORM_I,
+ LAPD_FORM_S,
+ LAPD_FORM_U,
+};
+
+/*! \brief LAPD message context */
+struct lapd_msg_ctx {
+ struct lapd_datalink *dl;
+ int n201;
+ /* address */
+ uint8_t cr;
+ uint8_t sapi;
+ uint8_t tei;
+ uint8_t lpd;
+ /* control */
+ uint8_t format;
+ uint8_t p_f; /* poll / final bit */
+ uint8_t n_send;
+ uint8_t n_recv;
+ uint8_t s_u; /* S or repectivly U function bits */
+ /* length */
+ int length;
+ uint8_t more;
+};
+
+struct lapd_cr_ent {
+ uint8_t cmd;
+ uint8_t resp;
+};
+
+struct lapd_history {
+ struct msgb *msg; /* message to be sent / NULL, if histoy is empty */
+ int more; /* if message is fragmented */
+};
+
+/*! \brief LAPD datalink */
+struct lapd_datalink {
+ int (*send_dlsap)(struct osmo_dlsap_prim *dp,
+ struct lapd_msg_ctx *lctx);
+ int (*send_ph_data_req)(struct lapd_msg_ctx *lctx, struct msgb *msg);
+ struct {
+ /*! \brief filled-in once we set the lapd_mode above */
+ struct lapd_cr_ent loc2rem;
+ struct lapd_cr_ent rem2loc;
+ } cr;
+ enum lapd_mode mode; /*!< \brief current mode of link */
+ int use_sabme; /*!< \brief use SABME instead of SABM */
+ int reestablish; /*!< \brief enable reestablish support */
+ int n200, n200_est_rel; /*!< \brief number of retranmissions */
+ struct lapd_msg_ctx lctx; /*!< \brief LAPD context */
+ int maxf; /*!< \brief maximum frame size (after defragmentation) */
+ uint8_t k; /*!< \brief maximum number of unacknowledged frames */
+ uint8_t v_range; /*!< \brief range of sequence numbers */
+ uint8_t v_send; /*!< \brief seq nr of next I frame to be transmitted */
+ uint8_t v_ack; /*!< \brief last frame ACKed by peer */
+ uint8_t v_recv; /*!< \brief seq nr of next I frame expected to be received */
+ uint32_t state; /*!< \brief LAPD state (\ref lapd_state) */
+ int seq_err_cond; /*!< \brief condition of sequence error */
+ uint8_t own_busy; /*!< \brief receiver busy on our side */
+ uint8_t peer_busy; /*!< \brief receiver busy on remote side */
+ int t200_sec, t200_usec; /*!< \brief retry timer (default 1 sec) */
+ int t203_sec, t203_usec; /*!< \brief retry timer (default 10 secs) */
+ struct osmo_timer_list t200; /*!< \brief T200 timer */
+ struct osmo_timer_list t203; /*!< \brief T203 timer */
+ uint8_t retrans_ctr; /*!< \brief re-transmission counter */
+ struct llist_head tx_queue; /*!< \brief frames to L1 */
+ struct llist_head send_queue; /*!< \brief frames from L3 */
+ struct msgb *send_buffer; /*!< \brief current frame transmitting */
+ int send_out; /*!< \brief how much was sent from send_buffer */
+ struct lapd_history *tx_hist; /*!< \brief tx history structure array */
+ uint8_t range_hist; /*!< \brief range of history buffer 2..2^n */
+ struct msgb *rcv_buffer; /*!< \brief buffer to assemble the received message */
+ struct msgb *cont_res; /*!< \brief buffer to store content resolution data on network side, to detect multiple phones on same channel */
+};
+
+void lapd_dl_init(struct lapd_datalink *dl, uint8_t k, uint8_t v_range,
+ int maxf);
+void lapd_dl_exit(struct lapd_datalink *dl);
+void lapd_dl_reset(struct lapd_datalink *dl);
+int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode);
+int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx);
+int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx);
+
+#endif /* _OSMOCOM_LAPD_H */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/lapdm.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/lapdm.h
index b71feef..52e8fc5 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/lapdm.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/lapdm.h
@@ -1,11 +1,7 @@
#ifndef _OSMOCOM_LAPDM_H
#define _OSMOCOM_LAPDM_H
-#include <stdint.h>
-
-#include <osmocom/core/timer.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/prim.h>
+#include <osmocom/gsm/lapd_core.h>
/*! \defgroup lapdm LAPDm implementation according to GSM TS 04.06
* @{
@@ -15,7 +11,7 @@
/* primitive related sutff */
-/*! \brief LAPDm related primitives */
+/*! \brief LAPDm related primitives (L1<->L2 SAP) */
enum osmo_ph_prim {
PRIM_PH_DATA, /*!< \brief PH-DATA */
PRIM_PH_RACH, /*!< \brief PH-RANDOM_ACCESS */
@@ -68,52 +64,22 @@ enum lapdm_mode {
LAPDM_MODE_BTS, /*!< \brief behave like a BTS (network) */
};
-/*! \brief LAPDm state */
-enum lapdm_state {
- LAPDm_STATE_NULL = 0,
- LAPDm_STATE_IDLE,
- LAPDm_STATE_SABM_SENT,
- LAPDm_STATE_MF_EST,
- LAPDm_STATE_TIMER_RECOV,
- LAPDm_STATE_DISC_SENT,
-};
-
struct lapdm_entity;
/*! \brief LAPDm message context */
struct lapdm_msg_ctx {
struct lapdm_datalink *dl;
int lapdm_fmt;
- uint8_t n201;
uint8_t chan_nr;
uint8_t link_id;
- uint8_t addr;
- uint8_t ctrl;
- uint8_t ta_ind;
- uint8_t tx_power_ind;
+ uint8_t ta_ind; /* TA indicated by network */
+ uint8_t tx_power_ind; /* MS power indicated by network */
};
/*! \brief LAPDm datalink like TS 04.06 / Section 3.5.2 */
struct lapdm_datalink {
- uint8_t V_send; /*!< \brief seq nr of next I frame to be transmitted */
- uint8_t V_ack; /*!< \brief last frame ACKed by peer */
- uint8_t N_send; /*!< \brief ? set to V_send at Tx time*/
- uint8_t V_recv; /*!< \brief seq nr of next I frame expected to be received */
- uint8_t N_recv; /*!< \brief expected send seq nr of the next received I frame */
- uint32_t state; /*!< \brief LAPDm state (\ref lapdm_state) */
- int seq_err_cond; /*!< \brief condition of sequence error */
- uint8_t own_busy; /*!< \brief receiver busy on our side */
- uint8_t peer_busy; /*!< \brief receiver busy on remote side */
- struct osmo_timer_list t200; /*!< \brief T200 timer */
- uint8_t retrans_ctr; /*!< \brief re-transmission counter */
- struct llist_head send_queue; /*!< \brief frames from L3 */
- struct msgb *send_buffer; /*!< \brief current frame transmitting */
- int send_out; /*!< \brief how much was sent from send_buffer */
- uint8_t tx_hist[8][200]; /*!< \brief tx history buffer */
- int tx_length[8]; /*!< \brief length in history buffer */
- struct llist_head tx_queue; /*!< \brief frames to L1 */
+ struct lapd_datalink dl; /* \brief common LAPD */
struct lapdm_msg_ctx mctx; /*!< \brief context of established connection */
- struct msgb *rcv_buffer; /*!< \brief buffer to assemble the received message */
struct lapdm_entity *entity; /*!< \brief LAPDm entity we are part of */
};
@@ -127,11 +93,6 @@ enum lapdm_dl_sapi {
typedef int (*lapdm_cb_t)(struct msgb *msg, struct lapdm_entity *le, void *ctx);
-struct lapdm_cr_ent {
- uint8_t cmd;
- uint8_t resp;
-};
-
#define LAPDM_ENT_F_EMPTY_FRAME 0x0001
#define LAPDM_ENT_F_POLLING_ONLY 0x0002
@@ -144,12 +105,6 @@ struct lapdm_entity {
enum lapdm_mode mode; /*!< \brief are we in BTS mode or MS mode */
unsigned int flags;
- struct {
- /*! \brief filled-in once we set the lapdm_mode above */
- struct lapdm_cr_ent loc2rem;
- struct lapdm_cr_ent rem2loc;
- } cr;
-
void *l1_ctx; /*!< \brief context for layer1 instance */
void *l3_ctx; /*!< \brief context for layer3 instance */
@@ -158,6 +113,9 @@ struct lapdm_entity {
/*! \brief pointer to \ref lapdm_channel of which we're part */
struct lapdm_channel *lapdm_ch;
+
+ uint8_t ta; /* TA used and indicated to network */
+ uint8_t tx_power; /* MS power used and indicated to network */
};
/*! \brief the two lapdm_entities that form a GSM logical channel (ACCH + DCCH) */
@@ -172,7 +130,7 @@ const char *get_rsl_name(int value);
extern const char *lapdm_state_names[];
/* initialize a LAPDm entity */
-void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode);
+void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode, int t200);
void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode);
/* deinitialize a LAPDm entity */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/Makefile.am b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/Makefile.am
index 7f6de63..6ed55e4 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/Makefile.am
@@ -1,6 +1,6 @@
osmogsm_proto_HEADERS = gsm_03_41.h \
gsm_04_08.h gsm_04_11.h gsm_04_12.h gsm_04_80.h \
- gsm_08_08.h gsm_08_58.h \
+ gsm_08_08.h gsm_08_58.h gsm_44_318.h \
gsm_12_21.h ipaccess.h
osmogsm_protodir = $(includedir)/osmocom/gsm/protocol
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h
index 39470e7..5057ada 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -213,15 +213,15 @@ struct gsm48_chan_desc {
tsc:3;
uint8_t hsn:6,
maio_low:2;
- } h1;
+ } __attribute__ ((packed)) h1;
struct {
uint8_t arfcn_high:2,
spare:2,
h:1,
tsc:3;
uint8_t arfcn_low;
- } h0;
- };
+ } __attribute__ ((packed)) h0;
+ } __attribute__ ((packed));
} __attribute__ ((packed));
/* Chapter 10.5.2.20 */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_11.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_11.h
index c6a2b19..f37152f 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_11.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_11.h
@@ -5,7 +5,7 @@
/* GSM TS 04.11 definitions */
-/* Chapter 5.2.3: SMC-CS states at the network side */
+/* Chapter 5.2.3: SMC-CS states at the user/network side */
enum gsm411_cp_state {
GSM411_CPS_IDLE = 0,
GSM411_CPS_MM_CONN_PENDING = 1, /* only MT ! */
@@ -13,11 +13,12 @@ enum gsm411_cp_state {
GSM411_CPS_MM_ESTABLISHED = 3,
};
-/* Chapter 6.2.2: SMR states at the network side */
+/* Chapter 6.2.2: SMR states at the user/network side */
enum gsm411_rp_state {
GSM411_RPS_IDLE = 0,
GSM411_RPS_WAIT_FOR_RP_ACK = 1,
GSM411_RPS_WAIT_TO_TX_RP_ACK = 3,
+ GSM411_RPS_WAIT_FOR_RETRANS_T = 4,
};
/* Chapter 8.1.2 (refers to GSM 04.07 Chapter 11.2.3.1.1 */
@@ -95,7 +96,8 @@ enum gsm411_rp_cause {
#define GSM411_TMR_TRAM 30, 0 /* 25 < x < 35 seconds */
#define GSM411_TMR_TR2M 15, 0 /* 12 < x < 20 seconds */
-#define GSM411_TMR_TC1A 30, 0
+#define GSM411_TMR_TC1A 30, 0 /* TR1M - 10 */
+#define GSM411_TMR_TC1A_SEC 30 /* TR1M - 10 */
/* Chapter 8.2.1 */
struct gsm411_rp_hdr {
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_44_318.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_44_318.h
new file mode 100644
index 0000000..31c0ea7
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_44_318.h
@@ -0,0 +1,153 @@
+#ifndef PROTO_GSM_44_318_H
+#define PROTO_GSM_44_318_H
+
+#include <stdint.h>
+
+/* Definitions according to 3GPP TS 44.318 6.8.0 Release 6 */
+
+/* Table 11.1.1.4.1: Message types for URR */
+
+enum gan_msg_type {
+ GA_MT_RC_DISCOVERY_REQUEST = 0x01,
+ GA_MT_RC_DISCOVERY_ACCEPT = 0x02,
+ GA_MT_RC_DISCOVERY_REJECT = 0x03,
+
+ GA_MT_RC_REGISTER_REQUEST = 0x10,
+ GA_MT_RC_REGISTER_ACCEPT = 0x11,
+ GA_MT_RC_REGISTER_REDIRECT = 0x12,
+ GA_MT_RC_REGISTER_REJECT = 0x13,
+ GA_MT_RC_DEREGISTER = 0x14,
+ GA_MT_RC_REGISTER_UPDATE_UL = 0x15,
+ GA_MT_RC_REGISTER_UPDATE_DL = 0x16,
+ GA_MT_RC_CELL_BCAST_INFO = 0x17,
+
+ GA_MT_CSR_CIPH_MODE_CMD = 0x20,
+ GA_MT_CSR_CIPH_MODE_COMPL = 0x21,
+
+ GA_MT_CSR_ACT_CHAN = 0x30,
+ GA_MT_CSR_ACT_CHAN_ACK = 0x31,
+ GA_MT_CSR_ACT_CHAN_COMPL = 0x32,
+ GA_MT_CSR_ACT_CHAN_FAIL = 0x33,
+ GA_MT_CSR_CHAN_MODE_MOD = 0x34,
+ GA_MT_CSR_CHAN_MODE_MOD_ACK = 0x35,
+
+ GA_MT_CSR_RELEASE = 0x40,
+ GA_MT_CSR_RELEASE_COMPL = 0x41,
+ GA_MT_CSR_CLEAR_REQ = 0x42,
+
+ GA_MT_CSR_HO_ACCESS = 0x50,
+ GA_MT_CSR_HO_COMPL = 0x51,
+ GA_MT_CSR_UL_QUAL_IND = 0x52,
+ GA_MT_CSR_HO_INFO = 0x53,
+ GA_MT_CSR_HO_CMD = 0x54,
+ GA_MT_CSR_HO_FAIL = 0x55,
+
+ GA_MT_CSR_PAGING_REQ = 0x60,
+ GA_MT_CSR_PAGING_RESP = 0x61,
+
+ GA_MT_CSR_UL_DIRECT_XFER = 0x70,
+ GA_MT_CSR_DL_DIRECT_XFER = 0x72,
+ GA_MT_CSR_STATUS = 0x73,
+ GA_MT_RC_KEEPALIVE = 0x74,
+ GA_MT_CSR_CM_ENQ = 0x75,
+ GA_MT_CSR_CM_CHANGE = 0x76,
+
+ GA_MT_CSR_REQUEST = 0x80,
+ GA_MT_CSR_REQUEST_ACCEPT = 0x81,
+ GA_MT_CSR_REQUEST_REJECT = 0x82,
+};
+
+/* All tables in 10.1.x and 10.2.x / Table 11.2.1 */
+enum gan_iei {
+ GA_IE_MI = 1,
+ GA_IE_GAN_RELEASE_IND = 2,
+ GA_IE_RADIO_IE = 3,
+ GA_IE_GERAN_CELL_ID = 4,
+ GA_IE_LAC = 5,
+ GA_IE_GERAN_COV_IND = 6,
+ GA_IE_GAN_CM = 7,
+ GA_IE_GEO_LOC = 8,
+ GA_IE_DEF_SEGW_IP = 9,
+ GA_IE_DEF_SEGW_FQDN = 10,
+ GA_IE_REDIR_CTR = 11,
+ GA_IE_DISCOV_REJ_CAUSE = 12,
+ GA_IE_GANC_CELL_DESC = 13,
+ GA_IE_GANC_CTRL_CH_DESC = 14,
+ GA_IE_GERAN_CELL_ID_LIST= 15,
+ GA_IE_TU3907_TIMER = 16,
+ GA_IE_RR_STATE = 17,
+ GA_IE_RAI = 18,
+ GA_IE_GAN_BAND = 19,
+ GA_IE_GARC_GACSR_STATE = 20,
+ GA_IE_REG_REJ_CAUSE = 21,
+ GA_IE_TU3906_TIMER = 22,
+ GA_IE_TU3910_TIMER = 23,
+ GA_IE_TU3902_TIMER = 24,
+ GA_IE_L3_MSG = 26,
+ GA_IE_CHAN_MODE = 27,
+ GA_IE_MS_CLASSMARK2 = 28,
+ GA_IE_RR_CAUSE = 29,
+ GA_EI_CIPH_MODE_SET = 30,
+ GA_IE_GPRS_RESUMPTION = 31,
+ GA_IE_HO_FROM_GAN_CMD = 32,
+ GA_IE_UL_QUAL_IND = 33,
+ GA_IE_TLLI = 34,
+ GA_IE_PFI = 35,
+ GA_IE_SUSP_CAUSE = 36,
+ GA_IE_TU3820_TIMER = 37,
+ GA_IE_REQD_QOS = 38,
+ GA_IE_P_DEACT_CAUSE = 39
+ GA_IE_REQD_UL_RATE = 40,
+ GA_IE_RAC = 41,
+ GA_IE_AP_LOCATION = 42,
+ GA_IE_TU4001_TIMER = 43,
+ GA_IE_LOC_STATUS = 44,
+ GA_IE_CIPH_RESP = 45,
+ GA_IE_CIPH_RAND = 46,
+ GA_IE_CIPH_MAC = 47,
+ GA_IE_CKSN = 48,
+ GA_IE_SAPI_ID = 49,
+ GA_IE_EST_CAUSE = 50,
+ GA_IE_CHAN_NEEDED = 51,
+ GA_IE_PDU_IN_ERROR = 52,
+ GA_IE_SAMPLE_SIZE = 53,
+ GA_IE_PAYLOAD_TYPE = 54,
+ GA_IE_MULTIRATE_CONF = 55,
+ GA_IE_MS_CLASSMARK3 = 56,
+ GA_IE_LLC_PDU = 57,
+ GA_IE_LOC_BLACKL_IND = 58,
+ GA_IE_RESET_IND = 59,
+ GA_IE_TU4003_TIMER = 60,
+ GA_IE_AP_SERV_NAME = 61,
+ GA_IE_SERV_ZONE_INFO = 62,
+ GA_IE_RTP_RED_CONF = 63,
+ GA_IE_UTRAN_CLASSMARK = 64,
+ GA_IE_CM_ENQ_MASK = 65,
+ GA_IE_UTRAN_CELLID_LIST = 66,
+ GA_IE_SERV_GANC_TBL_IND = 67,
+ GA_IE_AP_REG_IND = 68,
+ GA_IE_GAN_PLMN_LIST = 69,
+ GA_IE_REQD_GAN_SERV = 71,
+ GA_IE_BCAST_CONTAINER = 72,
+ GA_IE_3G_CELL_ID = 73,
+ GA_IE_MS_RADIO_ID = 96,
+ GA_IE_DEF_GANC_IP = 97,
+ GA_IE_DEF_GANC_FQDN = 98,
+ GA_IE_GPRS_IP_ADDR = 99,
+ GA_IE_GPRS_UDP_PORT = 100
+ GA_IE_GANC_TCP_PORT = 103,
+ GA_IE_RTP_UDP_PORT = 104,
+ GA_IE_RTCP_UDP_PORT = 105,
+ GA_IE_GERAN_RCV_SIGL_LIST = 106,
+ GA_IE_UTRAN_RCV_SIGL_LIST = 107,
+};
+
+/* 11.1.1 GA-RC and GA-CSR Message header IE */
+struct gan_rc_csr_hdr {
+ uint16_t len;
+ uint8_t pdisc:4,
+ skip_ind:4;
+ uint8_t msg_type;
+} __attribute__((packed));
+
+#endif /* PROTO_GSM_44_318_H */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/sysinfo.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/sysinfo.h
index b808d6f..06feb1d 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/sysinfo.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/sysinfo.h
@@ -37,7 +37,7 @@ typedef uint8_t sysinfo_buf_t[GSM_MACBLOCK_LEN];
extern const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE];
-uint8_t gsm_sitype2rsl(enum osmo_sysinfo_type si_type);
+uint8_t osmo_sitype2rsl(enum osmo_sysinfo_type si_type);
enum osmo_sysinfo_type osmo_rsl2sitype(uint8_t rsl_si);
#endif /* _OSMO_GSM_SYSINFO_H */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/tlv.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/tlv.h
index 7b41d2d..d2936d6 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/tlv.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/gsm/tlv.h
@@ -178,28 +178,32 @@ static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag,
return buf;
}
-/*! \brief put (append) a LV field to a \ref msgb */
+/*! \brief put (append) a LV field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_lv_put(struct msgb *msg, uint8_t len, const uint8_t *val)
{
uint8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
return lv_put(buf, len, val);
}
-/*! \brief put (append) a TLV field to a \ref msgb */
+/*! \brief put (append) a TLV field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_tlv_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
{
uint8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
return tlv_put(buf, tag, len, val);
}
-/*! \brief put (append) a TV field to a \ref msgb */
+/*! \brief put (append) a TV field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val)
{
uint8_t *buf = msgb_put(msg, 2);
return tv_put(buf, tag, val);
}
-/*! \brief put (append) a TVfixed field to a \ref msgb */
+/*! \brief put (append) a TVfixed field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag,
unsigned int len, const uint8_t *val)
{
@@ -207,47 +211,57 @@ static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag,
return tv_fixed_put(buf, tag, len, val);
}
-/*! \brief put (append) a V field to a \ref msgb */
+/*! \brief put (append) a V field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_v_put(struct msgb *msg, uint8_t val)
{
uint8_t *buf = msgb_put(msg, 1);
return v_put(buf, val);
}
-/*! \brief put (append) a TV16 field to a \ref msgb */
+/*! \brief put (append) a TV16 field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val)
{
uint8_t *buf = msgb_put(msg, 3);
return tv16_put(buf, tag, val);
}
-/*! \brief push (prepend) a TLV field to a \ref msgb */
+/*! \brief push (prepend) a TLV field to a \ref msgb
+ * \returns pointer to first byte of newly-pushed information */
static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
{
uint8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
- return tlv_put(buf, tag, len, val);
+ tlv_put(buf, tag, len, val);
+ return buf;
}
-/*! \brief push (prepend) a TV field to a \ref msgb */
+/*! \brief push (prepend) a TV field to a \ref msgb
+ * \returns pointer to first byte of newly-pushed information */
static inline uint8_t *msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val)
{
uint8_t *buf = msgb_push(msg, 2);
- return tv_put(buf, tag, val);
+ tv_put(buf, tag, val);
+ return buf;
}
-/*! \brief push (prepend) a TV16 field to a \ref msgb */
+/*! \brief push (prepend) a TV16 field to a \ref msgb
+ * \returns pointer to first byte of newly-pushed information */
static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t val)
{
uint8_t *buf = msgb_push(msg, 3);
- return tv16_put(buf, tag, val);
+ tv16_put(buf, tag, val);
+ return buf;
}
-/*! \brief push (prepend) a TvLV field to a \ref msgb */
+/*! \brief push (prepend) a TvLV field to a \ref msgb
+ * \returns pointer to first byte of newly-pushed information */
static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len,
const uint8_t *val)
{
uint8_t *buf = msgb_push(msg, TVLV_GROSS_LEN(len));
- return tvlv_put(buf, tag, len, val);
+ tvlv_put(buf, tag, len, val);
+ return buf;
}
/* TLV parsing */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/vty/telnet_interface.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/vty/telnet_interface.h
index 9a7c9e5..2de4f19 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/vty/telnet_interface.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/vty/telnet_interface.h
@@ -48,6 +48,8 @@ struct telnet_connection {
int telnet_init(void *tall_ctx, void *priv, int port);
+void telnet_exit(void);
+
/*! }@ */
#endif /* TELNET_INTERFACE_H */
diff --git a/Src/osmolib/src/shared/libosmocore/include/osmocom/vty/vty.h b/Src/osmolib/src/shared/libosmocore/include/osmocom/vty/vty.h
index d1f6f44..83506c5 100644
--- a/Src/osmolib/src/shared/libosmocore/include/osmocom/vty/vty.h
+++ b/Src/osmolib/src/shared/libosmocore/include/osmocom/vty/vty.h
@@ -176,9 +176,13 @@ int vty_shell_serv (struct vty *);
void vty_hello (struct vty *);
void *vty_current_index(struct vty *);
int vty_current_node(struct vty *vty);
+enum node_type vty_go_parent(struct vty *vty);
extern void *tall_vty_ctx;
+extern struct cmd_element cfg_description_cmd;
+extern struct cmd_element cfg_no_description_cmd;
+
/*! }@ */
#endif
diff --git a/Src/osmolib/src/shared/libosmocore/src/Makefile.am b/Src/osmolib/src/shared/libosmocore/src/Makefile.am
index 739095c..079d0b4 100644
--- a/Src/osmolib/src/shared/libosmocore/src/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/src/Makefile.am
@@ -2,9 +2,9 @@ SUBDIRS=. vty codec gsm
# This is _NOT_ the library release version, it's an API version.
# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
-LIBVERSION=2:0:0
+LIBVERSION=4:0:0
-INCLUDES = $(all_includes) -I$(top_srcdir)/include
+INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include
AM_CFLAGS = -fPIC -Wall
lib_LTLIBRARIES = libosmocore.la
@@ -14,17 +14,20 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \
write_queue.c utils.c socket.c \
logging.c logging_syslog.c rate_ctr.c \
gsmtap_util.c crc16.c panic.c backtrace.c \
- conv.c application.c
+ conv.c application.c rbtree.c \
+ crc8gen.c crc16gen.c crc32gen.c crc64gen.c
if ENABLE_PLUGIN
libosmocore_la_SOURCES += plugin.c
-libosmocore_la_LDFLAGS = -version-info $(LIBVERSION) -ldl
+libosmocore_la_LDFLAGS = -version-info $(LIBVERSION) $(LIBRARY_DL)
else
libosmocore_la_LDFLAGS = -version-info $(LIBVERSION)
endif
if ENABLE_TALLOC
libosmocore_la_SOURCES += talloc.c
+else
+libosmocore_la_LIBADD = -ltalloc
endif
if ENABLE_MSGFILE
@@ -34,3 +37,7 @@ endif
if ENABLE_SERIAL
libosmocore_la_SOURCES += serial.c
endif
+
+crc%gen.c: crcXXgen.c.tpl
+ @echo " SED $< -> $@"
+ @sed -e's/XX/$*/g' $< > $@
diff --git a/Src/osmolib/src/shared/libosmocore/src/backtrace.c b/Src/osmolib/src/shared/libosmocore/src/backtrace.c
index 189a3ce..023671c 100644
--- a/Src/osmolib/src/shared/libosmocore/src/backtrace.c
+++ b/Src/osmolib/src/shared/libosmocore/src/backtrace.c
@@ -57,4 +57,8 @@ void osmo_generate_backtrace(void)
free(strings);
}
+#else
+void osmo_generate_backtrace(void)
+{
+}
#endif
diff --git a/Src/osmolib/src/shared/libosmocore/src/conv.c b/Src/osmolib/src/shared/libosmocore/src/conv.c
index f47d75c..ac39e29 100644
--- a/Src/osmolib/src/shared/libosmocore/src/conv.c
+++ b/Src/osmolib/src/shared/libosmocore/src/conv.c
@@ -29,8 +29,10 @@
/*! \file conv.c
* \file Osmocom convolutional encoder and decoder
*/
-
+#include "config.h"
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -40,6 +42,40 @@
/* ------------------------------------------------------------------------ */
+/* Common */
+/* ------------------------------------------------------------------------ */
+
+int
+osmo_conv_get_input_length(const struct osmo_conv_code *code, int len)
+{
+ return len <= 0 ? code->len : len;
+}
+
+int
+osmo_conv_get_output_length(const struct osmo_conv_code *code, int len)
+{
+ int pbits, in_len, out_len;
+
+ /* Input length */
+ in_len = osmo_conv_get_input_length(code, len);
+
+ /* Output length */
+ out_len = in_len * code->N;
+
+ if (code->term == CONV_TERM_FLUSH)
+ out_len += code->N * (code->K - 1);
+
+ /* Count punctured bits */
+ if (code->puncture) {
+ for (pbits=0; code->puncture[pbits] >= 0; pbits++);
+ out_len -= pbits;
+ }
+
+ return out_len;
+}
+
+
+/* ------------------------------------------------------------------------ */
/* Encoding */
/* ------------------------------------------------------------------------ */
@@ -55,6 +91,19 @@ osmo_conv_encode_init(struct osmo_conv_encoder *encoder,
encoder->code = code;
}
+void
+osmo_conv_encode_load_state(struct osmo_conv_encoder *encoder,
+ const ubit_t *input)
+{
+ int i;
+ uint8_t state = 0;
+
+ for (i=0; i<(encoder->code->K-1); i++)
+ state = (state << 1) | input[i];
+
+ encoder->state = state;
+}
+
static inline int
_conv_encode_do_output(struct osmo_conv_encoder *encoder,
uint8_t out, ubit_t *output)
@@ -115,8 +164,8 @@ osmo_conv_encode_raw(struct osmo_conv_encoder *encoder,
}
int
-osmo_conv_encode_finish(struct osmo_conv_encoder *encoder,
- ubit_t *output)
+osmo_conv_encode_flush(struct osmo_conv_encoder *encoder,
+ ubit_t *output)
{
const struct osmo_conv_code *code = encoder->code;
uint8_t state;
@@ -154,10 +203,11 @@ osmo_conv_encode_finish(struct osmo_conv_encoder *encoder,
* \param[in] code description of convolutional code to be used
* \param[in] input array of unpacked bits (uncoded)
* \param[out] output array of unpacked bits (encoded)
+ * \return Number of produced output bits
*
* This is an all-in-one function, taking care of
- * \ref osmo_conv_init, \ref osmo_conv_encode_raw and
- * \ref osmo_conv_encode_finish.
+ * \ref osmo_conv_init, \ref osmo_conv_encode_load_state,
+ * \ref osmo_conv_encode_raw and \ref osmo_conv_encode_flush as needed.
*/
int
osmo_conv_encode(const struct osmo_conv_code *code,
@@ -167,8 +217,16 @@ osmo_conv_encode(const struct osmo_conv_code *code,
int l;
osmo_conv_encode_init(&encoder, code);
- l = osmo_conv_encode_raw(&encoder, input, output, code->len);
- l += osmo_conv_encode_finish(&encoder, &output[l]);
+
+ if (code->term == CONV_TERM_TAIL_BITING) {
+ int eidx = code->len - code->K + 1;
+ osmo_conv_encode_load_state(&encoder, &input[eidx]);
+ }
+
+ l = osmo_conv_encode_raw(&encoder, input, output, code->len);
+
+ if (code->term == CONV_TERM_FLUSH)
+ l += osmo_conv_encode_flush(&encoder, &output[l]);
return l;
}
@@ -182,7 +240,7 @@ osmo_conv_encode(const struct osmo_conv_code *code,
void
osmo_conv_decode_init(struct osmo_conv_decoder *decoder,
- const struct osmo_conv_code *code, int len)
+ const struct osmo_conv_code *code, int len, int start_state)
{
int n_states;
@@ -205,23 +263,48 @@ osmo_conv_decode_init(struct osmo_conv_decoder *decoder,
decoder->state_history = malloc(sizeof(uint8_t) * n_states * (len + decoder->code->K - 1));
/* Classic reset */
- osmo_conv_decode_reset(decoder);
+ osmo_conv_decode_reset(decoder, start_state);
+}
+
+void
+osmo_conv_decode_reset(struct osmo_conv_decoder *decoder, int start_state)
+{
+ int i;
+
+ /* Reset indexes */
+ decoder->o_idx = 0;
+ decoder->p_idx = 0;
+
+ /* Initial error */
+ if (start_state < 0) {
+ /* All states possible */
+ memset(decoder->ae, 0x00, sizeof(unsigned int) * decoder->n_states);
+ } else {
+ /* Fixed start state */
+ for (i=0; i<decoder->n_states; i++) {
+ decoder->ae[i] = (i == start_state) ? 0 : MAX_AE;
+ }
+ }
}
void
-osmo_conv_decode_reset(struct osmo_conv_decoder *decoder)
+osmo_conv_decode_rewind(struct osmo_conv_decoder *decoder)
{
int i;
+ unsigned int min_ae = MAX_AE;
/* Reset indexes */
decoder->o_idx = 0;
decoder->p_idx = 0;
- /* Initial error (only state 0 is valid) */
- decoder->ae[0] = 0;
- for (i=1; i<decoder->n_states; i++) {
- decoder->ae[i] = MAX_AE;
+ /* Initial error normalize (remove constant) */
+ for (i=0; i<decoder->n_states; i++) {
+ if (decoder->ae[i] < min_ae)
+ min_ae = decoder->ae[i];
}
+
+ for (i=0; i<decoder->n_states; i++)
+ decoder->ae[i] -= min_ae;
}
void
@@ -307,9 +390,12 @@ osmo_conv_decode_scan(struct osmo_conv_decoder *decoder,
m = 1 << (code->N - 1); /* mask for 'out' bit selection */
for (j=0; j<code->N; j++) {
- ov = (out & m) ? -127 : 127; /* sbit_t value for it */
- e = ((int)in_sym[j]) - ov; /* raw error for this bit */
- nae += (e * e) >> 9; /* acc the squared/scaled value */
+ int is = (int)in_sym[j];
+ if (is) {
+ ov = (out & m) ? -127 : 127; /* sbit_t value for it */
+ e = is - ov; /* raw error for this bit */
+ nae += (e * e) >> 9; /* acc the squared/scaled value */
+ }
m >>= 1; /* next mask bit */
}
@@ -333,8 +419,8 @@ osmo_conv_decode_scan(struct osmo_conv_decoder *decoder,
}
int
-osmo_conv_decode_finish(struct osmo_conv_decoder *decoder,
- const sbit_t *input)
+osmo_conv_decode_flush(struct osmo_conv_decoder *decoder,
+ const sbit_t *input)
{
const struct osmo_conv_code *code = decoder->code;
@@ -439,7 +525,7 @@ osmo_conv_decode_finish(struct osmo_conv_decoder *decoder,
int
osmo_conv_decode_get_output(struct osmo_conv_decoder *decoder,
- ubit_t *output, int has_finish)
+ ubit_t *output, int has_flush, int end_state)
{
const struct osmo_conv_code *code = decoder->code;
@@ -449,20 +535,26 @@ osmo_conv_decode_get_output(struct osmo_conv_decoder *decoder,
uint8_t *sh_ptr;
- /* Find state with least error */
- min_ae = MAX_AE;
- min_state = 0xff;
+ /* End state ? */
+ if (end_state < 0) {
+ /* Find state with least error */
+ min_ae = MAX_AE;
+ min_state = 0xff;
- for (s=0; s<decoder->n_states; s++)
- {
- if (decoder->ae[s] < min_ae) {
- min_ae = decoder->ae[s];
- min_state = s;
+ for (s=0; s<decoder->n_states; s++)
+ {
+ if (decoder->ae[s] < min_ae) {
+ min_ae = decoder->ae[s];
+ min_state = s;
+ }
}
- }
- if (min_state == 0xff)
- return -1;
+ if (min_state == 0xff)
+ return -1;
+ } else {
+ min_state = (uint8_t) end_state;
+ min_ae = decoder->ae[end_state];
+ }
/* Traceback */
cur_state = min_state;
@@ -472,7 +564,7 @@ osmo_conv_decode_get_output(struct osmo_conv_decoder *decoder,
sh_ptr = &decoder->state_history[decoder->n_states * (n-1)];
/* No output for the K-1 termination input bits */
- if (has_finish) {
+ if (has_flush) {
for (i=0; i<code->K-1; i++) {
cur_state = sh_ptr[cur_state];
sh_ptr -= decoder->n_states;
@@ -504,7 +596,7 @@ osmo_conv_decode_get_output(struct osmo_conv_decoder *decoder,
*
* This is an all-in-one function, taking care of
* \ref osmo_conv_decode_init, \ref osmo_conv_decode_scan,
- * \ref osmo_conv_decode_finish, \ref osmo_conv_decode_get_output and
+ * \ref osmo_conv_decode_flush, \ref osmo_conv_decode_get_output and
* \ref osmo_conv_decode_deinit.
*/
int
@@ -514,12 +606,22 @@ osmo_conv_decode(const struct osmo_conv_code *code,
struct osmo_conv_decoder decoder;
int rv, l;
- osmo_conv_decode_init(&decoder, code, 0);
+ osmo_conv_decode_init(&decoder, code, 0, 0);
+
+ if (code->term == CONV_TERM_TAIL_BITING) {
+ osmo_conv_decode_scan(&decoder, input, code->len);
+ osmo_conv_decode_rewind(&decoder);
+ }
l = osmo_conv_decode_scan(&decoder, input, code->len);
- l = osmo_conv_decode_finish(&decoder, &input[l]);
- rv = osmo_conv_decode_get_output(&decoder, output, 1);
+ if (code->term == CONV_TERM_FLUSH)
+ l = osmo_conv_decode_flush(&decoder, &input[l]);
+
+ rv = osmo_conv_decode_get_output(&decoder, output,
+ code->term == CONV_TERM_FLUSH, /* has_flush */
+ code->term == CONV_TERM_FLUSH ? 0 : -1 /* end_state */
+ );
osmo_conv_decode_deinit(&decoder);
diff --git a/Src/osmolib/src/shared/libosmocore/src/crcXXgen.c.tpl b/Src/osmolib/src/shared/libosmocore/src/crcXXgen.c.tpl
new file mode 100644
index 0000000..5d70753
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/crcXXgen.c.tpl
@@ -0,0 +1,120 @@
+/*
+ * crcXXgen.c
+ *
+ * Generic CRC routines (for max XX bits poly)
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crcXXgen.c
+ * \file Osmocom generic CRC routines (for max XX bits poly)
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/crcXXgen.h>
+
+
+/*! \brief Compute the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \returns The CRC value
+ */
+uintXX_t
+osmo_crcXXgen_compute_bits(const struct osmo_crcXXgen_code *code,
+ const ubit_t *in, int len)
+{
+ const uintXX_t poly = code->poly;
+ uintXX_t crc = code->init;
+ int i, n = code->bits-1;
+
+ for (i=0; i<len; i++) {
+ uintXX_t bit = in[i] & 1;
+ crc ^= (bit << n);
+ if (crc & (1 << n)) {
+ crc <<= 1;
+ crc ^= poly;
+ } else {
+ crc <<= 1;
+ }
+ crc &= (1ULL << code->bits) - 1;
+ }
+
+ crc ^= code->remainder;
+
+ return crc;
+}
+
+
+/*! \brief Checks the CRC value of a given array of hard-bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits with the alleged CRC
+ * \returns 0 if CRC matches. 1 in case of error.
+ *
+ * The crc_bits array must have a length of code->len
+ */
+int
+osmo_crcXXgen_check_bits(const struct osmo_crcXXgen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits)
+{
+ uintXX_t crc;
+ int i;
+
+ crc = osmo_crcXXgen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ if (crc_bits[i] ^ ((crc >> (code->bits-i-1)) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/*! \brief Computes and writes the CRC value of a given array of bits
+ * \param[in] code The CRC code description to apply
+ * \param[in] in Array of hard bits
+ * \param[in] len Length of the array of hard bits
+ * \param[in] crc_bits Array of hard bits to write the computed CRC to
+ *
+ * The crc_bits array must have a length of code->len
+ */
+void
+osmo_crcXXgen_set_bits(const struct osmo_crcXXgen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits)
+{
+ uintXX_t crc;
+ int i;
+
+ crc = osmo_crcXXgen_compute_bits(code, in, len);
+
+ for (i=0; i<code->bits; i++)
+ crc_bits[i] = ((crc >> (code->bits-i-1)) & 1);
+}
+
+/*! }@ */
+
+/* vim: set syntax=c: */
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/Makefile.am b/Src/osmolib/src/shared/libosmocore/src/gsm/Makefile.am
index f5e4676..46d40a1 100644
--- a/Src/osmolib/src/shared/libosmocore/src/gsm/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/Makefile.am
@@ -1,15 +1,25 @@
# This is _NOT_ the library release version, it's an API version.
# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
-LIBVERSION=1:0:0
+LIBVERSION=2:0:1
INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS = -fPIC -Wall
+# FIXME: this should eventually go into a milenage/Makefile.am
+noinst_HEADERS = milenage/aes.h milenage/aes_i.h milenage/aes_wrap.h \
+ milenage/common.h milenage/crypto.h milenage/includes.h \
+ milenage/milenage.h
+
lib_LTLIBRARIES = libosmogsm.la
libosmogsm_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c gsm_utils.c \
rsl.c gsm48.c gsm48_ie.c gsm0808.c sysinfo.c \
gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \
- lapdm.c
+ gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \
+ lapd_core.c lapdm.c \
+ auth_core.c auth_comp128v1.c auth_milenage.c \
+ milenage/aes-encblock.c milenage/aes-internal.c \
+ milenage/aes-internal-enc.c milenage/milenage.c
+
libosmogsm_la_LDFLAGS = -version-info $(LIBVERSION)
libosmogsm_la_LIBADD = $(top_builddir)/src/libosmocore.la
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/a5.c b/Src/osmolib/src/shared/libosmocore/src/gsm/a5.c
index d3f2b2c..e330c75 100644
--- a/Src/osmolib/src/shared/libosmocore/src/gsm/a5.c
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/a5.c
@@ -26,12 +26,30 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+/*! \addtogroup a5
+ * @{
+ */
+
+/*! \file gsm/a5.c
+ * \brief Osmocom GSM A5 ciphering algorithm implementation
+ */
+
#include <string.h>
#include <osmocom/gsm/a5.h>
+/*! \brief Main method to generate a A5/x cipher stream
+ * \param[in] n Which A5/x method to use
+ * \param[in] key 8 byte array for the key (as received from the SIM)
+ * \param[in] fn Frame number
+ * \param[out] dl Pointer to array of ubits to return Downlink cipher stream
+ * \param[out] ul Pointer to array of ubits to return Uplink cipher stream
+ *
+ * Currently A5/[0-2] are supported.
+ * Either (or both) of dl/ul can be NULL if not needed.
+ */
void
-osmo_a5(int n, uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
+osmo_a5(int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
{
switch (n)
{
@@ -76,23 +94,38 @@ osmo_a5(int n, uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
#define A5_R3_TAPS 0x700080 /* x^23 + x^15 + x^2 + x + 1 */
#define A5_R4_TAPS 0x010800 /* x^17 + x^5 + 1 */
+/*! \brief Computes parity of a 32-bit word
+ * \param[in] x 32 bit word
+ * \return Parity bit (xor of all bits) as 0 or 1
+ */
static inline uint32_t
_a5_12_parity(uint32_t x)
{
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
- x ^= x >> 2;
- x ^= x >> 1;
- return x & 1;
+ x &= 0xf;
+ return (0x6996 >> x) & 1;
}
+/*! \brief Compute majority bit from 3 taps
+ * \param[in] v1 LFSR state ANDed with tap-bit
+ * \param[in] v2 LFSR state ANDed with tap-bit
+ * \param[in] v3 LFSR state ANDed with tap-bit
+ * \return The majority bit (0 or 1)
+ */
static inline uint32_t
_a5_12_majority(uint32_t v1, uint32_t v2, uint32_t v3)
{
return (!!v1 + !!v2 + !!v3) >= 2;
}
+/*! \brief Compute the next LFSR state
+ * \param[in] r Current state
+ * \param[in] mask LFSR mask
+ * \param[in] taps LFSR taps
+ * \return Next state
+ */
static inline uint32_t
_a5_12_clock(uint32_t r, uint32_t mask, uint32_t taps)
{
@@ -108,6 +141,10 @@ _a5_12_clock(uint32_t r, uint32_t mask, uint32_t taps)
#define A51_R2_CLKBIT 0x000400
#define A51_R3_CLKBIT 0x000400
+/*! \brief GSM A5/1 Clocking function
+ * \param[in] r Register state
+ * \param[in] force Non-zero value disable conditional clocking
+ */
static inline void
_a5_1_clock(uint32_t r[], int force)
{
@@ -129,6 +166,10 @@ _a5_1_clock(uint32_t r[], int force)
r[2] = _a5_12_clock(r[2], A5_R3_MASK, A5_R3_TAPS);
}
+/*! \brief GSM A5/1 Output function
+ * \param[in] r Register state
+ * \return The A5/1 output function bit
+ */
static inline uint8_t
_a5_1_get_output(uint32_t r[])
{
@@ -137,8 +178,16 @@ _a5_1_get_output(uint32_t r[])
(r[2] >> (A5_R3_LEN-1));
}
+/*! \brief Generate a GSM A5/1 cipher stream
+ * \param[in] key 8 byte array for the key (as received from the SIM)
+ * \param[in] fn Frame number
+ * \param[out] dl Pointer to array of ubits to return Downlink cipher stream
+ * \param[out] ul Pointer to array of ubits to return Uplink cipher stream
+ *
+ * Either (or both) of dl/ul can be NULL if not needed.
+ */
void
-osmo_a5_1(uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
+osmo_a5_1(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
{
uint32_t r[3] = {0, 0, 0};
uint32_t fn_count;
@@ -200,6 +249,10 @@ osmo_a5_1(uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
#define A52_R4_CLKBIT1 0x000008
#define A52_R4_CLKBIT2 0x000080
+/*! \brief GSM A5/2 Clocking function
+ * \param[in] r Register state
+ * \param[in] force Non-zero value disable conditional clocking
+ */
static inline void
_a5_2_clock(uint32_t r[], int force)
{
@@ -223,33 +276,39 @@ _a5_2_clock(uint32_t r[], int force)
r[3] = _a5_12_clock(r[3], A5_R4_MASK, A5_R4_TAPS);
}
+/*! \brief GSM A5/2 Output function
+ * \param[in] r Register state
+ * \return The A5/2 output function bit
+ */
static inline uint8_t
-_a5_2_get_output(uint32_t r[], uint8_t *db)
+_a5_2_get_output(uint32_t r[])
{
- uint8_t cb, tb;
-
- tb = (r[0] >> (A5_R1_LEN-1)) ^
- (r[1] >> (A5_R2_LEN-1)) ^
- (r[2] >> (A5_R3_LEN-1));
-
- cb = *db;
+ uint8_t b;
- *db = ( tb ^
- _a5_12_majority( r[0] & 0x08000, ~r[0] & 0x04000, r[0] & 0x1000) ^
- _a5_12_majority(~r[1] & 0x10000, r[1] & 0x02000, r[1] & 0x0200) ^
- _a5_12_majority( r[2] & 0x40000, r[2] & 0x10000, ~r[2] & 0x2000)
- );
+ b = (r[0] >> (A5_R1_LEN-1)) ^
+ (r[1] >> (A5_R2_LEN-1)) ^
+ (r[2] >> (A5_R3_LEN-1)) ^
+ _a5_12_majority( r[0] & 0x08000, ~r[0] & 0x04000, r[0] & 0x1000) ^
+ _a5_12_majority(~r[1] & 0x10000, r[1] & 0x02000, r[1] & 0x0200) ^
+ _a5_12_majority( r[2] & 0x40000, r[2] & 0x10000, ~r[2] & 0x2000);
- return cb;
+ return b;
}
+/*! \brief Generate a GSM A5/1 cipher stream
+ * \param[in] key 8 byte array for the key (as received from the SIM)
+ * \param[in] fn Frame number
+ * \param[out] dl Pointer to array of ubits to return Downlink cipher stream
+ * \param[out] ul Pointer to array of ubits to return Uplink cipher stream
+ *
+ * Either (or both) of dl/ul can be NULL if not needed.
+ */
void
-osmo_a5_2(uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
+osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
{
uint32_t r[4] = {0, 0, 0, 0};
uint32_t fn_count;
uint32_t b;
- uint8_t db = 0, o;
int i;
/* Key load */
@@ -286,26 +345,23 @@ osmo_a5_2(uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
r[3] |= 1 << 10;
/* Mix */
- for (i=0; i<100; i++)
+ for (i=0; i<99; i++)
{
_a5_2_clock(r, 0);
}
- _a5_2_get_output(r, &db);
-
-
/* Output */
for (i=0; i<114; i++) {
_a5_2_clock(r, 0);
- o = _a5_2_get_output(r, &db);
if (dl)
- dl[i] = o;
+ dl[i] = _a5_2_get_output(r);
}
for (i=0; i<114; i++) {
_a5_2_clock(r, 0);
- o = _a5_2_get_output(r, &db);
if (ul)
- ul[i] = o;
+ ul[i] = _a5_2_get_output(r);
}
}
+
+/*! }@ */
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/auth_comp128v1.c b/Src/osmolib/src/shared/libosmocore/src/gsm/auth_comp128v1.c
new file mode 100644
index 0000000..41aef71
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/auth_comp128v1.c
@@ -0,0 +1,47 @@
+
+/* GSM/GPRS/3G authentication core infrastructure */
+
+/* (C) 2010-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 <osmocom/crypt/auth.h>
+#include <osmocom/gsm/comp128.h>
+
+static int c128v1_gen_vec(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data *aud,
+ const uint8_t *_rand)
+{
+ comp128(aud->u.gsm.ki, _rand, vec->sres, vec->kc);
+ vec->auth_types = OSMO_AUTH_TYPE_GSM;
+
+ return 0;
+}
+
+static struct osmo_auth_impl c128v1_alg = {
+ .algo = OSMO_AUTH_ALG_COMP128v1,
+ .name = "COMP128v1 (libosmogsm built-in)",
+ .priority = 1000,
+ .gen_vec = &c128v1_gen_vec,
+};
+
+static __attribute__((constructor)) void on_dso_load_c128(void)
+{
+ osmo_auth_register(&c128v1_alg);
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/auth_core.c b/Src/osmolib/src/shared/libosmocore/src/gsm/auth_core.c
new file mode 100644
index 0000000..f790ff5
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/auth_core.c
@@ -0,0 +1,121 @@
+/* GSM/GPRS/3G authentication core infrastructure */
+
+/* (C) 2010-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 <errno.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/plugin.h>
+
+#include <osmocom/crypt/auth.h>
+
+static LLIST_HEAD(osmo_auths);
+
+static struct osmo_auth_impl *selected_auths[_OSMO_AUTH_ALG_NUM];
+
+/* register a cipher with the core */
+int osmo_auth_register(struct osmo_auth_impl *impl)
+{
+ if (impl->algo >= ARRAY_SIZE(selected_auths))
+ return -ERANGE;
+
+ llist_add_tail(&impl->list, &osmo_auths);
+
+ /* check if we want to select this implementation over others */
+ if (!selected_auths[impl->algo] ||
+ (selected_auths[impl->algo]->priority > impl->priority))
+ selected_auths[impl->algo] = impl;
+
+ return 0;
+}
+
+/* load all available GPRS cipher plugins */
+int osmo_auth_load(const char *path)
+{
+ /* load all plugins available from path */
+ return osmo_plugin_load_all(path);
+}
+
+int osmo_auth_supported(enum osmo_auth_algo algo)
+{
+ if (algo >= ARRAY_SIZE(selected_auths))
+ return -ERANGE;
+
+ if (selected_auths[algo])
+ return 1;
+
+ return 0;
+}
+
+int osmo_auth_gen_vec(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data *aud,
+ const uint8_t *_rand)
+{
+ struct osmo_auth_impl *impl = selected_auths[aud->algo];
+ int rc;
+
+ if (!impl)
+ return -ENOENT;
+
+ rc = impl->gen_vec(vec, aud, _rand);
+ if (rc < 0)
+ return rc;
+
+ memcpy(vec->rand, _rand, sizeof(vec->rand));
+
+ return 0;
+}
+
+int osmo_auth_gen_vec_auts(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data *aud,
+ const uint8_t *rand_auts, const uint8_t *auts,
+ const uint8_t *_rand)
+{
+ struct osmo_auth_impl *impl = selected_auths[aud->algo];
+
+ if (!impl || !impl->gen_vec_auts)
+ return -ENOENT;
+
+ return impl->gen_vec_auts(vec, aud, rand_auts, auts, _rand);
+}
+
+const struct value_string auth_alg_vals[] = {
+ { OSMO_AUTH_ALG_NONE, "None" },
+ { OSMO_AUTH_ALG_COMP128v1, "COMP128v1" },
+ { OSMO_AUTH_ALG_COMP128v2, "COMP128v2" },
+ { OSMO_AUTH_ALG_COMP128v3, "COMP128v3" },
+ { OSMO_AUTH_ALG_XOR, "XOR" },
+ { OSMO_AUTH_ALG_MILENAGE, "MILENAGE" },
+ { 0, NULL }
+};
+
+const char *osmo_auth_alg_name(enum osmo_auth_algo alg)
+{
+ return get_value_string(auth_alg_vals, alg);
+}
+
+enum osmo_auth_algo osmo_auth_alg_parse(const char *name)
+{
+ return get_string_value(auth_alg_vals, name);
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/auth_milenage.c b/Src/osmolib/src/shared/libosmocore/src/gsm/auth_milenage.c
new file mode 100644
index 0000000..2a9ba33
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/auth_milenage.c
@@ -0,0 +1,109 @@
+/* GSM/GPRS/3G authentication core infrastructure */
+
+/* (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 <osmocom/crypt/auth.h>
+#include "milenage/common.h"
+#include "milenage/milenage.h"
+
+static void sqn_u64_to_48bit(uint8_t *sqn, const uint64_t sqn64)
+{
+ sqn[5] = (sqn64 >> 0) & 0xff;
+ sqn[4] = (sqn64 >> 8) & 0xff;
+ sqn[3] = (sqn64 >> 16) & 0xff;
+ sqn[2] = (sqn64 >> 24) & 0xff;
+ sqn[1] = (sqn64 >> 32) & 0xff;
+ sqn[0] = (sqn64 >> 40) & 0xff;
+}
+
+static uint64_t sqn_48bit_to_u64(const uint8_t *sqn)
+{
+ uint64_t sqn64;
+
+ sqn64 = sqn[0];
+ sqn64 <<= 8;
+ sqn64 |= sqn[1];
+ sqn64 <<= 8;
+ sqn64 |= sqn[2];
+ sqn64 <<= 8;
+ sqn64 |= sqn[3];
+ sqn64 <<= 8;
+ sqn64 |= sqn[4];
+ sqn64 <<= 8;
+ sqn64 |= sqn[5];
+
+ return sqn64;
+}
+
+
+static int milenage_gen_vec(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data *aud,
+ const uint8_t *_rand)
+{
+ size_t res_len = sizeof(vec->res);
+ uint8_t sqn[6];
+ int rc;
+
+ sqn_u64_to_48bit(sqn, aud->u.umts.sqn);
+ milenage_generate(aud->u.umts.opc, aud->u.umts.amf, aud->u.umts.k,
+ sqn, _rand,
+ vec->autn, vec->ik, vec->ck, vec->res, &res_len);
+ vec->res_len = res_len;
+ rc = gsm_milenage(aud->u.umts.opc, aud->u.umts.k, _rand, vec->sres, vec->kc);
+ if (rc < 0)
+ return rc;
+
+ vec->auth_types = OSMO_AUTH_TYPE_UMTS | OSMO_AUTH_TYPE_GSM;
+ aud->u.umts.sqn++;
+
+ return 0;
+}
+
+static int milenage_gen_vec_auts(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data *aud,
+ const uint8_t *auts, const uint8_t *rand_auts,
+ const uint8_t *_rand)
+{
+ uint8_t sqn_out[6];
+ int rc;
+
+ rc = milenage_auts(aud->u.umts.opc, aud->u.umts.k,
+ rand_auts, auts, sqn_out);
+ if (rc < 0)
+ return rc;
+
+ aud->u.umts.sqn = sqn_48bit_to_u64(sqn_out) + 1;
+
+ return milenage_gen_vec(vec, aud, _rand);
+}
+
+static struct osmo_auth_impl milenage_alg = {
+ .algo = OSMO_AUTH_ALG_MILENAGE,
+ .name = "MILENAGE (libosmogsm built-in)",
+ .priority = 1000,
+ .gen_vec = &milenage_gen_vec,
+ .gen_vec_auts = &milenage_gen_vec_auts,
+};
+
+static __attribute__((constructor)) void on_dso_load_milenage(void)
+{
+ osmo_auth_register(&milenage_alg);
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/comp128.c b/Src/osmolib/src/shared/libosmocore/src/gsm/comp128.c
index 5d5680c..b7a2382 100644
--- a/Src/osmolib/src/shared/libosmocore/src/gsm/comp128.c
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/comp128.c
@@ -185,7 +185,7 @@ _comp128_permutation(uint8_t *x, uint8_t *bits)
}
void
-comp128(uint8_t *ki, uint8_t *rand, uint8_t *sres, uint8_t *kc)
+comp128(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc)
{
int i;
uint8_t x[32], bits[128];
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_smc.c b/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_smc.c
new file mode 100644
index 0000000..54e6129
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_smc.c
@@ -0,0 +1,539 @@
+/* Point-to-Point (PP) Short Message Service (SMS)
+ * Support on Mobile Radio Interface
+ * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
+
+/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
+ * (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * (C) 2011 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 Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* Notes on msg:
+ *
+ * Messages from lower layer are freed by lower layer.
+ *
+ * Messages to upper layer are freed after upper layer call returns, so upper
+ * layer cannot use data after returning. Upper layer must not free the msg.
+ *
+ * This implies: Lower layer messages can be forwarded to upper layer.
+ *
+ * Upper layer messages are freed by lower layer, so they must not be freed
+ * after calling lower layer.
+ *
+ *
+ * Notes on release:
+ *
+ * Whenever the process returns to IDLE, the MM connection is released using
+ * MMSMS-REL-REQ. It is allowed to destroy this process while processing
+ * this message.
+ *
+ * There is expeption, if MMSMS-REL-IND is received from lower layer, the
+ * process returns to IDLE without sending MMSMS-REL-REQ.
+ *
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/timer.h>
+
+#include <osmocom/gsm/gsm0411_utils.h>
+#include <osmocom/gsm/gsm0411_smc.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+static void cp_timer_expired(void *data);
+
+#define MAX_SMS_RETRY 2
+
+/* init a new instance */
+void gsm411_smc_init(struct gsm411_smc_inst *inst, int network,
+ int (*mn_recv) (struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg),
+ int (*mm_send) (struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg, int cp_msg_type))
+{
+ memset(inst, 0, sizeof(*inst));
+ inst->network = network;
+ inst->cp_max_retr = MAX_SMS_RETRY;
+ inst->cp_tc1 = GSM411_TMR_TC1A_SEC / (inst->cp_max_retr + 1);
+ inst->cp_state = GSM411_CPS_IDLE;
+ inst->mn_recv = mn_recv;
+ inst->mm_send = mm_send;
+
+ LOGP(DLSMS, LOGL_INFO, "New SMC instance created\n");
+}
+
+/* clear instance */
+void gsm411_smc_clear(struct gsm411_smc_inst *inst)
+{
+ LOGP(DLSMS, LOGL_INFO, "Clear SMC instance\n");
+
+ osmo_timer_del(&inst->cp_timer);
+
+ /* free stored msg */
+ if (inst->cp_msg) {
+ LOGP(DLSMS, LOGL_INFO, "Dropping pending message\n");
+ msgb_free(inst->cp_msg);
+ inst->cp_msg = NULL;
+ }
+}
+
+const char *smc_state_names[] = {
+ "IDLE",
+ "MM_CONN_PENDING",
+ "WAIT_CP_ACK",
+ "MM_ESTABLISHED",
+};
+
+const struct value_string gsm411_cp_cause_strs[] = {
+ { GSM411_CP_CAUSE_NET_FAIL, "Network Failure" },
+ { GSM411_CP_CAUSE_CONGESTION, "Congestion" },
+ { GSM411_CP_CAUSE_INV_TRANS_ID, "Invalid Transaction ID" },
+ { GSM411_CP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
+ { GSM411_CP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
+ { GSM411_CP_CAUSE_MSGTYPE_NOTEXIST, "Message Type doesn't exist" },
+ { GSM411_CP_CAUSE_MSG_INCOMP_STATE,
+ "Message incompatible with protocol state" },
+ { GSM411_CP_CAUSE_IE_NOTEXIST, "IE does not exist" },
+ { GSM411_CP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
+ { 0, 0 }
+};
+
+static void new_cp_state(struct gsm411_smc_inst *inst,
+ enum gsm411_cp_state state)
+{
+ LOGP(DLSMS, LOGL_INFO, "New CP state %s -> %s\n",
+ smc_state_names[inst->cp_state], smc_state_names[state]);
+ inst->cp_state = state;
+}
+
+static int gsm411_tx_cp_error(struct gsm411_smc_inst *inst, uint8_t cause)
+{
+ struct msgb *nmsg = gsm411_msgb_alloc();
+ uint8_t *causep;
+
+ LOGP(DLSMS, LOGL_NOTICE, "TX CP-ERROR, cause %d (%s)\n", cause,
+ get_value_string(gsm411_cp_cause_strs, cause));
+
+ causep = msgb_put(nmsg, 1);
+ *causep = cause;
+
+ return inst->mm_send(inst, GSM411_MMSMS_DATA_REQ, nmsg,
+ GSM411_MT_CP_ERROR);
+}
+
+/* etablish SMC connection */
+static int gsm411_mnsms_est_req(struct gsm411_smc_inst *inst, struct msgb *msg)
+{
+ struct msgb *nmsg;
+
+ if (inst->cp_msg) {
+ LOGP(DLSMS, LOGL_FATAL, "EST REQ, but we already have an "
+ "cp_msg. This should never happen, please fix!\n");
+ msgb_free(inst->cp_msg);
+ }
+
+ inst->cp_msg = msg;
+ new_cp_state(inst, GSM411_CPS_MM_CONN_PENDING);
+ /* clear stored release flag */
+ inst->cp_rel = 0;
+ /* send MMSMS_EST_REQ */
+ nmsg = gsm411_msgb_alloc();
+ return inst->mm_send(inst, GSM411_MMSMS_EST_REQ, nmsg, 0);
+}
+
+static int gsm411_mmsms_send_msg(struct gsm411_smc_inst *inst)
+{
+ struct msgb *nmsg;
+
+ LOGP(DLSMS, LOGL_INFO, "Send CP data\n");
+ /* reset retry counter */
+ if (inst->cp_state != GSM411_CPS_WAIT_CP_ACK)
+ inst->cp_retx = 0;
+ /* 5.2.3.1.2: enter MO-wait for CP-ACK */
+ /* 5.2.3.2.3: enter MT-wait for CP-ACK */
+ new_cp_state(inst, GSM411_CPS_WAIT_CP_ACK);
+ inst->cp_timer.data = inst;
+ inst->cp_timer.cb = cp_timer_expired;
+ /* 5.3.2.1: Set Timer TC1A */
+ osmo_timer_schedule(&inst->cp_timer, inst->cp_tc1, 0);
+ /* clone cp_msg */
+ nmsg = gsm411_msgb_alloc();
+ memcpy(msgb_put(nmsg, inst->cp_msg->len), inst->cp_msg->data,
+ inst->cp_msg->len);
+ /* send MMSMS_DATA_REQ with CP-DATA */
+ return inst->mm_send(inst, GSM411_MMSMS_DATA_REQ, nmsg,
+ GSM411_MT_CP_DATA);
+}
+
+static int gsm411_mmsms_est_cnf(struct gsm411_smc_inst *inst, struct msgb *msg)
+{
+ if (!inst->cp_msg) {
+ LOGP(DLSMS, LOGL_FATAL, "EST CNF, but we have no cp_msg. This "
+ "should never happen, please fix!\n");
+ return -EINVAL;
+ }
+
+ return gsm411_mmsms_send_msg(inst);
+}
+
+/* SMC TC1* is expired */
+static void cp_timer_expired(void *data)
+{
+ struct gsm411_smc_inst *inst = data;
+ struct msgb *nmsg;
+
+ if (inst->cp_retx == inst->cp_max_retr) {
+
+ LOGP(DLSMS, LOGL_INFO, "TC1* timeout, no more retries.\n");
+ /* 5.3.2.1: enter idle state */
+ new_cp_state(inst, GSM411_CPS_IDLE);
+ /* indicate error */
+ nmsg = gsm411_msgb_alloc();
+ inst->mn_recv(inst, GSM411_MNSMS_ERROR_IND, nmsg);
+ msgb_free(nmsg);
+ /* free pending stored msg */
+ if (inst->cp_msg) {
+ msgb_free(inst->cp_msg);
+ inst->cp_msg = NULL;
+ }
+ /* release MM connection */
+ nmsg = gsm411_msgb_alloc();
+ inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg, 0);
+ return;
+ }
+
+ LOGP(DLSMS, LOGL_INFO, "TC1* timeout, retrying...\n");
+ inst->cp_retx++;
+ gsm411_mmsms_est_cnf(inst, NULL);
+}
+
+static int gsm411_mmsms_cp_ack(struct gsm411_smc_inst *inst, struct msgb *msg)
+{
+ /* free stored msg */
+ if (inst->cp_msg) {
+ msgb_free(inst->cp_msg);
+ inst->cp_msg = NULL;
+ }
+
+ LOGP(DLSMS, LOGL_INFO, "Received CP-ACK\n");
+ /* 5.3.2.1 enter MM Connection established */
+ new_cp_state(inst, GSM411_CPS_MM_ESTABLISHED);
+ /* 5.3.2.1: Reset Timer TC1* */
+ osmo_timer_del(&inst->cp_timer);
+
+ /* pending release? */
+ if (inst->cp_rel) {
+ struct msgb *nmsg;
+
+ LOGP(DLSMS, LOGL_INFO, "We have pending release.\n");
+ new_cp_state(inst, GSM411_CPS_IDLE);
+ /* release MM connection */
+ nmsg = gsm411_msgb_alloc();
+ return inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg, 0);
+ }
+
+ return 0;
+}
+
+static int gsm411_mmsms_cp_data(struct gsm411_smc_inst *inst, struct msgb *msg)
+{
+ struct msgb *nmsg;
+ int mt = GSM411_MNSMS_DATA_IND;
+
+ LOGP(DLSMS, LOGL_INFO, "Received CP-DATA\n");
+ /* 5.3.1 enter MM Connection established (if idle) */
+ if (inst->cp_state == GSM411_CPS_IDLE) {
+ new_cp_state(inst, GSM411_CPS_MM_ESTABLISHED);
+ mt = GSM411_MNSMS_EST_IND;
+ /* clear stored release flag */
+ inst->cp_rel = 0;
+ }
+ /* send MMSMS_DATA_REQ (CP ACK) */
+ nmsg = gsm411_msgb_alloc();
+ inst->mm_send(inst, GSM411_MMSMS_DATA_REQ, nmsg, GSM411_MT_CP_ACK);
+ /* indicate data */
+ inst->mn_recv(inst, mt, msg);
+
+ return 0;
+}
+
+/* send CP DATA */
+static int gsm411_mnsms_data_req(struct gsm411_smc_inst *inst, struct msgb *msg)
+{
+ if (inst->cp_msg) {
+ LOGP(DLSMS, LOGL_FATAL, "DATA REQ, but we already have an "
+ "cp_msg. This should never happen, please fix!\n");
+ msgb_free(inst->cp_msg);
+ }
+
+ /* store and send */
+ inst->cp_msg = msg;
+ return gsm411_mmsms_send_msg(inst);
+}
+
+/* release SMC connection */
+static int gsm411_mnsms_rel_req(struct gsm411_smc_inst *inst, struct msgb *msg)
+{
+ struct msgb *nmsg;
+
+ msgb_free(msg);
+
+ /* discard silently */
+ if (inst->cp_state == GSM411_CPS_IDLE)
+ return 0;
+
+ /* store release, until established or released */
+ if (inst->cp_state != GSM411_CPS_MM_ESTABLISHED) {
+ LOGP(DLSMS, LOGL_NOTICE, "Cannot release yet.\n");
+ inst->cp_rel = 1;
+ return 0;
+ }
+
+ /* free stored msg */
+ if (inst->cp_msg) {
+ msgb_free(inst->cp_msg);
+ inst->cp_msg = NULL;
+ }
+
+ new_cp_state(inst, GSM411_CPS_IDLE);
+ /* release MM connection */
+ nmsg = gsm411_msgb_alloc();
+ return inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg, 0);
+}
+
+static int gsm411_mmsms_cp_error(struct gsm411_smc_inst *inst, struct msgb *msg)
+{
+ struct msgb *nmsg;
+
+ /* free stored msg */
+ if (inst->cp_msg) {
+ msgb_free(inst->cp_msg);
+ inst->cp_msg = NULL;
+ }
+
+ LOGP(DLSMS, LOGL_INFO, "Received CP-ERROR\n");
+ /* 5.3.4 enter idle */
+ new_cp_state(inst, GSM411_CPS_IDLE);
+ /* indicate error */
+ inst->mn_recv(inst, GSM411_MNSMS_ERROR_IND, msg);
+ /* release MM connection */
+ nmsg = gsm411_msgb_alloc();
+ return inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg, 0);
+}
+
+static int gsm411_mmsms_rel_ind(struct gsm411_smc_inst *inst, struct msgb *msg)
+{
+ struct msgb *nmsg;
+
+ /* free stored msg */
+ if (inst->cp_msg) {
+ msgb_free(inst->cp_msg);
+ inst->cp_msg = NULL;
+ }
+
+ LOGP(DLSMS, LOGL_INFO, "MM layer is released\n");
+ /* 5.3.4 enter idle */
+ new_cp_state(inst, GSM411_CPS_IDLE);
+ /* indicate error */
+ nmsg = gsm411_msgb_alloc();
+ inst->mn_recv(inst, GSM411_MNSMS_ERROR_IND, nmsg);
+ msgb_free(nmsg);
+
+ return 0;
+}
+
+/* abort SMC connection */
+static int gsm411_mnsms_abort_req(struct gsm411_smc_inst *inst,
+ struct msgb *msg)
+{
+ struct msgb *nmsg;
+
+ /* free stored msg */
+ if (inst->cp_msg) {
+ msgb_free(inst->cp_msg);
+ inst->cp_msg = NULL;
+ }
+
+ /* 5.3.4 go idle */
+ new_cp_state(inst, GSM411_CPS_IDLE);
+ /* send MMSMS_DATA_REQ with CP-ERROR */
+ inst->mm_send(inst, GSM411_MMSMS_DATA_REQ, msg, GSM411_MT_CP_ERROR);
+ /* release MM connection */
+ nmsg = gsm411_msgb_alloc();
+ return inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg, 0);
+}
+
+/* statefull handling for MNSMS SAP messages */
+static struct smcdownstate {
+ uint32_t states;
+ int type;
+ const char *name;
+ int (*rout) (struct gsm411_smc_inst *inst,
+ struct msgb *msg);
+} smcdownstatelist[] = {
+ /* establish request */
+ {SBIT(GSM411_CPS_IDLE),
+ GSM411_MNSMS_EST_REQ,
+ "MNSMS-EST-REQ", gsm411_mnsms_est_req},
+
+ /* release request */
+ {ALL_STATES,
+ GSM411_MNSMS_REL_REQ,
+ "MNSMS-REL-REQ", gsm411_mnsms_rel_req},
+
+ /* data request */
+ {SBIT(GSM411_CPS_MM_ESTABLISHED),
+ GSM411_MNSMS_DATA_REQ,
+ "MNSMS-DATA-REQ", gsm411_mnsms_data_req},
+
+ /* abort request */
+ {ALL_STATES - SBIT(GSM411_CPS_IDLE),
+ GSM411_MNSMS_ABORT_REQ,
+ "MNSMS-ABORT-REQ", gsm411_mnsms_abort_req},
+};
+
+#define SMCDOWNSLLEN \
+ (sizeof(smcdownstatelist) / sizeof(struct smcdownstate))
+
+/* message from upper layer */
+int gsm411_smc_send(struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg)
+{
+ int i, rc;
+
+ /* find function for current state and message */
+ for (i = 0; i < SMCDOWNSLLEN; i++) {
+ if ((msg_type == smcdownstatelist[i].type)
+ && (SBIT(inst->cp_state) & smcdownstatelist[i].states))
+ break;
+ }
+ if (i == SMCDOWNSLLEN) {
+ LOGP(DLSMS, LOGL_NOTICE, "Message %u unhandled at this state "
+ "%s.\n", msg_type, smc_state_names[inst->cp_state]);
+ msgb_free(msg);
+ return 0;
+ }
+
+ LOGP(DLSMS, LOGL_INFO, "Message %s received in state %s\n",
+ smcdownstatelist[i].name, smc_state_names[inst->cp_state]);
+
+ rc = smcdownstatelist[i].rout(inst, msg);
+
+ return rc;
+}
+
+/* statefull handling for MMSMS SAP messages */
+static struct smcdatastate {
+ uint32_t states;
+ int type, cp_type;
+ const char *name;
+ int (*rout) (struct gsm411_smc_inst *inst,
+ struct msgb *msg);
+} smcdatastatelist[] = {
+ /* establish confirm */
+ {SBIT(GSM411_CPS_MM_CONN_PENDING),
+ GSM411_MMSMS_EST_CNF, 0,
+ "MMSMS-EST-CNF", gsm411_mmsms_est_cnf},
+
+ /* establish indication (CP DATA) */
+ {SBIT(GSM411_CPS_IDLE),
+ GSM411_MMSMS_EST_IND, GSM411_MT_CP_DATA,
+ "MMSMS-EST-IND (CP DATA)", gsm411_mmsms_cp_data},
+
+ /* data indication (CP DATA) */
+ {SBIT(GSM411_CPS_MM_ESTABLISHED),
+ GSM411_MMSMS_DATA_IND, GSM411_MT_CP_DATA,
+ "MMSMS-DATA-IND (CP DATA)", gsm411_mmsms_cp_data},
+
+ /* data indication (CP ACK) */
+ {SBIT(GSM411_CPS_WAIT_CP_ACK),
+ GSM411_MMSMS_DATA_IND, GSM411_MT_CP_ACK,
+ "MMSMS-DATA-IND (CP ACK)", gsm411_mmsms_cp_ack},
+
+ /* data indication (CP ERROR) */
+ {ALL_STATES,
+ GSM411_MMSMS_DATA_IND, GSM411_MT_CP_ERROR,
+ "MMSMS-DATA-IND (CP_ERROR)", gsm411_mmsms_cp_error},
+
+ /* release indication */
+ {ALL_STATES - SBIT(GSM411_CPS_IDLE),
+ GSM411_MMSMS_REL_IND, 0,
+ "MMSMS-REL-IND", gsm411_mmsms_rel_ind},
+
+};
+
+#define SMCDATASLLEN \
+ (sizeof(smcdatastatelist) / sizeof(struct smcdatastate))
+
+/* message from lower layer
+ * WARNING: We must not free msg, since it will be performed by the
+ * lower layer. */
+int gsm411_smc_recv(struct gsm411_smc_inst *inst, int msg_type,
+ struct msgb *msg, int cp_msg_type)
+{
+ int i, rc;
+
+ /* find function for current state and message */
+ for (i = 0; i < SMCDATASLLEN; i++) {
+ /* state must machtch, MM message must match
+ * CP msg must match only in case of MMSMS_DATA_IND
+ */
+ if ((msg_type == smcdatastatelist[i].type)
+ && (SBIT(inst->cp_state) & smcdatastatelist[i].states)
+ && (msg_type != GSM411_MMSMS_DATA_IND
+ || cp_msg_type == smcdatastatelist[i].cp_type))
+ break;
+ }
+ if (i == SMCDATASLLEN) {
+ LOGP(DLSMS, LOGL_NOTICE, "Message 0x%x/%u unhandled at this "
+ "state %s.\n", msg_type, cp_msg_type,
+ smc_state_names[inst->cp_state]);
+ if (msg_type == GSM411_MMSMS_EST_IND
+ || msg_type == GSM411_MMSMS_DATA_IND) {
+ struct msgb *nmsg;
+
+ LOGP(DLSMS, LOGL_NOTICE, "RX Unimplemented CP "
+ "msg_type: 0x%02x\n", msg_type);
+ /* 5.3.4 enter idle */
+ new_cp_state(inst, GSM411_CPS_IDLE);
+ /* indicate error */
+ gsm411_tx_cp_error(inst,
+ GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
+ /* send error indication to upper layer */
+ nmsg = gsm411_msgb_alloc();
+ inst->mn_recv(inst, GSM411_MNSMS_ERROR_IND, nmsg);
+ msgb_free(nmsg);
+ /* release MM connection */
+ nmsg = gsm411_msgb_alloc();
+ return inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg,
+ 0);
+ }
+ return 0;
+ }
+
+ LOGP(DLSMS, LOGL_INFO, "Message %s received in state %s\n",
+ smcdatastatelist[i].name, smc_state_names[inst->cp_state]);
+
+ rc = smcdatastatelist[i].rout(inst, msg);
+
+ return rc;
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_smr.c b/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_smr.c
new file mode 100644
index 0000000..d5ca923
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_smr.c
@@ -0,0 +1,451 @@
+/* Point-to-Point (PP) Short Message Service (SMS)
+ * Support on Mobile Radio Interface
+ * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
+
+/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
+ * (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * (C) 2011 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 Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* Notes on msg:
+ *
+ * Messages from lower layer are freed by lower layer.
+ *
+ * Messages to upper layer are freed after upper layer call returns, so upper
+ * layer cannot use data after returning. Upper layer must not free the msg.
+ *
+ * This implies: Lower layer messages can be forwarded to upper layer.
+ *
+ * Upper layer messages are freed by lower layer, so they must not be freed
+ * after calling lower layer.
+ *
+ *
+ * Notes on release:
+ *
+ * Sending Abort/Release (MNSMS-ABORT-REQ or MNSMS-REL-REQ) may cause the
+ * lower layer to become IDLE. Then it is allowed to destroy this instance,
+ * so sending this this MUST be the last thing that is done.
+ *
+ */
+
+
+#include <string.h>
+#include <errno.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/gsm/tlv.h>
+
+#include <osmocom/gsm/gsm0411_utils.h>
+#include <osmocom/gsm/gsm0411_smc.h>
+#include <osmocom/gsm/gsm0411_smr.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+static void rp_timer_expired(void *data);
+
+/* init a new instance */
+void gsm411_smr_init(struct gsm411_smr_inst *inst, int network,
+ int (*rl_recv) (struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg),
+ int (*mn_send) (struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg))
+{
+ memset(inst, 0, sizeof(*inst));
+ inst->network = network;
+ inst->rp_state = GSM411_RPS_IDLE;
+ inst->rl_recv = rl_recv;
+ inst->mn_send = mn_send;
+ inst->rp_timer.data = inst;
+ inst->rp_timer.cb = rp_timer_expired;
+
+ LOGP(DLSMS, LOGL_INFO, "New SMR instance created\n");
+}
+
+/* clear instance */
+void gsm411_smr_clear(struct gsm411_smr_inst *inst)
+{
+ LOGP(DLSMS, LOGL_INFO, "Clear SMR instance\n");
+
+ osmo_timer_del(&inst->rp_timer);
+}
+
+const char *smr_state_names[] = {
+ "IDLE",
+ "WAIT_FOR_RP_ACK",
+ "illegal state 2"
+ "WAIT_TO_TX_RP_ACK",
+ "WAIT_FOR_RETRANS_T",
+};
+
+const struct value_string gsm411_rp_cause_strs[] = {
+ { GSM411_RP_CAUSE_MO_NUM_UNASSIGNED, "(MO) Number not assigned" },
+ { GSM411_RP_CAUSE_MO_OP_DET_BARR, "(MO) Operator determined barring" },
+ { GSM411_RP_CAUSE_MO_CALL_BARRED, "(MO) Call barred" },
+ { GSM411_RP_CAUSE_MO_SMS_REJECTED, "(MO) SMS rejected" },
+ { GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER, "(MO) Destination out of order" },
+ { GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR, "(MO) Unidentified subscriber" },
+ { GSM411_RP_CAUSE_MO_FACILITY_REJ, "(MO) Facility reject" },
+ { GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR, "(MO) Unknown subscriber" },
+ { GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER, "(MO) Network out of order" },
+ { GSM411_RP_CAUSE_MO_TEMP_FAIL, "(MO) Temporary failure" },
+ { GSM411_RP_CAUSE_MO_CONGESTION, "(MO) Congestion" },
+ { GSM411_RP_CAUSE_MO_RES_UNAVAIL, "(MO) Resource unavailable" },
+ { GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR, "(MO) Requested facility not subscribed" },
+ { GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL, "(MO) Requested facility not implemented" },
+ { GSM411_RP_CAUSE_MO_INTERWORKING, "(MO) Interworking" },
+ /* valid only for MT */
+ { GSM411_RP_CAUSE_MT_MEM_EXCEEDED, "(MT) Memory Exceeded" },
+ /* valid for both directions */
+ { GSM411_RP_CAUSE_INV_TRANS_REF, "Invalid Transaction Reference" },
+ { GSM411_RP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
+ { GSM411_RP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
+ { GSM411_RP_CAUSE_MSGTYPE_NOTEXIST, "Message Type non-existant" },
+ { GSM411_RP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" },
+ { GSM411_RP_CAUSE_IE_NOTEXIST, "Information Element not existing" },
+ { GSM411_RP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
+ { 0, NULL }
+};
+
+static void new_rp_state(struct gsm411_smr_inst *inst,
+ enum gsm411_rp_state state)
+{
+ LOGP(DLSMS, LOGL_INFO, "New RP state %s -> %s\n",
+ smr_state_names[inst->rp_state], smr_state_names[state]);
+ inst->rp_state = state;
+
+ /* stop timer when going idle */
+ if (state == GSM411_RPS_IDLE)
+ osmo_timer_del(&inst->rp_timer);
+}
+
+/* Prefix msg with a RP-DATA header and send as CP-DATA */
+static int gsm411_rp_sendmsg(struct gsm411_smr_inst *inst, struct msgb *msg,
+ uint8_t rp_msg_type, uint8_t rp_msg_ref,
+ int mnsms_msg_type)
+{
+ struct gsm411_rp_hdr *rp;
+ uint8_t len = msg->len;
+
+ /* GSM 04.11 RP-DATA header */
+ rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
+ rp->len = len + 2;
+ rp->msg_type = rp_msg_type;
+ rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
+
+ return inst->mn_send(inst, mnsms_msg_type, msg);
+}
+
+static int gsm411_send_rp_error(struct gsm411_smr_inst *inst,
+ uint8_t msg_ref, uint8_t cause)
+{
+ struct msgb *msg = gsm411_msgb_alloc();
+
+ msgb_tv_put(msg, 1, cause);
+
+ LOGP(DLSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
+ get_value_string(gsm411_rp_cause_strs, cause));
+
+ return gsm411_rp_sendmsg(inst, msg,
+ (inst->network) ? GSM411_MT_RP_ERROR_MT : GSM411_MT_RP_ERROR_MO,
+ msg_ref, GSM411_MNSMS_DATA_REQ);
+}
+
+static int gsm411_send_release(struct gsm411_smr_inst *inst)
+{
+ struct msgb *msg = gsm411_msgb_alloc();
+
+ LOGP(DLSMS, LOGL_NOTICE, "TX: MNSMS-REL-REQ\n");
+
+ return inst->mn_send(inst, GSM411_MNSMS_REL_REQ, msg);
+}
+
+static int gsm411_send_abort(struct gsm411_smr_inst *inst)
+{
+ struct msgb *msg = gsm411_msgb_alloc();
+
+ msgb_tv_put(msg, 1, 111); //FIXME: better idea ? */
+ LOGP(DLSMS, LOGL_NOTICE, "TX: MNSMS-ABORT-REQ\n");
+
+ return inst->mn_send(inst, GSM411_MNSMS_ABORT_REQ, msg);
+}
+
+static int gsm411_send_report(struct gsm411_smr_inst *inst)
+{
+ struct msgb *msg = gsm411_msgb_alloc();
+
+ LOGP(DLSMS, LOGL_NOTICE, "send empty SM_RL_REPORT_IND\n");
+
+ return inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
+}
+
+static int gsm411_rl_data_req(struct gsm411_smr_inst *inst, struct msgb *msg)
+{
+ LOGP(DLSMS, LOGL_DEBUG, "TX SMS RP-DATA\n");
+ /* start TR1N and enter 'wait for RP-ACK state' */
+ osmo_timer_schedule(&inst->rp_timer, GSM411_TMR_TR1M);
+ new_rp_state(inst, GSM411_RPS_WAIT_FOR_RP_ACK);
+
+ return inst->mn_send(inst, GSM411_MNSMS_EST_REQ, msg);
+}
+
+static int gsm411_rl_report_req(struct gsm411_smr_inst *inst, struct msgb *msg)
+{
+ LOGP(DLSMS, LOGL_DEBUG, "TX SMS REPORT\n");
+ new_rp_state(inst, GSM411_RPS_IDLE);
+
+ inst->mn_send(inst, GSM411_MNSMS_DATA_REQ, msg);
+ gsm411_send_release(inst);
+ return 0;
+}
+
+static int gsm411_mnsms_est_ind(struct gsm411_smr_inst *inst, struct msgb *msg)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr*)msg->l3h;
+ struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
+ uint8_t msg_type = rp_data->msg_type & 0x07;
+ int rc;
+
+ /* check direction */
+ if (inst->network == (msg_type & 1)) {
+ LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
+ gsm411_send_rp_error(inst, rp_data->msg_ref,
+ GSM411_RP_CAUSE_MSG_INCOMP_STATE);
+ new_rp_state(inst, GSM411_RPS_IDLE);
+ gsm411_send_release(inst);
+ return -EINVAL;
+ }
+
+ switch (msg_type) {
+ case GSM411_MT_RP_DATA_MT:
+ case GSM411_MT_RP_DATA_MO:
+ LOGP(DLSMS, LOGL_DEBUG, "RX SMS RP-DATA\n");
+ /* start TR2N and enter 'wait to send RP-ACK state' */
+ osmo_timer_schedule(&inst->rp_timer, GSM411_TMR_TR2M);
+ new_rp_state(inst, GSM411_RPS_WAIT_TO_TX_RP_ACK);
+ rc = inst->rl_recv(inst, GSM411_SM_RL_DATA_IND, msg);
+ break;
+ case GSM411_MT_RP_SMMA_MO:
+ LOGP(DLSMS, LOGL_DEBUG, "RX SMS RP-SMMA\n");
+ /* start TR2N and enter 'wait to send RP-ACK state' */
+ osmo_timer_schedule(&inst->rp_timer, GSM411_TMR_TR2M);
+ new_rp_state(inst, GSM411_RPS_WAIT_TO_TX_RP_ACK);
+ rc = inst->rl_recv(inst, GSM411_SM_RL_DATA_IND, msg);
+ break;
+ default:
+ LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
+ gsm411_send_rp_error(inst, rp_data->msg_ref,
+ GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
+ new_rp_state(inst, GSM411_RPS_IDLE);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static int gsm411_mnsms_data_ind_tx(struct gsm411_smr_inst *inst,
+ struct msgb *msg)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr*)msg->l3h;
+ struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
+ uint8_t msg_type = rp_data->msg_type & 0x07;
+ int rc;
+
+ /* check direction */
+ if (inst->network == (msg_type & 1)) {
+ LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
+ gsm411_send_rp_error(inst, rp_data->msg_ref,
+ GSM411_RP_CAUSE_MSG_INCOMP_STATE);
+ new_rp_state(inst, GSM411_RPS_IDLE);
+ gsm411_send_release(inst);
+ return -EINVAL;
+ }
+
+ switch (msg_type) {
+ case GSM411_MT_RP_ACK_MO:
+ case GSM411_MT_RP_ACK_MT:
+ LOGP(DLSMS, LOGL_DEBUG, "RX SMS RP-ACK\n");
+ new_rp_state(inst, GSM411_RPS_IDLE);
+ inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
+ gsm411_send_release(inst);
+ return 0;
+ case GSM411_MT_RP_ERROR_MO:
+ case GSM411_MT_RP_ERROR_MT:
+ LOGP(DLSMS, LOGL_DEBUG, "RX SMS RP-ERROR\n");
+ new_rp_state(inst, GSM411_RPS_IDLE);
+ inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
+ gsm411_send_release(inst);
+ return 0;
+ default:
+ LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
+ gsm411_send_rp_error(inst, rp_data->msg_ref,
+ GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
+ new_rp_state(inst, GSM411_RPS_IDLE);
+ gsm411_send_release(inst);
+ return -EINVAL;
+ }
+
+ return rc;
+}
+
+static int gsm411_mnsms_error_ind_tx(struct gsm411_smr_inst *inst,
+ struct msgb *msg)
+{
+ LOGP(DLSMS, LOGL_DEBUG, "RX SMS MNSMS-ERROR-IND\n");
+ new_rp_state(inst, GSM411_RPS_IDLE);
+ inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
+ gsm411_send_release(inst);
+ return 0;
+}
+
+static int gsm411_mnsms_error_ind_rx(struct gsm411_smr_inst *inst,
+ struct msgb *msg)
+{
+ LOGP(DLSMS, LOGL_DEBUG, "RX SMS MNSMS-ERROR-IND\n");
+ new_rp_state(inst, GSM411_RPS_IDLE);
+ return inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
+}
+
+/* SMR TR1* is expired */
+static void rp_timer_expired(void *data)
+{
+ struct gsm411_smr_inst *inst = data;
+
+ if (inst->rp_state == GSM411_RPS_WAIT_TO_TX_RP_ACK)
+ LOGP(DLSMS, LOGL_DEBUG, "TR2N\n");
+ else
+ LOGP(DLSMS, LOGL_DEBUG, "TR1N\n");
+ gsm411_send_report(inst);
+ gsm411_send_abort(inst);
+}
+
+/* statefull handling for SM-RL SAP messages */
+static struct smrdownstate {
+ uint32_t states;
+ int type;
+ const char *name;
+ int (*rout) (struct gsm411_smr_inst *inst,
+ struct msgb *msg);
+} smrdownstatelist[] = {
+ /* data request */
+ {SBIT(GSM411_RPS_IDLE),
+ GSM411_SM_RL_DATA_REQ,
+ "SM-RL-DATA_REQ", gsm411_rl_data_req},
+
+ /* report request */
+ {SBIT(GSM411_RPS_WAIT_TO_TX_RP_ACK),
+ GSM411_SM_RL_REPORT_REQ,
+ "SM-RL-REPORT_REQ", gsm411_rl_report_req},
+};
+
+#define SMRDOWNSLLEN \
+ (sizeof(smrdownstatelist) / sizeof(struct smrdownstate))
+
+/* message from upper layer */
+int gsm411_smr_send(struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg)
+{
+ int i, rc;
+
+ /* find function for current state and message */
+ for (i = 0; i < SMRDOWNSLLEN; i++) {
+ if ((msg_type == smrdownstatelist[i].type)
+ && (SBIT(inst->rp_state) & smrdownstatelist[i].states))
+ break;
+ }
+ if (i == SMRDOWNSLLEN) {
+ LOGP(DLSMS, LOGL_NOTICE, "Message %u unhandled at this state "
+ "%s.\n", msg_type, smr_state_names[inst->rp_state]);
+ msgb_free(msg);
+ return 0;
+ }
+
+ LOGP(DLSMS, LOGL_INFO, "Message %s received in state %s\n",
+ smrdownstatelist[i].name, smr_state_names[inst->rp_state]);
+
+ rc = smrdownstatelist[i].rout(inst, msg);
+
+ return rc;
+}
+
+/* statefull handling for MMSMS SAP messages */
+static struct smrdatastate {
+ uint32_t states;
+ int type;
+ const char *name;
+ int (*rout) (struct gsm411_smr_inst *inst,
+ struct msgb *msg);
+} smrdatastatelist[] = {
+ /* establish indication */
+ {SBIT(GSM411_RPS_IDLE),
+ GSM411_MNSMS_EST_IND,
+ "MNSMS-EST-IND", gsm411_mnsms_est_ind},
+
+ /* data indication */
+ {SBIT(GSM411_RPS_WAIT_FOR_RP_ACK),
+ GSM411_MNSMS_DATA_IND,
+ "MNSMS-DATA-IND", gsm411_mnsms_data_ind_tx},
+
+ /* error indication */
+ {SBIT(GSM411_RPS_WAIT_FOR_RP_ACK),
+ GSM411_MNSMS_ERROR_IND,
+ "MNSMS-ERROR-IND", gsm411_mnsms_error_ind_tx},
+
+ /* error indication */
+ {SBIT(GSM411_RPS_WAIT_TO_TX_RP_ACK),
+ GSM411_MNSMS_ERROR_IND,
+ "MNSMS-ERROR-IND", gsm411_mnsms_error_ind_rx},
+
+};
+
+#define SMRDATASLLEN \
+ (sizeof(smrdatastatelist) / sizeof(struct smrdatastate))
+
+/* message from lower layer
+ * WARNING: We must not free msg, since it will be performed by the
+ * lower layer. */
+int gsm411_smr_recv(struct gsm411_smr_inst *inst, int msg_type,
+ struct msgb *msg)
+{
+ int i, rc;
+
+ /* find function for current state and message */
+ for (i = 0; i < SMRDATASLLEN; i++) {
+ /* state must machtch, MM message must match
+ * CP msg must match only in case of MMSMS_DATA_IND
+ */
+ if ((msg_type == smrdatastatelist[i].type)
+ && (SBIT(inst->rp_state) & smrdatastatelist[i].states))
+ break;
+ }
+ if (i == SMRDATASLLEN) {
+ LOGP(DLSMS, LOGL_NOTICE, "Message %u unhandled at this state "
+ "%s.\n", msg_type, smr_state_names[inst->rp_state]);
+ return 0;
+ }
+
+ LOGP(DLSMS, LOGL_INFO, "Message %s received in state %s\n",
+ smrdatastatelist[i].name, smr_state_names[inst->rp_state]);
+
+ rc = smrdatastatelist[i].rout(inst, msg);
+
+ return rc;
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_utils.c b/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_utils.c
new file mode 100644
index 0000000..5076ec8
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0411_utils.c
@@ -0,0 +1,306 @@
+/* Point-to-Point (PP) Short Message Service (SMS)
+ * Support on Mobile Radio Interface
+ * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
+
+/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
+ * (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * (C) 2011 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 Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include <time.h>
+#include <string.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
+
+#include <osmocom/gsm/gsm48.h>
+#include <osmocom/gsm/protocol/gsm_04_11.h>
+
+#define GSM411_ALLOC_SIZE 1024
+#define GSM411_ALLOC_HEADROOM 128
+
+struct msgb *gsm411_msgb_alloc(void)
+{
+ return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
+ "GSM 04.11");
+}
+
+/* Turn int into semi-octet representation: 98 => 0x89 */
+uint8_t gsm411_bcdify(uint8_t value)
+{
+ uint8_t ret;
+
+ ret = value / 10;
+ ret |= (value % 10) << 4;
+
+ return ret;
+}
+
+/* Turn semi-octet representation into int: 0x89 => 98 */
+uint8_t gsm411_unbcdify(uint8_t value)
+{
+ uint8_t ret;
+
+ if ((value & 0x0F) > 9 || (value >> 4) > 9)
+ LOGP(DLSMS, LOGL_ERROR,
+ "gsm411_unbcdify got too big nibble: 0x%02X\n", value);
+
+ ret = (value&0x0F)*10;
+ ret += value>>4;
+
+ return ret;
+}
+
+/* Generate 03.40 TP-SCTS */
+void gsm340_gen_scts(uint8_t *scts, time_t time)
+{
+ struct tm *tm = gmtime(&time);
+
+ *scts++ = gsm411_bcdify(tm->tm_year % 100);
+ *scts++ = gsm411_bcdify(tm->tm_mon + 1);
+ *scts++ = gsm411_bcdify(tm->tm_mday);
+ *scts++ = gsm411_bcdify(tm->tm_hour);
+ *scts++ = gsm411_bcdify(tm->tm_min);
+ *scts++ = gsm411_bcdify(tm->tm_sec);
+ *scts++ = gsm411_bcdify(0); /* GMT */
+}
+
+/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
+time_t gsm340_scts(uint8_t *scts)
+{
+ struct tm tm;
+ uint8_t yr = gsm411_unbcdify(*scts++);
+ int ofs;
+
+ memset(&tm, 0x00, sizeof(struct tm));
+
+ if (yr <= 80)
+ tm.tm_year = 100 + yr;
+ else
+ tm.tm_year = yr;
+ tm.tm_mon = gsm411_unbcdify(*scts++) - 1;
+ tm.tm_mday = gsm411_unbcdify(*scts++);
+ tm.tm_hour = gsm411_unbcdify(*scts++);
+ tm.tm_min = gsm411_unbcdify(*scts++);
+ tm.tm_sec = gsm411_unbcdify(*scts++);
+
+ /* according to gsm 03.40 time zone is
+ "expressed in quarters of an hour" */
+ ofs = gsm411_unbcdify(*scts++) * 15*60;
+
+ return mktime(&tm) - ofs;
+}
+
+/* Return the default validity period in minutes */
+static unsigned long gsm340_vp_default(void)
+{
+ unsigned long minutes;
+ /* Default validity: two days */
+ minutes = 24 * 60 * 2;
+ return minutes;
+}
+
+/* Decode validity period format 'relative' */
+static unsigned long gsm340_vp_relative(uint8_t *sms_vp)
+{
+ /* Chapter 9.2.3.12.1 */
+ uint8_t vp;
+ unsigned long minutes;
+
+ vp = *(sms_vp);
+ if (vp <= 143)
+ minutes = vp + 1 * 5;
+ else if (vp <= 167)
+ minutes = 12*60 + (vp-143) * 30;
+ else if (vp <= 196)
+ minutes = vp-166 * 60 * 24;
+ else
+ minutes = vp-192 * 60 * 24 * 7;
+ return minutes;
+}
+
+/* Decode validity period format 'absolute' */
+static unsigned long gsm340_vp_absolute(uint8_t *sms_vp)
+{
+ /* Chapter 9.2.3.12.2 */
+ time_t expires, now;
+ unsigned long minutes;
+
+ expires = gsm340_scts(sms_vp);
+ now = time(NULL);
+ if (expires <= now)
+ minutes = 0;
+ else
+ minutes = (expires-now)/60;
+ return minutes;
+}
+
+/* Decode validity period format 'relative in integer representation' */
+static unsigned long gsm340_vp_relative_integer(uint8_t *sms_vp)
+{
+ uint8_t vp;
+ unsigned long minutes;
+ vp = *(sms_vp);
+ if (vp == 0) {
+ LOGP(DLSMS, LOGL_ERROR,
+ "reserved relative_integer validity period\n");
+ return gsm340_vp_default();
+ }
+ minutes = vp/60;
+ return minutes;
+}
+
+/* Decode validity period format 'relative in semi-octet representation' */
+static unsigned long gsm340_vp_relative_semioctet(uint8_t *sms_vp)
+{
+ unsigned long minutes;
+ minutes = gsm411_unbcdify(*sms_vp++)*60; /* hours */
+ minutes += gsm411_unbcdify(*sms_vp++); /* minutes */
+ minutes += gsm411_unbcdify(*sms_vp++)/60; /* seconds */
+ return minutes;
+}
+
+/* decode validity period. return minutes */
+unsigned long gsm340_validity_period(uint8_t sms_vpf, uint8_t *sms_vp)
+{
+ uint8_t fi; /* functionality indicator */
+
+ switch (sms_vpf) {
+ case GSM340_TP_VPF_RELATIVE:
+ return gsm340_vp_relative(sms_vp);
+ case GSM340_TP_VPF_ABSOLUTE:
+ return gsm340_vp_absolute(sms_vp);
+ case GSM340_TP_VPF_ENHANCED:
+ /* Chapter 9.2.3.12.3 */
+ fi = *sms_vp++;
+ /* ignore additional fi */
+ if (fi & (1<<7)) sms_vp++;
+ /* read validity period format */
+ switch (fi & 0x7) {
+ case 0x0:
+ return gsm340_vp_default(); /* no vpf specified */
+ case 0x1:
+ return gsm340_vp_relative(sms_vp);
+ case 0x2:
+ return gsm340_vp_relative_integer(sms_vp);
+ case 0x3:
+ return gsm340_vp_relative_semioctet(sms_vp);
+ default:
+ /* The GSM spec says that the SC should reject any
+ unsupported and/or undefined values. FIXME */
+ LOGP(DLSMS, LOGL_ERROR,
+ "Reserved enhanced validity period format\n");
+ return gsm340_vp_default();
+ }
+ case GSM340_TP_VPF_NONE:
+ default:
+ return gsm340_vp_default();
+ }
+}
+
+/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
+enum sms_alphabet gsm338_get_sms_alphabet(uint8_t dcs)
+{
+ uint8_t cgbits = dcs >> 4;
+ enum sms_alphabet alpha = DCS_NONE;
+
+ if ((cgbits & 0xc) == 0) {
+ if (cgbits & 2) {
+ LOGP(DLSMS, LOGL_NOTICE,
+ "Compressed SMS not supported yet\n");
+ return 0xffffffff;
+ }
+
+ switch ((dcs >> 2)&0x03) {
+ case 0:
+ alpha = DCS_7BIT_DEFAULT;
+ break;
+ case 1:
+ alpha = DCS_8BIT_DATA;
+ break;
+ case 2:
+ alpha = DCS_UCS2;
+ break;
+ }
+ } else if (cgbits == 0xc || cgbits == 0xd)
+ alpha = DCS_7BIT_DEFAULT;
+ else if (cgbits == 0xe)
+ alpha = DCS_UCS2;
+ else if (cgbits == 0xf) {
+ if (dcs & 4)
+ alpha = DCS_8BIT_DATA;
+ else
+ alpha = DCS_7BIT_DEFAULT;
+ }
+
+ return alpha;
+}
+
+/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
+int gsm340_gen_oa(uint8_t *oa, unsigned int oa_len, uint8_t type,
+ uint8_t plan, const char *number)
+{
+ int len_in_bytes;
+
+ /* prevent buffer overflows */
+ if (strlen(number) > 20)
+ number = "";
+
+// oa[1] = 0xb9; /* networks-specific number, private numbering plan */
+ oa[1] = 0x80 | (type << 4) | plan;
+
+ len_in_bytes = gsm48_encode_bcd_number(oa, oa_len, 1, number);
+
+ /* GSM 03.40 tells us the length is in 'useful semi-octets' */
+ oa[0] = strlen(number) & 0xff;
+
+ return len_in_bytes;
+}
+
+/* Prefix msg with a RP header */
+int gsm411_push_rp_header(struct msgb *msg, uint8_t rp_msg_type,
+ uint8_t rp_msg_ref)
+{
+ struct gsm411_rp_hdr *rp;
+ uint8_t len = msg->len;
+
+ /* GSM 04.11 RP-DATA header */
+ rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
+ rp->len = len + 2;
+ rp->msg_type = rp_msg_type;
+ rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
+
+ return 0;
+}
+
+/* Prefix msg with a 04.08/04.11 CP header */
+int gsm411_push_cp_header(struct msgb *msg, uint8_t proto, uint8_t trans,
+ uint8_t msg_type)
+{
+ struct gsm48_hdr *gh;
+
+ gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
+ /* Outgoing needs the highest bit set */
+ gh->proto_discr = proto | (trans << 4);
+ gh->msg_type = msg_type;
+
+ return 0;
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0808.c b/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0808.c
index 01221bd..3009827 100644
--- a/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0808.c
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/gsm0808.c
@@ -27,69 +27,52 @@
#define BSSMAP_MSG_SIZE 512
#define BSSMAP_MSG_HEADROOM 128
-static void put_data_16(uint8_t *data, const uint16_t val)
-{
- memcpy(data, &val, sizeof(val));
-}
-
struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc, uint16_t cc, int lac, uint16_t _ci)
{
- uint8_t *data;
- uint8_t *ci;
struct msgb* msg;
- struct gsm48_loc_area_id *lai;
+ struct {
+ uint8_t ident;
+ struct gsm48_loc_area_id lai;
+ uint16_t ci;
+ } __attribute__ ((packed)) lai_ci;
msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
"bssmap cmpl l3");
if (!msg)
return NULL;
- /* create the bssmap header */
- msg->l3h = msgb_put(msg, 2);
- msg->l3h[0] = 0x0;
-
/* create layer 3 header */
- data = msgb_put(msg, 1);
- data[0] = BSS_MAP_MSG_COMPLETE_LAYER_3;
+ msgb_v_put(msg, BSS_MAP_MSG_COMPLETE_LAYER_3);
/* create the cell header */
- data = msgb_put(msg, 3);
- data[0] = GSM0808_IE_CELL_IDENTIFIER;
- data[1] = 1 + sizeof(*lai) + 2;
- data[2] = CELL_IDENT_WHOLE_GLOBAL;
-
- lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
- gsm48_generate_lai(lai, cc, nc, lac);
-
- ci = msgb_put(msg, 2);
- put_data_16(ci, htons(_ci));
+ lai_ci.ident = CELL_IDENT_WHOLE_GLOBAL;
+ gsm48_generate_lai(&lai_ci.lai, cc, nc, lac);
+ lai_ci.ci = htons(_ci);
+ msgb_tlv_put(msg, GSM0808_IE_CELL_IDENTIFIER, sizeof(lai_ci),
+ (uint8_t *) &lai_ci);
/* copy the layer3 data */
- data = msgb_put(msg, msgb_l3len(msg_l3) + 2);
- data[0] = GSM0808_IE_LAYER_3_INFORMATION;
- data[1] = msgb_l3len(msg_l3);
- memcpy(&data[2], msg_l3->l3h, data[1]);
+ msgb_tlv_put(msg, GSM0808_IE_LAYER_3_INFORMATION,
+ msgb_l3len(msg_l3), msg_l3->l3h);
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
+ /* push the bssmap header */
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
return msg;
}
struct msgb *gsm0808_create_reset(void)
{
+ uint8_t cause = GSM0808_CAUSE_EQUIPMENT_FAILURE;
struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
"bssmap: reset");
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 6);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0x04;
- msg->l3h[2] = 0x30;
- msg->l3h[3] = 0x04;
- msg->l3h[4] = 0x01;
- msg->l3h[5] = 0x20;
+ msgb_v_put(msg, BSS_MAP_MSG_RESET);
+ msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause);
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
+
return msg;
}
@@ -97,13 +80,12 @@ struct msgb *gsm0808_create_clear_complete(void)
{
struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
"bssmap: clear complete");
+ uint8_t val = BSS_MAP_MSG_CLEAR_COMPLETE;
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 1;
- msg->l3h[2] = BSS_MAP_MSG_CLEAR_COMPLETE;
+ msg->l3h = msg->data;
+ msgb_tlv_put(msg, BSSAP_MSG_BSS_MANAGEMENT, 1, &val);
return msg;
}
@@ -118,6 +100,7 @@ struct msgb *gsm0808_create_clear_command(uint8_t reason)
msg->l3h = msgb_tv_put(msg, BSSAP_MSG_BSS_MANAGEMENT, 4);
msgb_v_put(msg, BSS_MAP_MSG_CLEAR_CMD);
msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &reason);
+
return msg;
}
@@ -129,26 +112,20 @@ struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id)
return NULL;
/* send response with BSS override for A5/1... cheating */
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_COMPLETE;
+ msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_COMPLETE);
/* include layer3 in case we have at least two octets */
if (layer3 && msgb_l3len(layer3) > 2) {
- msg->l4h = msgb_put(msg, msgb_l3len(layer3) + 2);
- msg->l4h[0] = GSM0808_IE_LAYER_3_MESSAGE_CONTENTS;
- msg->l4h[1] = msgb_l3len(layer3);
- memcpy(&msg->l4h[2], layer3->l3h, msgb_l3len(layer3));
+ msg->l4h = msgb_tlv_put(msg, GSM0808_IE_LAYER_3_MESSAGE_CONTENTS,
+ msgb_l3len(layer3), layer3->l3h);
}
/* and the optional BSS message */
- msg->l4h = msgb_put(msg, 2);
- msg->l4h[0] = GSM0808_IE_CHOSEN_ENCR_ALG;
- msg->l4h[1] = alg_id;
+ msgb_tv_put(msg, GSM0808_IE_CHOSEN_ENCR_ALG, alg_id);
+
+ /* pre-pend the header */
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
return msg;
}
@@ -159,32 +136,29 @@ struct msgb *gsm0808_create_cipher_reject(uint8_t cause)
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 4);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 2;
- msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_REJECT;
- msg->l3h[3] = cause;
+ msgb_tv_put(msg, BSS_MAP_MSG_CIPHER_MODE_REJECT, cause);
+
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
return msg;
}
-struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark_data, uint8_t length)
+struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,
+ const uint8_t *cm3, uint8_t cm3_len)
{
struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
"classmark-update");
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_CLASSMARK_UPDATE;
+ msgb_v_put(msg, BSS_MAP_MSG_CLASSMARK_UPDATE);
+ msgb_tlv_put(msg, GSM0808_IE_CLASSMARK_INFORMATION_T2, cm2_len, cm2);
+ if (cm3)
+ msgb_tlv_put(msg, GSM0808_IE_CLASSMARK_INFORMATION_T3,
+ cm3_len, cm3);
- msg->l4h = msgb_put(msg, length);
- memcpy(msg->l4h, classmark_data, length);
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
return msg;
}
@@ -195,12 +169,11 @@ struct msgb *gsm0808_create_sapi_reject(uint8_t link_id)
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 5);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 3;
- msg->l3h[2] = BSS_MAP_MSG_SAPI_N_REJECT;
- msg->l3h[3] = link_id;
- msg->l3h[4] = GSM0808_CAUSE_BSS_NOT_EQUIPPED;
+ msgb_v_put(msg, BSS_MAP_MSG_SAPI_N_REJECT);
+ msgb_v_put(msg, link_id);
+ msgb_v_put(msg, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
+
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
return msg;
}
@@ -209,78 +182,56 @@ struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause,
uint8_t chosen_channel, uint8_t encr_alg_id,
uint8_t speech_mode)
{
- uint8_t *data;
-
- struct msgb *msg = msgb_alloc(35, "bssmap: ass compl");
+ struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+ "bssmap: ass compl");
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_COMPLETE;
+ msgb_v_put(msg, BSS_MAP_MSG_ASSIGMENT_COMPLETE);
/* write 3.2.2.22 */
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_RR_CAUSE;
- data[1] = rr_cause;
+ msgb_tv_put(msg, GSM0808_IE_RR_CAUSE, rr_cause);
/* write cirtcuit identity code 3.2.2.2 */
/* write cell identifier 3.2.2.17 */
/* write chosen channel 3.2.2.33 when BTS picked it */
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_CHOSEN_CHANNEL;
- data[1] = chosen_channel;
+ msgb_tv_put(msg, GSM0808_IE_CHOSEN_CHANNEL, chosen_channel);
/* write chosen encryption algorithm 3.2.2.44 */
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_CHOSEN_ENCR_ALG;
- data[1] = encr_alg_id;
+ msgb_tv_put(msg, GSM0808_IE_CHOSEN_ENCR_ALG, encr_alg_id);
/* write circuit pool 3.2.2.45 */
/* write speech version chosen: 3.2.2.51 when BTS picked it */
- if (speech_mode != 0) {
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_SPEECH_VERSION;
- data[1] = speech_mode;
- }
+ if (speech_mode != 0)
+ msgb_tv_put(msg, GSM0808_IE_SPEECH_VERSION, speech_mode);
/* write LSA identifier 3.2.2.15 */
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
return msg;
}
struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause)
{
- uint8_t *data;
struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
"bssmap: ass fail");
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 6);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_FAILURE;
- msg->l3h[3] = GSM0808_IE_CAUSE;
- msg->l3h[4] = 1;
- msg->l3h[5] = cause;
+ msgb_v_put(msg, BSS_MAP_MSG_ASSIGMENT_FAILURE);
+ msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause);
/* RR cause 3.2.2.22 */
- if (rr_cause) {
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_RR_CAUSE;
- data[1] = *rr_cause;
- }
+ if (rr_cause)
+ msgb_tv_put(msg, GSM0808_IE_RR_CAUSE, *rr_cause);
/* Circuit pool 3.22.45 */
/* Circuit pool list 3.2.2.46 */
/* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
+
return msg;
}
@@ -293,14 +244,10 @@ struct msgb *gsm0808_create_clear_rqst(uint8_t cause)
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 2 + 4);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 4;
+ msgb_v_put(msg, BSS_MAP_MSG_CLEAR_RQST);
+ msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause);
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
- msg->l3h[2] = BSS_MAP_MSG_CLEAR_RQST;
- msg->l3h[3] = GSM0808_IE_CAUSE;
- msg->l3h[4] = 1;
- msg->l3h[5] = cause;
return msg;
}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/gsm48.c b/Src/osmolib/src/shared/libosmocore/src/gsm/gsm48.c
index 44baec6..379ed65 100644
--- a/Src/osmolib/src/shared/libosmocore/src/gsm/gsm48.c
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/gsm48.c
@@ -406,7 +406,7 @@ int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid)
buf[2] = ((mnc / 10) % 10) | ((mnc % 10) << 4);
} else {
buf[1] |= (mnc % 10) << 4;
- buf[2] = ((mnc / 100) % 10) | (((mcc / 10) % 10) << 4);
+ buf[2] = ((mnc / 100) % 10) | (((mnc / 10) % 10) << 4);
}
*(uint16_t *)(buf+3) = htons(raid->lac);
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/lapd_core.c b/Src/osmolib/src/shared/libosmocore/src/gsm/lapd_core.c
new file mode 100644
index 0000000..fb79a2f
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/lapd_core.c
@@ -0,0 +1,2170 @@
+/* LAPD core implementation */
+
+/* (C) 2010-2011 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010-2011 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.
+ *
+ */
+
+/*! \addtogroup lapd
+ * @{
+ */
+
+/*! \file lapd.c */
+
+/*!
+ * Notes on Buffering: rcv_buffer, tx_queue, tx_hist, send_buffer, send_queue
+ *
+ * RX data is stored in the rcv_buffer (pointer). If the message is complete, it
+ * is removed from rcv_buffer pointer and forwarded to L3. If the RX data is
+ * received while there is an incomplete rcv_buffer, it is appended to it.
+ *
+ * TX data is stored in the send_queue first. When transmitting a frame,
+ * the first message in the send_queue is moved to the send_buffer. There it
+ * resides until all fragments are acknowledged. Fragments to be sent by I
+ * frames are stored in the tx_hist buffer for resend, if required. Also the
+ * current fragment is copied into the tx_queue. There it resides until it is
+ * forwarded to layer 1.
+ *
+ * In case we have SAPI 0, we only have a window size of 1, so the unack-
+ * nowledged message resides always in the send_buffer. In case of a suspend,
+ * it can be written back to the first position of the send_queue.
+ *
+ * The layer 1 normally sends a PH-READY-TO-SEND. But because we use
+ * asynchronous transfer between layer 1 and layer 2 (serial link), we must
+ * send a frame before layer 1 reaches the right timeslot to send it. So we
+ * move the tx_queue to layer 1 when there is not already a pending frame, and
+ * wait until acknowledge after the frame has been sent. If we receive an
+ * acknowledge, we can send the next frame from the buffer, if any.
+ *
+ * The moving of tx_queue to layer 1 may also trigger T200, if desired. Also it
+ * will trigger next I frame, if possible.
+ *
+ * T203 is optional. It will be stated when entering MF EST state. It will also
+ * be started when I or S frame is received in that state . It will be
+ * restarted in the lapd_acknowledge() function, in case outstanding frames
+ * will not trigger T200. It will be stoped, when T200 is started in MF EST
+ * state. It will also be stoped when leaving MF EST state.
+ *
+ */
+
+/* Enable this to test content resolution on network side:
+ * - The first SABM is received, UA is dropped.
+ * - The phone repeats SABM, but it's content is wrong, so it is ignored
+ * - The phone repeats SABM again, content is right, so UA is sent.
+ */
+//#define TEST_CONTENT_RESOLUTION_NETWORK
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#include <osmocom/core/logging.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/lapd_core.h>
+
+/* TS 04.06 Table 4 / Section 3.8.1 */
+#define LAPD_U_SABM 0x7
+#define LAPD_U_SABME 0xf
+#define LAPD_U_DM 0x3
+#define LAPD_U_UI 0x0
+#define LAPD_U_DISC 0x8
+#define LAPD_U_UA 0xC
+#define LAPD_U_FRMR 0x11
+
+#define LAPD_S_RR 0x0
+#define LAPD_S_RNR 0x1
+#define LAPD_S_REJ 0x2
+
+#define CR_USER2NET_CMD 0
+#define CR_USER2NET_RESP 1
+#define CR_NET2USER_CMD 1
+#define CR_NET2USER_RESP 0
+
+#define LAPD_HEADROOM 56
+
+#define SBIT(a) (1 << a)
+#define ALL_STATES 0xffffffff
+
+static void lapd_t200_cb(void *data);
+static void lapd_t203_cb(void *data);
+static int lapd_send_i(struct lapd_msg_ctx *lctx, int line);
+static int lapd_est_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx);
+
+/* UTILITY FUNCTIONS */
+
+struct msgb *lapd_msgb_alloc(int length, const char *name)
+{
+ /* adding space for padding, FIXME: add as an option */
+ if (length < 21)
+ length = 21;
+ return msgb_alloc_headroom(length + LAPD_HEADROOM, LAPD_HEADROOM, name);
+}
+
+static inline uint8_t do_mod(uint8_t x, uint8_t m)
+{
+ return x & (m - 1);
+}
+
+static inline uint8_t inc_mod(uint8_t x, uint8_t m)
+{
+ return (x + 1) & (m - 1);
+}
+
+static inline uint8_t add_mod(uint8_t x, uint8_t y, uint8_t m)
+{
+ return (x + y) & (m - 1);
+}
+
+static inline uint8_t sub_mod(uint8_t x, uint8_t y, uint8_t m)
+{
+ return (x - y) & (m - 1); /* handle negative results correctly */
+}
+
+static void lapd_dl_flush_send(struct lapd_datalink *dl)
+{
+ struct msgb *msg;
+
+ /* Flush send-queue */
+ while ((msg = msgb_dequeue(&dl->send_queue)))
+ msgb_free(msg);
+
+ /* Clear send-buffer */
+ if (dl->send_buffer) {
+ msgb_free(dl->send_buffer);
+ dl->send_buffer = NULL;
+ }
+}
+
+static void lapd_dl_flush_hist(struct lapd_datalink *dl)
+{
+ unsigned int i;
+
+ for (i = 0; i < dl->range_hist; i++) {
+ if (dl->tx_hist[i].msg) {
+ msgb_free(dl->tx_hist[i].msg);
+ dl->tx_hist[i].msg = NULL;
+ }
+ }
+}
+
+static void lapd_dl_flush_tx(struct lapd_datalink *dl)
+{
+ struct msgb *msg;
+
+ while ((msg = msgb_dequeue(&dl->tx_queue)))
+ msgb_free(msg);
+ lapd_dl_flush_hist(dl);
+}
+
+/* Figure B.2/Q.921 */
+const char *lapd_state_names[] = {
+ "LAPD_STATE_NULL",
+ "LAPD_STATE_TEI_UNASS",
+ "LAPD_STATE_ASS_TEI_WAIT",
+ "LAPD_STATE_EST_TEI_WAIT",
+ "LAPD_STATE_IDLE",
+ "LAPD_STATE_SABM_SENT",
+ "LAPD_STATE_DISC_SENT",
+ "LAPD_STATE_MF_EST",
+ "LAPD_STATE_TIMER_RECOV",
+
+};
+
+static void lapd_start_t200(struct lapd_datalink *dl)
+{
+ if (osmo_timer_pending(&dl->t200))
+ return;
+ LOGP(DLLAPD, LOGL_INFO, "start T200\n");
+ osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
+}
+
+static void lapd_start_t203(struct lapd_datalink *dl)
+{
+ if (osmo_timer_pending(&dl->t203))
+ return;
+ LOGP(DLLAPD, LOGL_INFO, "start T203\n");
+ osmo_timer_schedule(&dl->t203, dl->t203_sec, dl->t203_usec);
+}
+
+static void lapd_stop_t200(struct lapd_datalink *dl)
+{
+ if (!osmo_timer_pending(&dl->t200))
+ return;
+ LOGP(DLLAPD, LOGL_INFO, "stop T200\n");
+ osmo_timer_del(&dl->t200);
+}
+
+static void lapd_stop_t203(struct lapd_datalink *dl)
+{
+ if (!osmo_timer_pending(&dl->t203))
+ return;
+ LOGP(DLLAPD, LOGL_INFO, "stop T203\n");
+ osmo_timer_del(&dl->t203);
+}
+
+static void lapd_dl_newstate(struct lapd_datalink *dl, uint32_t state)
+{
+ LOGP(DLLAPD, LOGL_INFO, "new state %s -> %s\n",
+ lapd_state_names[dl->state], lapd_state_names[state]);
+
+ if (state != LAPD_STATE_MF_EST && dl->state == LAPD_STATE_MF_EST) {
+ /* stop T203 on leaving MF EST state, if running */
+ lapd_stop_t203(dl);
+ /* remove content res. (network side) on leaving MF EST state */
+ if (dl->cont_res) {
+ msgb_free(dl->cont_res);
+ dl->cont_res = NULL;
+ }
+ }
+
+ /* start T203 on entering MF EST state, if enabled */
+ if ((dl->t203_sec || dl->t203_usec)
+ && state == LAPD_STATE_MF_EST && dl->state != LAPD_STATE_MF_EST)
+ lapd_start_t203(dl);
+
+ dl->state = state;
+}
+
+static void *tall_lapd_ctx = NULL;
+
+/* init datalink instance and allocate history */
+void lapd_dl_init(struct lapd_datalink *dl, uint8_t k, uint8_t v_range,
+ int maxf)
+{
+ int m;
+
+ memset(dl, 0, sizeof(*dl));
+ INIT_LLIST_HEAD(&dl->send_queue);
+ INIT_LLIST_HEAD(&dl->tx_queue);
+ dl->reestablish = 1;
+ dl->n200_est_rel = 3;
+ dl->n200 = 3;
+ dl->t200_sec = 1;
+ dl->t200_usec = 0;
+ dl->t200.data = dl;
+ dl->t200.cb = &lapd_t200_cb;
+ dl->t203_sec = 10;
+ dl->t203_usec = 0;
+ dl->t203.data = dl;
+ dl->t203.cb = &lapd_t203_cb;
+ dl->maxf = maxf;
+ if (k > v_range - 1)
+ k = v_range - 1;
+ dl->k = k;
+ dl->v_range = v_range;
+
+ /* Calculate modulo for history array:
+ * - The history range must be at least k+1.
+ * - The history range must be 2^x, where x is as low as possible.
+ */
+ k++;
+ for (m = 0x80; m; m >>= 1) {
+ if ((m & k)) {
+ if (k > m)
+ m <<= 1;
+ dl->range_hist = m;
+ break;
+ }
+ }
+
+ LOGP(DLLAPD, LOGL_INFO, "Init DL layer: sequence range = %d, k = %d, "
+ "history range = %d\n", dl->v_range, dl->k, dl->range_hist);
+
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+
+ if (!tall_lapd_ctx)
+ tall_lapd_ctx = talloc_named_const(NULL, 1, "lapd context");
+ dl->tx_hist = (struct lapd_history *) talloc_zero_array(tall_lapd_ctx,
+ struct log_info, dl->range_hist);
+}
+
+/* reset to IDLE state */
+void lapd_dl_reset(struct lapd_datalink *dl)
+{
+ if (dl->state == LAPD_STATE_IDLE)
+ return;
+ LOGP(DLLAPD, LOGL_INFO, "Resetting LAPDm instance\n");
+ /* enter idle state (and remove eventual cont_res) */
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+ /* flush buffer */
+ lapd_dl_flush_tx(dl);
+ lapd_dl_flush_send(dl);
+ /* Discard partly received L3 message */
+ if (dl->rcv_buffer) {
+ msgb_free(dl->rcv_buffer);
+ dl->rcv_buffer = NULL;
+ }
+ /* stop Timers */
+ lapd_stop_t200(dl);
+ lapd_stop_t203(dl);
+}
+
+/* reset and de-allocate history buffer */
+void lapd_dl_exit(struct lapd_datalink *dl)
+{
+ /* free all ressources except history buffer */
+ lapd_dl_reset(dl);
+ /* free history buffer list */
+ talloc_free(dl->tx_hist);
+}
+
+/*! \brief Set the \ref lapdm_mode of a LAPDm entity */
+int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode)
+{
+ switch (mode) {
+ case LAPD_MODE_USER:
+ dl->cr.loc2rem.cmd = CR_USER2NET_CMD;
+ dl->cr.loc2rem.resp = CR_USER2NET_RESP;
+ dl->cr.rem2loc.cmd = CR_NET2USER_CMD;
+ dl->cr.rem2loc.resp = CR_NET2USER_RESP;
+ break;
+ case LAPD_MODE_NETWORK:
+ dl->cr.loc2rem.cmd = CR_NET2USER_CMD;
+ dl->cr.loc2rem.resp = CR_NET2USER_RESP;
+ dl->cr.rem2loc.cmd = CR_USER2NET_CMD;
+ dl->cr.rem2loc.resp = CR_USER2NET_RESP;
+ break;
+ default:
+ return -EINVAL;
+ }
+ dl->mode = mode;
+
+ return 0;
+}
+
+/* send DL message with optional msgb */
+static int send_dl_l3(uint8_t prim, uint8_t op, struct lapd_msg_ctx *lctx,
+ struct msgb *msg)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ struct osmo_dlsap_prim dp;
+
+ osmo_prim_init(&dp.oph, 0, prim, op, msg);
+ return dl->send_dlsap(&dp, lctx);
+}
+
+/* send simple DL message */
+static inline int send_dl_simple(uint8_t prim, uint8_t op,
+ struct lapd_msg_ctx *lctx)
+{
+ struct msgb *msg = lapd_msgb_alloc(0, "DUMMY");
+
+ return send_dl_l3(prim, op, lctx, msg);
+}
+
+/* send MDL-ERROR INDICATION */
+static int mdl_error(uint8_t cause, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ struct osmo_dlsap_prim dp;
+
+ LOGP(DLLAPD, LOGL_NOTICE, "sending MDL-ERROR-IND cause %d\n",
+ cause);
+ osmo_prim_init(&dp.oph, 0, PRIM_MDL_ERROR, PRIM_OP_INDICATION, NULL);
+ dp.u.error_ind.cause = cause;
+ return dl->send_dlsap(&dp, lctx);
+}
+
+/* send UA response */
+static int lapd_send_ua(struct lapd_msg_ctx *lctx, uint8_t len, uint8_t *data)
+{
+ struct msgb *msg = lapd_msgb_alloc(len, "LAPD UA");
+ struct lapd_msg_ctx nctx;
+ struct lapd_datalink *dl = lctx->dl;
+
+ memcpy(&nctx, lctx, sizeof(nctx));
+ msg->l3h = msgb_put(msg, len);
+ if (len)
+ memcpy(msg->l3h, data, len);
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.resp;
+ nctx.format = LAPD_FORM_U;
+ nctx.s_u = LAPD_U_UA;
+ /* keep nctx.p_f */
+ nctx.length = len;
+ nctx.more = 0;
+
+ return dl->send_ph_data_req(&nctx, msg);
+}
+
+/* send DM response */
+static int lapd_send_dm(struct lapd_msg_ctx *lctx)
+{
+ struct msgb *msg = lapd_msgb_alloc(0, "LAPD DM");
+ struct lapd_msg_ctx nctx;
+ struct lapd_datalink *dl = lctx->dl;
+
+ memcpy(&nctx, lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.resp;
+ nctx.format = LAPD_FORM_U;
+ nctx.s_u = LAPD_U_DM;
+ /* keep nctx.p_f */
+ nctx.length = 0;
+ nctx.more = 0;
+
+ return dl->send_ph_data_req(&nctx, msg);
+}
+
+/* send RR response / command */
+static int lapd_send_rr(struct lapd_msg_ctx *lctx, uint8_t f_bit, uint8_t cmd)
+{
+ struct msgb *msg = lapd_msgb_alloc(0, "LAPD RR");
+ struct lapd_msg_ctx nctx;
+ struct lapd_datalink *dl = lctx->dl;
+
+ memcpy(&nctx, lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = (cmd) ? dl->cr.loc2rem.cmd : dl->cr.loc2rem.resp;
+ nctx.format = LAPD_FORM_S;
+ nctx.s_u = LAPD_S_RR;
+ nctx.p_f = f_bit;
+ nctx.n_recv = dl->v_recv;
+ nctx.length = 0;
+ nctx.more = 0;
+
+ return dl->send_ph_data_req(&nctx, msg);
+}
+
+/* send RNR response / command */
+static int lapd_send_rnr(struct lapd_msg_ctx *lctx, uint8_t f_bit, uint8_t cmd)
+{
+ struct msgb *msg = lapd_msgb_alloc(0, "LAPD RNR");
+ struct lapd_msg_ctx nctx;
+ struct lapd_datalink *dl = lctx->dl;
+
+ memcpy(&nctx, lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = (cmd) ? dl->cr.loc2rem.cmd : dl->cr.loc2rem.resp;
+ nctx.format = LAPD_FORM_S;
+ nctx.s_u = LAPD_S_RNR;
+ nctx.p_f = f_bit;
+ nctx.n_recv = dl->v_recv;
+ nctx.length = 0;
+ nctx.more = 0;
+
+ return dl->send_ph_data_req(&nctx, msg);
+}
+
+/* send REJ response */
+static int lapd_send_rej(struct lapd_msg_ctx *lctx, uint8_t f_bit)
+{
+ struct msgb *msg = lapd_msgb_alloc(0, "LAPD REJ");
+ struct lapd_msg_ctx nctx;
+ struct lapd_datalink *dl = lctx->dl;
+
+ memcpy(&nctx, lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.resp;
+ nctx.format = LAPD_FORM_S;
+ nctx.s_u = LAPD_S_REJ;
+ nctx.p_f = f_bit;
+ nctx.n_recv = dl->v_recv;
+ nctx.length = 0;
+ nctx.more = 0;
+
+ return dl->send_ph_data_req(&nctx, msg);
+}
+
+/* resend SABM or DISC message */
+static int lapd_send_resend(struct lapd_datalink *dl)
+{
+ struct msgb *msg;
+ uint8_t h = do_mod(dl->v_send, dl->range_hist);
+ int length = dl->tx_hist[h].msg->len;
+ struct lapd_msg_ctx nctx;
+
+ /* assemble message */
+ memcpy(&nctx, &dl->lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.cmd;
+ nctx.format = LAPD_FORM_U;
+ if (dl->state == LAPD_STATE_SABM_SENT)
+ nctx.s_u = (dl->use_sabme) ? LAPD_U_SABME : LAPD_U_SABM;
+ else
+ nctx.s_u = LAPD_U_DISC;
+ nctx.p_f = 1;
+ nctx.length = length;
+ nctx.more = 0;
+
+ /* Resend SABM/DISC from tx_hist */
+ msg = lapd_msgb_alloc(length, "LAPD resend");
+ msg->l3h = msgb_put(msg, length);
+ if (length)
+ memcpy(msg->l3h, dl->tx_hist[h].msg->data, length);
+
+ return dl->send_ph_data_req(&nctx, msg);
+}
+
+/* reestablish link */
+static int lapd_reestablish(struct lapd_datalink *dl)
+{
+ struct osmo_dlsap_prim dp;
+ struct msgb *msg;
+
+ msg = lapd_msgb_alloc(0, "DUMMY");
+ osmo_prim_init(&dp.oph, 0, PRIM_DL_EST, PRIM_OP_REQUEST, msg);
+
+ return lapd_est_req(&dp, &dl->lctx);
+}
+
+/* Timer callback on T200 expiry */
+static void lapd_t200_cb(void *data)
+{
+ struct lapd_datalink *dl = data;
+
+ LOGP(DLLAPD, LOGL_INFO, "Timeout T200 (%p) state=%d\n", dl,
+ (int) dl->state);
+
+ switch (dl->state) {
+ case LAPD_STATE_SABM_SENT:
+ /* 5.4.1.3 */
+ if (dl->retrans_ctr + 1 >= dl->n200_est_rel + 1) {
+ /* send RELEASE INDICATION to L3 */
+ send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION,
+ &dl->lctx);
+ /* send MDL ERROR INIDCATION to L3 */
+ mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx);
+ /* flush tx and send buffers */
+ lapd_dl_flush_tx(dl);
+ lapd_dl_flush_send(dl);
+ /* go back to idle state */
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+ /* NOTE: we must not change any other states or buffers
+ * and queues, since we may reconnect after handover
+ * failure. the buffered messages is replaced there */
+ break;
+ }
+ /* retransmit SABM command */
+ lapd_send_resend(dl);
+ /* increment re-transmission counter */
+ dl->retrans_ctr++;
+ /* restart T200 (PH-READY-TO-SEND) */
+ lapd_start_t200(dl);
+ break;
+ case LAPD_STATE_DISC_SENT:
+ /* 5.4.4.3 */
+ if (dl->retrans_ctr + 1 >= dl->n200_est_rel + 1) {
+ /* send RELEASE INDICATION to L3 */
+ send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, &dl->lctx);
+ /* send MDL ERROR INIDCATION to L3 */
+ mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx);
+ /* flush tx and send buffers */
+ lapd_dl_flush_tx(dl);
+ lapd_dl_flush_send(dl);
+ /* go back to idle state */
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+ /* NOTE: we must not change any other states or buffers
+ * and queues, since we may reconnect after handover
+ * failure. the buffered messages is replaced there */
+ break;
+ }
+ /* retransmit DISC command */
+ lapd_send_resend(dl);
+ /* increment re-transmission counter */
+ dl->retrans_ctr++;
+ /* restart T200 (PH-READY-TO-SEND) */
+ lapd_start_t200(dl);
+ break;
+ case LAPD_STATE_MF_EST:
+ /* 5.5.7 */
+ dl->retrans_ctr = 0;
+ lapd_dl_newstate(dl, LAPD_STATE_TIMER_RECOV);
+ /* fall through */
+ case LAPD_STATE_TIMER_RECOV:
+ dl->retrans_ctr++;
+ if (dl->retrans_ctr < dl->n200) {
+ uint8_t vs = sub_mod(dl->v_send, 1, dl->v_range);
+ uint8_t h = do_mod(vs, dl->range_hist);
+ /* retransmit I frame (V_s-1) with P=1, if any */
+ if (dl->tx_hist[h].msg) {
+ struct msgb *msg;
+ int length = dl->tx_hist[h].msg->len;
+ struct lapd_msg_ctx nctx;
+
+ LOGP(DLLAPD, LOGL_INFO, "retransmit last frame"
+ " V(S)=%d\n", vs);
+ /* Create I frame (segment) from tx_hist */
+ memcpy(&nctx, &dl->lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.cmd;
+ nctx.format = LAPD_FORM_I;
+ nctx.p_f = 1;
+ nctx.n_send = vs;
+ nctx.n_recv = dl->v_recv;
+ nctx.length = length;
+ nctx.more = dl->tx_hist[h].more;
+ msg = lapd_msgb_alloc(length, "LAPD I resend");
+ msg->l3h = msgb_put(msg, length);
+ memcpy(msg->l3h, dl->tx_hist[h].msg->data,
+ length);
+ dl->send_ph_data_req(&nctx, msg);
+ } else {
+ /* OR send appropriate supervision frame with P=1 */
+ if (!dl->own_busy && !dl->seq_err_cond) {
+ lapd_send_rr(&dl->lctx, 1, 1);
+ /* NOTE: In case of sequence error
+ * condition, the REJ frame has been
+ * transmitted when entering the
+ * condition, so it has not be done
+ * here
+ */
+ } else if (dl->own_busy) {
+ lapd_send_rnr(&dl->lctx, 1, 1);
+ } else {
+ LOGP(DLLAPD, LOGL_INFO, "unhandled, "
+ "pls. fix\n");
+ }
+ }
+ /* restart T200 (PH-READY-TO-SEND) */
+ lapd_start_t200(dl);
+ } else {
+ /* send MDL ERROR INIDCATION to L3 */
+ mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx);
+ /* reestablish */
+ if (!dl->reestablish)
+ break;
+ LOGP(DLLAPD, LOGL_NOTICE, "N200 reached, performing "
+ "reestablishment.\n");
+ lapd_reestablish(dl);
+ }
+ break;
+ default:
+ LOGP(DLLAPD, LOGL_INFO, "T200 expired in unexpected "
+ "dl->state %d\n", (int) dl->state);
+ }
+}
+
+/* Timer callback on T203 expiry */
+static void lapd_t203_cb(void *data)
+{
+ struct lapd_datalink *dl = data;
+
+ LOGP(DLLAPD, LOGL_INFO, "Timeout T203 (%p) state=%d\n", dl,
+ (int) dl->state);
+
+ if (dl->state != LAPD_STATE_MF_EST) {
+ LOGP(DLLAPD, LOGL_ERROR, "T203 fired outside MF EST state, "
+ "please fix!\n");
+ return;
+ }
+
+ /* set retransmission counter to 0 */
+ dl->retrans_ctr = 0;
+ /* enter timer recovery state */
+ lapd_dl_newstate(dl, LAPD_STATE_TIMER_RECOV);
+ /* transmit a supervisory command with P bit set to 1 as follows: */
+ if (!dl->own_busy) {
+ LOGP(DLLAPD, LOGL_INFO, "transmit an RR poll command\n");
+ /* Send RR with P=1 */
+ lapd_send_rr(&dl->lctx, 1, 1);
+ } else {
+ LOGP(DLLAPD, LOGL_INFO, "transmit an RNR poll command\n");
+ /* Send RNR with P=1 */
+ lapd_send_rnr(&dl->lctx, 1, 1);
+ }
+ /* start T200 */
+ lapd_start_t200(dl);
+}
+
+/* 5.5.3.1: Common function to acknowlege frames up to the given N(R) value */
+static void lapd_acknowledge(struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ uint8_t nr = lctx->n_recv;
+ int s = 0, rej = 0, t200_reset = 0, t200_start = 0;
+ int i, h;
+
+ /* supervisory frame ? */
+ if (lctx->format == LAPD_FORM_S)
+ s = 1;
+ /* REJ frame ? */
+ if (s && lctx->s_u == LAPD_S_REJ)
+ rej = 1;
+
+ /* Flush all transmit buffers of acknowledged frames */
+ for (i = dl->v_ack; i != nr; i = inc_mod(i, dl->v_range)) {
+ h = do_mod(i, dl->range_hist);
+ if (dl->tx_hist[h].msg) {
+ msgb_free(dl->tx_hist[h].msg);
+ dl->tx_hist[h].msg = NULL;
+ LOGP(DLLAPD, LOGL_INFO, "ack frame %d\n", i);
+ }
+ }
+
+ if (dl->state != LAPD_STATE_TIMER_RECOV) {
+ /* When not in the timer recovery condition, the data
+ * link layer entity shall reset the timer T200 on
+ * receipt of a valid I frame with N(R) higher than V(A),
+ * or an REJ with an N(R) equal to V(A). */
+ if ((!rej && nr != dl->v_ack)
+ || (rej && nr == dl->v_ack)) {
+ t200_reset = 1;
+ lapd_stop_t200(dl);
+ /* 5.5.3.1 Note 1 + 2 imply timer recovery cond. */
+ }
+ /* 5.7.4: N(R) sequence error
+ * N(R) is called valid, if and only if
+ * (N(R)-V(A)) mod 8 <= (V(S)-V(A)) mod 8.
+ */
+ if (sub_mod(nr, dl->v_ack, dl->v_range)
+ > sub_mod(dl->v_send, dl->v_ack, dl->v_range)) {
+ LOGP(DLLAPD, LOGL_NOTICE, "N(R) sequence error\n");
+ mdl_error(MDL_CAUSE_SEQ_ERR, lctx);
+ }
+ }
+
+ /* V(A) shall be set to the value of N(R) */
+ dl->v_ack = nr;
+
+ /* If T200 has been stopped by the receipt of an I, RR or RNR frame,
+ * and if there are outstanding I frames, restart T200 */
+ if (t200_reset && !rej) {
+ if (dl->tx_hist[sub_mod(dl->v_send, 1, dl->range_hist)].msg) {
+ LOGP(DLLAPD, LOGL_INFO, "start T200, due to unacked I "
+ "frame(s)\n");
+ t200_start = 1;
+ lapd_start_t200(dl);
+ }
+ }
+
+ /* This also does a restart, when I or S frame is received */
+
+ /* Stop T203, if running */
+ lapd_stop_t203(dl);
+ /* Start T203, if T200 is not running in MF EST state, if enabled */
+ if (!osmo_timer_pending(&dl->t200)
+ && (dl->t203_sec || dl->t203_usec)
+ && (dl->state == LAPD_STATE_MF_EST)) {
+ lapd_start_t203(dl);
+ }
+}
+
+/* L1 -> L2 */
+
+/* Receive a LAPD U (Unnumbered) message from L1 */
+static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ int length = lctx->length;
+ int rc = 0;
+ uint8_t prim, op;
+
+ switch (lctx->s_u) {
+ case LAPD_U_SABM:
+ case LAPD_U_SABME:
+ prim = PRIM_DL_EST;
+ op = PRIM_OP_INDICATION;
+
+ LOGP(DLLAPD, LOGL_INFO, "SABM(E) received in state %s\n",
+ lapd_state_names[dl->state]);
+ /* 5.7.1 */
+ dl->seq_err_cond = 0;
+ /* G.2.2 Wrong value of the C/R bit */
+ if (lctx->cr == dl->cr.rem2loc.resp) {
+ LOGP(DLLAPD, LOGL_NOTICE, "SABM response error\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
+ return -EINVAL;
+ }
+
+ /* G.4.5 If SABM is received with L>N201 or with M bit
+ * set, AN MDL-ERROR-INDICATION is sent to MM.
+ */
+ if (lctx->more || length > lctx->n201) {
+ LOGP(DLLAPD, LOGL_NOTICE, "SABM too large error\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
+ return -EIO;
+ }
+
+ switch (dl->state) {
+ case LAPD_STATE_IDLE:
+ break;
+ case LAPD_STATE_MF_EST:
+ LOGP(DLLAPD, LOGL_INFO, "SABM command, multiple "
+ "frame established state\n");
+ /* If link is lost on the remote side, we start over
+ * and send DL-ESTABLISH indication again. */
+ if (dl->v_send != dl->v_recv) {
+ LOGP(DLLAPD, LOGL_INFO, "Remote reestablish\n");
+ mdl_error(MDL_CAUSE_SABM_MF, lctx);
+ break;
+ }
+ /* Ignore SABM if content differs from first SABM. */
+ if (dl->mode == LAPD_MODE_NETWORK && length
+ && dl->cont_res) {
+#ifdef TEST_CONTENT_RESOLUTION_NETWORK
+ dl->cont_res->data[0] ^= 0x01;
+#endif
+ if (memcmp(dl->cont_res, msg->data, length)) {
+ LOGP(DLLAPD, LOGL_INFO, "Another SABM "
+ "with diffrent content - "
+ "ignoring!\n");
+ msgb_free(msg);
+ return 0;
+ }
+ }
+ /* send UA again */
+ lapd_send_ua(lctx, length, msg->l3h);
+ msgb_free(msg);
+ return 0;
+ case LAPD_STATE_DISC_SENT:
+ /* 5.4.6.2 send DM with F=P */
+ lapd_send_dm(lctx);
+ /* stop Timer T200 */
+ lapd_stop_t200(dl);
+ msgb_free(msg);
+ return send_dl_simple(prim, op, lctx);
+ default:
+ /* collision: Send UA, but still wait for rx UA, then
+ * change to MF_EST state.
+ */
+ /* check for contention resoultion */
+ if (dl->tx_hist[0].msg && dl->tx_hist[0].msg->len) {
+ LOGP(DLLAPD, LOGL_NOTICE, "SABM not allowed "
+ "during contention resolution\n");
+ mdl_error(MDL_CAUSE_SABM_INFO_NOTALL, lctx);
+ }
+ lapd_send_ua(lctx, length, msg->l3h);
+ msgb_free(msg);
+ return 0;
+ }
+ /* save message context for further use */
+ memcpy(&dl->lctx, lctx, sizeof(dl->lctx));
+#ifndef TEST_CONTENT_RESOLUTION_NETWORK
+ /* send UA response */
+ lapd_send_ua(lctx, length, msg->l3h);
+#endif
+ /* set Vs, Vr and Va to 0 */
+ dl->v_send = dl->v_recv = dl->v_ack = 0;
+ /* clear tx_hist */
+ lapd_dl_flush_hist(dl);
+ /* enter multiple-frame-established state */
+ lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
+ /* store content resolution data on network side
+ * Note: cont_res will be removed when changing state again,
+ * so it must be allocated AFTER lapd_dl_newstate(). */
+ if (dl->mode == LAPD_MODE_NETWORK && length) {
+ dl->cont_res = lapd_msgb_alloc(length, "CONT RES");
+ memcpy(msgb_put(dl->cont_res, length), msg->l3h,
+ length);
+ LOGP(DLLAPD, LOGL_NOTICE, "Store content res.\n");
+ }
+ /* send notification to L3 */
+ if (length == 0) {
+ /* 5.4.1.2 Normal establishment procedures */
+ rc = send_dl_simple(prim, op, lctx);
+ msgb_free(msg);
+ } else {
+ /* 5.4.1.4 Contention resolution establishment */
+ rc = send_dl_l3(prim, op, lctx, msg);
+ }
+ break;
+ case LAPD_U_DM:
+ LOGP(DLLAPD, LOGL_INFO, "DM received in state %s\n",
+ lapd_state_names[dl->state]);
+ /* G.2.2 Wrong value of the C/R bit */
+ if (lctx->cr == dl->cr.rem2loc.cmd) {
+ LOGP(DLLAPD, LOGL_NOTICE, "DM command error\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
+ return -EINVAL;
+ }
+ if (!lctx->p_f) {
+ /* 5.4.1.2 DM responses with the F bit set to "0"
+ * shall be ignored.
+ */
+ msgb_free(msg);
+ return 0;
+ }
+ switch (dl->state) {
+ case LAPD_STATE_SABM_SENT:
+ break;
+ case LAPD_STATE_MF_EST:
+ if (lctx->p_f) {
+ LOGP(DLLAPD, LOGL_INFO, "unsolicited DM "
+ "response\n");
+ mdl_error(MDL_CAUSE_UNSOL_DM_RESP, lctx);
+ } else {
+ LOGP(DLLAPD, LOGL_INFO, "unsolicited DM "
+ "response, multiple frame established "
+ "state\n");
+ mdl_error(MDL_CAUSE_UNSOL_DM_RESP_MF, lctx);
+ /* reestablish */
+ if (!dl->reestablish) {
+ msgb_free(msg);
+ return 0;
+ }
+ LOGP(DLLAPD, LOGL_NOTICE, "Performing "
+ "reestablishment.\n");
+ lapd_reestablish(dl);
+ }
+ msgb_free(msg);
+ return 0;
+ case LAPD_STATE_TIMER_RECOV:
+ /* FP = 0 (DM is normal in case PF = 1) */
+ if (!lctx->p_f) {
+ LOGP(DLLAPD, LOGL_INFO, "unsolicited DM "
+ "response, multiple frame established "
+ "state\n");
+ mdl_error(MDL_CAUSE_UNSOL_DM_RESP_MF, lctx);
+ msgb_free(msg);
+ /* reestablish */
+ if (!dl->reestablish)
+ return 0;
+ LOGP(DLLAPD, LOGL_NOTICE, "Performing "
+ "reestablishment.\n");
+ return lapd_reestablish(dl);
+ }
+ break;
+ case LAPD_STATE_DISC_SENT:
+ /* stop Timer T200 */
+ lapd_stop_t200(dl);
+ /* go to idle state */
+ lapd_dl_flush_tx(dl);
+ lapd_dl_flush_send(dl);
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+ rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, lctx);
+ msgb_free(msg);
+ return 0;
+ case LAPD_STATE_IDLE:
+ /* 5.4.5 all other frame types shall be discarded */
+ default:
+ LOGP(DLLAPD, LOGL_INFO, "unsolicited DM response! "
+ "(discarding)\n");
+ msgb_free(msg);
+ return 0;
+ }
+ /* stop timer T200 */
+ lapd_stop_t200(dl);
+ /* go to idle state */
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+ rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION, lctx);
+ msgb_free(msg);
+ break;
+ case LAPD_U_UI:
+ LOGP(DLLAPD, LOGL_INFO, "UI received\n");
+ /* G.2.2 Wrong value of the C/R bit */
+ if (lctx->cr == dl->cr.rem2loc.resp) {
+ LOGP(DLLAPD, LOGL_NOTICE, "UI indicates response "
+ "error\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
+ return -EINVAL;
+ }
+
+ /* G.4.5 If UI is received with L>N201 or with M bit
+ * set, AN MDL-ERROR-INDICATION is sent to MM.
+ */
+ if (length > lctx->n201 || lctx->more) {
+ LOGP(DLLAPD, LOGL_NOTICE, "UI too large error "
+ "(%d > N201(%d) or M=%d)\n", length,
+ lctx->n201, lctx->more);
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
+ return -EIO;
+ }
+
+ /* do some length checks */
+ if (length == 0) {
+ /* 5.3.3 UI frames received with the length indicator
+ * set to "0" shall be ignored
+ */
+ LOGP(DLLAPD, LOGL_INFO, "length=0 (discarding)\n");
+ msgb_free(msg);
+ return 0;
+ }
+ rc = send_dl_l3(PRIM_DL_UNIT_DATA, PRIM_OP_INDICATION, lctx,
+ msg);
+ break;
+ case LAPD_U_DISC:
+ prim = PRIM_DL_REL;
+ op = PRIM_OP_INDICATION;
+
+ LOGP(DLLAPD, LOGL_INFO, "DISC received in state %s\n",
+ lapd_state_names[dl->state]);
+ /* flush tx and send buffers */
+ lapd_dl_flush_tx(dl);
+ lapd_dl_flush_send(dl);
+ /* 5.7.1 */
+ dl->seq_err_cond = 0;
+ /* G.2.2 Wrong value of the C/R bit */
+ if (lctx->cr == dl->cr.rem2loc.resp) {
+ LOGP(DLLAPD, LOGL_NOTICE, "DISC response error\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
+ return -EINVAL;
+ }
+ if (length > 0 || lctx->more) {
+ /* G.4.4 If a DISC or DM frame is received with L>0 or
+ * with the M bit set to "1", an MDL-ERROR-INDICATION
+ * primitive with cause "U frame with incorrect
+ * parameters" is sent to the mobile management entity.
+ */
+ LOGP(DLLAPD, LOGL_NOTICE,
+ "U frame iwth incorrect parameters ");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
+ return -EIO;
+ }
+ switch (dl->state) {
+ case LAPD_STATE_IDLE:
+ LOGP(DLLAPD, LOGL_INFO, "DISC in idle state\n");
+ /* send DM with F=P */
+ msgb_free(msg);
+ return lapd_send_dm(lctx);
+ case LAPD_STATE_SABM_SENT:
+ LOGP(DLLAPD, LOGL_INFO, "DISC in SABM state\n");
+ /* 5.4.6.2 send DM with F=P */
+ lapd_send_dm(lctx);
+ /* stop Timer T200 */
+ lapd_stop_t200(dl);
+ /* go to idle state */
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+ msgb_free(msg);
+ return send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION,
+ lctx);
+ case LAPD_STATE_MF_EST:
+ case LAPD_STATE_TIMER_RECOV:
+ LOGP(DLLAPD, LOGL_INFO, "DISC in est state\n");
+ break;
+ case LAPD_STATE_DISC_SENT:
+ LOGP(DLLAPD, LOGL_INFO, "DISC in disc state\n");
+ prim = PRIM_DL_REL;
+ op = PRIM_OP_CONFIRM;
+ break;
+ default:
+ lapd_send_ua(lctx, length, msg->l3h);
+ msgb_free(msg);
+ return 0;
+ }
+ /* send UA response */
+ lapd_send_ua(lctx, length, msg->l3h);
+ /* stop Timer T200 */
+ lapd_stop_t200(dl);
+ /* enter idle state, keep tx-buffer with UA response */
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+ /* send notification to L3 */
+ rc = send_dl_simple(prim, op, lctx);
+ msgb_free(msg);
+ break;
+ case LAPD_U_UA:
+ LOGP(DLLAPD, LOGL_INFO, "UA received in state %s\n",
+ lapd_state_names[dl->state]);
+ /* G.2.2 Wrong value of the C/R bit */
+ if (lctx->cr == dl->cr.rem2loc.cmd) {
+ LOGP(DLLAPD, LOGL_NOTICE, "UA indicates command "
+ "error\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
+ return -EINVAL;
+ }
+
+ /* G.4.5 If UA is received with L>N201 or with M bit
+ * set, AN MDL-ERROR-INDICATION is sent to MM.
+ */
+ if (lctx->more || length > lctx->n201) {
+ LOGP(DLLAPD, LOGL_NOTICE, "UA too large error\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
+ return -EIO;
+ }
+
+ if (!lctx->p_f) {
+ /* 5.4.1.2 A UA response with the F bit set to "0"
+ * shall be ignored.
+ */
+ LOGP(DLLAPD, LOGL_INFO, "F=0 (discarding)\n");
+ msgb_free(msg);
+ return 0;
+ }
+ switch (dl->state) {
+ case LAPD_STATE_SABM_SENT:
+ break;
+ case LAPD_STATE_MF_EST:
+ case LAPD_STATE_TIMER_RECOV:
+ LOGP(DLLAPD, LOGL_INFO, "unsolicited UA response! "
+ "(discarding)\n");
+ mdl_error(MDL_CAUSE_UNSOL_UA_RESP, lctx);
+ msgb_free(msg);
+ return 0;
+ case LAPD_STATE_DISC_SENT:
+ LOGP(DLLAPD, LOGL_INFO, "UA in disconnect state\n");
+ /* stop Timer T200 */
+ lapd_stop_t200(dl);
+ /* go to idle state */
+ lapd_dl_flush_tx(dl);
+ lapd_dl_flush_send(dl);
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+ rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, lctx);
+ msgb_free(msg);
+ return 0;
+ case LAPD_STATE_IDLE:
+ /* 5.4.5 all other frame types shall be discarded */
+ default:
+ LOGP(DLLAPD, LOGL_INFO, "unsolicited UA response! "
+ "(discarding)\n");
+ msgb_free(msg);
+ return 0;
+ }
+ LOGP(DLLAPD, LOGL_INFO, "UA in SABM state\n");
+ /* stop Timer T200 */
+ lapd_stop_t200(dl);
+ /* compare UA with SABME if contention resolution is applied */
+ if (dl->tx_hist[0].msg->len) {
+ if (length != (dl->tx_hist[0].msg->len)
+ || !!memcmp(dl->tx_hist[0].msg->data, msg->l3h,
+ length)) {
+ LOGP(DLLAPD, LOGL_INFO, "**** UA response "
+ "mismatches ****\n");
+ rc = send_dl_simple(PRIM_DL_REL,
+ PRIM_OP_INDICATION, lctx);
+ msgb_free(msg);
+ /* go to idle state */
+ lapd_dl_flush_tx(dl);
+ lapd_dl_flush_send(dl);
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+ return 0;
+ }
+ }
+ /* set Vs, Vr and Va to 0 */
+ dl->v_send = dl->v_recv = dl->v_ack = 0;
+ /* clear tx_hist */
+ lapd_dl_flush_hist(dl);
+ /* enter multiple-frame-established state */
+ lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
+ /* send outstanding frames, if any (resume / reconnect) */
+ lapd_send_i(lctx, __LINE__);
+ /* send notification to L3 */
+ rc = send_dl_simple(PRIM_DL_EST, PRIM_OP_CONFIRM, lctx);
+ msgb_free(msg);
+ break;
+ case LAPD_U_FRMR:
+ LOGP(DLLAPD, LOGL_NOTICE, "Frame reject received\n");
+ /* send MDL ERROR INIDCATION to L3 */
+ mdl_error(MDL_CAUSE_FRMR, lctx);
+ msgb_free(msg);
+ /* reestablish */
+ if (!dl->reestablish)
+ break;
+ LOGP(DLLAPD, LOGL_NOTICE, "Performing reestablishment.\n");
+ rc = lapd_reestablish(dl);
+ break;
+ default:
+ /* G.3.1 */
+ LOGP(DLLAPD, LOGL_NOTICE, "Unnumbered frame not allowed.\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
+ return -EINVAL;
+ }
+ return rc;
+}
+
+/* Receive a LAPD S (Supervisory) message from L1 */
+static int lapd_rx_s(struct msgb *msg, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ int length = lctx->length;
+
+ if (length > 0 || lctx->more) {
+ /* G.4.3 If a supervisory frame is received with L>0 or
+ * with the M bit set to "1", an MDL-ERROR-INDICATION
+ * primitive with cause "S frame with incorrect
+ * parameters" is sent to the mobile management entity. */
+ LOGP(DLLAPD, LOGL_NOTICE,
+ "S frame with incorrect parameters\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_SFRM_INC_PARAM, lctx);
+ return -EIO;
+ }
+
+ if (lctx->cr == dl->cr.rem2loc.resp
+ && lctx->p_f
+ && dl->state != LAPD_STATE_TIMER_RECOV) {
+ /* 5.4.2.2: Inidcate error on supervisory reponse F=1 */
+ LOGP(DLLAPD, LOGL_NOTICE, "S frame response with F=1 error\n");
+ mdl_error(MDL_CAUSE_UNSOL_SPRV_RESP, lctx);
+ }
+
+ switch (dl->state) {
+ case LAPD_STATE_IDLE:
+ /* if P=1, respond DM with F=1 (5.2.2) */
+ /* 5.4.5 all other frame types shall be discarded */
+ if (lctx->p_f)
+ lapd_send_dm(lctx); /* F=P */
+ /* fall though */
+ case LAPD_STATE_SABM_SENT:
+ case LAPD_STATE_DISC_SENT:
+ LOGP(DLLAPD, LOGL_NOTICE, "S frame ignored in this state\n");
+ msgb_free(msg);
+ return 0;
+ }
+ switch (lctx->s_u) {
+ case LAPD_S_RR:
+ LOGP(DLLAPD, LOGL_INFO, "RR received in state %s\n",
+ lapd_state_names[dl->state]);
+ /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
+ lapd_acknowledge(lctx);
+
+ /* 5.5.3.2 */
+ if (lctx->cr == dl->cr.rem2loc.cmd
+ && lctx->p_f) {
+ if (!dl->own_busy && !dl->seq_err_cond) {
+ LOGP(DLLAPD, LOGL_INFO, "RR frame command "
+ "with polling bit set and we are not "
+ "busy, so we reply with RR frame "
+ "response\n");
+ lapd_send_rr(lctx, 1, 0);
+ /* NOTE: In case of sequence error condition,
+ * the REJ frame has been transmitted when
+ * entering the condition, so it has not be
+ * done here
+ */
+ } else if (dl->own_busy) {
+ LOGP(DLLAPD, LOGL_INFO, "RR frame command "
+ "with polling bit set and we are busy, "
+ "so we reply with RR frame response\n");
+ lapd_send_rnr(lctx, 1, 0);
+ }
+ } else if (lctx->cr == dl->cr.rem2loc.resp
+ && lctx->p_f
+ && dl->state == LAPD_STATE_TIMER_RECOV) {
+ LOGP(DLLAPD, LOGL_INFO, "RR response with F==1, "
+ "and we are in timer recovery state, so "
+ "we leave that state\n");
+ /* V(S) to the N(R) in the RR frame */
+ dl->v_send = lctx->n_recv;
+ /* stop Timer T200 */
+ lapd_stop_t200(dl);
+ /* 5.5.7 Clear timer recovery condition */
+ lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
+ }
+ /* Send message, if possible due to acknowledged data */
+ lapd_send_i(lctx, __LINE__);
+
+ break;
+ case LAPD_S_RNR:
+ LOGP(DLLAPD, LOGL_INFO, "RNR received in state %s\n",
+ lapd_state_names[dl->state]);
+ /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
+ lapd_acknowledge(lctx);
+
+ /* 5.5.5 */
+ /* Set peer receiver busy condition */
+ dl->peer_busy = 1;
+
+ if (lctx->p_f) {
+ if (lctx->cr == dl->cr.rem2loc.cmd) {
+ if (!dl->own_busy) {
+ LOGP(DLLAPD, LOGL_INFO, "RNR poll "
+ "command and we are not busy, "
+ "so we reply with RR final "
+ "response\n");
+ /* Send RR with F=1 */
+ lapd_send_rr(lctx, 1, 0);
+ } else {
+ LOGP(DLLAPD, LOGL_INFO, "RNR poll "
+ "command and we are busy, so "
+ "we reply with RNR final "
+ "response\n");
+ /* Send RNR with F=1 */
+ lapd_send_rnr(lctx, 1, 0);
+ }
+ } else if (dl->state == LAPD_STATE_TIMER_RECOV) {
+ LOGP(DLLAPD, LOGL_INFO, "RNR poll response "
+ "and we in timer recovery state, so "
+ "we leave that state\n");
+ /* 5.5.7 Clear timer recovery condition */
+ lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
+ /* V(S) to the N(R) in the RNR frame */
+ dl->v_send = lctx->n_recv;
+ }
+ } else
+ LOGP(DLLAPD, LOGL_INFO, "RNR not polling/final state "
+ "received\n");
+
+ /* Send message, if possible due to acknowledged data */
+ lapd_send_i(lctx, __LINE__);
+
+ break;
+ case LAPD_S_REJ:
+ LOGP(DLLAPD, LOGL_INFO, "REJ received in state %s\n",
+ lapd_state_names[dl->state]);
+ /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
+ lapd_acknowledge(lctx);
+
+ /* 5.5.4.1 */
+ if (dl->state != LAPD_STATE_TIMER_RECOV) {
+ /* Clear an existing peer receiver busy condition */
+ dl->peer_busy = 0;
+ /* V(S) and V(A) to the N(R) in the REJ frame */
+ dl->v_send = dl->v_ack = lctx->n_recv;
+ /* stop Timer T200 */
+ lapd_stop_t200(dl);
+ /* 5.5.3.2 */
+ if (lctx->cr == dl->cr.rem2loc.cmd && lctx->p_f) {
+ if (!dl->own_busy && !dl->seq_err_cond) {
+ LOGP(DLLAPD, LOGL_INFO, "REJ poll "
+ "command not in timer recovery "
+ "state and not in own busy "
+ "condition received, so we "
+ "respond with RR final "
+ "response\n");
+ lapd_send_rr(lctx, 1, 0);
+ /* NOTE: In case of sequence error
+ * condition, the REJ frame has been
+ * transmitted when entering the
+ * condition, so it has not be done
+ * here
+ */
+ } else if (dl->own_busy) {
+ LOGP(DLLAPD, LOGL_INFO, "REJ poll "
+ "command not in timer recovery "
+ "state and in own busy "
+ "condition received, so we "
+ "respond with RNR final "
+ "response\n");
+ lapd_send_rnr(lctx, 1, 0);
+ }
+ } else
+ LOGP(DLLAPD, LOGL_INFO, "REJ response or not "
+ "polling command not in timer recovery "
+ "state received\n");
+ /* send MDL ERROR INIDCATION to L3 */
+ if (lctx->cr == dl->cr.rem2loc.resp && lctx->p_f) {
+ mdl_error(MDL_CAUSE_UNSOL_SPRV_RESP, lctx);
+ }
+
+ } else if (lctx->cr == dl->cr.rem2loc.resp && lctx->p_f) {
+ LOGP(DLLAPD, LOGL_INFO, "REJ poll response in timer "
+ "recovery state received\n");
+ /* Clear an existing peer receiver busy condition */
+ dl->peer_busy = 0;
+ /* V(S) and V(A) to the N(R) in the REJ frame */
+ dl->v_send = dl->v_ack = lctx->n_recv;
+ /* stop Timer T200 */
+ lapd_stop_t200(dl);
+ /* 5.5.7 Clear timer recovery condition */
+ lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
+ } else {
+ /* Clear an existing peer receiver busy condition */
+ dl->peer_busy = 0;
+ /* V(S) and V(A) to the N(R) in the REJ frame */
+ dl->v_send = dl->v_ack = lctx->n_recv;
+ /* 5.5.3.2 */
+ if (lctx->cr == dl->cr.rem2loc.cmd && lctx->p_f) {
+ if (!dl->own_busy && !dl->seq_err_cond) {
+ LOGP(DLLAPD, LOGL_INFO, "REJ poll "
+ "command in timer recovery "
+ "state and not in own busy "
+ "condition received, so we "
+ "respond with RR final "
+ "response\n");
+ lapd_send_rr(lctx, 1, 0);
+ /* NOTE: In case of sequence error
+ * condition, the REJ frame has been
+ * transmitted when entering the
+ * condition, so it has not be done
+ * here
+ */
+ } else if (dl->own_busy) {
+ LOGP(DLLAPD, LOGL_INFO, "REJ poll "
+ "command in timer recovery "
+ "state and in own busy "
+ "condition received, so we "
+ "respond with RNR final "
+ "response\n");
+ lapd_send_rnr(lctx, 1, 0);
+ }
+ } else
+ LOGP(DLLAPD, LOGL_INFO, "REJ response or not "
+ "polling command in timer recovery "
+ "state received\n");
+ }
+
+ /* FIXME: 5.5.4.2 2) */
+
+ /* Send message, if possible due to acknowledged data */
+ lapd_send_i(lctx, __LINE__);
+
+ break;
+ default:
+ /* G.3.1 */
+ LOGP(DLLAPD, LOGL_NOTICE, "Supervisory frame not allowed.\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
+ return -EINVAL;
+ }
+ msgb_free(msg);
+ return 0;
+}
+
+/* Receive a LAPD I (Information) message from L1 */
+static int lapd_rx_i(struct msgb *msg, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ //uint8_t nr = lctx->n_recv;
+ uint8_t ns = lctx->n_send;
+ int length = lctx->length;
+ int rc;
+
+ LOGP(DLLAPD, LOGL_INFO, "I received in state %s\n",
+ lapd_state_names[dl->state]);
+
+ /* G.2.2 Wrong value of the C/R bit */
+ if (lctx->cr == dl->cr.rem2loc.resp) {
+ LOGP(DLLAPD, LOGL_NOTICE, "I frame response not allowed\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
+ return -EINVAL;
+ }
+
+ if (length == 0 || length > lctx->n201) {
+ /* G.4.2 If the length indicator of an I frame is set
+ * to a numerical value L>N201 or L=0, an MDL-ERROR-INDICATION
+ * primitive with cause "I frame with incorrect length"
+ * is sent to the mobile management entity. */
+ LOGP(DLLAPD, LOGL_NOTICE, "I frame length not allowed\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_IFRM_INC_LEN, lctx);
+ return -EIO;
+ }
+
+ /* G.4.2 If the numerical value of L is L<N201 and the M
+ * bit is set to "1", then an MDL-ERROR-INDICATION primitive with
+ * cause "I frame with incorrect use of M bit" is sent to the
+ * mobile management entity. */
+ if (lctx->more && length < lctx->n201) {
+ LOGP(DLLAPD, LOGL_NOTICE, "I frame with M bit too short\n");
+ msgb_free(msg);
+ mdl_error(MDL_CAUSE_IFRM_INC_MBITS, lctx);
+ return -EIO;
+ }
+
+ switch (dl->state) {
+ case LAPD_STATE_IDLE:
+ /* if P=1, respond DM with F=1 (5.2.2) */
+ /* 5.4.5 all other frame types shall be discarded */
+ if (lctx->p_f)
+ lapd_send_dm(lctx); /* F=P */
+ /* fall though */
+ case LAPD_STATE_SABM_SENT:
+ case LAPD_STATE_DISC_SENT:
+ LOGP(DLLAPD, LOGL_NOTICE, "I frame ignored in this state\n");
+ msgb_free(msg);
+ return 0;
+ }
+
+ /* 5.7.1: N(s) sequence error */
+ if (ns != dl->v_recv) {
+ LOGP(DLLAPD, LOGL_NOTICE, "N(S) sequence error: N(S)=%u, "
+ "V(R)=%u\n", ns, dl->v_recv);
+ /* discard data */
+ msgb_free(msg);
+ if (dl->seq_err_cond != 1) {
+ /* FIXME: help me understand what exactly todo here
+ */
+ dl->seq_err_cond = 1;
+ lapd_send_rej(lctx, lctx->p_f);
+ } else {
+ /* If there are two subsequent sequence errors received,
+ * ignore it. (Ignore every second subsequent error.)
+ * This happens if our reply with the REJ is too slow,
+ * so the remote gets a T200 timeout and sends another
+ * frame with a sequence error.
+ * Test showed that replying with two subsequent REJ
+ * messages could the remote L2 process to abort.
+ * Replying too slow shouldn't happen, but may happen
+ * over serial link between BB and LAPD.
+ */
+ dl->seq_err_cond = 2;
+ }
+ /* Even if N(s) sequence error, acknowledge to N(R)-1 */
+ /* 5.5.3.1: Acknowlege all transmitted frames up the N(R)-1 */
+ lapd_acknowledge(lctx); /* V(A) is also set here */
+
+ /* Send message, if possible due to acknowledged data */
+ lapd_send_i(lctx, __LINE__);
+
+ return 0;
+ }
+ dl->seq_err_cond = 0;
+
+ /* Increment receiver state */
+ dl->v_recv = inc_mod(dl->v_recv, dl->v_range);
+ LOGP(DLLAPD, LOGL_INFO, "incrementing V(R) to %u\n", dl->v_recv);
+
+ /* 5.5.3.1: Acknowlege all transmitted frames up the the N(R)-1 */
+ lapd_acknowledge(lctx); /* V(A) is also set here */
+
+ /* Only if we are not in own receiver busy condition */
+ if (!dl->own_busy) {
+ /* if the frame carries a complete segment */
+ if (!lctx->more && !dl->rcv_buffer) {
+ LOGP(DLLAPD, LOGL_INFO, "message in single I frame\n");
+ /* send a DATA INDICATION to L3 */
+ msg->len = length;
+ msg->tail = msg->data + length;
+ rc = send_dl_l3(PRIM_DL_DATA, PRIM_OP_INDICATION, lctx,
+ msg);
+ } else {
+ /* create rcv_buffer */
+ if (!dl->rcv_buffer) {
+ LOGP(DLLAPD, LOGL_INFO, "message in multiple "
+ "I frames (first message)\n");
+ dl->rcv_buffer = lapd_msgb_alloc(dl->maxf,
+ "LAPD RX");
+ dl->rcv_buffer->l3h = dl->rcv_buffer->data;
+ }
+ /* concat. rcv_buffer */
+ if (msgb_l3len(dl->rcv_buffer) + length > dl->maxf) {
+ LOGP(DLLAPD, LOGL_NOTICE, "Received frame "
+ "overflow!\n");
+ } else {
+ memcpy(msgb_put(dl->rcv_buffer, length),
+ msg->l3h, length);
+ }
+ /* if the last segment was received */
+ if (!lctx->more) {
+ LOGP(DLLAPD, LOGL_INFO, "message in multiple "
+ "I frames (last message)\n");
+ rc = send_dl_l3(PRIM_DL_DATA,
+ PRIM_OP_INDICATION, lctx,
+ dl->rcv_buffer);
+ dl->rcv_buffer = NULL;
+ } else
+ LOGP(DLLAPD, LOGL_INFO, "message in multiple "
+ "I frames (next message)\n");
+ msgb_free(msg);
+
+ }
+ } else
+ LOGP(DLLAPD, LOGL_INFO, "I frame ignored during own receiver "
+ "busy condition\n");
+
+ /* Check for P bit */
+ if (lctx->p_f) {
+ /* 5.5.2.1 */
+ /* check if we are not in own receiver busy */
+ if (!dl->own_busy) {
+ LOGP(DLLAPD, LOGL_INFO, "we are not busy, send RR\n");
+ /* Send RR with F=1 */
+ rc = lapd_send_rr(lctx, 1, 0);
+ } else {
+ LOGP(DLLAPD, LOGL_INFO, "we are busy, send RNR\n");
+ /* Send RNR with F=1 */
+ rc = lapd_send_rnr(lctx, 1, 0);
+ }
+ } else {
+ /* 5.5.2.2 */
+ /* check if we are not in own receiver busy */
+ if (!dl->own_busy) {
+ /* NOTE: V(R) is already set above */
+ rc = lapd_send_i(lctx, __LINE__);
+ if (rc) {
+ LOGP(DLLAPD, LOGL_INFO, "we are not busy and "
+ "have no pending data, send RR\n");
+ /* Send RR with F=0 */
+ return lapd_send_rr(lctx, 0, 0);
+ }
+ /* all I or one RR is sent, we are done */
+ return 0;
+ } else {
+ LOGP(DLLAPD, LOGL_INFO, "we are busy, send RNR\n");
+ /* Send RNR with F=0 */
+ rc = lapd_send_rnr(lctx, 0, 0);
+ }
+ }
+
+ /* Send message, if possible due to acknowledged data */
+ lapd_send_i(lctx, __LINE__);
+
+ return rc;
+}
+
+/* Receive a LAPD message from L1 */
+int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx)
+{
+ int rc;
+
+ switch (lctx->format) {
+ case LAPD_FORM_U:
+ rc = lapd_rx_u(msg, lctx);
+ break;
+ case LAPD_FORM_S:
+ rc = lapd_rx_s(msg, lctx);
+ break;
+ case LAPD_FORM_I:
+ rc = lapd_rx_i(msg, lctx);
+ break;
+ default:
+ LOGP(DLLAPD, LOGL_NOTICE, "unknown LAPD format\n");
+ msgb_free(msg);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+/* L3 -> L2 */
+
+/* send unit data */
+static int lapd_udata_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ struct msgb *msg = dp->oph.msg;
+ struct lapd_msg_ctx nctx;
+
+ memcpy(&nctx, lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.cmd;
+ nctx.format = LAPD_FORM_U;
+ nctx.s_u = LAPD_U_UI;
+ /* keep nctx.p_f */
+ nctx.length = msg->len;
+ nctx.more = 0;
+
+ return dl->send_ph_data_req(&nctx, msg);
+}
+
+/* request link establishment */
+static int lapd_est_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ struct msgb *msg = dp->oph.msg;
+ struct lapd_msg_ctx nctx;
+
+ if (msg->len)
+ LOGP(DLLAPD, LOGL_INFO, "perform establishment with content "
+ "(SABM)\n");
+ else
+ LOGP(DLLAPD, LOGL_INFO, "perform normal establishm. (SABM)\n");
+
+ /* Flush send-queue */
+ /* Clear send-buffer */
+ lapd_dl_flush_send(dl);
+ /* be sure that history is empty */
+ lapd_dl_flush_hist(dl);
+
+ /* save message context for further use */
+ memcpy(&dl->lctx, lctx, sizeof(dl->lctx));
+
+ /* Discard partly received L3 message */
+ if (dl->rcv_buffer) {
+ msgb_free(dl->rcv_buffer);
+ dl->rcv_buffer = NULL;
+ }
+
+ /* assemble message */
+ memcpy(&nctx, &dl->lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.cmd;
+ nctx.format = LAPD_FORM_U;
+ nctx.s_u = (dl->use_sabme) ? LAPD_U_SABME : LAPD_U_SABM;
+ nctx.p_f = 1;
+ nctx.length = msg->len;
+ nctx.more = 0;
+
+ /* Transmit-buffer carries exactly one segment */
+ dl->tx_hist[0].msg = lapd_msgb_alloc(msg->len, "HIST");
+ msgb_put(dl->tx_hist[0].msg, msg->len);
+ if (msg->len)
+ memcpy(dl->tx_hist[0].msg->data, msg->l3h, msg->len);
+ dl->tx_hist[0].more = 0;
+ /* set Vs to 0, because it is used as index when resending SABM */
+ dl->v_send = 0;
+
+ /* Set states */
+ dl->own_busy = dl->peer_busy = 0;
+ dl->retrans_ctr = 0;
+ lapd_dl_newstate(dl, LAPD_STATE_SABM_SENT);
+
+ /* Tramsmit and start T200 */
+ dl->send_ph_data_req(&nctx, msg);
+ lapd_start_t200(dl);
+
+ return 0;
+}
+
+/* send data */
+static int lapd_data_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ struct msgb *msg = dp->oph.msg;
+
+ if (msgb_l3len(msg) == 0) {
+ LOGP(DLLAPD, LOGL_ERROR,
+ "writing an empty message is not possible.\n");
+ msgb_free(msg);
+ return -1;
+ }
+
+ LOGP(DLLAPD, LOGL_INFO,
+ "writing message to send-queue: l3len: %d\n", msgb_l3len(msg));
+
+ /* Write data into the send queue */
+ msgb_enqueue(&dl->send_queue, msg);
+
+ /* Send message, if possible */
+ lapd_send_i(&dl->lctx, __LINE__);
+
+ return 0;
+}
+
+/* Send next I frame from queued/buffered data */
+static int lapd_send_i(struct lapd_msg_ctx *lctx, int line)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ uint8_t k = dl->k;
+ uint8_t h;
+ struct msgb *msg;
+ int length, left;
+ int rc = - 1; /* we sent nothing */
+ struct lapd_msg_ctx nctx;
+
+
+ LOGP(DLLAPD, LOGL_INFO, "%s() called from line %d\n", __func__, line);
+
+ next_frame:
+
+ if (dl->peer_busy) {
+ LOGP(DLLAPD, LOGL_INFO, "peer busy, not sending\n");
+ return rc;
+ }
+
+ if (dl->state == LAPD_STATE_TIMER_RECOV) {
+ LOGP(DLLAPD, LOGL_INFO, "timer recovery, not sending\n");
+ return rc;
+ }
+
+ /* If the send state variable V(S) is equal to V(A) plus k
+ * (where k is the maximum number of outstanding I frames - see
+ * subclause 5.8.4), the data link layer entity shall not transmit any
+ * new I frames, but shall retransmit an I frame as a result
+ * of the error recovery procedures as described in subclauses 5.5.4 and
+ * 5.5.7. */
+ if (dl->v_send == add_mod(dl->v_ack, k, dl->v_range)) {
+ LOGP(DLLAPD, LOGL_INFO, "k frames outstanding, not sending "
+ "more (k=%u V(S)=%u V(A)=%u)\n", k, dl->v_send,
+ dl->v_ack);
+ return rc;
+ }
+
+ h = do_mod(dl->v_send, dl->range_hist);
+
+ /* if we have no tx_hist yet, we create it */
+ if (!dl->tx_hist[h].msg) {
+ /* Get next message into send-buffer, if any */
+ if (!dl->send_buffer) {
+ next_message:
+ dl->send_out = 0;
+ dl->send_buffer = msgb_dequeue(&dl->send_queue);
+ /* No more data to be sent */
+ if (!dl->send_buffer)
+ return rc;
+ LOGP(DLLAPD, LOGL_INFO, "get message from "
+ "send-queue\n");
+ }
+
+ /* How much is left in the send-buffer? */
+ left = msgb_l3len(dl->send_buffer) - dl->send_out;
+ /* Segment, if data exceeds N201 */
+ length = left;
+ if (length > lctx->n201)
+ length = lctx->n201;
+ LOGP(DLLAPD, LOGL_INFO, "msg-len %d sent %d left %d N201 %d "
+ "length %d first byte %02x\n",
+ msgb_l3len(dl->send_buffer), dl->send_out, left,
+ lctx->n201, length, dl->send_buffer->l3h[0]);
+ /* If message in send-buffer is completely sent */
+ if (left == 0) {
+ msgb_free(dl->send_buffer);
+ dl->send_buffer = NULL;
+ goto next_message;
+ }
+
+ LOGP(DLLAPD, LOGL_INFO, "send I frame %sV(S)=%d\n",
+ (left > length) ? "segment " : "", dl->v_send);
+
+ /* Create I frame (segment) and transmit-buffer content */
+ msg = lapd_msgb_alloc(length, "LAPD I");
+ msg->l3h = msgb_put(msg, length);
+ /* assemble message */
+ memcpy(&nctx, &dl->lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.cmd;
+ nctx.format = LAPD_FORM_I;
+ nctx.p_f = 0;
+ nctx.n_send = dl->v_send;
+ nctx.n_recv = dl->v_recv;
+ nctx.length = length;
+ if (left > length)
+ nctx.more = 1;
+ else
+ nctx.more = 0;
+ if (length)
+ memcpy(msg->l3h, dl->send_buffer->l3h + dl->send_out,
+ length);
+ /* store in tx_hist */
+ dl->tx_hist[h].msg = lapd_msgb_alloc(msg->len, "HIST");
+ msgb_put(dl->tx_hist[h].msg, msg->len);
+ if (length)
+ memcpy(dl->tx_hist[h].msg->data, msg->l3h, msg->len);
+ dl->tx_hist[h].more = nctx.more;
+ /* Add length to track how much is already in the tx buffer */
+ dl->send_out += length;
+ } else {
+ LOGP(DLLAPD, LOGL_INFO, "resend I frame from tx buffer "
+ "V(S)=%d\n", dl->v_send);
+
+ /* Create I frame (segment) from tx_hist */
+ length = dl->tx_hist[h].msg->len;
+ msg = lapd_msgb_alloc(length, "LAPD I resend");
+ msg->l3h = msgb_put(msg, length);
+ /* assemble message */
+ memcpy(&nctx, &dl->lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.cmd;
+ nctx.format = LAPD_FORM_I;
+ nctx.p_f = 0;
+ nctx.n_send = dl->v_send;
+ nctx.n_recv = dl->v_recv;
+ nctx.length = length;
+ nctx.more = dl->tx_hist[h].more;
+ if (length)
+ memcpy(msg->l3h, dl->tx_hist[h].msg->data, length);
+ }
+
+ /* The value of the send state variable V(S) shall be incremented by 1
+ * at the end of the transmission of the I frame */
+ dl->v_send = inc_mod(dl->v_send, dl->v_range);
+
+ /* If timer T200 is not running at the time right before transmitting a
+ * frame, when the PH-READY-TO-SEND primitive is received from the
+ * physical layer., it shall be set. */
+ if (!osmo_timer_pending(&dl->t200)) {
+ /* stop Timer T203, if running */
+ lapd_stop_t203(dl);
+ /* start Timer T200 */
+ lapd_start_t200(dl);
+ }
+
+ dl->send_ph_data_req(&nctx, msg);
+
+ rc = 0; /* we sent something */
+ goto next_frame;
+}
+
+/* request link suspension */
+static int lapd_susp_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ struct msgb *msg = dp->oph.msg;
+
+ LOGP(DLLAPD, LOGL_INFO, "perform suspension\n");
+
+ /* put back the send-buffer to the send-queue (first position) */
+ if (dl->send_buffer) {
+ LOGP(DLLAPD, LOGL_INFO, "put frame in sendbuffer back to "
+ "queue\n");
+ llist_add(&dl->send_buffer->list, &dl->send_queue);
+ dl->send_buffer = NULL;
+ } else
+ LOGP(DLLAPD, LOGL_INFO, "no frame in sendbuffer\n");
+
+ /* Clear transmit buffer, but keep send buffer */
+ lapd_dl_flush_tx(dl);
+ /* Stop timers (there is no state change, so we must stop all timers */
+ lapd_stop_t200(dl);
+ lapd_stop_t203(dl);
+
+ msgb_free(msg);
+
+ return send_dl_simple(PRIM_DL_SUSP, PRIM_OP_CONFIRM, &dl->lctx);
+}
+
+/* requesst resume or reconnect of link */
+static int lapd_res_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ struct msgb *msg = dp->oph.msg;
+ struct lapd_msg_ctx nctx;
+
+ LOGP(DLLAPD, LOGL_INFO, "perform re-establishment (SABM) length=%d\n",
+ msg->len);
+
+ /* be sure that history is empty */
+ lapd_dl_flush_hist(dl);
+
+ /* save message context for further use */
+ memcpy(&dl->lctx, lctx, sizeof(dl->lctx));
+
+ /* Replace message in the send-buffer (reconnect) */
+ if (dl->send_buffer)
+ msgb_free(dl->send_buffer);
+ dl->send_out = 0;
+ if (msg && msg->len)
+ /* Write data into the send buffer, to be sent first */
+ dl->send_buffer = msg;
+ else
+ dl->send_buffer = NULL;
+
+ /* Discard partly received L3 message */
+ if (dl->rcv_buffer) {
+ msgb_free(dl->rcv_buffer);
+ dl->rcv_buffer = NULL;
+ }
+
+ /* Create new msgb (old one is now free) */
+ msg = lapd_msgb_alloc(0, "LAPD SABM");
+ msg->l3h = msg->data;
+ /* assemble message */
+ memcpy(&nctx, &dl->lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.cmd;
+ nctx.format = LAPD_FORM_U;
+ nctx.s_u = (dl->use_sabme) ? LAPD_U_SABME : LAPD_U_SABM;
+ nctx.p_f = 1;
+ nctx.length = 0;
+ nctx.more = 0;
+
+ dl->tx_hist[0].msg = lapd_msgb_alloc(msg->len, "HIST");
+ msgb_put(dl->tx_hist[0].msg, msg->len);
+ if (msg->len)
+ memcpy(dl->tx_hist[0].msg->data, msg->l3h, msg->len);
+ dl->tx_hist[0].more = 0;
+ /* set Vs to 0, because it is used as index when resending SABM */
+ dl->v_send = 0;
+
+ /* Set states */
+ dl->own_busy = dl->peer_busy = 0;
+ dl->retrans_ctr = 0;
+ lapd_dl_newstate(dl, LAPD_STATE_SABM_SENT);
+
+ /* Tramsmit and start T200 */
+ dl->send_ph_data_req(&nctx, msg);
+ lapd_start_t200(dl);
+
+ return 0;
+}
+
+/* requesst release of link */
+static int lapd_rel_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ struct msgb *msg = dp->oph.msg;
+ struct lapd_msg_ctx nctx;
+
+ /* local release */
+ if (dp->u.rel_req.mode) {
+ LOGP(DLLAPD, LOGL_INFO, "perform local release\n");
+ msgb_free(msg);
+ /* stop Timer T200 */
+ lapd_stop_t200(dl);
+ /* enter idle state, T203 is stopped here, if running */
+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);
+ /* flush buffers */
+ lapd_dl_flush_tx(dl);
+ lapd_dl_flush_send(dl);
+ /* send notification to L3 */
+ return send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, &dl->lctx);
+ }
+
+ /* in case we are already disconnecting */
+ if (dl->state == LAPD_STATE_DISC_SENT)
+ return -EBUSY;
+
+ /* flush tx_hist */
+ lapd_dl_flush_hist(dl);
+
+ LOGP(DLLAPD, LOGL_INFO, "perform normal release (DISC)\n");
+
+ /* Push LAPD header on msgb */
+ /* assemble message */
+ memcpy(&nctx, &dl->lctx, sizeof(nctx));
+ /* keep nctx.ldp */
+ /* keep nctx.sapi */
+ /* keep nctx.tei */
+ nctx.cr = dl->cr.loc2rem.cmd;
+ nctx.format = LAPD_FORM_U;
+ nctx.s_u = LAPD_U_DISC;
+ nctx.p_f = 1;
+ nctx.length = 0;
+ nctx.more = 0;
+
+ dl->tx_hist[0].msg = lapd_msgb_alloc(msg->len, "HIST");
+ msgb_put(dl->tx_hist[0].msg, msg->len);
+ if (msg->len)
+ memcpy(dl->tx_hist[0].msg->data, msg->l3h, msg->len);
+ dl->tx_hist[0].more = 0;
+ /* set Vs to 0, because it is used as index when resending DISC */
+ dl->v_send = 0;
+
+ /* Set states */
+ dl->own_busy = dl->peer_busy = 0;
+ dl->retrans_ctr = 0;
+ lapd_dl_newstate(dl, LAPD_STATE_DISC_SENT);
+
+ /* Tramsmit and start T200 */
+ dl->send_ph_data_req(&nctx, msg);
+ lapd_start_t200(dl);
+
+ return 0;
+}
+
+/* request release of link in idle state */
+static int lapd_rel_req_idle(struct osmo_dlsap_prim *dp,
+ struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ struct msgb *msg = dp->oph.msg;
+
+ msgb_free(msg);
+
+ /* send notification to L3 */
+ return send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, &dl->lctx);
+}
+
+/* statefull handling for DL SAP messages from L3 */
+static struct l2downstate {
+ uint32_t states;
+ int prim, op;
+ const char *name;
+ int (*rout) (struct osmo_dlsap_prim *dp,
+ struct lapd_msg_ctx *lctx);
+} l2downstatelist[] = {
+ /* create and send UI command */
+ {ALL_STATES,
+ PRIM_DL_UNIT_DATA, PRIM_OP_REQUEST,
+ "DL-UNIT-DATA-REQUEST", lapd_udata_req},
+
+ /* create and send SABM command */
+ {SBIT(LAPD_STATE_IDLE),
+ PRIM_DL_EST, PRIM_OP_REQUEST,
+ "DL-ESTABLISH-REQUEST", lapd_est_req},
+
+ /* create and send I command */
+ {SBIT(LAPD_STATE_MF_EST) |
+ SBIT(LAPD_STATE_TIMER_RECOV),
+ PRIM_DL_DATA, PRIM_OP_REQUEST,
+ "DL-DATA-REQUEST", lapd_data_req},
+
+ /* suspend datalink */
+ {SBIT(LAPD_STATE_MF_EST) |
+ SBIT(LAPD_STATE_TIMER_RECOV),
+ PRIM_DL_SUSP, PRIM_OP_REQUEST,
+ "DL-SUSPEND-REQUEST", lapd_susp_req},
+
+ /* create and send SABM command (resume) */
+ {SBIT(LAPD_STATE_MF_EST) |
+ SBIT(LAPD_STATE_TIMER_RECOV),
+ PRIM_DL_RES, PRIM_OP_REQUEST,
+ "DL-RESUME-REQUEST", lapd_res_req},
+
+ /* create and send SABM command (reconnect) */
+ {SBIT(LAPD_STATE_IDLE) |
+ SBIT(LAPD_STATE_MF_EST) |
+ SBIT(LAPD_STATE_TIMER_RECOV),
+ PRIM_DL_RECON, PRIM_OP_REQUEST,
+ "DL-RECONNECT-REQUEST", lapd_res_req},
+
+ /* create and send DISC command */
+ {SBIT(LAPD_STATE_SABM_SENT) |
+ SBIT(LAPD_STATE_MF_EST) |
+ SBIT(LAPD_STATE_TIMER_RECOV) |
+ SBIT(LAPD_STATE_DISC_SENT),
+ PRIM_DL_REL, PRIM_OP_REQUEST,
+ "DL-RELEASE-REQUEST", lapd_rel_req},
+
+ /* release in idle state */
+ {SBIT(LAPD_STATE_IDLE),
+ PRIM_DL_REL, PRIM_OP_REQUEST,
+ "DL-RELEASE-REQUEST", lapd_rel_req_idle},
+};
+
+#define L2DOWNSLLEN \
+ (sizeof(l2downstatelist) / sizeof(struct l2downstate))
+
+int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ int i, supported = 0;
+ struct msgb *msg = dp->oph.msg;
+ int rc;
+
+ /* find function for current state and message */
+ for (i = 0; i < L2DOWNSLLEN; i++) {
+ if (dp->oph.primitive == l2downstatelist[i].prim
+ && dp->oph.operation == l2downstatelist[i].op) {
+ supported = 1;
+ if ((SBIT(dl->state) & l2downstatelist[i].states))
+ break;
+ }
+ }
+ if (!supported) {
+ LOGP(DLLAPD, LOGL_NOTICE, "Message %u/%u unsupported.\n",
+ dp->oph.primitive, dp->oph.operation);
+ msgb_free(msg);
+ return 0;
+ }
+ if (i == L2DOWNSLLEN) {
+ LOGP(DLLAPD, LOGL_NOTICE, "Message %u/%u unhandled at this "
+ "state %s.\n", dp->oph.primitive, dp->oph.operation,
+ lapd_state_names[dl->state]);
+ msgb_free(msg);
+ return 0;
+ }
+
+ LOGP(DLLAPD, LOGL_INFO, "Message %s received in state %s\n",
+ l2downstatelist[i].name, lapd_state_names[dl->state]);
+
+ rc = l2downstatelist[i].rout(dp, lctx);
+
+ return rc;
+}
+
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/lapdm.c b/Src/osmolib/src/shared/libosmocore/src/gsm/lapdm.c
index f99c119..e9ce881 100644
--- a/Src/osmolib/src/shared/libosmocore/src/gsm/lapdm.c
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/lapdm.c
@@ -1,7 +1,7 @@
/* GSM LAPDm (TS 04.06) implementation */
/* (C) 2010-2011 by Harald Welte <laforge@gnumonks.org>
- * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2010-2011 by Andreas Eversberg <jolly@eversberg.eu>
*
* All Rights Reserved
*
@@ -27,36 +27,6 @@
/*! \file lapdm.c */
-/*!
- * Notes on Buffering: rcv_buffer, tx_queue, tx_hist, send_buffer, send_queue
- *
- * RX data is stored in the rcv_buffer (pointer). If the message is complete, it
- * is removed from rcv_buffer pointer and forwarded to L3. If the RX data is
- * received while there is an incomplete rcv_buffer, it is appended to it.
- *
- * TX data is stored in the send_queue first. When transmitting a frame,
- * the first message in the send_queue is moved to the send_buffer. There it
- * resides until all fragments are acknowledged. Fragments to be sent by I
- * frames are stored in the tx_hist buffer for resend, if required. Also the
- * current fragment is copied into the tx_queue. There it resides until it is
- * forwarded to layer 1.
- *
- * In case we have SAPI 0, we only have a window size of 1, so the unack-
- * nowledged message resides always in the send_buffer. In case of a suspend,
- * it can be written back to the first position of the send_queue.
- *
- * The layer 1 normally sends a PH-READY-TO-SEND. But because we use
- * asynchronous transfer between layer 1 and layer 2 (serial link), we must
- * send a frame before layer 1 reaches the right timeslot to send it. So we
- * move the tx_queue to layer 1 when there is not already a pending frame, and
- * wait until acknowledge after the frame has been sent. If we receive an
- * acknowledge, we can send the next frame from the buffer, if any.
- *
- * The moving of tx_queue to layer 1 may also trigger T200, if desired. Also it
- * will trigger next I frame, if possible.
- *
- */
-
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -84,6 +54,7 @@
#define LAPDm_SAPI_SMS 3
#define LAPDm_ADDR(lpd, sapi, cr) ((((lpd) & 0x3) << 5) | (((sapi) & 0x7) << 2) | (((cr) & 0x1) << 1) | 0x1)
+#define LAPDm_ADDR_LPD(addr) (((addr) >> 5) & 0x3)
#define LAPDm_ADDR_SAPI(addr) (((addr) >> 2) & 0x7)
#define LAPDm_ADDR_CR(addr) (((addr) >> 1) & 0x1)
#define LAPDm_ADDR_EA(addr) ((addr) & 0x1)
@@ -105,19 +76,11 @@
#define LAPDm_CTRL_I_Ns(ctrl) (((ctrl) & 0xE) >> 1)
#define LAPDm_CTRL_Nr(ctrl) (((ctrl) & 0xE0) >> 5)
-/* TS 04.06 Table 4 / Section 3.8.1 */
-#define LAPDm_U_SABM 0x7
-#define LAPDm_U_DM 0x3
-#define LAPDm_U_UI 0x0
-#define LAPDm_U_DISC 0x8
-#define LAPDm_U_UA 0xC
-
-#define LAPDm_S_RR 0x0
-#define LAPDm_S_RNR 0x1
-#define LAPDm_S_REJ 0x2
-
#define LAPDm_LEN(len) ((len << 2) | 0x1)
#define LAPDm_MORE 0x2
+#define LAPDm_EL 0x1
+
+#define LAPDm_U_UI 0x0
/* TS 04.06 Section 5.8.3 */
#define N201_AB_SACCH 18
@@ -137,19 +100,8 @@
#define N200_TR_FACCH_FR 34
#define N200_TR_EFACCH_FR 48
#define N200_TR_FACCH_HR 29
-/* FIXME: this depends on chan type */
-#define N200 N200_TR_SACCH
-
-#define CR_MS2BS_CMD 0
-#define CR_MS2BS_RESP 1
-#define CR_BS2MS_CMD 1
-#define CR_BS2MS_RESP 0
-
-/* Set T200 to 1 Second (OpenBTS uses 900ms) */
-#define T200 1, 0
-
-/* k value for each SAPI */
-static uint8_t k_sapi[] = {1, 1, 1, 1, 1, 1, 1, 1};
+/* FIXME: set N200 depending on chan_nr */
+#define N200 N200_TR_SDCCH
enum lapdm_format {
LAPDm_FMT_A,
@@ -159,48 +111,35 @@ enum lapdm_format {
LAPDm_FMT_B4,
};
-static void lapdm_t200_cb(void *data);
-static int rslms_send_i(struct lapdm_msg_ctx *mctx, int line);
-
-/* UTILITY FUNCTIONS */
-
-static inline uint8_t inc_mod8(uint8_t x)
-{
- return (x + 1) & 7;
-}
-
-static inline uint8_t add_mod8(uint8_t x, uint8_t y)
-{
- return (x + y) & 7;
-}
-
-static inline uint8_t sub_mod8(uint8_t x, uint8_t y)
-{
- return (x - y) & 7; /* handle negative results correctly */
-}
+static int lapdm_send_ph_data_req(struct lapd_msg_ctx *lctx, struct msgb *msg);
+static int send_rslms_dlsap(struct osmo_dlsap_prim *dp,
+ struct lapd_msg_ctx *lctx);
static void lapdm_dl_init(struct lapdm_datalink *dl,
- struct lapdm_entity *entity)
+ struct lapdm_entity *entity, int t200)
{
memset(dl, 0, sizeof(*dl));
- INIT_LLIST_HEAD(&dl->send_queue);
- INIT_LLIST_HEAD(&dl->tx_queue);
- dl->state = LAPDm_STATE_IDLE;
- dl->t200.data = dl;
- dl->t200.cb = &lapdm_t200_cb;
dl->entity = entity;
+ lapd_dl_init(&dl->dl, 1, 8, 200);
+ dl->dl.reestablish = 0; /* GSM uses no reestablish */
+ dl->dl.send_ph_data_req = lapdm_send_ph_data_req;
+ dl->dl.send_dlsap = send_rslms_dlsap;
+ dl->dl.n200_est_rel = N200_EST_REL;
+ dl->dl.n200 = N200;
+ dl->dl.t203_sec = 0; dl->dl.t203_usec = 0;
+ dl->dl.t200_sec = t200; dl->dl.t200_usec = 0;
}
/*! \brief initialize a LAPDm entity and all datalinks inside
* \param[in] le LAPDm entity
* \param[in] mode \ref lapdm_mode (BTS/MS)
*/
-void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode)
+void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode, int t200)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(le->datalink); i++)
- lapdm_dl_init(&le->datalink[i], le);
+ lapdm_dl_init(&le->datalink[i], le, t200);
lapdm_entity_set_mode(le, mode);
}
@@ -214,34 +153,9 @@ void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode)
*/
void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode)
{
- lapdm_entity_init(&lc->lapdm_acch, mode);
- lapdm_entity_init(&lc->lapdm_dcch, mode);
-}
-
-static void lapdm_dl_flush_send(struct lapdm_datalink *dl)
-{
- struct msgb *msg;
-
- /* Flush send-queue */
- while ((msg = msgb_dequeue(&dl->send_queue)))
- msgb_free(msg);
-
- /* Clear send-buffer */
- if (dl->send_buffer) {
- msgb_free(dl->send_buffer);
- dl->send_buffer = NULL;
- }
-}
-
-static void lapdm_dl_flush_tx(struct lapdm_datalink *dl)
-{
- struct msgb *msg;
- unsigned int i;
-
- while ((msg = msgb_dequeue(&dl->tx_queue)))
- msgb_free(msg);
- for (i = 0; i < 8; i++)
- dl->tx_length[i] = 0;
+ lapdm_entity_init(&lc->lapdm_acch, mode, 2);
+ /* FIXME: this depends on chan type */
+ lapdm_entity_init(&lc->lapdm_dcch, mode, 1);
}
/*! \brief flush and release all resoures in LAPDm entity */
@@ -252,10 +166,7 @@ void lapdm_entity_exit(struct lapdm_entity *le)
for (i = 0; i < ARRAY_SIZE(le->datalink); i++) {
dl = &le->datalink[i];
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
- if (dl->rcv_buffer)
- msgb_free(dl->rcv_buffer);
+ lapd_dl_exit(&dl->dl);
}
}
@@ -270,14 +181,6 @@ void lapdm_channel_exit(struct lapdm_channel *lc)
lapdm_entity_exit(&lc->lapdm_dcch);
}
-static void lapdm_dl_newstate(struct lapdm_datalink *dl, uint32_t state)
-{
- LOGP(DLLAPDM, LOGL_INFO, "new state %s -> %s\n",
- lapdm_state_names[dl->state], lapdm_state_names[state]);
-
- dl->state = state;
-}
-
static struct lapdm_datalink *datalink_for_sapi(struct lapdm_entity *le, uint8_t sapi)
{
switch (sapi) {
@@ -305,7 +208,7 @@ static void lapdm_pad_msgb(struct msgb *msg, uint8_t n201)
uint8_t *data;
if (pad_len < 0) {
- LOGP(DLLAPDM, LOGL_ERROR,
+ LOGP(DLLAPD, LOGL_ERROR,
"cannot pad message that is already too big!\n");
return;
}
@@ -328,17 +231,17 @@ static int rslms_sendmsg(struct msgb *msg, struct lapdm_entity *le)
/* write a frame into the tx queue */
static int tx_ph_data_enqueue(struct lapdm_datalink *dl, struct msgb *msg,
- uint8_t chan_nr, uint8_t link_id, uint8_t n201)
+ uint8_t chan_nr, uint8_t link_id, uint8_t pad)
{
struct lapdm_entity *le = dl->entity;
struct osmo_phsap_prim pp;
/* if there is a pending message, queue it */
if (le->tx_pending || le->flags & LAPDM_ENT_F_POLLING_ONLY) {
- *msgb_push(msg, 1) = n201;
+ *msgb_push(msg, 1) = pad;
*msgb_push(msg, 1) = link_id;
*msgb_push(msg, 1) = chan_nr;
- msgb_enqueue(&dl->tx_queue, msg);
+ msgb_enqueue(&dl->dl.tx_queue, msg);
return -EBUSY;
}
@@ -349,7 +252,7 @@ static int tx_ph_data_enqueue(struct lapdm_datalink *dl, struct msgb *msg,
/* send the frame now */
le->tx_pending = 0; /* disabled flow control */
- lapdm_pad_msgb(msg, n201);
+ lapdm_pad_msgb(msg, pad);
return le->l1_prim_cb(&pp.oph, le->l1_ctx);
}
@@ -366,7 +269,7 @@ static struct msgb *tx_dequeue_msgb(struct lapdm_entity *le)
/* next */
i = (i + 1) % n;
dl = &le->datalink[i];
- if ((msg = msgb_dequeue(&dl->tx_queue)))
+ if ((msg = msgb_dequeue(&dl->dl.tx_queue)))
break;
} while (i != last);
@@ -383,7 +286,7 @@ static struct msgb *tx_dequeue_msgb(struct lapdm_entity *le)
int lapdm_phsap_dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp)
{
struct msgb *msg;
- uint8_t n201;
+ uint8_t pad;
msg = tx_dequeue_msgb(le);
if (!msg)
@@ -398,11 +301,11 @@ int lapdm_phsap_dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp
msgb_pull(msg, 1);
pp->u.data.link_id = *msg->data;
msgb_pull(msg, 1);
- n201 = *msg->data;
+ pad = *msg->data;
msgb_pull(msg, 1);
/* Pad the frame, we can transmit now */
- lapdm_pad_msgb(msg, n201);
+ lapdm_pad_msgb(msg, pad);
return 0;
}
@@ -486,1157 +389,148 @@ static int rsl_rll_error(uint8_t cause, struct lapdm_msg_ctx *mctx)
{
struct msgb *msg;
- LOGP(DLLAPDM, LOGL_NOTICE, "sending MDL-ERROR-IND %d\n", cause);
+ LOGP(DLLAPD, LOGL_NOTICE, "sending MDL-ERROR-IND %d\n", cause);
msg = rsl_rll_simple(RSL_MT_ERROR_IND, mctx->chan_nr, mctx->link_id, 1);
msg->l2h = msgb_put(msg, sizeof(struct abis_rsl_rll_hdr));
msgb_tlv_put(msg, RSL_IE_RLM_CAUSE, 1, &cause);
return rslms_sendmsg(msg, mctx->dl->entity);
}
-static int check_length_ind(struct lapdm_msg_ctx *mctx, uint8_t length_ind)
-{
- if (!(length_ind & 0x01)) {
- /* G.4.1 If the EL bit is set to "0", an MDL-ERROR-INDICATION
- * primitive with cause "frame not implemented" is sent to the
- * mobile management entity. */
- LOGP(DLLAPDM, LOGL_NOTICE,
- "we don't support multi-octet length\n");
- rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
- return -EINVAL;
- }
- return 0;
-}
-
-static int lapdm_send_resend(struct lapdm_datalink *dl)
+/* DLSAP L2 -> L3 (RSLms) */
+static int send_rslms_dlsap(struct osmo_dlsap_prim *dp,
+ struct lapd_msg_ctx *lctx)
{
- struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm resend");
- int length;
-
- /* Resend SABM/DISC from tx_hist */
- length = dl->tx_length[0];
- msg->l2h = msgb_put(msg, length);
- memcpy(msg->l2h, dl->tx_hist[dl->V_send], length);
-
- return tx_ph_data_enqueue(dl, msg, dl->mctx.chan_nr, dl->mctx.link_id,
- dl->mctx.n201);
-}
-
-static int lapdm_send_ua(struct lapdm_msg_ctx *mctx, uint8_t len, uint8_t *data)
-{
- uint8_t sapi = mctx->link_id & 7;
- uint8_t f_bit = LAPDm_CTRL_PF_BIT(mctx->ctrl);
- struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm UA");
- struct lapdm_entity *le = mctx->dl->entity;
-
- msg->l2h = msgb_put(msg, 3 + len);
- msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.resp);
- msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_UA, f_bit);
- msg->l2h[2] = LAPDm_LEN(len);
- if (len)
- memcpy(msg->l2h + 3, data, len);
-
- return tx_ph_data_enqueue(mctx->dl, msg, mctx->chan_nr, mctx->link_id,
- mctx->n201);
-}
-
-static int lapdm_send_dm(struct lapdm_msg_ctx *mctx)
-{
- uint8_t sapi = mctx->link_id & 7;
- uint8_t f_bit = LAPDm_CTRL_PF_BIT(mctx->ctrl);
- struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm DM");
- struct lapdm_entity *le = mctx->dl->entity;
-
- msg->l2h = msgb_put(msg, 3);
- msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.resp);
- msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_DM, f_bit);
- msg->l2h[2] = 0;
-
- return tx_ph_data_enqueue(mctx->dl, msg, mctx->chan_nr, mctx->link_id,
- mctx->n201);
-}
-
-static int lapdm_send_rr(struct lapdm_msg_ctx *mctx, uint8_t f_bit)
-{
- uint8_t sapi = mctx->link_id & 7;
- struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm RR");
- struct lapdm_entity *le = mctx->dl->entity;
-
- msg->l2h = msgb_put(msg, 3);
- msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.resp);
- msg->l2h[1] = LAPDm_CTRL_S(mctx->dl->V_recv, LAPDm_S_RR, f_bit);
- msg->l2h[2] = LAPDm_LEN(0);
-
- return tx_ph_data_enqueue(mctx->dl, msg, mctx->chan_nr, mctx->link_id,
- mctx->n201);
-}
-
-static int lapdm_send_rnr(struct lapdm_msg_ctx *mctx, uint8_t f_bit)
-{
- uint8_t sapi = mctx->link_id & 7;
- struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm RNR");
- struct lapdm_entity *le = mctx->dl->entity;
-
- msg->l2h = msgb_put(msg, 3);
- msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.resp);
- msg->l2h[1] = LAPDm_CTRL_S(mctx->dl->V_recv, LAPDm_S_RNR, f_bit);
- msg->l2h[2] = LAPDm_LEN(0);
-
- return tx_ph_data_enqueue(mctx->dl, msg, mctx->chan_nr, mctx->link_id,
- mctx->n201);
-}
-
-static int lapdm_send_rej(struct lapdm_msg_ctx *mctx, uint8_t f_bit)
-{
- uint8_t sapi = mctx->link_id & 7;
- struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm REJ");
- struct lapdm_entity *le = mctx->dl->entity;
-
- msg->l2h = msgb_put(msg, 3);
- msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.resp);
- msg->l2h[1] = LAPDm_CTRL_S(mctx->dl->V_recv, LAPDm_S_REJ, f_bit);
- msg->l2h[2] = LAPDm_LEN(0);
-
- return tx_ph_data_enqueue(mctx->dl, msg, mctx->chan_nr, mctx->link_id,
- mctx->n201);
-}
-
-/* Timer callback on T200 expiry */
-static void lapdm_t200_cb(void *data)
-{
- struct lapdm_datalink *dl = data;
-
- LOGP(DLLAPDM, LOGL_INFO, "lapdm_t200_cb(%p) state=%u\n", dl, dl->state);
-
- switch (dl->state) {
- case LAPDm_STATE_SABM_SENT:
- /* 5.4.1.3 */
- if (dl->retrans_ctr + 1 >= N200_EST_REL + 1) {
- /* send RELEASE INDICATION to L3 */
- send_rll_simple(RSL_MT_REL_IND, &dl->mctx);
- /* send MDL ERROR INIDCATION to L3 */
- rsl_rll_error(RLL_CAUSE_T200_EXPIRED, &dl->mctx);
- /* flush tx buffers */
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
- /* go back to idle state */
- lapdm_dl_newstate(dl, LAPDm_STATE_IDLE);
- /* NOTE: we must not change any other states or buffers
- * and queues, since we may reconnect after handover
- * failure. the buffered messages is replaced there */
- break;
- }
- /* retransmit SABM command */
- lapdm_send_resend(dl);
- /* increment re-transmission counter */
- dl->retrans_ctr++;
- /* restart T200 (PH-READY-TO-SEND) */
- osmo_timer_schedule(&dl->t200, T200);
+ struct lapd_datalink *dl = lctx->dl;
+ struct lapdm_datalink *mdl =
+ container_of(dl, struct lapdm_datalink, dl);
+ struct lapdm_msg_ctx *mctx = &mdl->mctx;
+ uint8_t rll_msg = 0;
+
+ switch (OSMO_PRIM_HDR(&dp->oph)) {
+ case OSMO_PRIM(PRIM_DL_EST, PRIM_OP_INDICATION):
+ rll_msg = RSL_MT_EST_IND;
break;
- case LAPDm_STATE_DISC_SENT:
- /* 5.4.4.3 */
- if (dl->retrans_ctr + 1 >= N200_EST_REL + 1) {
- /* send RELEASE INDICATION to L3 */
- send_rll_simple(RSL_MT_REL_CONF, &dl->mctx);
- /* send MDL ERROR INIDCATION to L3 */
- rsl_rll_error(RLL_CAUSE_T200_EXPIRED, &dl->mctx);
- /* flush buffers */
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
- /* go back to idle state */
- lapdm_dl_newstate(dl, LAPDm_STATE_IDLE);
- /* NOTE: we must not change any other states or buffers
- * and queues, since we may reconnect after handover
- * failure. the buffered messages is replaced there */
- break;
- }
- /* retransmit DISC command */
- lapdm_send_resend(dl);
- /* increment re-transmission counter */
- dl->retrans_ctr++;
- /* restart T200 (PH-READY-TO-SEND) */
- osmo_timer_schedule(&dl->t200, T200);
+ case OSMO_PRIM(PRIM_DL_EST, PRIM_OP_CONFIRM):
+ rll_msg = RSL_MT_EST_CONF;
break;
- case LAPDm_STATE_MF_EST:
- /* 5.5.7 */
- dl->retrans_ctr = 0;
- lapdm_dl_newstate(dl, LAPDm_STATE_TIMER_RECOV);
- /* fall through */
- case LAPDm_STATE_TIMER_RECOV:
- dl->retrans_ctr++;
- if (dl->retrans_ctr < N200) {
- /* retransmit I frame (V_s-1) with P=1, if any */
- if (dl->tx_length[sub_mod8(dl->V_send, 1)]) {
- struct msgb *msg;
- int length;
-
- LOGP(DLLAPDM, LOGL_INFO, "retransmit last frame "
- "V(S)=%d\n", sub_mod8(dl->V_send, 1));
- /* Create I frame (segment) from tx_hist */
- length = dl->tx_length[sub_mod8(dl->V_send, 1)];
- msg = msgb_alloc_headroom(23+10, 10, "LAPDm I");
- msg->l2h = msgb_put(msg, length);
- memcpy(msg->l2h,
- dl->tx_hist[sub_mod8(dl->V_send, 1)],
- length);
- msg->l2h[1] = LAPDm_CTRL_I(dl->V_recv,
- sub_mod8(dl->V_send, 1), 1); /* P=1 */
- tx_ph_data_enqueue(dl, msg, dl->mctx.chan_nr,
- dl->mctx.link_id, dl->mctx.n201);
- } else {
- /* OR send appropriate supervision frame with P=1 */
- if (!dl->own_busy && !dl->seq_err_cond) {
- lapdm_send_rr(&dl->mctx, 1);
- /* NOTE: In case of sequence error
- * condition, the REJ frame has been
- * transmitted when entering the
- * condition, so it has not be done
- * here
- */
- } else if (dl->own_busy) {
- lapdm_send_rnr(&dl->mctx, 1);
- } else {
- LOGP(DLLAPDM, LOGL_INFO, "unhandled, "
- "pls. fix\n");
- }
- }
- /* restart T200 (PH-READY-TO-SEND) */
- osmo_timer_schedule(&dl->t200, T200);
- } else {
- /* send MDL ERROR INIDCATION to L3 */
- rsl_rll_error(RLL_CAUSE_T200_EXPIRED, &dl->mctx);
- }
+ case OSMO_PRIM(PRIM_DL_DATA, PRIM_OP_INDICATION):
+ rll_msg = RSL_MT_DATA_IND;
break;
- default:
- LOGP(DLLAPDM, LOGL_INFO, "T200 expired in unexpected "
- "dl->state %u\n", dl->state);
- }
-}
-
-/* 5.5.3.1: Common function to acknowlege frames up to the given N(R) value */
-static void lapdm_acknowledge(struct lapdm_msg_ctx *mctx)
-{
- struct lapdm_datalink *dl = mctx->dl;
- uint8_t nr = LAPDm_CTRL_Nr(mctx->ctrl);
- int s = 0, rej = 0, t200_reset = 0;
- int i;
-
- /* supervisory frame ? */
- if (LAPDm_CTRL_is_S(mctx->ctrl))
- s = 1;
- /* REJ frame ? */
- if (s && LAPDm_CTRL_S_BITS(mctx->ctrl) == LAPDm_S_REJ)
- rej = 1;
-
- /* Flush all transmit buffers of acknowledged frames */
- for (i = dl->V_ack; i != nr; i = inc_mod8(i)) {
- if (dl->tx_length[i]) {
- dl->tx_length[i] = 0;
- LOGP(DLLAPDM, LOGL_INFO, "ack frame %d\n", i);
- }
- }
-
- if (dl->state != LAPDm_STATE_TIMER_RECOV) {
- /* When not in the timer recovery condition, the data
- * link layer entity shall reset the timer T200 on
- * receipt of a valid I frame with N(R) higher than V(A),
- * or an REJ with an N(R) equal to V(A). */
- if ((!rej && nr != dl->V_ack)
- || (rej && nr == dl->V_ack)) {
- LOGP(DLLAPDM, LOGL_INFO, "reset t200\n");
- t200_reset = 1;
- osmo_timer_del(&dl->t200);
- /* 5.5.3.1 Note 1 + 2 imply timer recovery cond. */
- }
- /* 5.7.4: N(R) sequence error
- * N(R) is called valid, if and only if
- * (N(R)-V(A)) mod 8 <= (V(S)-V(A)) mod 8.
- */
- if (sub_mod8(nr, dl->V_ack) > sub_mod8(dl->V_send, dl->V_ack)) {
- LOGP(DLLAPDM, LOGL_NOTICE, "N(R) sequence error\n");
- rsl_rll_error(RLL_CAUSE_SEQ_ERR, mctx);
- }
- }
-
- /* V(A) shall be set to the value of N(R) */
- dl->V_ack = nr;
-
- /* If T200 has been reset by the receipt of an I, RR or RNR frame,
- * and if there are outstanding I frames, restart T200 */
- if (t200_reset && !rej) {
- if (dl->tx_length[dl->V_send - 1]) {
- LOGP(DLLAPDM, LOGL_INFO, "start T200, due to unacked I "
- "frame(s)\n");
- osmo_timer_schedule(&dl->t200, T200);
- }
- }
-}
-
-/* L1 -> L2 */
-
-/* Receive a LAPDm U (Unnumbered) message from L1 */
-static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
-{
- struct lapdm_datalink *dl = mctx->dl;
- struct lapdm_entity *le = dl->entity;
- uint8_t length;
- int rc;
- int rsl_msg;
-
- switch (LAPDm_CTRL_U_BITS(mctx->ctrl)) {
- case LAPDm_U_SABM:
- rsl_msg = RSL_MT_EST_IND;
-
- LOGP(DLLAPDM, LOGL_INFO, "SABM received\n");
- /* 5.7.1 */
- dl->seq_err_cond = 0;
- /* G.2.2 Wrong value of the C/R bit */
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp) {
- LOGP(DLLAPDM, LOGL_NOTICE, "SABM response error\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
- return -EINVAL;
- }
-
- length = msg->l2h[2] >> 2;
- /* G.4.5 If SABM is received with L>N201 or with M bit
- * set, AN MDL-ERROR-INDICATION is sent to MM.
- */
- if ((msg->l2h[2] & LAPDm_MORE) || length + 3 > mctx->n201) {
- LOGP(DLLAPDM, LOGL_NOTICE, "SABM too large error\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_UFRM_INC_PARAM, mctx);
- return -EIO;
- }
-
- /* Must be Format B */
- rc = check_length_ind(mctx, msg->l2h[2]);
- if (rc < 0) {
- msgb_free(msg);
- return rc;
- }
- switch (dl->state) {
- case LAPDm_STATE_IDLE:
- /* Set chan_nr and link_id for established connection */
- memset(&dl->mctx, 0, sizeof(dl->mctx));
- dl->mctx.dl = dl;
- dl->mctx.chan_nr = mctx->chan_nr;
- dl->mctx.link_id = mctx->link_id;
- dl->mctx.n201 = mctx->n201;
- break;
- case LAPDm_STATE_MF_EST:
- if (length == 0) {
- rsl_msg = RSL_MT_EST_CONF;
- break;
- }
- LOGP(DLLAPDM, LOGL_INFO, "SABM command, multiple "
- "frame established state\n");
- /* check for contention resoultion */
- if (dl->tx_hist[0][2] >> 2) {
- LOGP(DLLAPDM, LOGL_NOTICE, "SABM not allowed "
- "during contention resolution\n");
- rsl_rll_error(RLL_CAUSE_SABM_INFO_NOTALL, mctx);
- }
- msgb_free(msg);
- return 0;
- case LAPDm_STATE_DISC_SENT:
- /* 5.4.6.2 send DM with F=P */
- lapdm_send_dm(mctx);
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- msgb_free(msg);
- return send_rll_simple(RSL_MT_REL_CONF, mctx);
- default:
- lapdm_send_ua(mctx, length, msg->l2h + 3);
- msgb_free(msg);
- return 0;
- }
- /* send UA response */
- lapdm_send_ua(mctx, length, msg->l2h + 3);
- /* set Vs, Vr and Va to 0 */
- dl->V_send = dl->V_recv = dl->V_ack = 0;
- /* clear tx_hist */
- dl->tx_length[0] = 0;
- /* enter multiple-frame-established state */
- lapdm_dl_newstate(dl, LAPDm_STATE_MF_EST);
- /* send notification to L3 */
- if (length == 0) {
- /* 5.4.1.2 Normal establishment procedures */
- rc = send_rll_simple(rsl_msg, mctx);
- msgb_free(msg);
- } else {
- /* 5.4.1.4 Contention resolution establishment */
- msg->l3h = msg->l2h + 3;
- msgb_pull_l2h(msg);
- rc = send_rslms_rll_l3(rsl_msg, mctx, msg);
- }
+ case OSMO_PRIM(PRIM_DL_UNIT_DATA, PRIM_OP_INDICATION):
+ return send_rslms_rll_l3_ui(mctx, dp->oph.msg);
+ case OSMO_PRIM(PRIM_DL_REL, PRIM_OP_INDICATION):
+ rll_msg = RSL_MT_REL_IND;
break;
- case LAPDm_U_DM:
- LOGP(DLLAPDM, LOGL_INFO, "DM received\n");
- /* G.2.2 Wrong value of the C/R bit */
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd) {
- LOGP(DLLAPDM, LOGL_NOTICE, "DM command error\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
- return -EINVAL;
- }
- if (!LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
- /* 5.4.1.2 DM responses with the F bit set to "0"
- * shall be ignored.
- */
- msgb_free(msg);
- return 0;
- }
- switch (dl->state) {
- case LAPDm_STATE_SABM_SENT:
- break;
- case LAPDm_STATE_MF_EST:
- if (LAPDm_CTRL_PF_BIT(mctx->ctrl) == 1) {
- LOGP(DLLAPDM, LOGL_INFO, "unsolicited DM "
- "response\n");
- rsl_rll_error(RLL_CAUSE_UNSOL_DM_RESP, mctx);
- } else {
- LOGP(DLLAPDM, LOGL_INFO, "unsolicited DM "
- "response, multiple frame established "
- "state\n");
- rsl_rll_error(RLL_CAUSE_UNSOL_DM_RESP_MF, mctx);
- }
- msgb_free(msg);
- return 0;
- case LAPDm_STATE_TIMER_RECOV:
- /* DM is normal in case PF = 1 */
- if (LAPDm_CTRL_PF_BIT(mctx->ctrl) == 0) {
- LOGP(DLLAPDM, LOGL_INFO, "unsolicited DM "
- "response, multiple frame established "
- "state\n");
- rsl_rll_error(RLL_CAUSE_UNSOL_DM_RESP_MF, mctx);
- msgb_free(msg);
- return 0;
- }
- break;
- case LAPDm_STATE_DISC_SENT:
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- /* go to idle state */
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
- lapdm_dl_newstate(dl, LAPDm_STATE_IDLE);
- rc = send_rll_simple(RSL_MT_REL_CONF, mctx);
- msgb_free(msg);
- return 0;
- case LAPDm_STATE_IDLE:
- /* 5.4.5 all other frame types shall be discarded */
- default:
- LOGP(DLLAPDM, LOGL_INFO, "unsolicited DM response! "
- "(discarding)\n");
- msgb_free(msg);
- return 0;
- }
- /* reset T200 */
- osmo_timer_del(&dl->t200);
- rc = send_rll_simple(RSL_MT_REL_IND, mctx);
- msgb_free(msg);
- break;
- case LAPDm_U_UI:
- LOGP(DLLAPDM, LOGL_INFO, "UI received\n");
- /* G.2.2 Wrong value of the C/R bit */
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp) {
- LOGP(DLLAPDM, LOGL_NOTICE, "UI indicates response "
- "error\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
- return -EINVAL;
- }
-
- length = msg->l2h[2] >> 2;
- /* FIXME: G.4.5 If UI is received with L>N201 or with M bit
- * set, AN MDL-ERROR-INDICATION is sent to MM.
- */
-
- if (mctx->lapdm_fmt == LAPDm_FMT_B4) {
- length = N201_B4;
- msg->l3h = msg->l2h + 2;
- } else {
- rc = check_length_ind(mctx, msg->l2h[2]);
- if (rc < 0) {
- msgb_free(msg);
- return rc;
- }
- length = msg->l2h[2] >> 2;
- msg->l3h = msg->l2h + 3;
- }
- /* do some length checks */
- if (length == 0) {
- /* 5.3.3 UI frames received with the length indicator
- * set to "0" shall be ignored
- */
- LOGP(DLLAPDM, LOGL_INFO, "length=0 (discarding)\n");
- msgb_free(msg);
- return 0;
- }
- switch (LAPDm_ADDR_SAPI(mctx->addr)) {
- case LAPDm_SAPI_NORMAL:
- case LAPDm_SAPI_SMS:
- break;
- default:
- /* 5.3.3 UI frames with invalid SAPI values shall be
- * discarded
- */
- LOGP(DLLAPDM, LOGL_INFO, "sapi=%u (discarding)\n",
- LAPDm_ADDR_SAPI(mctx->addr));
- msgb_free(msg);
- return 0;
- }
- msgb_pull_l2h(msg);
- rc = send_rslms_rll_l3_ui(mctx, msg);
+ case OSMO_PRIM(PRIM_DL_REL, PRIM_OP_CONFIRM):
+ rll_msg = RSL_MT_REL_CONF;
break;
- case LAPDm_U_DISC:
- rsl_msg = RSL_MT_REL_IND;
-
- LOGP(DLLAPDM, LOGL_INFO, "DISC received\n");
- /* flush buffers */
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
- /* 5.7.1 */
- dl->seq_err_cond = 0;
- /* G.2.2 Wrong value of the C/R bit */
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp) {
- LOGP(DLLAPDM, LOGL_NOTICE, "DISC response error\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
- return -EINVAL;
- }
- length = msg->l2h[2] >> 2;
- if (length > 0 || msg->l2h[2] & 0x02) {
- /* G.4.4 If a DISC or DM frame is received with L>0 or
- * with the M bit set to "1", an MDL-ERROR-INDICATION
- * primitive with cause "U frame with incorrect
- * parameters" is sent to the mobile management entity.
- */
- LOGP(DLLAPDM, LOGL_NOTICE,
- "U frame iwth incorrect parameters ");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_UFRM_INC_PARAM, mctx);
- return -EIO;
- }
- switch (dl->state) {
- case LAPDm_STATE_IDLE:
- LOGP(DLLAPDM, LOGL_INFO, "DISC in idle state\n");
- /* send DM with F=P */
- msgb_free(msg);
- return lapdm_send_dm(mctx);
- case LAPDm_STATE_SABM_SENT:
- LOGP(DLLAPDM, LOGL_INFO, "DISC in SABM state\n");
- /* 5.4.6.2 send DM with F=P */
- lapdm_send_dm(mctx);
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- msgb_free(msg);
- return send_rll_simple(RSL_MT_REL_IND, mctx);
- case LAPDm_STATE_MF_EST:
- case LAPDm_STATE_TIMER_RECOV:
- LOGP(DLLAPDM, LOGL_INFO, "DISC in est state\n");
- break;
- case LAPDm_STATE_DISC_SENT:
- LOGP(DLLAPDM, LOGL_INFO, "DISC in disc state\n");
- rsl_msg = RSL_MT_REL_CONF;
- break;
- default:
- lapdm_send_ua(mctx, length, msg->l2h + 3);
- msgb_free(msg);
- return 0;
- }
- /* send UA response */
- lapdm_send_ua(mctx, length, msg->l2h + 3);
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- /* enter idle state */
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
- lapdm_dl_newstate(dl, LAPDm_STATE_IDLE);
- /* send notification to L3 */
- rc = send_rll_simple(rsl_msg, mctx);
- msgb_free(msg);
+ case OSMO_PRIM(PRIM_DL_SUSP, PRIM_OP_CONFIRM):
+ rll_msg = RSL_MT_SUSP_CONF;
break;
- case LAPDm_U_UA:
- LOGP(DLLAPDM, LOGL_INFO, "UA received\n");
- /* G.2.2 Wrong value of the C/R bit */
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd) {
- LOGP(DLLAPDM, LOGL_NOTICE, "UA indicates command "
- "error\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
- return -EINVAL;
- }
-
- length = msg->l2h[2] >> 2;
- /* G.4.5 If UA is received with L>N201 or with M bit
- * set, AN MDL-ERROR-INDICATION is sent to MM.
- */
- if ((msg->l2h[2] & LAPDm_MORE) || length + 3 > mctx->n201) {
- LOGP(DLLAPDM, LOGL_NOTICE, "UA too large error\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_UFRM_INC_PARAM, mctx);
- return -EIO;
- }
-
- if (!LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
- /* 5.4.1.2 A UA response with the F bit set to "0"
- * shall be ignored.
- */
- LOGP(DLLAPDM, LOGL_INFO, "F=0 (discarding)\n");
- msgb_free(msg);
- return 0;
- }
- switch (dl->state) {
- case LAPDm_STATE_SABM_SENT:
- break;
- case LAPDm_STATE_MF_EST:
- case LAPDm_STATE_TIMER_RECOV:
- LOGP(DLLAPDM, LOGL_INFO, "unsolicited UA response! "
- "(discarding)\n");
- rsl_rll_error(RLL_CAUSE_UNSOL_UA_RESP, mctx);
- msgb_free(msg);
- return 0;
- case LAPDm_STATE_DISC_SENT:
- LOGP(DLLAPDM, LOGL_INFO, "UA in disconnect state\n");
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- /* go to idle state */
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
- lapdm_dl_newstate(dl, LAPDm_STATE_IDLE);
- rc = send_rll_simple(RSL_MT_REL_CONF, mctx);
- msgb_free(msg);
- return 0;
- case LAPDm_STATE_IDLE:
- /* 5.4.5 all other frame types shall be discarded */
- default:
- LOGP(DLLAPDM, LOGL_INFO, "unsolicited UA response! "
- "(discarding)\n");
- msgb_free(msg);
- return 0;
- }
- LOGP(DLLAPDM, LOGL_INFO, "UA in SABM state\n");
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- /* compare UA with SABME if contention resolution is applied */
- if (dl->tx_hist[0][2] >> 2) {
- rc = check_length_ind(mctx, msg->l2h[2]);
- if (rc < 0) {
- rc = send_rll_simple(RSL_MT_REL_IND, mctx);
- msgb_free(msg);
- /* go to idle state */
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
- lapdm_dl_newstate(dl, LAPDm_STATE_IDLE);
- return 0;
- }
- length = msg->l2h[2] >> 2;
- if (length != (dl->tx_hist[0][2] >> 2)
- || !!memcmp(dl->tx_hist[0] + 3, msg->l2h + 3,
- length)) {
- LOGP(DLLAPDM, LOGL_INFO, "**** UA response "
- "mismatches ****\n");
- rc = send_rll_simple(RSL_MT_REL_IND, mctx);
- msgb_free(msg);
- /* go to idle state */
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
- lapdm_dl_newstate(dl, LAPDm_STATE_IDLE);
- return 0;
- }
- }
- /* set Vs, Vr and Va to 0 */
- dl->V_send = dl->V_recv = dl->V_ack = 0;
- /* clear tx_hist */
- dl->tx_length[0] = 0;
- /* enter multiple-frame-established state */
- lapdm_dl_newstate(dl, LAPDm_STATE_MF_EST);
- /* send outstanding frames, if any (resume / reconnect) */
- rslms_send_i(mctx, __LINE__);
- /* send notification to L3 */
- rc = send_rll_simple(RSL_MT_EST_CONF, mctx);
- msgb_free(msg);
- break;
- default:
- /* G.3.1 */
- LOGP(DLLAPDM, LOGL_NOTICE, "Unnumbered frame not allowed.\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
- return -EINVAL;
+ case OSMO_PRIM(PRIM_MDL_ERROR, PRIM_OP_INDICATION):
+ rsl_rll_error(dp->u.error_ind.cause, mctx);
+ if (dp->oph.msg)
+ msgb_free(dp->oph.msg);
+ return 0;
}
- return rc;
-}
-
-/* Receive a LAPDm S (Supervisory) message from L1 */
-static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
-{
- struct lapdm_datalink *dl = mctx->dl;
- struct lapdm_entity *le = dl->entity;
- uint8_t length;
- length = msg->l2h[2] >> 2;
- if (length > 0 || msg->l2h[2] & 0x02) {
- /* G.4.3 If a supervisory frame is received with L>0 or
- * with the M bit set to "1", an MDL-ERROR-INDICATION
- * primitive with cause "S frame with incorrect
- * parameters" is sent to the mobile management entity. */
- LOGP(DLLAPDM, LOGL_NOTICE,
- "S frame with incorrect parameters\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_SFRM_INC_PARAM, mctx);
- return -EIO;
+ if (!rll_msg) {
+ LOGP(DLLAPD, LOGL_ERROR, "Unsupported op %d, prim %d. Please "
+ "fix!\n", dp->oph.primitive, dp->oph.operation);
+ return -EINVAL;
}
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp
- && LAPDm_CTRL_PF_BIT(mctx->ctrl)
- && dl->state != LAPDm_STATE_TIMER_RECOV) {
- /* 5.4.2.2: Inidcate error on supervisory reponse F=1 */
- LOGP(DLLAPDM, LOGL_NOTICE, "S frame response with F=1 error\n");
- rsl_rll_error(RLL_CAUSE_UNSOL_SPRV_RESP, mctx);
- }
+ if (!dp->oph.msg)
+ return send_rll_simple(rll_msg, mctx);
- switch (dl->state) {
- case LAPDm_STATE_IDLE:
- /* if P=1, respond DM with F=1 (5.2.2) */
- /* 5.4.5 all other frame types shall be discarded */
- if (LAPDm_CTRL_PF_BIT(mctx->ctrl))
- lapdm_send_dm(mctx); /* F=P */
- /* fall though */
- case LAPDm_STATE_SABM_SENT:
- case LAPDm_STATE_DISC_SENT:
- LOGP(DLLAPDM, LOGL_NOTICE, "S frame ignored in this state\n");
- msgb_free(msg);
- return 0;
- }
- switch (LAPDm_CTRL_S_BITS(mctx->ctrl)) {
- case LAPDm_S_RR:
- LOGP(DLLAPDM, LOGL_INFO, "RR received\n");
- /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
- lapdm_acknowledge(mctx);
-
- /* 5.5.3.2 */
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd
- && LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
- if (!dl->own_busy && !dl->seq_err_cond) {
- LOGP(DLLAPDM, LOGL_NOTICE, "RR frame command "
- "with polling bit set and we are not "
- "busy, so we reply with RR frame\n");
- lapdm_send_rr(mctx, 1);
- /* NOTE: In case of sequence error condition,
- * the REJ frame has been transmitted when
- * entering the condition, so it has not be
- * done here
- */
- } else if (dl->own_busy) {
- LOGP(DLLAPDM, LOGL_NOTICE, "RR frame command "
- "with polling bit set and we are busy, "
- "so we reply with RR frame\n");
- lapdm_send_rnr(mctx, 1);
- }
- } else if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp
- && LAPDm_CTRL_PF_BIT(mctx->ctrl)
- && dl->state == LAPDm_STATE_TIMER_RECOV) {
- LOGP(DLLAPDM, LOGL_INFO, "RR response with F==1, "
- "and we are in timer recovery state, so "
- "we leave that state\n");
- /* V(S) to the N(R) in the RR frame */
- dl->V_send = LAPDm_CTRL_Nr(mctx->ctrl);
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- /* 5.5.7 Clear timer recovery condition */
- lapdm_dl_newstate(dl, LAPDm_STATE_MF_EST);
- }
- /* Send message, if possible due to acknowledged data */
- rslms_send_i(mctx, __LINE__);
+ return send_rslms_rll_l3(rll_msg, mctx, dp->oph.msg);
+}
+/* send a data frame to layer 1 */
+static int lapdm_send_ph_data_req(struct lapd_msg_ctx *lctx, struct msgb *msg)
+{
+ uint8_t l3_len = msg->tail - msg->data;
+ struct lapd_datalink *dl = lctx->dl;
+ struct lapdm_datalink *mdl =
+ container_of(dl, struct lapdm_datalink, dl);
+ struct lapdm_msg_ctx *mctx = &mdl->mctx;
+ int format = lctx->format;
+
+ /* prepend l2 header */
+ msg->l2h = msgb_push(msg, 3);
+ msg->l2h[0] = LAPDm_ADDR(lctx->lpd, lctx->sapi, lctx->cr);
+ /* EA is set here too */
+ switch (format) {
+ case LAPD_FORM_I:
+ msg->l2h[1] = LAPDm_CTRL_I(lctx->n_recv, lctx->n_send,
+ lctx->p_f);
break;
- case LAPDm_S_RNR:
- LOGP(DLLAPDM, LOGL_INFO, "RNR received\n");
- /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
- lapdm_acknowledge(mctx);
-
- /* 5.5.5 */
- /* Set peer receiver busy condition */
- dl->peer_busy = 1;
-
- if (LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd) {
- if (!dl->own_busy) {
- LOGP(DLLAPDM, LOGL_INFO, "RNR poll "
- "command and we are not busy, "
- "so we reply with RR final "
- "response\n");
- /* Send RR with F=1 */
- lapdm_send_rr(mctx, 1);
- } else {
- LOGP(DLLAPDM, LOGL_INFO, "RNR poll "
- "command and we are busy, so "
- "we reply with RNR final "
- "response\n");
- /* Send RNR with F=1 */
- lapdm_send_rnr(mctx, 1);
- }
- } else if (dl->state == LAPDm_STATE_TIMER_RECOV) {
- LOGP(DLLAPDM, LOGL_INFO, "RNR poll response "
- "and we in timer recovery state, so "
- "we leave that state\n");
- /* 5.5.7 Clear timer recovery condition */
- lapdm_dl_newstate(dl, LAPDm_STATE_MF_EST);
- /* V(S) to the N(R) in the RNR frame */
- dl->V_send = LAPDm_CTRL_Nr(mctx->ctrl);
- }
- } else
- LOGP(DLLAPDM, LOGL_INFO, "RNR not polling/final state "
- "received\n");
-
- /* Send message, if possible due to acknowledged data */
- rslms_send_i(mctx, __LINE__);
-
+ case LAPD_FORM_S:
+ msg->l2h[1] = LAPDm_CTRL_S(lctx->n_recv, lctx->s_u, lctx->p_f);
break;
- case LAPDm_S_REJ:
- LOGP(DLLAPDM, LOGL_INFO, "REJ received\n");
- /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
- lapdm_acknowledge(mctx);
-
- /* 5.5.4.1 */
- if (dl->state != LAPDm_STATE_TIMER_RECOV) {
- /* Clear an existing peer receiver busy condition */
- dl->peer_busy = 0;
- /* V(S) and V(A) to the N(R) in the REJ frame */
- dl->V_send = dl->V_ack = LAPDm_CTRL_Nr(mctx->ctrl);
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- /* 5.5.3.2 */
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd
- && LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
- if (!dl->own_busy && !dl->seq_err_cond) {
- LOGP(DLLAPDM, LOGL_INFO, "REJ poll "
- "command not in timer recovery "
- "state and not in own busy "
- "condition received, so we "
- "respond with RR final "
- "response\n");
- lapdm_send_rr(mctx, 1);
- /* NOTE: In case of sequence error
- * condition, the REJ frame has been
- * transmitted when entering the
- * condition, so it has not be done
- * here
- */
- } else if (dl->own_busy) {
- LOGP(DLLAPDM, LOGL_INFO, "REJ poll "
- "command not in timer recovery "
- "state and in own busy "
- "condition received, so we "
- "respond with RNR final "
- "response\n");
- lapdm_send_rnr(mctx, 1);
- }
- } else
- LOGP(DLLAPDM, LOGL_INFO, "REJ response or not "
- "polling command not in timer recovery "
- "state received\n");
- /* send MDL ERROR INIDCATION to L3 */
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp
- && LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
- rsl_rll_error(RLL_CAUSE_UNSOL_SPRV_RESP, mctx);
- }
-
- } else if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp
- && LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
- LOGP(DLLAPDM, LOGL_INFO, "REJ poll response in timer "
- "recovery state received\n");
- /* Clear an existing peer receiver busy condition */
- dl->peer_busy = 0;
- /* 5.5.7 Clear timer recovery condition */
- lapdm_dl_newstate(dl, LAPDm_STATE_MF_EST);
- /* V(S) and V(A) to the N(R) in the REJ frame */
- dl->V_send = dl->V_ack = LAPDm_CTRL_Nr(mctx->ctrl);
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- } else {
- /* Clear an existing peer receiver busy condition */
- dl->peer_busy = 0;
- /* V(S) and V(A) to the N(R) in the REJ frame */
- dl->V_send = dl->V_ack = LAPDm_CTRL_Nr(mctx->ctrl);
- /* 5.5.3.2 */
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd
- && LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
- if (!dl->own_busy && !dl->seq_err_cond) {
- LOGP(DLLAPDM, LOGL_INFO, "REJ poll "
- "command in timer recovery "
- "state and not in own busy "
- "condition received, so we "
- "respond with RR final "
- "response\n");
- lapdm_send_rr(mctx, 1);
- /* NOTE: In case of sequence error
- * condition, the REJ frame has been
- * transmitted when entering the
- * condition, so it has not be done
- * here
- */
- } else if (dl->own_busy) {
- LOGP(DLLAPDM, LOGL_INFO, "REJ poll "
- "command in timer recovery "
- "state and in own busy "
- "condition received, so we "
- "respond with RNR final "
- "response\n");
- lapdm_send_rnr(mctx, 1);
- }
- } else
- LOGP(DLLAPDM, LOGL_INFO, "REJ response or not "
- "polling command in timer recovery "
- "state received\n");
- }
-
- /* FIXME: 5.5.4.2 2) */
-
- /* Send message, if possible due to acknowledged data */
- rslms_send_i(mctx, __LINE__);
-
+ case LAPD_FORM_U:
+ msg->l2h[1] = LAPDm_CTRL_U(lctx->s_u, lctx->p_f);
break;
default:
- /* G.3.1 */
- LOGP(DLLAPDM, LOGL_NOTICE, "Supervisory frame not allowed.\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
- return -EINVAL;
- }
- msgb_free(msg);
- return 0;
-}
-
-/* Receive a LAPDm I (Information) message from L1 */
-static int lapdm_rx_i(struct msgb *msg, struct lapdm_msg_ctx *mctx)
-{
- struct lapdm_datalink *dl = mctx->dl;
- struct lapdm_entity *le = dl->entity;
- //uint8_t nr = LAPDm_CTRL_Nr(mctx->ctrl);
- uint8_t ns = LAPDm_CTRL_I_Ns(mctx->ctrl);
- uint8_t length;
- int rc;
-
- LOGP(DLLAPDM, LOGL_NOTICE, "I received\n");
-
- /* G.2.2 Wrong value of the C/R bit */
- if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp) {
- LOGP(DLLAPDM, LOGL_NOTICE, "I frame response not allowed\n");
msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
return -EINVAL;
}
+ msg->l2h[2] = LAPDm_LEN(l3_len); /* EL is set here too */
+ if (lctx->more)
+ msg->l2h[2] |= LAPDm_MORE;
- length = msg->l2h[2] >> 2;
- if (length == 0 || length + 3 > mctx->n201) {
- /* G.4.2 If the length indicator of an I frame is set
- * to a numerical value L>N201 or L=0, an MDL-ERROR-INDICATION
- * primitive with cause "I frame with incorrect length"
- * is sent to the mobile management entity. */
- LOGP(DLLAPDM, LOGL_NOTICE, "I frame length not allowed\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_IFRM_INC_LEN, mctx);
- return -EIO;
- }
-
- /* G.4.2 If the numerical value of L is L<N201 and the M
- * bit is set to "1", then an MDL-ERROR-INDICATION primitive with
- * cause "I frame with incorrect use of M bit" is sent to the
- * mobile management entity. */
- if ((msg->l2h[2] & LAPDm_MORE) && length + 3 < mctx->n201) {
- LOGP(DLLAPDM, LOGL_NOTICE, "I frame with M bit too short\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_IFRM_INC_MBITS, mctx);
- return -EIO;
- }
-
- switch (dl->state) {
- case LAPDm_STATE_IDLE:
- /* if P=1, respond DM with F=1 (5.2.2) */
- /* 5.4.5 all other frame types shall be discarded */
- if (LAPDm_CTRL_PF_BIT(mctx->ctrl))
- lapdm_send_dm(mctx); /* F=P */
- /* fall though */
- case LAPDm_STATE_SABM_SENT:
- case LAPDm_STATE_DISC_SENT:
- LOGP(DLLAPDM, LOGL_NOTICE, "I frame ignored in this state\n");
- msgb_free(msg);
- return 0;
- }
+ /* add ACCH header with last indicated tx-power and TA */
+ if ((mctx->link_id & 0x40)) {
+ struct lapdm_entity *le = mdl->entity;
- /* 5.7.1: N(s) sequence error */
- if (ns != dl->V_recv) {
- LOGP(DLLAPDM, LOGL_NOTICE, "N(S) sequence error: N(S)=%u, "
- "V(R)=%u\n", ns, dl->V_recv);
- /* discard data */
- msgb_free(msg);
- if (!dl->seq_err_cond) {
- /* FIXME: help me understand what exactly todo here
- dl->seq_err_cond = 1;
- */
- lapdm_send_rej(mctx, LAPDm_CTRL_PF_BIT(mctx->ctrl));
- } else {
- }
- return -EIO;
+ msg->l2h = msgb_push(msg, 2);
+ msg->l2h[0] = le->tx_power;
+ msg->l2h[1] = le->ta;
}
- dl->seq_err_cond = 0;
-
- /* Increment receiver state */
- dl->V_recv = inc_mod8(dl->V_recv);
- LOGP(DLLAPDM, LOGL_NOTICE, "incrementing V(R) to %u\n", dl->V_recv);
-
- /* 5.5.3.1: Acknowlege all transmitted frames up the the N(R)-1 */
- lapdm_acknowledge(mctx); /* V(A) is also set here */
-
- /* Only if we are not in own receiver busy condition */
- if (!dl->own_busy) {
- /* if the frame carries a complete segment */
- if (!(msg->l2h[2] & LAPDm_MORE)
- && !dl->rcv_buffer) {
- LOGP(DLLAPDM, LOGL_INFO, "message in single I frame\n");
- /* send a DATA INDICATION to L3 */
- msg->l3h = msg->l2h + 3;
- msgb_pull_l2h(msg);
- msg->len = length;
- msg->tail = msg->data + length;
- rc = send_rslms_rll_l3(RSL_MT_DATA_IND, mctx, msg);
- } else {
- /* create rcv_buffer */
- if (!dl->rcv_buffer) {
- LOGP(DLLAPDM, LOGL_INFO, "message in multiple I "
- "frames (first message)\n");
- dl->rcv_buffer = msgb_alloc_headroom(200+56, 56,
- "LAPDm RX");
- dl->rcv_buffer->l3h = dl->rcv_buffer->data;
- }
- /* concat. rcv_buffer */
- if (msgb_l3len(dl->rcv_buffer) + length > 200) {
- LOGP(DLLAPDM, LOGL_NOTICE, "Received frame "
- "overflow!\n");
- } else {
- memcpy(msgb_put(dl->rcv_buffer, length),
- msg->l2h + 3, length);
- }
- /* if the last segment was received */
- if (!(msg->l2h[2] & LAPDm_MORE)) {
- LOGP(DLLAPDM, LOGL_INFO, "message in multiple I "
- "frames (last message)\n");
- rc = send_rslms_rll_l3(RSL_MT_DATA_IND, mctx,
- dl->rcv_buffer);
- dl->rcv_buffer = NULL;
- } else
- LOGP(DLLAPDM, LOGL_INFO, "message in multiple I "
- "frames (next message)\n");
- msgb_free(msg);
-
- }
- } else
- LOGP(DLLAPDM, LOGL_INFO, "I frame ignored during own receiver "
- "busy condition\n");
-
- /* Check for P bit */
- if (LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
- /* 5.5.2.1 */
- /* check if we are not in own receiver busy */
- if (!dl->own_busy) {
- LOGP(DLLAPDM, LOGL_INFO, "we are not busy, send RR\n");
- /* Send RR with F=1 */
- rc = lapdm_send_rr(mctx, 1);
- } else {
- LOGP(DLLAPDM, LOGL_INFO, "we are busy, send RNR\n");
- /* Send RNR with F=1 */
- rc = lapdm_send_rnr(mctx, 1);
- }
- } else {
- /* 5.5.2.2 */
- /* check if we are not in own receiver busy */
- if (!dl->own_busy) {
- /* NOTE: V(R) is already set above */
- rc = rslms_send_i(mctx, __LINE__);
- if (rc) {
- LOGP(DLLAPDM, LOGL_INFO, "we are not busy and "
- "have no pending data, send RR\n");
- /* Send RR with F=0 */
- return lapdm_send_rr(mctx, 0);
- }
- /* all I or one RR is sent, we are done */
- return 0;
- } else {
- LOGP(DLLAPDM, LOGL_INFO, "we are busy, send RNR\n");
- /* Send RNR with F=0 */
- rc = lapdm_send_rnr(mctx, 0);
- }
- }
-
- /* Send message, if possible due to acknowledged data */
- rslms_send_i(mctx, __LINE__);
-
- return rc;
-}
-/* Receive a LAPDm message from L1 */
-static int lapdm_ph_data_ind(struct msgb *msg, struct lapdm_msg_ctx *mctx)
-{
- int rc;
-
- /* G.2.3 EA bit set to "0" is not allowed in GSM */
- if (!LAPDm_ADDR_EA(mctx->addr)) {
- LOGP(DLLAPDM, LOGL_NOTICE, "EA bit 0 is not allowed in GSM\n");
- msgb_free(msg);
- rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
- return -EINVAL;
- }
-
- if (LAPDm_CTRL_is_U(mctx->ctrl))
- rc = lapdm_rx_u(msg, mctx);
- else if (LAPDm_CTRL_is_S(mctx->ctrl))
- rc = lapdm_rx_s(msg, mctx);
- else if (LAPDm_CTRL_is_I(mctx->ctrl))
- rc = lapdm_rx_i(msg, mctx);
- else {
- LOGP(DLLAPDM, LOGL_NOTICE, "unknown LAPDm format\n");
- msgb_free(msg);
- rc = -EINVAL;
- }
- return rc;
+ return tx_ph_data_enqueue(mctx->dl, msg, mctx->chan_nr, mctx->link_id,
+ 23);
}
/* input into layer2 (from layer 1) */
-static int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, uint8_t chan_nr, uint8_t link_id)
+static int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le,
+ uint8_t chan_nr, uint8_t link_id)
{
uint8_t cbits = chan_nr >> 3;
uint8_t sapi; /* we cannot take SAPI from link_id, as L1 has no clue */
struct lapdm_msg_ctx mctx;
+ struct lapd_msg_ctx lctx;
int rc = 0;
+ int n201;
/* when we reach here, we have a msgb with l2h pointing to the raw
* 23byte mac block. The l1h has already been purged. */
+ memset(&mctx, 0, sizeof(mctx));
mctx.chan_nr = chan_nr;
mctx.link_id = link_id;
- mctx.addr = mctx.ctrl = 0;
/* check for L1 chan_nr/link_id and determine LAPDm hdr format */
if (cbits == 0x10 || cbits == 0x12) {
/* Format Bbis is used on BCCH and CCCH(PCH, NCH and AGCH) */
mctx.lapdm_fmt = LAPDm_FMT_Bbis;
- mctx.n201 = N201_Bbis;
+ n201 = N201_Bbis;
sapi = 0;
} else {
if (mctx.link_id & 0x40) {
/* It was received from network on SACCH */
- /* If sent by BTS, lapdm_fmt must be B4 */
- if (le->mode == LAPDM_MODE_MS) {
+ /* If UI on SACCH sent by BTS, lapdm_fmt must be B4 */
+ if (le->mode == LAPDM_MODE_MS
+ && LAPDm_CTRL_is_U(msg->l2h[3])
+ && LAPDm_CTRL_U_BITS(msg->l2h[3]) == 0) {
mctx.lapdm_fmt = LAPDm_FMT_B4;
- mctx.n201 = N201_B4;
- LOGP(DLLAPDM, LOGL_INFO, "fmt=B4\n");
+ n201 = N201_B4;
+ LOGP(DLLAPD, LOGL_INFO, "fmt=B4\n");
} else {
mctx.lapdm_fmt = LAPDm_FMT_B;
- mctx.n201 = N201_AB_SACCH;
- LOGP(DLLAPDM, LOGL_INFO, "fmt=B\n");
+ n201 = N201_AB_SACCH;
+ LOGP(DLLAPD, LOGL_INFO, "fmt=B\n");
}
/* SACCH frames have a two-byte L1 header that
* OsmocomBB L1 doesn't strip */
@@ -1647,8 +541,8 @@ static int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, uint8_t cha
sapi = (msg->l2h[0] >> 2) & 7;
} else {
mctx.lapdm_fmt = LAPDm_FMT_B;
- LOGP(DLLAPDM, LOGL_INFO, "fmt=B\n");
- mctx.n201 = 23; // FIXME: select correct size by chan.
+ LOGP(DLLAPD, LOGL_INFO, "fmt=B\n");
+ n201 = N201_AB_SDCCH;
sapi = (msg->l2h[0] >> 2) & 7;
}
}
@@ -1656,7 +550,7 @@ static int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, uint8_t cha
mctx.dl = datalink_for_sapi(le, sapi);
/* G.2.1 No action on frames containing an unallocated SAPI. */
if (!mctx.dl) {
- LOGP(DLLAPDM, LOGL_NOTICE, "Received frame for unsupported "
+ LOGP(DLLAPD, LOGL_NOTICE, "Received frame for unsupported "
"SAPI %d!\n", sapi);
msgb_free(msg);
return -EIO;
@@ -1666,17 +560,77 @@ static int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, uint8_t cha
case LAPDm_FMT_A:
case LAPDm_FMT_B:
case LAPDm_FMT_B4:
- mctx.addr = msg->l2h[0];
- if (!(mctx.addr & 0x01)) {
- LOGP(DLLAPDM, LOGL_ERROR, "we don't support "
- "multibyte addresses (discarding)\n");
+ lctx.dl = &mctx.dl->dl;
+ /* obtain SAPI from address field */
+ mctx.link_id |= LAPDm_ADDR_SAPI(msg->l2h[0]);
+ /* G.2.3 EA bit set to "0" is not allowed in GSM */
+ if (!LAPDm_ADDR_EA(msg->l2h[0])) {
+ LOGP(DLLAPD, LOGL_NOTICE, "EA bit 0 is not allowed in "
+ "GSM\n");
msgb_free(msg);
+ rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, &mctx);
return -EINVAL;
}
- mctx.ctrl = msg->l2h[1];
- /* obtain SAPI from address field */
- mctx.link_id |= LAPDm_ADDR_SAPI(mctx.addr);
- rc = lapdm_ph_data_ind(msg, &mctx);
+ /* adress field */
+ lctx.lpd = LAPDm_ADDR_LPD(msg->l2h[0]);
+ lctx.sapi = LAPDm_ADDR_SAPI(msg->l2h[0]);
+ lctx.cr = LAPDm_ADDR_CR(msg->l2h[0]);
+ /* command field */
+ if (LAPDm_CTRL_is_I(msg->l2h[1])) {
+ lctx.format = LAPD_FORM_I;
+ lctx.n_send = LAPDm_CTRL_I_Ns(msg->l2h[1]);
+ lctx.n_recv = LAPDm_CTRL_Nr(msg->l2h[1]);
+ } else if (LAPDm_CTRL_is_S(msg->l2h[1])) {
+ lctx.format = LAPD_FORM_S;
+ lctx.n_recv = LAPDm_CTRL_Nr(msg->l2h[1]);
+ lctx.s_u = LAPDm_CTRL_S_BITS(msg->l2h[1]);
+ } else if (LAPDm_CTRL_is_U(msg->l2h[1])) {
+ lctx.format = LAPD_FORM_U;
+ lctx.s_u = LAPDm_CTRL_U_BITS(msg->l2h[1]);
+ } else
+ lctx.format = LAPD_FORM_UKN;
+ lctx.p_f = LAPDm_CTRL_PF_BIT(msg->l2h[1]);
+ if (lctx.sapi != LAPDm_SAPI_NORMAL
+ && lctx.sapi != LAPDm_SAPI_SMS
+ && lctx.format == LAPD_FORM_U
+ && lctx.s_u == LAPDm_U_UI) {
+ /* 5.3.3 UI frames with invalid SAPI values shall be
+ * discarded
+ */
+ LOGP(DLLAPD, LOGL_INFO, "sapi=%u (discarding)\n",
+ lctx.sapi);
+ msgb_free(msg);
+ return 0;
+ }
+ if (mctx.lapdm_fmt == LAPDm_FMT_B4) {
+ lctx.n201 = n201;
+ lctx.length = n201;
+ lctx.more = 0;
+ msg->l3h = msg->l2h + 2;
+ msgb_pull_l2h(msg);
+ } else {
+ /* length field */
+ if (!(msg->l2h[2] & LAPDm_EL)) {
+ /* G.4.1 If the EL bit is set to "0", an
+ * MDL-ERROR-INDICATION primitive with cause
+ * "frame not implemented" is sent to the
+ * mobile management entity. */
+ LOGP(DLLAPD, LOGL_NOTICE, "we don't support "
+ "multi-octet length\n");
+ msgb_free(msg);
+ rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, &mctx);
+ return -EINVAL;
+ }
+ lctx.n201 = n201;
+ lctx.length = msg->l2h[2] >> 2;
+ lctx.more = !!(msg->l2h[2] & LAPDm_MORE);
+ msg->l3h = msg->l2h + 3;
+ msgb_pull_l2h(msg);
+ }
+ /* store context for messages from lapd */
+ memcpy(&mctx.dl->mctx, &mctx, sizeof(mctx.dl->mctx));
+ /* send to LAPD */
+ rc = lapd_ph_data_ind(msg, &lctx);
break;
case LAPDm_FMT_Bter:
/* FIXME */
@@ -1684,7 +638,7 @@ static int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, uint8_t cha
break;
case LAPDm_FMT_Bbis:
/* directly pass up to layer3 */
- LOGP(DLLAPDM, LOGL_INFO, "fmt=Bbis UI\n");
+ LOGP(DLLAPD, LOGL_INFO, "fmt=Bbis UI\n");
msg->l3h = msg->l2h;
msgb_pull_l2h(msg);
rc = send_rslms_rll_l3(RSL_MT_UNIT_DATA_IND, &mctx, msg);
@@ -1732,7 +686,7 @@ int lapdm_phsap_up(struct osmo_prim_hdr *oph, struct lapdm_entity *le)
int rc = 0;
if (oph->sap != SAP_GSM_PH) {
- LOGP(DLLAPDM, LOGL_ERROR, "primitive for unknown SAP %u\n",
+ LOGP(DLLAPD, LOGL_ERROR, "primitive for unknown SAP %u\n",
oph->sap);
return -ENODEV;
}
@@ -1740,7 +694,7 @@ int lapdm_phsap_up(struct osmo_prim_hdr *oph, struct lapdm_entity *le)
switch (oph->primitive) {
case PRIM_PH_DATA:
if (oph->operation != PRIM_OP_INDICATION) {
- LOGP(DLLAPDM, LOGL_ERROR, "PH_DATA is not INDICATION %u\n",
+ LOGP(DLLAPD, LOGL_ERROR, "PH_DATA is not INDICATION %u\n",
oph->operation);
return -ENODEV;
}
@@ -1749,7 +703,7 @@ int lapdm_phsap_up(struct osmo_prim_hdr *oph, struct lapdm_entity *le)
break;
case PRIM_PH_RTS:
if (oph->operation != PRIM_OP_INDICATION) {
- LOGP(DLLAPDM, LOGL_ERROR, "PH_RTS is not INDICATION %u\n",
+ LOGP(DLLAPD, LOGL_ERROR, "PH_RTS is not INDICATION %u\n",
oph->operation);
return -ENODEV;
}
@@ -1776,33 +730,44 @@ int lapdm_phsap_up(struct osmo_prim_hdr *oph, struct lapdm_entity *le)
/* L3 -> L2 / RSLMS -> LAPDm */
+/* Set LAPDm context for established connection */
+static int set_lapdm_context(struct lapdm_datalink *dl, uint8_t chan_nr,
+ uint8_t link_id, int n201, uint8_t sapi)
+{
+ memset(&dl->mctx, 0, sizeof(dl->mctx));
+ dl->mctx.dl = dl;
+ dl->mctx.chan_nr = chan_nr;
+ dl->mctx.link_id = link_id;
+ dl->dl.lctx.dl = &dl->dl;
+ dl->dl.lctx.n201 = n201;
+ dl->dl.lctx.sapi = sapi;
+
+ return 0;
+}
+
/* L3 requests establishment of data link */
static int rslms_rx_rll_est_req(struct msgb *msg, struct lapdm_datalink *dl)
{
- struct lapdm_entity *le = dl->entity;
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
uint8_t chan_nr = rllh->chan_nr;
uint8_t link_id = rllh->link_id;
uint8_t sapi = rllh->link_id & 7;
struct tlv_parsed tv;
uint8_t length;
- uint8_t n201 = 23; //FIXME
+ uint8_t n201 = (rllh->link_id & 0x40) ? N201_AB_SACCH : N201_AB_SDCCH;
+ struct osmo_dlsap_prim dp;
- /* Set chan_nr and link_id for established connection */
- memset(&dl->mctx, 0, sizeof(dl->mctx));
- dl->mctx.dl = dl;
- dl->mctx.n201 = n201;
- dl->mctx.chan_nr = chan_nr;
- dl->mctx.link_id = link_id;
+ /* Set LAPDm context for established connection */
+ set_lapdm_context(dl, chan_nr, link_id, n201, sapi);
- rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
+ rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg) - sizeof(*rllh));
if (TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
- msg->l3h = TLVP_VAL(&tv, RSL_IE_L3_INFO);
+ msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
/* contention resolution establishment procedure */
if (sapi != 0) {
/* According to clause 6, the contention resolution
* procedure is only permitted with SAPI value 0 */
- LOGP(DLLAPDM, LOGL_ERROR, "SAPI != 0 but contention"
+ LOGP(DLLAPD, LOGL_ERROR, "SAPI != 0 but contention"
"resolution (discarding)\n");
msgb_free(msg);
return send_rll_simple(RSL_MT_REL_IND, &dl->mctx);
@@ -1810,112 +775,89 @@ static int rslms_rx_rll_est_req(struct msgb *msg, struct lapdm_datalink *dl)
/* transmit a SABM command with the P bit set to "1". The SABM
* command shall contain the layer 3 message unit */
length = TLVP_LEN(&tv, RSL_IE_L3_INFO);
- LOGP(DLLAPDM, LOGL_INFO, "perform establishment with content "
- "(SABM)\n");
} else {
/* normal establishment procedure */
+ msg->l3h = msg->l2h + sizeof(*rllh);
length = 0;
- LOGP(DLLAPDM, LOGL_INFO, "perform normal establishm. (SABM)\n");
}
/* check if the layer3 message length exceeds N201 */
- if (length + 3 > 21) { /* FIXME: do we know the channel N201? */
- LOGP(DLLAPDM, LOGL_ERROR, "frame too large: %d > N201(%d) "
- "(discarding)\n", length + 3, 21);
+ if (length > n201) {
+ LOGP(DLLAPD, LOGL_ERROR, "frame too large: %d > N201(%d) "
+ "(discarding)\n", length, n201);
msgb_free(msg);
return send_rll_simple(RSL_MT_REL_IND, &dl->mctx);
}
- /* Flush send-queue */
- /* Clear send-buffer */
- lapdm_dl_flush_send(dl);
-
- /* Discard partly received L3 message */
- if (dl->rcv_buffer) {
- msgb_free(dl->rcv_buffer);
- dl->rcv_buffer = NULL;
- }
-
- /* Remove RLL header from msgb */
+ /* Remove RLL header from msgb and set length to L3-info */
msgb_pull_l2h(msg);
+ msg->len = length;
+ msg->tail = msg->l3h + length;
- /* Push LAPDm header on msgb */
- msg->l2h = msgb_push(msg, 3);
- msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.cmd);
- msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_SABM, 1);
- msg->l2h[2] = LAPDm_LEN(length);
- /* Transmit-buffer carries exactly one segment */
- memcpy(dl->tx_hist[0], msg->l2h, 3 + length);
- dl->tx_length[0] = 3 + length;
- /* set Vs to 0, because it is used as index when resending SABM */
- dl->V_send = 0;
-
- /* Set states */
- dl->own_busy = dl->peer_busy = 0;
- dl->retrans_ctr = 0;
- lapdm_dl_newstate(dl, LAPDm_STATE_SABM_SENT);
-
- /* Tramsmit and start T200 */
- osmo_timer_schedule(&dl->t200, T200);
- return tx_ph_data_enqueue(dl, msg, chan_nr, link_id, n201);
+ /* prepare prim */
+ osmo_prim_init(&dp.oph, 0, PRIM_DL_EST, PRIM_OP_REQUEST, msg);
+
+ /* send to L2 */
+ return lapd_recv_dlsap(&dp, &dl->dl.lctx);
}
/* L3 requests transfer of unnumbered information */
static int rslms_rx_rll_udata_req(struct msgb *msg, struct lapdm_datalink *dl)
{
struct lapdm_entity *le = dl->entity;
+ int ui_bts = (le->mode == LAPDM_MODE_BTS);
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
uint8_t chan_nr = rllh->chan_nr;
uint8_t link_id = rllh->link_id;
uint8_t sapi = link_id & 7;
struct tlv_parsed tv;
int length;
- uint8_t n201 = 23; //FIXME
- uint8_t ta = 0, tx_power = 0;
/* check if the layer3 message length exceeds N201 */
rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
if (TLVP_PRESENT(&tv, RSL_IE_TIMING_ADVANCE)) {
- ta = *TLVP_VAL(&tv, RSL_IE_TIMING_ADVANCE);
+ le->ta = *TLVP_VAL(&tv, RSL_IE_TIMING_ADVANCE);
}
if (TLVP_PRESENT(&tv, RSL_IE_MS_POWER)) {
- tx_power = *TLVP_VAL(&tv, RSL_IE_MS_POWER);
+ le->tx_power = *TLVP_VAL(&tv, RSL_IE_MS_POWER);
}
if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
- LOGP(DLLAPDM, LOGL_ERROR, "unit data request without message "
+ LOGP(DLLAPD, LOGL_ERROR, "unit data request without message "
"error\n");
msgb_free(msg);
return -EINVAL;
}
- msg->l3h = TLVP_VAL(&tv, RSL_IE_L3_INFO);
+ msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
length = TLVP_LEN(&tv, RSL_IE_L3_INFO);
/* check if the layer3 message length exceeds N201 */
- if (length + 5 > 23) { /* FIXME: do we know the channel N201? */
- LOGP(DLLAPDM, LOGL_ERROR, "frame too large: %d > N201(%d) "
- "(discarding)\n", length + 5, 23);
+ if (length + 4 + !ui_bts > 23) {
+ LOGP(DLLAPD, LOGL_ERROR, "frame too large: %d > N201(%d) "
+ "(discarding)\n", length, 18 + ui_bts);
msgb_free(msg);
return -EIO;
}
- LOGP(DLLAPDM, LOGL_INFO, "sending unit data (tx_power=%d, ta=%d)\n",
- tx_power, ta);
+ LOGP(DLLAPD, LOGL_INFO, "sending unit data (tx_power=%d, ta=%d)\n",
+ le->tx_power, le->ta);
- /* Remove RLL header from msgb */
+ /* Remove RLL header from msgb and set length to L3-info */
msgb_pull_l2h(msg);
+ msg->len = length;
+ msg->tail = msg->l3h + length;
/* Push L1 + LAPDm header on msgb */
- msg->l2h = msgb_push(msg, 2 + 3);
- msg->l2h[0] = tx_power;
- msg->l2h[1] = ta;
- msg->l2h[2] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.cmd);
+ msg->l2h = msgb_push(msg, 4 + !ui_bts);
+ msg->l2h[0] = le->tx_power;
+ msg->l2h[1] = le->ta;
+ msg->l2h[2] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, dl->dl.cr.loc2rem.cmd);
msg->l2h[3] = LAPDm_CTRL_U(LAPDm_U_UI, 0);
- msg->l2h[4] = LAPDm_LEN(length);
- // FIXME: short L2 header support
+ if (!ui_bts)
+ msg->l2h[4] = LAPDm_LEN(length);
/* Tramsmit */
- return tx_ph_data_enqueue(dl, msg, chan_nr, link_id, n201);
+ return tx_ph_data_enqueue(dl, msg, chan_nr, link_id, 23);
}
/* L3 requests transfer of acknowledged information */
@@ -1923,143 +865,29 @@ static int rslms_rx_rll_data_req(struct msgb *msg, struct lapdm_datalink *dl)
{
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
struct tlv_parsed tv;
+ int length;
+ struct osmo_dlsap_prim dp;
rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
- LOGP(DLLAPDM, LOGL_ERROR, "data request without message "
+ LOGP(DLLAPD, LOGL_ERROR, "data request without message "
"error\n");
msgb_free(msg);
return -EINVAL;
}
- msg->l3h = TLVP_VAL(&tv, RSL_IE_L3_INFO);
-
- LOGP(DLLAPDM, LOGL_INFO, "writing message to send-queue\n");
+ msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
+ length = TLVP_LEN(&tv, RSL_IE_L3_INFO);
- /* Remove the RSL/RLL header */
+ /* Remove RLL header from msgb and set length to L3-info */
msgb_pull_l2h(msg);
+ msg->len = length;
+ msg->tail = msg->l3h + length;
- /* Write data into the send queue */
- msgb_enqueue(&dl->send_queue, msg);
+ /* prepare prim */
+ osmo_prim_init(&dp.oph, 0, PRIM_DL_DATA, PRIM_OP_REQUEST, msg);
- /* Send message, if possible */
- rslms_send_i(&dl->mctx, __LINE__);
- return 0;
-}
-
-/* Send next I frame from queued/buffered data */
-static int rslms_send_i(struct lapdm_msg_ctx *mctx, int line)
-{
- struct lapdm_datalink *dl = mctx->dl;
- struct lapdm_entity *le = dl->entity;
- uint8_t chan_nr = mctx->chan_nr;
- uint8_t link_id = mctx->link_id;
- uint8_t sapi = link_id & 7;
- int k = k_sapi[sapi];
- struct msgb *msg;
- int length, left;
- int rc = - 1; /* we sent nothing */
-
- LOGP(DLLAPDM, LOGL_INFO, "%s() called from line %d\n", __func__, line);
-
- next_frame:
-
- if (dl->peer_busy) {
- LOGP(DLLAPDM, LOGL_INFO, "peer busy, not sending\n");
- return rc;
- }
-
- if (dl->state == LAPDm_STATE_TIMER_RECOV) {
- LOGP(DLLAPDM, LOGL_INFO, "timer recovery, not sending\n");
- return rc;
- }
-
- /* If the send state variable V(S) is equal to V(A) plus k
- * (where k is the maximum number of outstanding I frames - see
- * subclause 5.8.4), the data link layer entity shall not transmit any
- * new I frames, but shall retransmit an I frame as a result
- * of the error recovery procedures as described in subclauses 5.5.4 and
- * 5.5.7. */
- if (dl->V_send == add_mod8(dl->V_ack, k)) {
- LOGP(DLLAPDM, LOGL_INFO, "k frames outstanding, not sending "
- "more (k=%u V(S)=%u V(A)=%u)\n", k, dl->V_send,
- dl->V_ack);
- return rc;
- }
-
- /* if we have no tx_hist yet, we create it */
- if (!dl->tx_length[dl->V_send]) {
- /* Get next message into send-buffer, if any */
- if (!dl->send_buffer) {
- next_message:
- dl->send_out = 0;
- dl->send_buffer = msgb_dequeue(&dl->send_queue);
- /* No more data to be sent */
- if (!dl->send_buffer)
- return rc;
- LOGP(DLLAPDM, LOGL_INFO, "get message from "
- "send-queue\n");
- }
-
- /* How much is left in the send-buffer? */
- left = msgb_l3len(dl->send_buffer) - dl->send_out;
- /* Segment, if data exceeds N201 */
- length = left;
- if (length > mctx->n201 - 3)
- length = mctx->n201 - 3;
- LOGP(DLLAPDM, LOGL_INFO, "msg-len %d sent %d left %d N201 %d "
- "length %d first byte %02x\n",
- msgb_l3len(dl->send_buffer), dl->send_out, left,
- mctx->n201, length, dl->send_buffer->l3h[0]);
- /* If message in send-buffer is completely sent */
- if (left == 0) {
- msgb_free(dl->send_buffer);
- dl->send_buffer = NULL;
- goto next_message;
- }
-
- LOGP(DLLAPDM, LOGL_INFO, "send I frame %sV(S)=%d\n",
- (left > length) ? "segment " : "", dl->V_send);
-
- /* Create I frame (segment) and transmit-buffer content */
- msg = msgb_alloc_headroom(23+10, 10, "LAPDm I");
- msg->l2h = msgb_put(msg, 3 + length);
- msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.cmd);
- msg->l2h[1] = LAPDm_CTRL_I(dl->V_recv, dl->V_send, 0);
- msg->l2h[2] = LAPDm_LEN(length);
- if (left > length)
- msg->l2h[2] |= LAPDm_MORE;
- memcpy(msg->l2h + 3, dl->send_buffer->l3h + dl->send_out,
- length);
- memcpy(dl->tx_hist[dl->V_send], msg->l2h, 3 + length);
- dl->tx_length[dl->V_send] = 3 + length;
- /* Add length to track how much is already in the tx buffer */
- dl->send_out += length;
- } else {
- LOGP(DLLAPDM, LOGL_INFO, "resend I frame from tx buffer "
- "V(S)=%d\n", dl->V_send);
-
- /* Create I frame (segment) from tx_hist */
- length = dl->tx_length[dl->V_send];
- msg = msgb_alloc_headroom(23+10, 10, "LAPDm I");
- msg->l2h = msgb_put(msg, length);
- memcpy(msg->l2h, dl->tx_hist[dl->V_send], length);
- msg->l2h[1] = LAPDm_CTRL_I(dl->V_recv, dl->V_send, 0);
- }
-
- /* The value of the send state variable V(S) shall be incremented by 1
- * at the end of the transmission of the I frame */
- dl->V_send = inc_mod8(dl->V_send);
-
- /* If timer T200 is not running at the time right before transmitting a
- * frame, when the PH-READY-TO-SEND primitive is received from the
- * physical layer., it shall be set. */
- if (!osmo_timer_pending(&dl->t200))
- osmo_timer_schedule(&dl->t200, T200);
-
- tx_ph_data_enqueue(dl, msg, chan_nr, link_id, mctx->n201);
-
- rc = 0; /* we sent something */
- goto next_frame;
+ /* send to L2 */
+ return lapd_recv_dlsap(&dp, &dl->dl.lctx);
}
/* L3 requests suspension of data link */
@@ -2067,165 +895,79 @@ static int rslms_rx_rll_susp_req(struct msgb *msg, struct lapdm_datalink *dl)
{
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
uint8_t sapi = rllh->link_id & 7;
+ struct osmo_dlsap_prim dp;
if (sapi != 0) {
- LOGP(DLLAPDM, LOGL_ERROR, "SAPI != 0 while suspending\n");
+ LOGP(DLLAPD, LOGL_ERROR, "SAPI != 0 while suspending\n");
msgb_free(msg);
return -EINVAL;
}
- LOGP(DLLAPDM, LOGL_INFO, "perform suspension\n");
-
- /* put back the send-buffer to the send-queue (first position) */
- if (dl->send_buffer) {
- LOGP(DLLAPDM, LOGL_INFO, "put frame in sendbuffer back to "
- "queue\n");
- llist_add(&dl->send_buffer->list, &dl->send_queue);
- dl->send_buffer = NULL;
- } else
- LOGP(DLLAPDM, LOGL_INFO, "no frame in sendbuffer\n");
-
- /* Clear transmit buffer, but keep send buffer */
- lapdm_dl_flush_tx(dl);
-
- msgb_free(msg);
+ /* prepare prim */
+ osmo_prim_init(&dp.oph, 0, PRIM_DL_SUSP, PRIM_OP_REQUEST, msg);
- return send_rll_simple(RSL_MT_SUSP_CONF, &dl->mctx);
+ /* send to L2 */
+ return lapd_recv_dlsap(&dp, &dl->dl.lctx);
}
/* L3 requests resume of data link */
static int rslms_rx_rll_res_req(struct msgb *msg, struct lapdm_datalink *dl)
{
- struct lapdm_entity *le = dl->entity;
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ int msg_type = rllh->c.msg_type;
uint8_t chan_nr = rllh->chan_nr;
uint8_t link_id = rllh->link_id;
uint8_t sapi = rllh->link_id & 7;
struct tlv_parsed tv;
uint8_t length;
- uint8_t n201 = 23; //FIXME
+ uint8_t n201 = (rllh->link_id & 0x40) ? N201_AB_SACCH : N201_AB_SDCCH;
+ struct osmo_dlsap_prim dp;
- /* Set chan_nr and link_id for established connection */
- memset(&dl->mctx, 0, sizeof(dl->mctx));
- dl->mctx.dl = dl;
- dl->mctx.n201 = n201;
- dl->mctx.chan_nr = chan_nr;
- dl->mctx.link_id = link_id;
+ /* Set LAPDm context for established connection */
+ set_lapdm_context(dl, chan_nr, link_id, n201, sapi);
rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
- LOGP(DLLAPDM, LOGL_ERROR, "resume without message error\n");
+ LOGP(DLLAPD, LOGL_ERROR, "resume without message error\n");
msgb_free(msg);
return send_rll_simple(RSL_MT_REL_IND, &dl->mctx);
}
+ msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
length = TLVP_LEN(&tv, RSL_IE_L3_INFO);
- LOGP(DLLAPDM, LOGL_INFO, "perform re-establishment (SABM) length=%d\n",
- length);
-
- /* Replace message in the send-buffer (reconnect) */
- if (dl->send_buffer)
- msgb_free(dl->send_buffer);
- dl->send_out = 0;
- if (length) {
- /* Remove the RSL/RLL header */
- msgb_pull_l2h(msg);
- /* Write data into the send buffer, to be sent first */
- dl->send_buffer = msg;
- }
+ /* Remove RLL header from msgb and set length to L3-info */
+ msgb_pull_l2h(msg);
+ msg->len = length;
+ msg->tail = msg->l3h + length;
- /* Discard partly received L3 message */
- if (dl->rcv_buffer) {
- msgb_free(dl->rcv_buffer);
- dl->rcv_buffer = NULL;
- }
+ /* prepare prim */
+ osmo_prim_init(&dp.oph, 0, (msg_type == RSL_MT_RES_REQ) ? PRIM_DL_RES
+ : PRIM_DL_RECON, PRIM_OP_REQUEST, msg);
- /* Create new msgb (old one is now free) */
- msg = msgb_alloc_headroom(23+10, 10, "LAPDm SABM");
- msg->l2h = msgb_put(msg, 3);
- msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.cmd);
- msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_SABM, 1);
- msg->l2h[2] = LAPDm_LEN(0);
- /* Transmit-buffer carries exactly one segment */
- memcpy(dl->tx_hist[0], msg->l2h, 3);
- dl->tx_length[0] = 3;
- /* set Vs to 0, because it is used as index when resending SABM */
- dl->V_send = 0;
-
- /* Set states */
- dl->own_busy = dl->peer_busy = 0;
- dl->retrans_ctr = 0;
- lapdm_dl_newstate(dl, LAPDm_STATE_SABM_SENT);
-
- /* Tramsmit and start T200 */
- osmo_timer_schedule(&dl->t200, T200);
- return tx_ph_data_enqueue(dl, msg, chan_nr, link_id, n201);
+ /* send to L2 */
+ return lapd_recv_dlsap(&dp, &dl->dl.lctx);
}
/* L3 requests release of data link */
static int rslms_rx_rll_rel_req(struct msgb *msg, struct lapdm_datalink *dl)
{
- struct lapdm_entity *le = dl->entity;
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
- uint8_t chan_nr = rllh->chan_nr;
- uint8_t link_id = rllh->link_id;
- uint8_t sapi = rllh->link_id & 7;
uint8_t mode = 0;
+ struct osmo_dlsap_prim dp;
/* get release mode */
if (rllh->data[0] == RSL_IE_RELEASE_MODE)
mode = rllh->data[1] & 1;
- /* local release */
- if (mode) {
- LOGP(DLLAPDM, LOGL_INFO, "perform local release\n");
- msgb_free(msg);
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- /* enter idle state */
- lapdm_dl_newstate(dl, LAPDm_STATE_IDLE);
- /* flush buffers */
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
- /* send notification to L3 */
- return send_rll_simple(RSL_MT_REL_CONF, &dl->mctx);
- }
-
- /* in case we are already disconnecting */
- if (dl->state == LAPDm_STATE_DISC_SENT)
- return -EBUSY;
-
- LOGP(DLLAPDM, LOGL_INFO, "perform normal release (DISC)\n");
-
/* Pull rllh */
msgb_pull(msg, msg->tail - msg->l2h);
- /* Push LAPDm header on msgb */
- msg->l2h = msgb_push(msg, 3);
- msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.cmd);
- msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_DISC, 1);
- msg->l2h[2] = LAPDm_LEN(0);
- /* Transmit-buffer carries exactly one segment */
- memcpy(dl->tx_hist[0], msg->l2h, 3);
- dl->tx_length[0] = 3;
-
- /* Set states */
- dl->own_busy = dl->peer_busy = 0;
- dl->retrans_ctr = 0;
- lapdm_dl_newstate(dl, LAPDm_STATE_DISC_SENT);
-
- /* Tramsmit and start T200 */
- osmo_timer_schedule(&dl->t200, T200);
- return tx_ph_data_enqueue(dl, msg, chan_nr, link_id, dl->mctx.n201);
-}
+ /* prepare prim */
+ osmo_prim_init(&dp.oph, 0, PRIM_DL_REL, PRIM_OP_REQUEST, msg);
+ dp.u.rel_req.mode = mode;
-/* L3 requests release in idle state */
-static int rslms_rx_rll_rel_req_idle(struct msgb *msg, struct lapdm_datalink *dl)
-{
- msgb_free(msg);
-
- /* send notification to L3 */
- return send_rll_simple(RSL_MT_REL_CONF, &dl->mctx);
+ /* send to L2 */
+ return lapd_recv_dlsap(&dp, &dl->dl.lctx);
}
/* L3 requests channel in idle state */
@@ -2239,11 +981,11 @@ static int rslms_rx_chan_rqd(struct lapdm_channel *lc, struct msgb *msg)
PRIM_OP_REQUEST, NULL);
if (msgb_l2len(msg) < sizeof(*cch) + 4 + 2 + 2) {
- LOGP(DLLAPDM, LOGL_ERROR, "Message too short for CHAN RQD!\n");
+ LOGP(DLLAPD, LOGL_ERROR, "Message too short for CHAN RQD!\n");
return -EINVAL;
}
if (cch->data[0] != RSL_IE_REQ_REFERENCE) {
- LOGP(DLLAPDM, LOGL_ERROR, "Missing REQ REFERENCE IE\n");
+ LOGP(DLLAPD, LOGL_ERROR, "Missing REQ REFERENCE IE\n");
return -EINVAL;
}
pp.u.rach_req.ra = cch->data[1];
@@ -2251,14 +993,14 @@ static int rslms_rx_chan_rqd(struct lapdm_channel *lc, struct msgb *msg)
pp.u.rach_req.is_combined_ccch = cch->data[2] >> 7;
if (cch->data[4] != RSL_IE_ACCESS_DELAY) {
- LOGP(DLLAPDM, LOGL_ERROR, "Missing ACCESS_DELAY IE\n");
+ LOGP(DLLAPD, LOGL_ERROR, "Missing ACCESS_DELAY IE\n");
return -EINVAL;
}
/* TA = 0 - delay */
pp.u.rach_req.ta = 0 - cch->data[5];
if (cch->data[6] != RSL_IE_MS_POWER) {
- LOGP(DLLAPDM, LOGL_ERROR, "Missing MS POWER IE\n");
+ LOGP(DLLAPD, LOGL_ERROR, "Missing MS POWER IE\n");
return -EINVAL;
}
pp.u.rach_req.tx_power = cch->data[7];
@@ -2292,65 +1034,6 @@ static int l2_ph_chan_conf(struct msgb *msg, struct lapdm_entity *le, uint32_t f
return rslms_sendmsg(msg, le);
}
-const char *lapdm_state_names[] = {
- "LAPDm_STATE_NULL",
- "LAPDm_STATE_IDLE",
- "LAPDm_STATE_SABM_SENT",
- "LAPDm_STATE_MF_EST",
- "LAPDm_STATE_TIMER_RECOV",
- "LAPDm_STATE_DISC_SENT",
-};
-
-/* statefull handling for RSLms RLL messages from L3 */
-static struct l2downstate {
- uint32_t states;
- int type;
- int (*rout) (struct msgb *msg, struct lapdm_datalink *dl);
-} l2downstatelist[] = {
- /* create and send UI command */
- {ALL_STATES,
- RSL_MT_UNIT_DATA_REQ, rslms_rx_rll_udata_req},
-
- /* create and send SABM command */
- {SBIT(LAPDm_STATE_IDLE),
- RSL_MT_EST_REQ, rslms_rx_rll_est_req},
-
- /* create and send I command */
- {SBIT(LAPDm_STATE_MF_EST) |
- SBIT(LAPDm_STATE_TIMER_RECOV),
- RSL_MT_DATA_REQ, rslms_rx_rll_data_req},
-
- /* suspend datalink */
- {SBIT(LAPDm_STATE_MF_EST) |
- SBIT(LAPDm_STATE_TIMER_RECOV),
- RSL_MT_SUSP_REQ, rslms_rx_rll_susp_req},
-
- /* create and send SABM command (resume) */
- {SBIT(LAPDm_STATE_MF_EST) |
- SBIT(LAPDm_STATE_TIMER_RECOV),
- RSL_MT_RES_REQ, rslms_rx_rll_res_req},
-
- /* create and send SABM command (reconnect) */
- {SBIT(LAPDm_STATE_IDLE) |
- SBIT(LAPDm_STATE_MF_EST) |
- SBIT(LAPDm_STATE_TIMER_RECOV),
- RSL_MT_RECON_REQ, rslms_rx_rll_res_req},
-
- /* create and send DISC command */
- {SBIT(LAPDm_STATE_SABM_SENT) |
- SBIT(LAPDm_STATE_MF_EST) |
- SBIT(LAPDm_STATE_TIMER_RECOV) |
- SBIT(LAPDm_STATE_DISC_SENT),
- RSL_MT_REL_REQ, rslms_rx_rll_rel_req},
-
- /* release in idle state */
- {SBIT(LAPDm_STATE_IDLE),
- RSL_MT_REL_REQ, rslms_rx_rll_rel_req_idle},
-};
-
-#define L2DOWNSLLEN \
- (sizeof(l2downstatelist) / sizeof(struct l2downstate))
-
/* incoming RSLms RLL message from L3 */
static int rslms_rx_rll(struct msgb *msg, struct lapdm_channel *lc)
{
@@ -2359,11 +1042,11 @@ static int rslms_rx_rll(struct msgb *msg, struct lapdm_channel *lc)
uint8_t sapi = rllh->link_id & 7;
struct lapdm_entity *le;
struct lapdm_datalink *dl;
- int i, supported = 0;
int rc = 0;
if (msgb_l2len(msg) < sizeof(*rllh)) {
- LOGP(DLLAPDM, LOGL_ERROR, "Message too short for RLL hdr!\n");
+ LOGP(DLLAPD, LOGL_ERROR, "Message too short for RLL hdr!\n");
+ msgb_free(msg);
return -EINVAL;
}
@@ -2377,34 +1060,42 @@ static int rslms_rx_rll(struct msgb *msg, struct lapdm_channel *lc)
*/
dl = datalink_for_sapi(le, sapi);
if (!dl) {
- LOGP(DLLAPDM, LOGL_ERROR, "No instance for SAPI %d!\n", sapi);
+ LOGP(DLLAPD, LOGL_ERROR, "No instance for SAPI %d!\n", sapi);
+ msgb_free(msg);
return -EINVAL;
}
- LOGP(DLLAPDM, LOGL_INFO, "(%p) RLL Message '%s' received in state %s\n",
- lc->name, rsl_msg_name(msg_type), lapdm_state_names[dl->state]);
+ LOGP(DLLAPD, LOGL_INFO, "(%p) RLL Message '%s' received. (sapi %d)\n",
+ lc->name, rsl_msg_name(msg_type), sapi);
- /* find function for current state and message */
- for (i = 0; i < L2DOWNSLLEN; i++) {
- if (msg_type == l2downstatelist[i].type)
- supported = 1;
- if ((msg_type == l2downstatelist[i].type)
- && ((1 << dl->state) & l2downstatelist[i].states))
- break;
- }
- if (!supported) {
- LOGP(DLLAPDM, LOGL_NOTICE, "Message unsupported.\n");
- msgb_free(msg);
- return 0;
- }
- if (i == L2DOWNSLLEN) {
- LOGP(DLLAPDM, LOGL_NOTICE, "Message unhandled at this state.\n");
+ switch (msg_type) {
+ case RSL_MT_UNIT_DATA_REQ:
+ rc = rslms_rx_rll_udata_req(msg, dl);
+ break;
+ case RSL_MT_EST_REQ:
+ rc = rslms_rx_rll_est_req(msg, dl);
+ break;
+ case RSL_MT_DATA_REQ:
+ rc = rslms_rx_rll_data_req(msg, dl);
+ break;
+ case RSL_MT_SUSP_REQ:
+ rc = rslms_rx_rll_susp_req(msg, dl);
+ break;
+ case RSL_MT_RES_REQ:
+ rc = rslms_rx_rll_res_req(msg, dl);
+ break;
+ case RSL_MT_RECON_REQ:
+ rc = rslms_rx_rll_res_req(msg, dl);
+ break;
+ case RSL_MT_REL_REQ:
+ rc = rslms_rx_rll_rel_req(msg, dl);
+ break;
+ default:
+ LOGP(DLLAPD, LOGL_NOTICE, "Message unsupported.\n");
msgb_free(msg);
- return 0;
+ rc = -EINVAL;
}
- rc = l2downstatelist[i].rout(msg, dl);
-
return rc;
}
@@ -2416,7 +1107,7 @@ static int rslms_rx_com_chan(struct msgb *msg, struct lapdm_channel *lc)
int rc = 0;
if (msgb_l2len(msg) < sizeof(*cch)) {
- LOGP(DLLAPDM, LOGL_ERROR, "Message too short for COM CHAN hdr!\n");
+ LOGP(DLLAPD, LOGL_ERROR, "Message too short for COM CHAN hdr!\n");
return -EINVAL;
}
@@ -2426,7 +1117,7 @@ static int rslms_rx_com_chan(struct msgb *msg, struct lapdm_channel *lc)
rc = rslms_rx_chan_rqd(lc, msg);
break;
default:
- LOGP(DLLAPDM, LOGL_NOTICE, "Unknown COMMON CHANNEL msg %d!\n",
+ LOGP(DLLAPD, LOGL_NOTICE, "Unknown COMMON CHANNEL msg %d!\n",
msg_type);
msgb_free(msg);
return 0;
@@ -2442,7 +1133,7 @@ int lapdm_rslms_recvmsg(struct msgb *msg, struct lapdm_channel *lc)
int rc = 0;
if (msgb_l2len(msg) < sizeof(*rslh)) {
- LOGP(DLLAPDM, LOGL_ERROR, "Message too short RSL hdr!\n");
+ LOGP(DLLAPD, LOGL_ERROR, "Message too short RSL hdr!\n");
return -EINVAL;
}
@@ -2454,7 +1145,7 @@ int lapdm_rslms_recvmsg(struct msgb *msg, struct lapdm_channel *lc)
rc = rslms_rx_com_chan(msg, lc);
break;
default:
- LOGP(DLLAPDM, LOGL_ERROR, "unknown RSLms message "
+ LOGP(DLLAPD, LOGL_ERROR, "unknown RSLms message "
"discriminator 0x%02x", rslh->msg_discr);
msgb_free(msg);
return -EINVAL;
@@ -2466,23 +1157,24 @@ int lapdm_rslms_recvmsg(struct msgb *msg, struct lapdm_channel *lc)
/*! \brief Set the \ref lapdm_mode of a LAPDm entity */
int lapdm_entity_set_mode(struct lapdm_entity *le, enum lapdm_mode mode)
{
+ int i;
+ enum lapd_mode lm;
+
switch (mode) {
case LAPDM_MODE_MS:
- le->cr.loc2rem.cmd = CR_MS2BS_CMD;
- le->cr.loc2rem.resp = CR_MS2BS_RESP;
- le->cr.rem2loc.cmd = CR_BS2MS_CMD;
- le->cr.rem2loc.resp = CR_BS2MS_RESP;
+ lm = LAPD_MODE_USER;
break;
case LAPDM_MODE_BTS:
- le->cr.loc2rem.cmd = CR_BS2MS_CMD;
- le->cr.loc2rem.resp = CR_BS2MS_RESP;
- le->cr.rem2loc.cmd = CR_MS2BS_CMD;
- le->cr.rem2loc.resp = CR_MS2BS_RESP;
+ lm = LAPD_MODE_NETWORK;
break;
default:
return -EINVAL;
}
+ for (i = 0; i < ARRAY_SIZE(le->datalink); i++) {
+ lapd_set_mode(&le->datalink[i].dl, lm);
+ }
+
le->mode = mode;
return 0;
@@ -2526,16 +1218,7 @@ void lapdm_entity_reset(struct lapdm_entity *le)
for (i = 0; i < ARRAY_SIZE(le->datalink); i++) {
dl = &le->datalink[i];
- if (dl->state == LAPDm_STATE_IDLE)
- continue;
- LOGP(DLLAPDM, LOGL_INFO, "Resetting LAPDm instance\n");
- /* reset Timer T200 */
- osmo_timer_del(&dl->t200);
- /* enter idle state */
- dl->state = LAPDm_STATE_IDLE;
- /* flush buffer */
- lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
+ lapd_dl_reset(&dl->dl);
}
}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-encblock.c b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-encblock.c
new file mode 100644
index 0000000..8f35caa
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-encblock.c
@@ -0,0 +1,38 @@
+/*
+ * AES encrypt_block
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "aes.h"
+#include "aes_wrap.h"
+
+/**
+ * aes_128_encrypt_block - Perform one AES 128-bit block operation
+ * @key: Key for AES
+ * @in: Input data (16 bytes)
+ * @out: Output of the AES block operation (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
+{
+ void *ctx;
+ ctx = aes_encrypt_init(key, 16);
+ if (ctx == NULL)
+ return -1;
+ aes_encrypt(ctx, in, out);
+ aes_encrypt_deinit(ctx);
+ return 0;
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-internal-enc.c b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-internal-enc.c
new file mode 100644
index 0000000..8726aa7
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-internal-enc.c
@@ -0,0 +1,121 @@
+/*
+ * AES (Rijndael) cipher - encrypt
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ * cost of reduced throughput (quite small difference on Pentium 4,
+ * 10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto.h"
+#include "aes_i.h"
+
+static void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
+{
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const int Nr = 10;
+#ifndef FULL_UNROLL
+ int r;
+#endif /* ?FULL_UNROLL */
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = GETU32(pt ) ^ rk[0];
+ s1 = GETU32(pt + 4) ^ rk[1];
+ s2 = GETU32(pt + 8) ^ rk[2];
+ s3 = GETU32(pt + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
+d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
+d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
+d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
+
+#ifdef FULL_UNROLL
+
+ ROUND(1,t,s);
+ ROUND(2,s,t);
+ ROUND(3,t,s);
+ ROUND(4,s,t);
+ ROUND(5,t,s);
+ ROUND(6,s,t);
+ ROUND(7,t,s);
+ ROUND(8,s,t);
+ ROUND(9,t,s);
+
+ rk += Nr << 2;
+
+#else /* !FULL_UNROLL */
+
+ /* Nr - 1 full rounds: */
+ r = Nr >> 1;
+ for (;;) {
+ ROUND(1,t,s);
+ rk += 8;
+ if (--r == 0)
+ break;
+ ROUND(0,s,t);
+ }
+
+#endif /* ?FULL_UNROLL */
+
+#undef ROUND
+
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
+ PUTU32(ct , s0);
+ s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
+ PUTU32(ct + 4, s1);
+ s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
+ PUTU32(ct + 8, s2);
+ s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
+ PUTU32(ct + 12, s3);
+}
+
+
+void * aes_encrypt_init(const u8 *key, size_t len)
+{
+ u32 *rk;
+ if (len != 16)
+ return NULL;
+ rk = os_malloc(AES_PRIV_SIZE);
+ if (rk == NULL)
+ return NULL;
+ rijndaelKeySetupEnc(rk, key);
+ return rk;
+}
+
+
+void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
+{
+ rijndaelEncrypt(ctx, plain, crypt);
+}
+
+
+void aes_encrypt_deinit(void *ctx)
+{
+ os_memset(ctx, 0, AES_PRIV_SIZE);
+ os_free(ctx);
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-internal.c b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-internal.c
new file mode 100644
index 0000000..4161220
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes-internal.c
@@ -0,0 +1,805 @@
+/*
+ * AES (Rijndael) cipher
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ * cost of reduced throughput (quite small difference on Pentium 4,
+ * 10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto.h"
+#include "aes_i.h"
+
+/*
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+const u32 Te0[256] = {
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+#ifndef AES_SMALL_TABLES
+const u32 Te1[256] = {
+ 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+ 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+ 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+ 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+ 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+ 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+ 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+ 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+ 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+ 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+ 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+ 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+ 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+ 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+ 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+ 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+ 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+ 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+ 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+ 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+ 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+ 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+ 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+ 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+ 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+ 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+ 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+ 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+ 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+ 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+ 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+ 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+ 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+ 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+ 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+ 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+ 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+ 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+ 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+ 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+ 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+ 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+ 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+ 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+ 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+ 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+ 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+ 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+ 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+ 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+ 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+ 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+ 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+ 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+ 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+ 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+ 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+ 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+ 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+ 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+ 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+ 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+ 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+ 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+const u32 Te2[256] = {
+ 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+ 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+ 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+ 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+ 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+ 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+ 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+ 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+ 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+ 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+ 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+ 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+ 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+ 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+ 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+ 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+ 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+ 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+ 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+ 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+ 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+ 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+ 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+ 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+ 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+ 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+ 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+ 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+ 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+ 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+ 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+ 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+ 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+ 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+ 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+ 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+ 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+ 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+ 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+ 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+ 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+ 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+ 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+ 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+ 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+ 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+ 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+ 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+ 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+ 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+ 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+ 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+ 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+ 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+ 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+ 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+ 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+ 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+ 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+ 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+ 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+ 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+ 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+ 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+const u32 Te3[256] = {
+
+ 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+ 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+ 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+ 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+ 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+ 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+ 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+ 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+ 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+ 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+ 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+ 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+ 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+ 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+ 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+ 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+ 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+ 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+ 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+ 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+ 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+ 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+ 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+ 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+ 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+ 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+ 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+ 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+ 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+ 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+ 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+ 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+ 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+ 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+ 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+ 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+ 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+ 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+ 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+ 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+ 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+ 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+ 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+ 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+ 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+ 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+ 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+ 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+ 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+ 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+ 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+ 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+ 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+ 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+ 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+ 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+ 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+ 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+ 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+ 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+ 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+ 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+ 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+ 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+const u32 Te4[256] = {
+ 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+ 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+ 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+ 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+ 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+ 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+ 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+ 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+ 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+ 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+ 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+ 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+ 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+ 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+ 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+ 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+ 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+ 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+ 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+ 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+ 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+ 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+ 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+ 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+ 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+ 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+ 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+ 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+ 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+ 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+ 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+ 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+ 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+ 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+ 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+ 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+ 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+ 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+ 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+ 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+ 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+ 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+ 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+ 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+ 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+ 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+ 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+ 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+ 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+ 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+ 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+ 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+ 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+ 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+ 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+ 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+ 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+ 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+ 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+ 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+ 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+ 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+ 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+ 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+#endif /* AES_SMALL_TABLES */
+const u32 Td0[256] = {
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+#ifndef AES_SMALL_TABLES
+const u32 Td1[256] = {
+ 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+ 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+ 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+ 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+ 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+ 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+ 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+ 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+ 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+ 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+ 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+ 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+ 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+ 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+ 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+ 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+ 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+ 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+ 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+ 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+ 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+ 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+ 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+ 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+ 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+ 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+ 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+ 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+ 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+ 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+ 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+ 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+ 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+ 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+ 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+ 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+ 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+ 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+ 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+ 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+ 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+ 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+ 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+ 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+ 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+ 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+ 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+ 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+ 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+ 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+ 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+ 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+ 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+ 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+ 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+ 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+ 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+ 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+ 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+ 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+ 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+ 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+ 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+ 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+const u32 Td2[256] = {
+ 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+ 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+ 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+ 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+ 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+ 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+ 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+ 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+ 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+ 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+ 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+ 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+ 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+ 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+ 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+ 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+ 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+ 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+ 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+ 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+ 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+ 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+ 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+ 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+ 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+ 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+ 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+ 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+ 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+ 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+ 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+ 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+ 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+ 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+ 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+ 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+ 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+ 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+ 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+ 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+ 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+ 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+ 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+ 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+ 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+ 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+ 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+ 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+ 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+ 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+ 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+ 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+ 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+ 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+ 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+ 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+ 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+ 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+ 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+ 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+ 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+ 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+ 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+ 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+const u32 Td3[256] = {
+ 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+ 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+ 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+ 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+ 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+ 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+ 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+ 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+ 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+ 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+ 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+ 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+ 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+ 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+ 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+ 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+ 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+ 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+ 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+ 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+ 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+ 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+ 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+ 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+ 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+ 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+ 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+ 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+ 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+ 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+ 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+ 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+ 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+ 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+ 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+ 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+ 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+ 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+ 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+ 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+ 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+ 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+ 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+ 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+ 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+ 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+ 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+ 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+ 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+ 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+ 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+ 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+ 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+ 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+ 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+ 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+ 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+ 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+ 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+ 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+ 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+ 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+ 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+ 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+const u32 Td4[256] = {
+ 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+ 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+ 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+ 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+ 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+ 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+ 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+ 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+ 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+ 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+ 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+ 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+ 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+ 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+ 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+ 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+ 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+ 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+ 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+ 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+ 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+ 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+ 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+ 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+ 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+ 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+ 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+ 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+ 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+ 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+ 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+ 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+ 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+ 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+ 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+ 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+ 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+ 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+ 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+ 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+ 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+ 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+ 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+ 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+ 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+ 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+ 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+ 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+ 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+ 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+ 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+ 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+ 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+ 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+ 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+ 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+ 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+ 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+ 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+ 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+ 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+ 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+ 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+ 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+const u32 rcon[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+#else /* AES_SMALL_TABLES */
+const u8 Td4s[256] = {
+ 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+ 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+ 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+ 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+ 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+ 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+ 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+ 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+ 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+ 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+ 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+ 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+ 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+ 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+ 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+ 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+ 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+ 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+ 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+ 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+ 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+ 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+ 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+ 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+ 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+ 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+ 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+ 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+ 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+ 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+ 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+ 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+const u8 rcons[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+#endif /* AES_SMALL_TABLES */
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return the number of rounds for the given cipher key size.
+ */
+void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
+{
+ int i;
+ u32 temp;
+
+ rk[0] = GETU32(cipherKey );
+ rk[1] = GETU32(cipherKey + 4);
+ rk[2] = GETU32(cipherKey + 8);
+ rk[3] = GETU32(cipherKey + 12);
+ for (i = 0; i < 10; i++) {
+ temp = rk[3];
+ rk[4] = rk[0] ^
+ TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^
+ RCON(i);
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ rk += 4;
+ }
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes.h b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes.h
new file mode 100644
index 0000000..ba384a9
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes.h
@@ -0,0 +1,27 @@
+/*
+ * AES functions
+ * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#define AES_BLOCK_SIZE 16
+
+void * aes_encrypt_init(const u8 *key, size_t len);
+void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
+void aes_encrypt_deinit(void *ctx);
+void * aes_decrypt_init(const u8 *key, size_t len);
+void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
+void aes_decrypt_deinit(void *ctx);
+
+#endif /* AES_H */
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes_i.h b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes_i.h
new file mode 100644
index 0000000..6b40bc7
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes_i.h
@@ -0,0 +1,122 @@
+/*
+ * AES (Rijndael) cipher
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef AES_I_H
+#define AES_I_H
+
+#include "aes.h"
+
+/* #define FULL_UNROLL */
+#define AES_SMALL_TABLES
+
+extern const u32 Te0[256];
+extern const u32 Te1[256];
+extern const u32 Te2[256];
+extern const u32 Te3[256];
+extern const u32 Te4[256];
+extern const u32 Td0[256];
+extern const u32 Td1[256];
+extern const u32 Td2[256];
+extern const u32 Td3[256];
+extern const u32 Td4[256];
+extern const u32 rcon[10];
+extern const u8 Td4s[256];
+extern const u8 rcons[10];
+
+#ifndef AES_SMALL_TABLES
+
+#define RCON(i) rcon[(i)]
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) Te1[((i) >> 16) & 0xff]
+#define TE2(i) Te2[((i) >> 8) & 0xff]
+#define TE3(i) Te3[(i) & 0xff]
+#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
+#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff)
+#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000)
+#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff)
+#define TE4(i) (Te4[(i)] & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) Td1[((i) >> 16) & 0xff]
+#define TD2(i) Td2[((i) >> 8) & 0xff]
+#define TD3(i) Td3[(i) & 0xff]
+#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000)
+#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff)
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) Td1[(i) & 0xff]
+#define TD2_(i) Td2[(i) & 0xff]
+#define TD3_(i) Td3[(i) & 0xff]
+
+#else /* AES_SMALL_TABLES */
+
+#define RCON(i) (rcons[(i)] << 24)
+
+static inline u32 rotr(u32 val, int bits)
+{
+ return (val >> bits) | (val << (32 - bits));
+}
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
+#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
+#define TE3(i) rotr(Te0[(i) & 0xff], 24)
+#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
+#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
+#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
+#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
+#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
+#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
+#define TD3(i) rotr(Td0[(i) & 0xff], 24)
+#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
+#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
+#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
+#define TD44(i) (Td4s[(i) & 0xff])
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
+#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
+#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
+
+#endif /* AES_SMALL_TABLES */
+
+#ifdef _MSC_VER
+#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+#define GETU32(p) SWAP(*((u32 *)(p)))
+#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
+#else
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \
+((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { \
+(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \
+(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
+#endif
+
+#define AES_PRIV_SIZE (4 * 44)
+
+void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]);
+
+#endif /* AES_I_H */
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes_wrap.h b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes_wrap.h
new file mode 100644
index 0000000..4b1c7b0
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/aes_wrap.h
@@ -0,0 +1,48 @@
+/*
+ * AES-based functions
+ *
+ * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * - One-Key CBC MAC (OMAC1) hash with AES-128
+ * - AES-128 CTR mode encryption
+ * - AES-128 EAX mode encryption/decryption
+ * - AES-128 CBC
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef AES_WRAP_H
+#define AES_WRAP_H
+
+int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
+int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
+int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem,
+ const u8 *addr[], const size_t *len,
+ u8 *mac);
+int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len,
+ u8 *mac);
+int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
+int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
+ u8 *data, size_t data_len);
+int __must_check aes_128_eax_encrypt(const u8 *key,
+ const u8 *nonce, size_t nonce_len,
+ const u8 *hdr, size_t hdr_len,
+ u8 *data, size_t data_len, u8 *tag);
+int __must_check aes_128_eax_decrypt(const u8 *key,
+ const u8 *nonce, size_t nonce_len,
+ const u8 *hdr, size_t hdr_len,
+ u8 *data, size_t data_len, const u8 *tag);
+int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data,
+ size_t data_len);
+int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data,
+ size_t data_len);
+
+#endif /* AES_WRAP_H */
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/common.h b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/common.h
new file mode 100644
index 0000000..aaf82b9
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/common.h
@@ -0,0 +1,20 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MSG_DEBUG
+#define wpa_hexdump(x, args...)
+#define wpa_hexdump_key(x, args...)
+#define wpa_printf(x, args...)
+
+#define os_memcpy(x, y, z) memcpy(x, y, z)
+#define os_memcmp(x, y, z) memcmp(x, y, z)
+#define os_memset(x, y, z) memset(x, y, z)
+#define os_malloc(x) malloc(x)
+#define os_free(x) free(x)
+
+typedef uint8_t u8;
+typedef uint32_t u32;
+
+#define __must_check
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/crypto.h b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/crypto.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/crypto.h
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/includes.h b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/includes.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/includes.h
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/milenage.c b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/milenage.c
new file mode 100644
index 0000000..cc4e95c
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/milenage.c
@@ -0,0 +1,329 @@
+/*
+ * 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
+ * Copyright (c) 2006-2007 <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ *
+ * This file implements an example authentication algorithm defined for 3GPP
+ * AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow
+ * EAP-AKA to be tested properly with real USIM cards.
+ *
+ * This implementations assumes that the r1..r5 and c1..c5 constants defined in
+ * TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00,
+ * c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to
+ * be AES (Rijndael).
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "aes_wrap.h"
+#include "milenage.h"
+
+
+/**
+ * milenage_f1 - Milenage f1 and f1* algorithms
+ * @opc: OPc = 128-bit value derived from OP and K
+ * @k: K = 128-bit subscriber key
+ * @_rand: RAND = 128-bit random challenge
+ * @sqn: SQN = 48-bit sequence number
+ * @amf: AMF = 16-bit authentication management field
+ * @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL
+ * @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL
+ * Returns: 0 on success, -1 on failure
+ */
+int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
+ const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s)
+{
+ u8 tmp1[16], tmp2[16], tmp3[16];
+ int i;
+
+ /* tmp1 = TEMP = E_K(RAND XOR OP_C) */
+ for (i = 0; i < 16; i++)
+ tmp1[i] = _rand[i] ^ opc[i];
+ if (aes_128_encrypt_block(k, tmp1, tmp1))
+ return -1;
+
+ /* tmp2 = IN1 = SQN || AMF || SQN || AMF */
+ os_memcpy(tmp2, sqn, 6);
+ os_memcpy(tmp2 + 6, amf, 2);
+ os_memcpy(tmp2 + 8, tmp2, 8);
+
+ /* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */
+
+ /* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */
+ for (i = 0; i < 16; i++)
+ tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i];
+ /* XOR with TEMP = E_K(RAND XOR OP_C) */
+ for (i = 0; i < 16; i++)
+ tmp3[i] ^= tmp1[i];
+ /* XOR with c1 (= ..00, i.e., NOP) */
+
+ /* f1 || f1* = E_K(tmp3) XOR OP_c */
+ if (aes_128_encrypt_block(k, tmp3, tmp1))
+ return -1;
+ for (i = 0; i < 16; i++)
+ tmp1[i] ^= opc[i];
+ if (mac_a)
+ os_memcpy(mac_a, tmp1, 8); /* f1 */
+ if (mac_s)
+ os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */
+ return 0;
+}
+
+
+/**
+ * milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
+ * @opc: OPc = 128-bit value derived from OP and K
+ * @k: K = 128-bit subscriber key
+ * @_rand: RAND = 128-bit random challenge
+ * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
+ * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
+ * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
+ * @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL
+ * @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL
+ * Returns: 0 on success, -1 on failure
+ */
+int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
+ u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar)
+{
+ u8 tmp1[16], tmp2[16], tmp3[16];
+ int i;
+
+ /* tmp2 = TEMP = E_K(RAND XOR OP_C) */
+ for (i = 0; i < 16; i++)
+ tmp1[i] = _rand[i] ^ opc[i];
+ if (aes_128_encrypt_block(k, tmp1, tmp2))
+ return -1;
+
+ /* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */
+ /* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */
+ /* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */
+ /* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */
+
+ /* f2 and f5 */
+ /* rotate by r2 (= 0, i.e., NOP) */
+ for (i = 0; i < 16; i++)
+ tmp1[i] = tmp2[i] ^ opc[i];
+ tmp1[15] ^= 1; /* XOR c2 (= ..01) */
+ /* f5 || f2 = E_K(tmp1) XOR OP_c */
+ if (aes_128_encrypt_block(k, tmp1, tmp3))
+ return -1;
+ for (i = 0; i < 16; i++)
+ tmp3[i] ^= opc[i];
+ if (res)
+ os_memcpy(res, tmp3 + 8, 8); /* f2 */
+ if (ak)
+ os_memcpy(ak, tmp3, 6); /* f5 */
+
+ /* f3 */
+ if (ck) {
+ /* rotate by r3 = 0x20 = 4 bytes */
+ for (i = 0; i < 16; i++)
+ tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i];
+ tmp1[15] ^= 2; /* XOR c3 (= ..02) */
+ if (aes_128_encrypt_block(k, tmp1, ck))
+ return -1;
+ for (i = 0; i < 16; i++)
+ ck[i] ^= opc[i];
+ }
+
+ /* f4 */
+ if (ik) {
+ /* rotate by r4 = 0x40 = 8 bytes */
+ for (i = 0; i < 16; i++)
+ tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i];
+ tmp1[15] ^= 4; /* XOR c4 (= ..04) */
+ if (aes_128_encrypt_block(k, tmp1, ik))
+ return -1;
+ for (i = 0; i < 16; i++)
+ ik[i] ^= opc[i];
+ }
+
+ /* f5* */
+ if (akstar) {
+ /* rotate by r5 = 0x60 = 12 bytes */
+ for (i = 0; i < 16; i++)
+ tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i];
+ tmp1[15] ^= 8; /* XOR c5 (= ..08) */
+ if (aes_128_encrypt_block(k, tmp1, tmp1))
+ return -1;
+ for (i = 0; i < 6; i++)
+ akstar[i] = tmp1[i] ^ opc[i];
+ }
+
+ return 0;
+}
+
+
+/**
+ * milenage_generate - Generate AKA AUTN,IK,CK,RES
+ * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
+ * @amf: AMF = 16-bit authentication management field
+ * @k: K = 128-bit subscriber key
+ * @sqn: SQN = 48-bit sequence number
+ * @_rand: RAND = 128-bit random challenge
+ * @autn: Buffer for AUTN = 128-bit authentication token
+ * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
+ * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
+ * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
+ * @res_len: Max length for res; set to used length or 0 on failure
+ */
+void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
+ const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik,
+ u8 *ck, u8 *res, size_t *res_len)
+{
+ int i;
+ u8 mac_a[8], ak[6];
+
+ if (*res_len < 8) {
+ *res_len = 0;
+ return;
+ }
+ if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) ||
+ milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) {
+ *res_len = 0;
+ return;
+ }
+ *res_len = 8;
+
+ /* AUTN = (SQN ^ AK) || AMF || MAC */
+ for (i = 0; i < 6; i++)
+ autn[i] = sqn[i] ^ ak[i];
+ os_memcpy(autn + 6, amf, 2);
+ os_memcpy(autn + 8, mac_a, 8);
+}
+
+
+/**
+ * milenage_auts - Milenage AUTS validation
+ * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
+ * @k: K = 128-bit subscriber key
+ * @_rand: RAND = 128-bit random challenge
+ * @auts: AUTS = 112-bit authentication token from client
+ * @sqn: Buffer for SQN = 48-bit sequence number
+ * Returns: 0 = success (sqn filled), -1 on failure
+ */
+int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
+ u8 *sqn)
+{
+ u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
+ u8 ak[6], mac_s[8];
+ int i;
+
+ if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
+ return -1;
+ for (i = 0; i < 6; i++)
+ sqn[i] = auts[i] ^ ak[i];
+ if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) ||
+ memcmp(mac_s, auts + 6, 8) != 0)
+ return -1;
+ return 0;
+}
+
+
+/**
+ * gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet
+ * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
+ * @k: K = 128-bit subscriber key
+ * @_rand: RAND = 128-bit random challenge
+ * @sres: Buffer for SRES = 32-bit SRES
+ * @kc: Buffer for Kc = 64-bit Kc
+ * Returns: 0 on success, -1 on failure
+ */
+int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc)
+{
+ u8 res[8], ck[16], ik[16];
+ int i;
+
+ if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL))
+ return -1;
+
+ for (i = 0; i < 8; i++)
+ kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8];
+
+#ifdef GSM_MILENAGE_ALT_SRES
+ os_memcpy(sres, res, 4);
+#else /* GSM_MILENAGE_ALT_SRES */
+ for (i = 0; i < 4; i++)
+ sres[i] = res[i] ^ res[i + 4];
+#endif /* GSM_MILENAGE_ALT_SRES */
+ return 0;
+}
+
+
+/**
+ * milenage_generate - Generate AKA AUTN,IK,CK,RES
+ * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
+ * @k: K = 128-bit subscriber key
+ * @sqn: SQN = 48-bit sequence number
+ * @_rand: RAND = 128-bit random challenge
+ * @autn: AUTN = 128-bit authentication token
+ * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
+ * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
+ * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
+ * @res_len: Variable that will be set to RES length
+ * @auts: 112-bit buffer for AUTS
+ * Returns: 0 on success, -1 on failure, or -2 on synchronization failure
+ */
+int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
+ const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
+ u8 *auts)
+{
+ int i;
+ u8 mac_a[8], ak[6], rx_sqn[6];
+ const u8 *amf;
+
+ wpa_hexdump(MSG_DEBUG, "Milenage: AUTN", autn, 16);
+ wpa_hexdump(MSG_DEBUG, "Milenage: RAND", _rand, 16);
+
+ if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
+ return -1;
+
+ *res_len = 8;
+ wpa_hexdump_key(MSG_DEBUG, "Milenage: RES", res, *res_len);
+ wpa_hexdump_key(MSG_DEBUG, "Milenage: CK", ck, 16);
+ wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 16);
+ wpa_hexdump_key(MSG_DEBUG, "Milenage: AK", ak, 6);
+
+ /* AUTN = (SQN ^ AK) || AMF || MAC */
+ for (i = 0; i < 6; i++)
+ rx_sqn[i] = autn[i] ^ ak[i];
+ wpa_hexdump(MSG_DEBUG, "Milenage: SQN", rx_sqn, 6);
+
+ if (os_memcmp(rx_sqn, sqn, 6) <= 0) {
+ u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
+ if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "Milenage: AK*", ak, 6);
+ for (i = 0; i < 6; i++)
+ auts[i] = sqn[i] ^ ak[i];
+ if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6))
+ return -1;
+ wpa_hexdump(MSG_DEBUG, "Milenage: AUTS", auts, 14);
+ return -2;
+ }
+
+ amf = autn + 6;
+ wpa_hexdump(MSG_DEBUG, "Milenage: AMF", amf, 2);
+ if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL))
+ return -1;
+
+ wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8);
+
+ if (os_memcmp(mac_a, autn + 8, 8) != 0) {
+ wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch");
+ wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A",
+ autn + 8, 8);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/milenage.h b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/milenage.h
new file mode 100644
index 0000000..d5054d6
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/gsm/milenage/milenage.h
@@ -0,0 +1,33 @@
+/*
+ * UMTS AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
+ * Copyright (c) 2006-2007 <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef MILENAGE_H
+#define MILENAGE_H
+
+void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
+ const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik,
+ u8 *ck, u8 *res, size_t *res_len);
+int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
+ u8 *sqn);
+int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres,
+ u8 *kc);
+int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
+ const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
+ u8 *auts);
+int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
+ const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s);
+int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
+ u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar);
+
+#endif /* MILENAGE_H */
diff --git a/Src/osmolib/src/shared/libosmocore/src/gsmtap_util.c b/Src/osmolib/src/shared/libosmocore/src/gsmtap_util.c
index 0e4d61e..ce722da 100644
--- a/Src/osmolib/src/shared/libosmocore/src/gsmtap_util.c
+++ b/Src/osmolib/src/shared/libosmocore/src/gsmtap_util.c
@@ -88,7 +88,8 @@ uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t link_id)
return ret;
}
-/*! \brief create L1/L2 data and put it into GSMTAP
+/*! \brief create an arbitrary type GSMTAP message
+ * \param[in] type The GSMTAP_TYPE_xxx constant of the message to create
* \param[in] arfcn GSM ARFCN (Channel Number)
* \param[in] ts GSM time slot
* \param[in] chan_type Channel Type
@@ -102,7 +103,7 @@ uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t link_id)
* This function will allocate a new msgb and fill it with a GSMTAP
* header containing the information
*/
-struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type,
+struct msgb *gsmtap_makemsg_ex(uint8_t type, uint16_t arfcn, uint8_t ts, uint8_t chan_type,
uint8_t ss, uint32_t fn, int8_t signal_dbm,
uint8_t snr, const uint8_t *data, unsigned int len)
{
@@ -118,7 +119,7 @@ struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type,
gh->version = GSMTAP_VERSION;
gh->hdr_len = sizeof(*gh)/4;
- gh->type = GSMTAP_TYPE_UM;
+ gh->type = type;
gh->timeslot = ts;
gh->sub_slot = ss;
gh->arfcn = htons(arfcn);
@@ -134,6 +135,28 @@ struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type,
return msg;
}
+/*! \brief create L1/L2 data and put it into GSMTAP
+ * \param[in] arfcn GSM ARFCN (Channel Number)
+ * \param[in] ts GSM time slot
+ * \param[in] chan_type Channel Type
+ * \param[in] ss Sub-slot
+ * \param[in] fn GSM Frame Number
+ * \param[in] signal_dbm Signal Strength (dBm)
+ * \param[in] snr Signal/Noise Ratio (SNR)
+ * \param[in] data Pointer to data buffer
+ * \param[in] len Length of \ref data
+ *
+ * This function will allocate a new msgb and fill it with a GSMTAP
+ * header containing the information
+ */
+struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type,
+ uint8_t ss, uint32_t fn, int8_t signal_dbm,
+ uint8_t snr, const uint8_t *data, unsigned int len)
+{
+ return gsmtap_makemsg_ex(GSMTAP_TYPE_UM, arfcn, ts, chan_type,
+ ss, fn, signal_dbm, snr, data, len);
+}
+
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@@ -208,8 +231,10 @@ int gsmtap_sendmsg(struct gsmtap_inst *gti, struct msgb *msg)
}
}
-/*! \brief receive a message from L1/L2 and put it in GSMTAP */
-int gsmtap_send(struct gsmtap_inst *gti, uint16_t arfcn, uint8_t ts,
+/*! \brief send an arbitrary type through GSMTAP.
+ * See \ref gsmtap_makemsg_ex for arguments
+ */
+int gsmtap_send_ex(struct gsmtap_inst *gti, uint8_t type, uint16_t arfcn, uint8_t ts,
uint8_t chan_type, uint8_t ss, uint32_t fn,
int8_t signal_dbm, uint8_t snr, const uint8_t *data,
unsigned int len)
@@ -219,7 +244,7 @@ int gsmtap_send(struct gsmtap_inst *gti, uint16_t arfcn, uint8_t ts,
if (!gti)
return -ENODEV;
- msg = gsmtap_makemsg(arfcn, ts, chan_type, ss, fn, signal_dbm,
+ msg = gsmtap_makemsg_ex(type, arfcn, ts, chan_type, ss, fn, signal_dbm,
snr, data, len);
if (!msg)
return -ENOMEM;
@@ -227,6 +252,18 @@ int gsmtap_send(struct gsmtap_inst *gti, uint16_t arfcn, uint8_t ts,
return gsmtap_sendmsg(gti, msg);
}
+/*! \brief send a message from L1/L2 through GSMTAP.
+ * See \ref gsmtap_makemsg for arguments
+ */
+int gsmtap_send(struct gsmtap_inst *gti, uint16_t arfcn, uint8_t ts,
+ uint8_t chan_type, uint8_t ss, uint32_t fn,
+ int8_t signal_dbm, uint8_t snr, const uint8_t *data,
+ unsigned int len)
+{
+ return gsmtap_send_ex(gti, GSMTAP_TYPE_UM, arfcn, ts, chan_type, ss, fn,
+ signal_dbm, snr, data, len);
+}
+
/* Callback from select layer if we can write to the socket */
static int gsmtap_wq_w_cb(struct osmo_fd *ofd, struct msgb *msg)
{
diff --git a/Src/osmolib/src/shared/libosmocore/src/logging.c b/Src/osmolib/src/shared/libosmocore/src/logging.c
index 9dd63e7..f8ed4cb 100644
--- a/Src/osmolib/src/shared/libosmocore/src/logging.c
+++ b/Src/osmolib/src/shared/libosmocore/src/logging.c
@@ -72,9 +72,9 @@ static const struct log_info_cat internal_cat[OSMO_NUM_DLIB] = {
.loglevel = LOGL_NOTICE,
.enabled = 1,
},
- [INT2IDX(DLLAPDM)] = { /* -2 becomes 1 */
- .name = "DLLAPDM",
- .description = "LAPDm in libosmogsm",
+ [INT2IDX(DLLAPD)] = { /* -2 becomes 1 */
+ .name = "DLLAPD",
+ .description = "LAPD in libosmogsm",
.loglevel = LOGL_NOTICE,
.enabled = 1,
},
@@ -100,6 +100,12 @@ static const struct log_info_cat internal_cat[OSMO_NUM_DLIB] = {
.description = "A-bis Input Driver for B-Channels (voice)",
.enabled = 0, .loglevel = LOGL_NOTICE,
},
+ [INT2IDX(DLSMS)] = {
+ .name = "DLSMS",
+ .description = "Layer3 Short Message Service (SMS)",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ .color = "\033[1;38m",
+ },
};
/* You have to keep this in sync with the structure loglevel_strs. */
diff --git a/Src/osmolib/src/shared/libosmocore/src/logging_syslog.c b/Src/osmolib/src/shared/libosmocore/src/logging_syslog.c
index b07b7fe..119dd74 100644
--- a/Src/osmolib/src/shared/libosmocore/src/logging_syslog.c
+++ b/Src/osmolib/src/shared/libosmocore/src/logging_syslog.c
@@ -43,7 +43,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/logging.h>
-static const int logp2syslog_level(unsigned int level)
+static int logp2syslog_level(unsigned int level)
{
if (level >= LOGL_FATAL)
return LOG_CRIT;
diff --git a/Src/osmolib/src/shared/libosmocore/src/rbtree.c b/Src/osmolib/src/shared/libosmocore/src/rbtree.c
new file mode 100644
index 0000000..4e7c0f3
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/src/rbtree.c
@@ -0,0 +1,383 @@
+/*
+ Red Black Trees
+ (C) 1999 Andrea Arcangeli <andrea@suse.de>
+ (C) 2002 David Woodhouse <dwmw2@infradead.org>
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ linux/lib/rbtree.c
+*/
+
+#include <osmocom/core/linuxrbtree.h>
+
+static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
+{
+ struct rb_node *right = node->rb_right;
+ struct rb_node *parent = rb_parent(node);
+
+ if ((node->rb_right = right->rb_left))
+ rb_set_parent(right->rb_left, node);
+ right->rb_left = node;
+
+ rb_set_parent(right, parent);
+
+ if (parent)
+ {
+ if (node == parent->rb_left)
+ parent->rb_left = right;
+ else
+ parent->rb_right = right;
+ }
+ else
+ root->rb_node = right;
+ rb_set_parent(node, right);
+}
+
+static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
+{
+ struct rb_node *left = node->rb_left;
+ struct rb_node *parent = rb_parent(node);
+
+ if ((node->rb_left = left->rb_right))
+ rb_set_parent(left->rb_right, node);
+ left->rb_right = node;
+
+ rb_set_parent(left, parent);
+
+ if (parent)
+ {
+ if (node == parent->rb_right)
+ parent->rb_right = left;
+ else
+ parent->rb_left = left;
+ }
+ else
+ root->rb_node = left;
+ rb_set_parent(node, left);
+}
+
+void rb_insert_color(struct rb_node *node, struct rb_root *root)
+{
+ struct rb_node *parent, *gparent;
+
+ while ((parent = rb_parent(node)) && rb_is_red(parent))
+ {
+ gparent = rb_parent(parent);
+
+ if (parent == gparent->rb_left)
+ {
+ {
+ register struct rb_node *uncle = gparent->rb_right;
+ if (uncle && rb_is_red(uncle))
+ {
+ rb_set_black(uncle);
+ rb_set_black(parent);
+ rb_set_red(gparent);
+ node = gparent;
+ continue;
+ }
+ }
+
+ if (parent->rb_right == node)
+ {
+ register struct rb_node *tmp;
+ __rb_rotate_left(parent, root);
+ tmp = parent;
+ parent = node;
+ node = tmp;
+ }
+
+ rb_set_black(parent);
+ rb_set_red(gparent);
+ __rb_rotate_right(gparent, root);
+ } else {
+ {
+ register struct rb_node *uncle = gparent->rb_left;
+ if (uncle && rb_is_red(uncle))
+ {
+ rb_set_black(uncle);
+ rb_set_black(parent);
+ rb_set_red(gparent);
+ node = gparent;
+ continue;
+ }
+ }
+
+ if (parent->rb_left == node)
+ {
+ register struct rb_node *tmp;
+ __rb_rotate_right(parent, root);
+ tmp = parent;
+ parent = node;
+ node = tmp;
+ }
+
+ rb_set_black(parent);
+ rb_set_red(gparent);
+ __rb_rotate_left(gparent, root);
+ }
+ }
+
+ rb_set_black(root->rb_node);
+}
+
+static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
+ struct rb_root *root)
+{
+ struct rb_node *other;
+
+ while ((!node || rb_is_black(node)) && node != root->rb_node)
+ {
+ if (parent->rb_left == node)
+ {
+ other = parent->rb_right;
+ if (rb_is_red(other))
+ {
+ rb_set_black(other);
+ rb_set_red(parent);
+ __rb_rotate_left(parent, root);
+ other = parent->rb_right;
+ }
+ if ((!other->rb_left || rb_is_black(other->rb_left)) &&
+ (!other->rb_right || rb_is_black(other->rb_right)))
+ {
+ rb_set_red(other);
+ node = parent;
+ parent = rb_parent(node);
+ }
+ else
+ {
+ if (!other->rb_right || rb_is_black(other->rb_right))
+ {
+ rb_set_black(other->rb_left);
+ rb_set_red(other);
+ __rb_rotate_right(other, root);
+ other = parent->rb_right;
+ }
+ rb_set_color(other, rb_color(parent));
+ rb_set_black(parent);
+ rb_set_black(other->rb_right);
+ __rb_rotate_left(parent, root);
+ node = root->rb_node;
+ break;
+ }
+ }
+ else
+ {
+ other = parent->rb_left;
+ if (rb_is_red(other))
+ {
+ rb_set_black(other);
+ rb_set_red(parent);
+ __rb_rotate_right(parent, root);
+ other = parent->rb_left;
+ }
+ if ((!other->rb_left || rb_is_black(other->rb_left)) &&
+ (!other->rb_right || rb_is_black(other->rb_right)))
+ {
+ rb_set_red(other);
+ node = parent;
+ parent = rb_parent(node);
+ }
+ else
+ {
+ if (!other->rb_left || rb_is_black(other->rb_left))
+ {
+ rb_set_black(other->rb_right);
+ rb_set_red(other);
+ __rb_rotate_left(other, root);
+ other = parent->rb_left;
+ }
+ rb_set_color(other, rb_color(parent));
+ rb_set_black(parent);
+ rb_set_black(other->rb_left);
+ __rb_rotate_right(parent, root);
+ node = root->rb_node;
+ break;
+ }
+ }
+ }
+ if (node)
+ rb_set_black(node);
+}
+
+void rb_erase(struct rb_node *node, struct rb_root *root)
+{
+ struct rb_node *child, *parent;
+ int color;
+
+ if (!node->rb_left)
+ child = node->rb_right;
+ else if (!node->rb_right)
+ child = node->rb_left;
+ else
+ {
+ struct rb_node *old = node, *left;
+
+ node = node->rb_right;
+ while ((left = node->rb_left) != NULL)
+ node = left;
+
+ if (rb_parent(old)) {
+ if (rb_parent(old)->rb_left == old)
+ rb_parent(old)->rb_left = node;
+ else
+ rb_parent(old)->rb_right = node;
+ } else
+ root->rb_node = node;
+
+ child = node->rb_right;
+ parent = rb_parent(node);
+ color = rb_color(node);
+
+ if (parent == old) {
+ parent = node;
+ } else {
+ if (child)
+ rb_set_parent(child, parent);
+ parent->rb_left = child;
+
+ node->rb_right = old->rb_right;
+ rb_set_parent(old->rb_right, node);
+ }
+
+ node->rb_parent_color = old->rb_parent_color;
+ node->rb_left = old->rb_left;
+ rb_set_parent(old->rb_left, node);
+
+ goto color;
+ }
+
+ parent = rb_parent(node);
+ color = rb_color(node);
+
+ if (child)
+ rb_set_parent(child, parent);
+ if (parent)
+ {
+ if (parent->rb_left == node)
+ parent->rb_left = child;
+ else
+ parent->rb_right = child;
+ }
+ else
+ root->rb_node = child;
+
+ color:
+ if (color == RB_BLACK)
+ __rb_erase_color(child, parent, root);
+}
+
+/*
+ * This function returns the first node (in sort order) of the tree.
+ */
+struct rb_node *rb_first(const struct rb_root *root)
+{
+ struct rb_node *n;
+
+ n = root->rb_node;
+ if (!n)
+ return NULL;
+ while (n->rb_left)
+ n = n->rb_left;
+ return n;
+}
+
+struct rb_node *rb_last(const struct rb_root *root)
+{
+ struct rb_node *n;
+
+ n = root->rb_node;
+ if (!n)
+ return NULL;
+ while (n->rb_right)
+ n = n->rb_right;
+ return n;
+}
+
+struct rb_node *rb_next(const struct rb_node *node)
+{
+ struct rb_node *parent;
+
+ if (rb_parent(node) == node)
+ return NULL;
+
+ /* If we have a right-hand child, go down and then left as far
+ as we can. */
+ if (node->rb_right) {
+ node = node->rb_right;
+ while (node->rb_left)
+ node=node->rb_left;
+ return (struct rb_node *)node;
+ }
+
+ /* No right-hand children. Everything down and left is
+ smaller than us, so any 'next' node must be in the general
+ direction of our parent. Go up the tree; any time the
+ ancestor is a right-hand child of its parent, keep going
+ up. First time it's a left-hand child of its parent, said
+ parent is our 'next' node. */
+ while ((parent = rb_parent(node)) && node == parent->rb_right)
+ node = parent;
+
+ return parent;
+}
+
+struct rb_node *rb_prev(const struct rb_node *node)
+{
+ struct rb_node *parent;
+
+ if (rb_parent(node) == node)
+ return NULL;
+
+ /* If we have a left-hand child, go down and then right as far
+ as we can. */
+ if (node->rb_left) {
+ node = node->rb_left;
+ while (node->rb_right)
+ node=node->rb_right;
+ return (struct rb_node *)node;
+ }
+
+ /* No left-hand children. Go up till we find an ancestor which
+ is a right-hand child of its parent */
+ while ((parent = rb_parent(node)) && node == parent->rb_left)
+ node = parent;
+
+ return parent;
+}
+
+void rb_replace_node(struct rb_node *victim, struct rb_node *new,
+ struct rb_root *root)
+{
+ struct rb_node *parent = rb_parent(victim);
+
+ /* Set the surrounding nodes to point to the replacement */
+ if (parent) {
+ if (victim == parent->rb_left)
+ parent->rb_left = new;
+ else
+ parent->rb_right = new;
+ } else {
+ root->rb_node = new;
+ }
+ if (victim->rb_left)
+ rb_set_parent(victim->rb_left, new);
+ if (victim->rb_right)
+ rb_set_parent(victim->rb_right, new);
+
+ /* Copy the pointers/colour from the victim to the replacement */
+ *new = *victim;
+}
diff --git a/Src/osmolib/src/shared/libosmocore/src/serial.c b/Src/osmolib/src/shared/libosmocore/src/serial.c
index 26cf59d..bc64b8a 100644
--- a/Src/osmolib/src/shared/libosmocore/src/serial.c
+++ b/Src/osmolib/src/shared/libosmocore/src/serial.c
@@ -38,8 +38,9 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
+#ifdef __linux__
#include <linux/serial.h>
-
+#endif
#include <osmocom/core/serial.h>
@@ -155,6 +156,7 @@ osmo_serial_set_baudrate(int fd, speed_t baudrate)
int
osmo_serial_set_custom_baudrate(int fd, int baudrate)
{
+#ifdef __linux__
int rc;
struct serial_struct ser_info;
@@ -174,6 +176,23 @@ osmo_serial_set_custom_baudrate(int fd, int baudrate)
}
return _osmo_serial_set_baudrate(fd, B38400); /* 38400 is a kind of magic ... */
+#elif defined(__APPLE__)
+#ifndef IOSSIOSPEED
+#define IOSSIOSPEED _IOW('T', 2, speed_t)
+#endif
+ int rc;
+
+ unsigned int speed = baudrate;
+ rc = ioctl(fd, IOSSIOSPEED, &speed);
+ if (rc < 0) {
+ dbg_perror("ioctl(IOSSIOSPEED)");
+ return -errno;
+ }
+ return 0;
+#else
+#warning osmo_serial_set_custom_baudrate: unsupported platform
+ return 0;
+#endif
}
/*! \brief Clear any custom baudrate
@@ -185,6 +204,7 @@ osmo_serial_set_custom_baudrate(int fd, int baudrate)
int
osmo_serial_clear_custom_baudrate(int fd)
{
+#ifdef __linux__
int rc;
struct serial_struct ser_info;
@@ -202,7 +222,7 @@ osmo_serial_clear_custom_baudrate(int fd)
dbg_perror("ioctl(TIOCSSERIAL)");
return -errno;
}
-
+#endif
return 0;
}
diff --git a/Src/osmolib/src/shared/libosmocore/src/socket.c b/Src/osmolib/src/shared/libosmocore/src/socket.c
index 1a1d71d..8a8829b 100644
--- a/Src/osmolib/src/shared/libosmocore/src/socket.c
+++ b/Src/osmolib/src/shared/libosmocore/src/socket.c
@@ -18,6 +18,8 @@
#include <sys/socket.h>
#include <sys/types.h>
+#include <netinet/in.h>
+
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
diff --git a/Src/osmolib/src/shared/libosmocore/src/timer.c b/Src/osmolib/src/shared/libosmocore/src/timer.c
index ed2b296..79d4ad6 100644
--- a/Src/osmolib/src/shared/libosmocore/src/timer.c
+++ b/Src/osmolib/src/shared/libosmocore/src/timer.c
@@ -1,7 +1,12 @@
/*
* (C) 2008,2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2011 by Harald Welte <laforge@gnumonks.org>
* All Rights Reserved
*
+ * Authors: Holger Hans Peter Freyther <zecke@selfish.org>
+ * Harald Welte <laforge@gnumonks.org>
+ * Pablo Neira Ayuso <pablo@gnumonks.org>
+ *
* 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
@@ -18,6 +23,10 @@
*
*/
+/* These store the amount of time that we wait until next timer expires. */
+static struct timeval nearest;
+static struct timeval *nearest_p;
+
/*! \addtogroup timer
* @{
*/
@@ -27,35 +36,43 @@
#include <assert.h>
#include <string.h>
+#include <limits.h>
#include <osmocom/core/timer.h>
+#include <osmocom/core/timer_compat.h>
+#include <osmocom/core/linuxlist.h>
+
+static struct rb_root timer_root = RB_ROOT;
+
+static void __add_timer(struct osmo_timer_list *timer)
+{
+ struct rb_node **new = &(timer_root.rb_node);
+ struct rb_node *parent = NULL;
-static LLIST_HEAD(timer_list);
-static struct timeval s_nearest_time;
-static struct timeval s_select_time;
+ while (*new) {
+ struct osmo_timer_list *this;
-#define MICRO_SECONDS 1000000LL
+ this = container_of(*new, struct osmo_timer_list, node);
-#define TIME_SMALLER(left, right) \
- (left.tv_sec*MICRO_SECONDS+left.tv_usec) <= (right.tv_sec*MICRO_SECONDS+right.tv_usec)
+ parent = *new;
+ if (timercmp(&timer->timeout, &this->timeout, <))
+ new = &((*new)->rb_left);
+ else
+ new = &((*new)->rb_right);
+ }
+ rb_link_node(&timer->node, parent, new);
+ rb_insert_color(&timer->node, &timer_root);
+}
/*! \brief add a new timer to the timer management
* \param[in] timer the timer that should be added
*/
void osmo_timer_add(struct osmo_timer_list *timer)
{
- struct osmo_timer_list *list_timer;
-
- /* TODO: Optimize and remember the closest item... */
+ osmo_timer_del(timer);
timer->active = 1;
-
- /* this might be called from within update_timers */
- llist_for_each_entry(list_timer, &timer_list, entry)
- if (timer == list_timer)
- return;
-
- timer->in_list = 1;
- llist_add(&timer->entry, &timer_list);
+ INIT_LLIST_HEAD(&timer->list);
+ __add_timer(timer);
}
/*! \brief schedule a timer at a given future relative time
@@ -74,10 +91,9 @@ osmo_timer_schedule(struct osmo_timer_list *timer, int seconds, int microseconds
struct timeval current_time;
gettimeofday(&current_time, NULL);
- unsigned long long currentTime = current_time.tv_sec * MICRO_SECONDS + current_time.tv_usec;
- currentTime += seconds * MICRO_SECONDS + microseconds;
- timer->timeout.tv_sec = currentTime / MICRO_SECONDS;
- timer->timeout.tv_usec = currentTime % MICRO_SECONDS;
+ timer->timeout.tv_sec = seconds;
+ timer->timeout.tv_usec = microseconds;
+ timeradd(&timer->timeout, &current_time, &timer->timeout);
osmo_timer_add(timer);
}
@@ -89,10 +105,12 @@ osmo_timer_schedule(struct osmo_timer_list *timer, int seconds, int microseconds
*/
void osmo_timer_del(struct osmo_timer_list *timer)
{
- if (timer->in_list) {
+ if (timer->active) {
timer->active = 0;
- timer->in_list = 0;
- llist_del(&timer->entry);
+ rb_erase(&timer->node, &timer_root);
+ /* make sure this is not already scheduled for removal. */
+ if (!llist_empty(&timer->list))
+ llist_del_init(&timer->list);
}
}
@@ -116,26 +134,26 @@ int osmo_timer_pending(struct osmo_timer_list *timer)
*/
struct timeval *osmo_timers_nearest(void)
{
- struct timeval current_time;
-
- if (s_nearest_time.tv_sec == 0 && s_nearest_time.tv_usec == 0)
- return NULL;
-
- if (gettimeofday(&current_time, NULL) == -1)
- return NULL;
-
- unsigned long long nearestTime = s_nearest_time.tv_sec * MICRO_SECONDS + s_nearest_time.tv_usec;
- unsigned long long currentTime = current_time.tv_sec * MICRO_SECONDS + current_time.tv_usec;
+ /* nearest_p is exactly what we need already: NULL if nothing is
+ * waiting, {0,0} if we must dispatch immediately, and the correct
+ * delay if we need to wait */
+ return nearest_p;
+}
- if (nearestTime < currentTime) {
- s_select_time.tv_sec = 0;
- s_select_time.tv_usec = 0;
+static void update_nearest(struct timeval *cand, struct timeval *current)
+{
+ if (cand->tv_sec != LONG_MAX) {
+ if (timercmp(cand, current, >))
+ timersub(cand, current, &nearest);
+ else {
+ /* loop again inmediately */
+ nearest.tv_sec = 0;
+ nearest.tv_usec = 0;
+ }
+ nearest_p = &nearest;
} else {
- s_select_time.tv_sec = (nearestTime - currentTime) / MICRO_SECONDS;
- s_select_time.tv_usec = (nearestTime - currentTime) % MICRO_SECONDS;
+ nearest_p = NULL;
}
-
- return &s_select_time;
}
/*
@@ -143,17 +161,18 @@ struct timeval *osmo_timers_nearest(void)
*/
void osmo_timers_prepare(void)
{
- struct osmo_timer_list *timer, *nearest_timer = NULL;
- llist_for_each_entry(timer, &timer_list, entry) {
- if (!nearest_timer || TIME_SMALLER(timer->timeout, nearest_timer->timeout)) {
- nearest_timer = timer;
- }
- }
+ struct rb_node *node;
+ struct timeval current;
+
+ gettimeofday(&current, NULL);
- if (nearest_timer) {
- s_nearest_time = nearest_timer->timeout;
+ node = rb_first(&timer_root);
+ if (node) {
+ struct osmo_timer_list *this;
+ this = container_of(node, struct osmo_timer_list, node);
+ update_nearest(&this->timeout, &current);
} else {
- memset(&s_nearest_time, 0, sizeof(struct timeval));
+ nearest_p = NULL;
}
}
@@ -163,46 +182,41 @@ void osmo_timers_prepare(void)
int osmo_timers_update(void)
{
struct timeval current_time;
- struct osmo_timer_list *timer, *tmp;
+ struct rb_node *node;
+ struct llist_head timer_eviction_list;
+ struct osmo_timer_list *this;
int work = 0;
gettimeofday(&current_time, NULL);
+ INIT_LLIST_HEAD(&timer_eviction_list);
+ for (node = rb_first(&timer_root); node; node = rb_next(node)) {
+ this = container_of(node, struct osmo_timer_list, node);
+
+ if (timercmp(&this->timeout, &current_time, >))
+ break;
+
+ llist_add(&this->list, &timer_eviction_list);
+ }
+
/*
* The callbacks might mess with our list and in this case
* even llist_for_each_entry_safe is not safe to use. To allow
- * del_timer, add_timer, schedule_timer to be called from within
- * the callback we jump through some loops.
+ * osmo_timer_del to be called from within the callback we need
+ * to restart the iteration for each element scheduled for removal.
*
- * First we set the handled flag of each active timer to zero,
- * then we iterate over the list and execute the callbacks. As the
- * list might have been changed (specially the next) from within
- * the callback we have to start over again. Once every callback
- * is dispatched we will remove the non-active from the list.
- *
- * TODO: If this is a performance issue we can poison a global
- * variable in add_timer and del_timer and only then restart.
+ * The problematic scenario is the following: Given two timers A
+ * and B that have expired at the same time. Thus, they are both
+ * in the eviction list in this order: A, then B. If we remove
+ * timer B from the A's callback, we continue with B in the next
+ * iteration step, leading to an access-after-release.
*/
- llist_for_each_entry(timer, &timer_list, entry) {
- timer->handled = 0;
- }
-
restart:
- llist_for_each_entry(timer, &timer_list, entry) {
- if (!timer->handled && TIME_SMALLER(timer->timeout, current_time)) {
- timer->handled = 1;
- timer->active = 0;
- (*timer->cb)(timer->data);
- work = 1;
- goto restart;
- }
- }
-
- llist_for_each_entry_safe(timer, tmp, &timer_list, entry) {
- timer->handled = 0;
- if (!timer->active) {
- osmo_timer_del(timer);
- }
+ llist_for_each_entry(this, &timer_eviction_list, list) {
+ osmo_timer_del(this);
+ this->cb(this->data);
+ work = 1;
+ goto restart;
}
return work;
@@ -210,10 +224,10 @@ restart:
int osmo_timers_check(void)
{
- struct osmo_timer_list *timer;
+ struct rb_node *node;
int i = 0;
- llist_for_each_entry(timer, &timer_list, entry) {
+ for (node = rb_first(&timer_root); node; node = rb_next(node)) {
i++;
}
return i;
diff --git a/Src/osmolib/src/shared/libosmocore/src/utils.c b/Src/osmolib/src/shared/libosmocore/src/utils.c
index a25479f..0a970ac 100644
--- a/Src/osmolib/src/shared/libosmocore/src/utils.c
+++ b/Src/osmolib/src/shared/libosmocore/src/utils.c
@@ -173,11 +173,15 @@ char *osmo_hexdump(const unsigned char *buf, int len)
* This function will print a sequence of bytes as hexadecimal numbers,
* without any space character between each byte (e.g. "1aefd9")
*/
-char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)
+char *osmo_hexdump_nospc(const unsigned char *buf, int len)
{
return _osmo_hexdump(buf, len, "");
}
+ /* Compat with previous typo to preserve abi */
+char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)
+ __attribute__((weak, alias("osmo_hexdump_nospc")));
+
#include "../config.h"
#ifdef HAVE_CTYPE_H
#include <ctype.h>
diff --git a/Src/osmolib/src/shared/libosmocore/src/vty/logging_vty.c b/Src/osmolib/src/shared/libosmocore/src/vty/logging_vty.c
index b037a5b..6be30b4 100644
--- a/Src/osmolib/src/shared/libosmocore/src/vty/logging_vty.c
+++ b/Src/osmolib/src/shared/libosmocore/src/vty/logging_vty.c
@@ -185,9 +185,10 @@ DEFUN(logging_level,
DEFUN(logging_set_category_mask,
logging_set_category_mask_cmd,
- "logging set log mask MASK",
+ "logging set-log-mask MASK",
LOGGING_STR
- "Decide which categories to output.\n")
+ "Set the logmask of this logging target\n"
+ "The logmask to use\n")
{
struct log_target *tgt = osmo_log_vty2tgt(vty);
@@ -198,6 +199,14 @@ DEFUN(logging_set_category_mask,
return CMD_SUCCESS;
}
+ALIAS_DEPRECATED(logging_set_category_mask,
+ logging_set_category_mask_old_cmd,
+ "logging set log mask MASK",
+ LOGGING_STR
+ "Decide which categories to output.\n"
+ "Log commands\n" "Mask commands\n" "The logmask to use\n");
+
+
DEFUN(diable_logging,
disable_logging_cmd,
"logging disable",
@@ -381,7 +390,16 @@ static struct value_string sysl_level_names[] = {
DEFUN(cfg_log_syslog, cfg_log_syslog_cmd,
"log syslog (authpriv|cron|daemon|ftp|lpr|mail|news|user|uucp)",
- LOG_STR "Logging via syslog\n")
+ LOG_STR "Logging via syslog\n"
+ "Security/authorization messages facility\n"
+ "Clock daemon (cron/at) facility\n"
+ "General system daemon facility\n"
+ "Ftp daemon facility\n"
+ "Line printer facility\n"
+ "Mail facility\n"
+ "News facility\n"
+ "Generic facility\n"
+ "UUCP facility\n")
{
int facility = get_string_value(sysl_level_names, argv[0]);
@@ -560,6 +578,7 @@ void logging_vty_add_cmds(const struct log_info *cat)
install_element_ve(&logging_use_clr_cmd);
install_element_ve(&logging_prnt_timestamp_cmd);
install_element_ve(&logging_set_category_mask_cmd);
+ install_element_ve(&logging_set_category_mask_old_cmd);
/* Logging level strings are generated dynamically. */
logging_level_cmd.string = log_vty_command_string(cat);
diff --git a/Src/osmolib/src/shared/libosmocore/src/vty/telnet_interface.c b/Src/osmolib/src/shared/libosmocore/src/vty/telnet_interface.c
index ed64cda..167acc1 100644
--- a/Src/osmolib/src/shared/libosmocore/src/vty/telnet_interface.c
+++ b/Src/osmolib/src/shared/libosmocore/src/vty/telnet_interface.c
@@ -221,4 +221,16 @@ void vty_event(enum event event, int sock, struct vty *vty)
}
}
+void telnet_exit(void)
+{
+ struct telnet_connection *tc, *tc2;
+
+ llist_for_each_entry_safe(tc, tc2, &active_connections, entry)
+ telnet_close_client(&tc->fd);
+
+ osmo_fd_unregister(&server_socket);
+ close(server_socket.fd);
+ talloc_free(tall_telnet_ctx);
+}
+
/*! }@ */
diff --git a/Src/osmolib/src/shared/libosmocore/src/vty/vty.c b/Src/osmolib/src/shared/libosmocore/src/vty/vty.c
index 5f5e6a4..da03596 100644
--- a/Src/osmolib/src/shared/libosmocore/src/vty/vty.c
+++ b/Src/osmolib/src/shared/libosmocore/src/vty/vty.c
@@ -802,9 +802,11 @@ static void vty_backward_word(struct vty *vty)
static void vty_down_level(struct vty *vty)
{
vty_out(vty, "%s", VTY_NEWLINE);
- /* FIXME: we need to call the exit function of the specific node
- * in question, not this generic one that doesn't know all nodes */
- (*config_exit_cmd.func) (NULL, vty, 0, NULL);
+ /* call the exit function of the specific node */
+ if (vty->node > CONFIG_NODE)
+ vty_go_parent(vty);
+ else
+ (*config_exit_cmd.func) (NULL, vty, 0, NULL);
vty_prompt(vty);
vty->cp = 0;
}
diff --git a/Src/osmolib/src/shared/libosmocore/tests/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/Makefile.am
index 6c3cb33..eff1ac4 100644
--- a/Src/osmolib/src/shared/libosmocore/tests/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/tests/Makefile.am
@@ -1,6 +1,47 @@
if ENABLE_TESTS
-SUBDIRS = timer sms ussd smscb bits
+SUBDIRS = timer sms ussd smscb bits a5 conv auth lapd gsm0808
if ENABLE_MSGFILE
SUBDIRS += msgfile
endif
+
+
+# The `:;' works around a Bash 3.2 bug when the output is not writeable.
+$(srcdir)/package.m4: $(top_srcdir)/configure.ac
+ :;{ \
+ echo '# Signature of the current package.' && \
+ echo 'm4_define([AT_PACKAGE_NAME],' && \
+ echo ' [$(PACKAGE_NAME)])' && \
+ echo 'm4_define([AT_PACKAGE_TARNAME],' && \
+ echo ' [$(PACKAGE_TARNAME)])' && \
+ echo 'm4_define([AT_PACKAGE_VERSION],' && \
+ echo ' [$(PACKAGE_VERSION)])' && \
+ echo 'm4_define([AT_PACKAGE_STRING],' && \
+ echo ' [$(PACKAGE_STRING)])' && \
+ echo 'm4_define([AT_PACKAGE_BUGREPORT],' && \
+ echo ' [$(PACKAGE_BUGREPORT)])'; \
+ echo 'm4_define([AT_PACKAGE_URL],' && \
+ echo ' [$(PACKAGE_URL)])'; \
+ } >'$(srcdir)/package.m4'
+
+EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE)
+TESTSUITE = $(srcdir)/testsuite
+
+check-local: atconfig $(TESTSUITE)
+ $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS)
+
+installcheck-local: atconfig $(TESTSUITE)
+ $(SHELL) '$(TESTSUITE)' AUTOTEST_PATH='$(bindir)' \
+ $(TESTSUITEFLAGS)
+
+clean-local:
+ test ! -f '$(TESTSUITE)' || \
+ $(SHELL) '$(TESTSUITE)' --clean
+ $(RM) -f atconfig
+
+AUTOM4TE = $(SHELL) $(top_srcdir)/missing --run autom4te
+AUTOTEST = $(AUTOM4TE) --language=autotest
+$(TESTSUITE): $(srcdir)/testsuite.at $(srcdir)/package.m4
+ $(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at
+ mv $@.tmp $@
+
endif
diff --git a/Src/osmolib/src/shared/libosmocore/tests/a5/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/a5/Makefile.am
new file mode 100644
index 0000000..3c6e6ba
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/a5/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+noinst_PROGRAMS = a5_test
+EXTRA_DIST = a5_test.ok
+
+a5_test_SOURCES = a5_test.c
+a5_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
diff --git a/Src/osmolib/src/shared/libosmocore/tests/a5/a5_test.c b/Src/osmolib/src/shared/libosmocore/tests/a5/a5_test.c
new file mode 100644
index 0000000..14436f1
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/a5/a5_test.c
@@ -0,0 +1,98 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/a5.h>
+
+static const uint8_t key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+static const uint32_t fn = 123456;
+static const uint8_t dl[] = {
+ /* A5/0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* A5/1 */
+ 0xcb, 0xa2, 0x55, 0x76, 0x17, 0x5d, 0x3b, 0x1c,
+ 0x7b, 0x2f, 0x29, 0xa8, 0xc1, 0xb6, 0x00,
+
+ /* A5/2 */
+ 0x45, 0x9c, 0x88, 0xc3, 0x82, 0xb7, 0xff, 0xb3,
+ 0x98, 0xd2, 0xf9, 0x6e, 0x0f, 0x14, 0x80,
+};
+static const uint8_t ul[] = {
+ /* A5/0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* A5/1 */
+ 0xd9, 0x03, 0x5e, 0x0f, 0x2a, 0xec, 0x13, 0x9a,
+ 0x05, 0xd4, 0xa8, 0x7b, 0xb1, 0x64, 0x80,
+
+ /* A5/2 */
+ 0xf0, 0x3a, 0xac, 0xde, 0xe3, 0x5b, 0x5e, 0x65,
+ 0x80, 0xba, 0xab, 0xc0, 0x59, 0x26, 0x40,
+};
+
+static const char *
+binstr(ubit_t *d, int n)
+{
+ static char str[256];
+ int i;
+
+ for (i=0; i<n; i++)
+ str[i] = d[i] ? '1' : '0';
+
+ str[i] = '\0';
+
+ return str;
+}
+
+int main(int argc, char **argv)
+{
+ ubit_t exp[114];
+ ubit_t out[114];
+ int n, i;
+
+ for (n=0; n<3; n++) {
+ /* "Randomize" */
+ for (i=0; i<114; i++)
+ out[i] = i & 1;
+
+ /* DL */
+ osmo_pbit2ubit(exp, &dl[15*n], 114);
+
+ osmo_a5(n, key, fn, out, NULL);
+
+ printf("A5/%d - DL: %s", n, binstr(out, 114));
+
+ if (!memcmp(exp, out, 114))
+ printf(" => OK\n");
+ else {
+ printf(" => BAD\n");
+ printf(" Expected: %s", binstr(out, 114));
+ fprintf(stderr, "[!] A5/%d DL failed", n);
+ exit(1);
+ }
+
+ /* UL */
+ osmo_pbit2ubit(exp, &ul[15*n], 114);
+
+ osmo_a5(n, key, fn, NULL, out);
+
+ printf("A5/%d - UL: %s", n, binstr(out, 114));
+
+ if (!memcmp(exp, out, 114))
+ printf(" => OK\n");
+ else {
+ printf(" => BAD\n");
+ printf(" Expected: %s", binstr(out, 114));
+ fprintf(stderr, "[!] A5/%d UL failed", n);
+ exit(1);
+ }
+ }
+
+ return 0;
+}
diff --git a/Src/osmolib/src/shared/libosmocore/tests/a5/a5_test.ok b/Src/osmolib/src/shared/libosmocore/tests/a5/a5_test.ok
new file mode 100644
index 0000000..4497e14
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/a5/a5_test.ok
@@ -0,0 +1,6 @@
+A5/0 - DL: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 => OK
+A5/0 - UL: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 => OK
+A5/1 - DL: 110010111010001001010101011101100001011101011101001110110001110001111011001011110010100110101000110000011011011000 => OK
+A5/1 - UL: 110110010000001101011110000011110010101011101100000100111001101000000101110101001010100001111011101100010110010010 => OK
+A5/2 - DL: 010001011001110010001000110000111000001010110111111111111011001110011000110100101111100101101110000011110001010010 => OK
+A5/2 - UL: 111100000011101010101100110111101110001101011011010111100110010110000000101110101010101111000000010110010010011001 => OK
diff --git a/Src/osmolib/src/shared/libosmocore/tests/auth/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/auth/Makefile.am
new file mode 100644
index 0000000..52976d0
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/auth/Makefile.am
@@ -0,0 +1,8 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+noinst_PROGRAMS = milenage_test
+EXTRA_DIST = milenage_test.ok
+
+milenage_test_SOURCES = milenage_test.c
+milenage_test_LDADD = $(top_builddir)/src/libosmocore.la \
+ $(top_builddir)/src/gsm/libosmogsm.la
+
diff --git a/Src/osmolib/src/shared/libosmocore/tests/auth/milenage_test.c b/Src/osmolib/src/shared/libosmocore/tests/auth/milenage_test.c
new file mode 100644
index 0000000..da7c800
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/auth/milenage_test.c
@@ -0,0 +1,78 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include <osmocom/crypt/auth.h>
+#include <osmocom/core/utils.h>
+
+static void dump_auth_vec(struct osmo_auth_vector *vec)
+{
+ printf("RAND:\t%s\n", osmo_hexdump(vec->rand, sizeof(vec->rand)));
+
+ if (vec->auth_types & OSMO_AUTH_TYPE_UMTS) {
+ printf("AUTN:\t%s\n", osmo_hexdump(vec->autn, sizeof(vec->autn)));
+ printf("IK:\t%s\n", osmo_hexdump(vec->ik, sizeof(vec->ik)));
+ printf("CK:\t%s\n", osmo_hexdump(vec->ck, sizeof(vec->ck)));
+ printf("RES:\t%s\n", osmo_hexdump(vec->res, vec->res_len));
+ }
+
+ if (vec->auth_types & OSMO_AUTH_TYPE_GSM) {
+ printf("SRES:\t%s\n", osmo_hexdump(vec->sres, sizeof(vec->sres)));
+ printf("Kc:\t%s\n", osmo_hexdump(vec->kc, sizeof(vec->kc)));
+ }
+}
+
+static struct osmo_sub_auth_data test_aud = {
+ .type = OSMO_AUTH_TYPE_UMTS,
+ .algo = OSMO_AUTH_ALG_MILENAGE,
+ .u.umts = {
+ .opc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ .k = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ .amf = { 0x00, 0x00 },
+ .sqn = 0x22,
+ },
+};
+
+int main(int argc, char **argv)
+{
+ struct osmo_auth_vector _vec;
+ struct osmo_auth_vector *vec = &_vec;
+ uint8_t _rand[16];
+ int rc;
+
+#if 0
+ srand(time(NULL));
+ *(uint32_t *)&_rand[0] = rand();
+ *(uint32_t *)(&_rand[4]) = rand();
+ *(uint32_t *)(&_rand[8]) = rand();
+ *(uint32_t *)(&_rand[12]) = rand();
+#else
+ memset(_rand, 0, sizeof(_rand));
+#endif
+ memset(vec, 0, sizeof(*vec));
+
+ rc = osmo_auth_gen_vec(vec, &test_aud, _rand);
+ if (rc < 0) {
+ fprintf(stderr, "error generating auth vector\n");
+ exit(1);
+ }
+
+ dump_auth_vec(vec);
+
+ const uint8_t auts[14] = { 0x87, 0x11, 0xa0, 0xec, 0x9e, 0x16, 0x37, 0xdf,
+ 0x17, 0xf8, 0x0b, 0x38, 0x4e, 0xe4 };
+
+ rc = osmo_auth_gen_vec_auts(vec, &test_aud, auts, _rand, _rand);
+ if (rc < 0) {
+ printf("AUTS failed\n");
+ } else {
+ printf("AUTS success: SEQ.MS = %lu\n", test_aud.u.umts.sqn);
+ }
+
+ exit(0);
+
+}
diff --git a/Src/osmolib/src/shared/libosmocore/tests/auth/milenage_test.ok b/Src/osmolib/src/shared/libosmocore/tests/auth/milenage_test.ok
new file mode 100644
index 0000000..66337ca
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/auth/milenage_test.ok
@@ -0,0 +1,8 @@
+RAND: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+AUTN: ec 93 20 c2 c2 12 00 00 c8 b7 de 2a 34 49 f1 bd
+IK: 12 cb 2d d3 e0 ec 83 78 f6 fc 1d 60 6c 61 9f 47
+CK: 72 00 a1 84 d8 f2 c7 58 fb df 87 90 0d db f2 75
+RES: e9 fc 88 cc c8 a3 53 81
+SRES: 21 5f db 4d
+Kc: 6d e8 16 a7 59 a4 29 12
+AUTS success: SEQ.MS = 33
diff --git a/Src/osmolib/src/shared/libosmocore/tests/bits/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/bits/Makefile.am
index dd03e83..d6fb2f2 100644
--- a/Src/osmolib/src/shared/libosmocore/tests/bits/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/tests/bits/Makefile.am
@@ -1,5 +1,6 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include
noinst_PROGRAMS = bitrev_test
+EXTRA_DIST = bitrev_test.ok
bitrev_test_SOURCES = bitrev_test.c
bitrev_test_LDADD = $(top_builddir)/src/libosmocore.la
diff --git a/Src/osmolib/src/shared/libosmocore/tests/bits/bitrev_test.ok b/Src/osmolib/src/shared/libosmocore/tests/bits/bitrev_test.ok
new file mode 100644
index 0000000..47f402f
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/bits/bitrev_test.ok
@@ -0,0 +1,24 @@
+INORDER: 01 02 04 08 10 20 40 80
+REVERSED: 80 40 20 10 08 04 02 01
+
+INORDER: 02 04 08 10 20 40 80
+REVERSED: 40 20 10 08 04 02 01
+
+INORDER: 04 08 10 20 40 80
+REVERSED: 20 10 08 04 02 01
+
+INORDER: 08 10 20 40 80
+REVERSED: 10 08 04 02 01
+
+INORDER: 10 20 40 80
+REVERSED: 08 04 02 01
+
+INORDER: 20 40 80
+REVERSED: 04 02 01
+
+INORDER: 40 80
+REVERSED: 02 01
+
+INORDER: 80
+REVERSED: 01
+
diff --git a/Src/osmolib/src/shared/libosmocore/tests/conv/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/conv/Makefile.am
new file mode 100644
index 0000000..75cfec8
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/conv/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+noinst_PROGRAMS = conv_test
+EXTRA_DIST = conv_test.ok
+
+conv_test_SOURCES = conv_test.c
+conv_test_LDADD = $(top_builddir)/src/libosmocore.la
diff --git a/Src/osmolib/src/shared/libosmocore/tests/conv/conv_test.c b/Src/osmolib/src/shared/libosmocore/tests/conv/conv_test.c
new file mode 100644
index 0000000..54e043e
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/conv/conv_test.c
@@ -0,0 +1,486 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/conv.h>
+#include <osmocom/core/utils.h>
+
+#define MAX_LEN_BITS 512
+#define MAX_LEN_BYTES (512/8)
+
+
+/* ------------------------------------------------------------------------ */
+/* Test codes */
+/* ------------------------------------------------------------------------ */
+
+/* GSM xCCH -> Non-recursive code, flushed, not punctured */
+static const uint8_t conv_gsm_xcch_next_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+static const uint8_t conv_gsm_xcch_next_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const struct osmo_conv_code conv_gsm_xcch = {
+ .N = 2,
+ .K = 5,
+ .len = 224,
+ .term = CONV_TERM_FLUSH,
+ .next_output = conv_gsm_xcch_next_output,
+ .next_state = conv_gsm_xcch_next_state,
+};
+
+
+/* GSM TCH/AFS 7.95 -> Recursive code, flushed, with puncturing */
+static const uint8_t conv_gsm_tch_afs_7_95_next_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+};
+
+static const uint8_t conv_gsm_tch_afs_7_95_next_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 5, 4 }, { 7, 6 },
+ { 9, 8 }, { 11, 10 }, { 12, 13 }, { 14, 15 },
+ { 16, 17 }, { 18, 19 }, { 21, 20 }, { 23, 22 },
+ { 25, 24 }, { 27, 26 }, { 28, 29 }, { 30, 31 },
+ { 33, 32 }, { 35, 34 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 45, 44 }, { 47, 46 },
+ { 49, 48 }, { 51, 50 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 61, 60 }, { 63, 62 },
+ { 1, 0 }, { 3, 2 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 13, 12 }, { 15, 14 },
+ { 17, 16 }, { 19, 18 }, { 20, 21 }, { 22, 23 },
+ { 24, 25 }, { 26, 27 }, { 29, 28 }, { 31, 30 },
+ { 32, 33 }, { 34, 35 }, { 37, 36 }, { 39, 38 },
+ { 41, 40 }, { 43, 42 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 53, 52 }, { 55, 54 },
+ { 57, 56 }, { 59, 58 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t conv_gsm_tch_afs_7_95_next_term_output[] = {
+ 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5, 6, 5, 3, 0,
+ 4, 7, 1, 2, 1, 2, 4, 7, 7, 4, 2, 1, 2, 1, 7, 4,
+ 7, 4, 2, 1, 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7,
+ 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6, 5, 6, 0, 3,
+};
+
+static const uint8_t conv_gsm_tch_afs_7_95_next_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
+};
+
+static int conv_gsm_tch_afs_7_95_puncture[] = {
+ 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310,
+ 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367,
+ 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415,
+ 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463,
+ 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505,
+ 506, 508, 509, 511, 512,
+ -1, /* end */
+};
+
+static const struct osmo_conv_code conv_gsm_tch_afs_7_95 = {
+ .N = 3,
+ .K = 7,
+ .len = 165,
+ .term = CONV_TERM_FLUSH,
+ .next_output = conv_gsm_tch_afs_7_95_next_output,
+ .next_state = conv_gsm_tch_afs_7_95_next_state,
+ .next_term_output = conv_gsm_tch_afs_7_95_next_term_output,
+ .next_term_state = conv_gsm_tch_afs_7_95_next_term_state,
+ .puncture = conv_gsm_tch_afs_7_95_puncture,
+};
+
+
+/* GMR-1 TCH3 Speech -> Non recursive code, tail-biting, punctured */
+static const uint8_t conv_gmr1_tch3_speech_next_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 },
+ { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 },
+ { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 },
+ { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 },
+ { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 },
+ { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 },
+ { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 },
+ { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 },
+ { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 },
+ { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 },
+};
+
+static const uint8_t conv_gmr1_tch3_speech_next_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 },
+ { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 },
+ { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const int conv_gmr1_tch3_speech_puncture[] = {
+ 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47,
+ 51, 55, 59, 63, 67, 71, 75, 79, 83, 87, 91, 95,
+ -1, /* end */
+};
+
+static const struct osmo_conv_code conv_gmr1_tch3_speech = {
+ .N = 2,
+ .K = 7,
+ .len = 48,
+ .term = CONV_TERM_TAIL_BITING,
+ .next_output = conv_gmr1_tch3_speech_next_output,
+ .next_state = conv_gmr1_tch3_speech_next_state,
+ .puncture = conv_gmr1_tch3_speech_puncture,
+};
+
+
+/* WiMax FCH -> Non recursive code, tail-biting, non-punctured */
+static const uint8_t conv_wimax_fch_next_output[][2] = {
+ { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 },
+ { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 },
+ { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 },
+ { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 },
+ { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 },
+ { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 },
+ { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 },
+ { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 },
+ { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 },
+ { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 },
+ { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 },
+ { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 },
+ { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 },
+ { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 },
+ { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 },
+ { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 },
+};
+
+static const uint8_t conv_wimax_fch_next_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 },
+ { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 },
+ { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const struct osmo_conv_code conv_wimax_fch = {
+ .N = 2,
+ .K = 7,
+ .len = 48,
+ .term = CONV_TERM_TAIL_BITING,
+ .next_output = conv_wimax_fch_next_output,
+ .next_state = conv_wimax_fch_next_state,
+};
+
+
+/* Random code -> Non recursive code, direct truncation, non-punctured */
+static const struct osmo_conv_code conv_trunc = {
+ .N = 2,
+ .K = 5,
+ .len = 224,
+ .term = CONV_TERM_TRUNCATION,
+ .next_output = conv_gsm_xcch_next_output,
+ .next_state = conv_gsm_xcch_next_state,
+};
+
+
+/* ------------------------------------------------------------------------ */
+/* Test vectors */
+/* ------------------------------------------------------------------------ */
+
+struct conv_test_vector {
+ const char *name;
+ const struct osmo_conv_code *code;
+ int in_len;
+ int out_len;
+ int has_vec;
+ pbit_t vec_in[MAX_LEN_BYTES];
+ pbit_t vec_out[MAX_LEN_BYTES];
+};
+
+static const struct conv_test_vector tests[] = {
+ {
+ .name = "GSM xCCH (non-recursive, flushed, not punctured)",
+ .code = &conv_gsm_xcch,
+ .in_len = 224,
+ .out_len = 456,
+ .has_vec = 1,
+ .vec_in = { 0xf3, 0x1d, 0xb4, 0x0c, 0x4d, 0x1d, 0x9d, 0xae,
+ 0xc0, 0x0a, 0x42, 0x57, 0x13, 0x60, 0x80, 0x96,
+ 0xef, 0x23, 0x7e, 0x4c, 0x1d, 0x96, 0x24, 0x19,
+ 0x17, 0xf2, 0x44, 0x99 },
+ .vec_out = { 0xe9, 0x4d, 0x70, 0xab, 0xa2, 0x87, 0xf0, 0xe7,
+ 0x04, 0x14, 0x7c, 0xab, 0xaf, 0x6b, 0xa1, 0x16,
+ 0xeb, 0x30, 0x00, 0xde, 0xc8, 0xfd, 0x0b, 0x85,
+ 0x80, 0x41, 0x4a, 0xcc, 0xd3, 0xc0, 0xd0, 0xb6,
+ 0x26, 0xe5, 0x4e, 0x32, 0x49, 0x69, 0x38, 0x17,
+ 0x33, 0xab, 0xaf, 0xb6, 0xc1, 0x08, 0xf3, 0x9f,
+ 0x8c, 0x75, 0x6a, 0x4e, 0x08, 0xc4, 0x20, 0x5f,
+ 0x8f },
+ },
+ {
+ .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)",
+ .code = &conv_gsm_tch_afs_7_95,
+ .in_len = 165,
+ .out_len = 448,
+ .has_vec = 1,
+ .vec_in = { 0x87, 0x66, 0xc3, 0x58, 0x09, 0xd4, 0x06, 0x59,
+ 0x10, 0xbf, 0x6b, 0x7f, 0xc8, 0xed, 0x72, 0xaa,
+ 0xc1, 0x3d, 0xf3, 0x1e, 0xb0 },
+ .vec_out = { 0x92, 0xbc, 0xde, 0xa0, 0xde, 0xbe, 0x01, 0x2f,
+ 0xbe, 0xe4, 0x61, 0x32, 0x4d, 0x4f, 0xdc, 0x41,
+ 0x43, 0x0d, 0x15, 0xe0, 0x23, 0xdd, 0x18, 0x91,
+ 0xe5, 0x36, 0x2d, 0xb7, 0xd9, 0x78, 0xb8, 0xb1,
+ 0xb7, 0xcb, 0x2f, 0xc0, 0x52, 0x8f, 0xe2, 0x8c,
+ 0x6f, 0xa6, 0x79, 0x88, 0xed, 0x0c, 0x2e, 0x9e,
+ 0xa1, 0x5f, 0x45, 0x4a, 0xfb, 0xe6, 0x5a, 0x9c },
+ },
+ {
+ .name = "GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)",
+ .code = &conv_gmr1_tch3_speech,
+ .in_len = 48,
+ .out_len = 72,
+ .has_vec = 1,
+ .vec_in = { 0x4d, 0xcb, 0xfc, 0x72, 0xf4, 0x8c },
+ .vec_out = { 0xc0, 0x86, 0x63, 0x4b, 0x8b, 0xd4, 0x6a, 0x76, 0xb2 },
+ },
+ {
+ .name = "WiMax FCH (non-recursive, tail-biting, not punctured)",
+ .code = &conv_wimax_fch,
+ .in_len = 48,
+ .out_len = 96,
+ .has_vec = 1,
+ .vec_in = { 0xfc, 0xa0, 0xa0, 0xfc, 0xa0, 0xa0 },
+ .vec_out = { 0x19, 0x42, 0x8a, 0xed, 0x21, 0xed, 0x19, 0x42,
+ 0x8a, 0xed, 0x21, 0xed },
+ },
+ {
+ .name = "??? (non-recursive, direct truncation, not punctured)",
+ .code = &conv_trunc,
+ .in_len = 224,
+ .out_len = 448,
+ .has_vec = 1,
+ .vec_in = { 0xe5, 0xe0, 0x85, 0x7e, 0xf7, 0x08, 0x19, 0x5a,
+ 0xb9, 0xad, 0x82, 0x37, 0x98, 0x8b, 0x26, 0xb9,
+ 0x81, 0x26, 0x9c, 0x75, 0xaf, 0xf3, 0xcb, 0x07,
+ 0xac, 0x63, 0xe2, 0x9c,
+ },
+ .vec_out = { 0xea, 0x3b, 0x55, 0x0c, 0xd3, 0xf7, 0x85, 0x69,
+ 0xe5, 0x79, 0x83, 0xd3, 0xc3, 0x9f, 0xb8, 0x61,
+ 0x21, 0x63, 0x51, 0x18, 0xac, 0xcd, 0x32, 0x49,
+ 0x53, 0x5c, 0x13, 0x1d, 0xbe, 0x05, 0x11, 0x63,
+ 0x5c, 0xc3, 0x42, 0x05, 0x1c, 0x68, 0x0a, 0xb4,
+ 0x61, 0x15, 0xaa, 0x4d, 0x94, 0xed, 0xb3, 0x3a,
+ 0x5d, 0x1b, 0x09, 0xc2, 0x99, 0x01, 0xec, 0x68 },
+ },
+ { /* end */ },
+};
+
+
+
+
+/* ------------------------------------------------------------------------ */
+/* Main */
+/* ------------------------------------------------------------------------ */
+
+static void
+fill_random(ubit_t *b, int n)
+{
+ int i;
+ for (i=0; i<n; i++)
+ b[i] = random() & 1;
+}
+
+static void
+ubit_to_sbit(sbit_t *dst, ubit_t *src, int n)
+{
+ int i;
+ for (i=0; i<n; i++)
+ dst[i] = src[i] ? -127 : 127;
+}
+
+static void
+sbit_to_ubit(ubit_t *dst, sbit_t *src, int n)
+{
+ int i;
+ for (i=0; i<n; i++)
+ dst[i] = src[i] < 0;
+}
+
+
+int main(int argc, char argv[])
+{
+ const struct conv_test_vector *tst;
+ ubit_t *bu0, *bu1;
+ sbit_t *bs;
+
+ srandom(time(NULL));
+
+ bu0 = malloc(sizeof(ubit_t) * MAX_LEN_BITS);
+ bu1 = malloc(sizeof(ubit_t) * MAX_LEN_BITS);
+ bs = malloc(sizeof(sbit_t) * MAX_LEN_BITS);
+
+ for (tst=tests; tst->name; tst++)
+ {
+ int i,l;
+
+ /* Test name */
+ printf("[+] Testing: %s\n", tst->name);
+
+ /* Check length */
+ l = osmo_conv_get_input_length(tst->code, 0);
+ printf("[.] Input length : ret = %3d exp = %3d -> %s\n",
+ l, tst->in_len, l == tst->in_len ? "OK" : "Bad !");
+
+ if (l != tst->in_len) {
+ fprintf(stderr, "[!] Failure for input length computation\n");
+ return -1;
+ }
+
+ l = osmo_conv_get_output_length(tst->code, 0);
+ printf("[.] Output length : ret = %3d exp = %3d -> %s\n",
+ l, tst->out_len, l == tst->out_len ? "OK" : "Bad !");
+
+ if (l != tst->out_len) {
+ fprintf(stderr, "[!] Failure for output length computation\n");
+ return -1;
+ }
+
+ /* Check pre-computed vector */
+ if (tst->has_vec) {
+ printf("[.] Pre computed vector checks:\n");
+
+ printf("[..] Encoding: ");
+
+ osmo_pbit2ubit(bu0, tst->vec_in, tst->in_len);
+
+ l = osmo_conv_encode(tst->code, bu0, bu1);
+ if (l != tst->out_len) {
+ printf("ERROR !\n");
+ fprintf(stderr, "[!] Failed encoding length check\n");
+ return -1;
+ }
+
+ osmo_pbit2ubit(bu0, tst->vec_out, tst->out_len);
+
+ if (memcmp(bu0, bu1, tst->out_len)) {
+ printf("ERROR !\n");
+ fprintf(stderr, "[!] Failed encoding: Results don't match\n");
+ return -1;
+ };
+
+ printf("OK\n");
+
+
+ printf("[..] Decoding: ");
+
+ ubit_to_sbit(bs, bu0, l);
+
+ l = osmo_conv_decode(tst->code, bs, bu1);
+ if (l != 0) {
+ printf("ERROR !\n");
+ fprintf(stderr, "[!] Failed decoding: non-zero path (%d)\n", l);
+ return -1;
+ }
+
+ osmo_pbit2ubit(bu0, tst->vec_in, tst->in_len);
+
+ if (memcmp(bu0, bu1, tst->in_len)) {
+ printf("ERROR !\n");
+ fprintf(stderr, "[!] Failed decoding: Results don't match\n");
+ return -1;
+ }
+
+ printf("OK\n");
+ }
+
+ /* Check random vector */
+ printf("[.] Random vector checks:\n");
+
+ for (i=0; i<3; i++) {
+ printf("[..] Encoding / Decoding cycle : ");
+
+ fill_random(bu0, tst->in_len);
+
+ l = osmo_conv_encode(tst->code, bu0, bu1);
+ if (l != tst->out_len) {
+ printf("ERROR !\n");
+ fprintf(stderr, "[!] Failed encoding length check\n");
+ return -1;
+ }
+
+ ubit_to_sbit(bs, bu1, l);
+
+ l = osmo_conv_decode(tst->code, bs, bu1);
+ if (l != 0) {
+ printf("ERROR !\n");
+ fprintf(stderr, "[!] Failed decoding: non-zero path (%d)\n", l);
+ return -1;
+ }
+
+ if (memcmp(bu0, bu1, tst->in_len)) {
+ printf("ERROR !\n");
+ fprintf(stderr, "[!] Failed decoding: Results don't match\n");
+ return -1;
+ }
+
+ printf("OK\n");
+ }
+
+ /* Spacing */
+ printf("\n");
+ }
+
+ free(bs);
+ free(bu1);
+ free(bu0);
+
+ return 0;
+}
diff --git a/Src/osmolib/src/shared/libosmocore/tests/conv/conv_test.ok b/Src/osmolib/src/shared/libosmocore/tests/conv/conv_test.ok
new file mode 100644
index 0000000..2122961
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/conv/conv_test.ok
@@ -0,0 +1,55 @@
+[+] Testing: GSM xCCH (non-recursive, flushed, not punctured)
+[.] Input length : ret = 224 exp = 224 -> OK
+[.] Output length : ret = 456 exp = 456 -> OK
+[.] Pre computed vector checks:
+[..] Encoding: OK
+[..] Decoding: OK
+[.] Random vector checks:
+[..] Encoding / Decoding cycle : OK
+[..] Encoding / Decoding cycle : OK
+[..] Encoding / Decoding cycle : OK
+
+[+] Testing: GSM TCH/AFS 7.95 (recursive, flushed, punctured)
+[.] Input length : ret = 165 exp = 165 -> OK
+[.] Output length : ret = 448 exp = 448 -> OK
+[.] Pre computed vector checks:
+[..] Encoding: OK
+[..] Decoding: OK
+[.] Random vector checks:
+[..] Encoding / Decoding cycle : OK
+[..] Encoding / Decoding cycle : OK
+[..] Encoding / Decoding cycle : OK
+
+[+] Testing: GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)
+[.] Input length : ret = 48 exp = 48 -> OK
+[.] Output length : ret = 72 exp = 72 -> OK
+[.] Pre computed vector checks:
+[..] Encoding: OK
+[..] Decoding: OK
+[.] Random vector checks:
+[..] Encoding / Decoding cycle : OK
+[..] Encoding / Decoding cycle : OK
+[..] Encoding / Decoding cycle : OK
+
+[+] Testing: WiMax FCH (non-recursive, tail-biting, not punctured)
+[.] Input length : ret = 48 exp = 48 -> OK
+[.] Output length : ret = 96 exp = 96 -> OK
+[.] Pre computed vector checks:
+[..] Encoding: OK
+[..] Decoding: OK
+[.] Random vector checks:
+[..] Encoding / Decoding cycle : OK
+[..] Encoding / Decoding cycle : OK
+[..] Encoding / Decoding cycle : OK
+
+[+] Testing: ??? (non-recursive, direct truncation, not punctured)
+[.] Input length : ret = 224 exp = 224 -> OK
+[.] Output length : ret = 448 exp = 448 -> OK
+[.] Pre computed vector checks:
+[..] Encoding: OK
+[..] Decoding: OK
+[.] Random vector checks:
+[..] Encoding / Decoding cycle : OK
+[..] Encoding / Decoding cycle : OK
+[..] Encoding / Decoding cycle : OK
+
diff --git a/Src/osmolib/src/shared/libosmocore/tests/gsm0808/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/gsm0808/Makefile.am
new file mode 100644
index 0000000..a238e7f
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/gsm0808/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+noinst_PROGRAMS = gsm0808_test
+EXTRA_DIST = gsm0808_test.ok
+
+gsm0808_test_SOURCES = gsm0808_test.c
+gsm0808_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
diff --git a/Src/osmolib/src/shared/libosmocore/tests/gsm0808/gsm0808_test.c b/Src/osmolib/src/shared/libosmocore/tests/gsm0808/gsm0808_test.c
new file mode 100644
index 0000000..7e5e97b
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/gsm0808/gsm0808_test.c
@@ -0,0 +1,269 @@
+/*
+ * (C) 2012 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.
+ *
+ */
+
+#include <osmocom/gsm/gsm0808.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define VERIFY(msg, data, len) \
+ if (msgb_l3len(msg) != len) { \
+ printf("%s:%d Length don't match: %d vs. %d. %s\n", \
+ __func__, __LINE__, msgb_l3len(msg), len, \
+ osmo_hexdump(msg->l3h, msgb_l3len(msg))); \
+ abort(); \
+ } else if (memcmp(msg->l3h, data, len) != 0) { \
+ printf("%s:%d didn't match: got: %s\n", \
+ __func__, __LINE__, \
+ osmo_hexdump(msg->l3h, msgb_l3len(msg))); \
+ abort(); \
+ }
+
+
+static void test_create_layer3(void)
+{
+ static const uint8_t res[] = {
+ 0x00, 0x0e, 0x57, 0x05, 0x08, 0x00, 0x77, 0x62,
+ 0x83, 0x33, 0x66, 0x44, 0x88, 0x17, 0x01, 0x23 };
+ struct msgb *msg, *in_msg;
+ printf("Testing creating Layer3\n");
+
+ in_msg = msgb_alloc_headroom(512, 128, "foo");
+ in_msg->l3h = in_msg->data;
+ msgb_v_put(in_msg, 0x23);
+
+ msg = gsm0808_create_layer3(in_msg, 0x1122, 0x2244, 0x3366, 0x4488);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+ msgb_free(in_msg);
+}
+
+static void test_create_reset()
+{
+ static const uint8_t res[] = { 0x00, 0x04, 0x30, 0x04, 0x01, 0x20 };
+ struct msgb *msg;
+
+ printf("Testing creating Reset\n");
+ msg = gsm0808_create_reset();
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_clear_command()
+{
+ static const uint8_t res[] = { 0x20, 0x04, 0x01, 0x23 };
+ struct msgb *msg;
+
+ printf("Testing creating Clear Command\n");
+ msg = gsm0808_create_clear_command(0x23);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_clear_complete()
+{
+ static const uint8_t res[] = { 0x00, 0x01, 0x21 };
+ struct msgb *msg;
+
+ printf("Testing creating Clear Complete\n");
+ msg = gsm0808_create_clear_complete();
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_cipher_complete()
+{
+ static const uint8_t res1[] = {
+ 0x00, 0x08, 0x55, 0x20, 0x03, 0x23, 0x42, 0x21, 0x2c, 0x04 };
+ static const uint8_t res2[] = { 0x00, 0x03, 0x55, 0x2c, 0x04};
+ struct msgb *l3, *msg;
+
+ printf("Testing creating Cipher Complete\n");
+ l3 = msgb_alloc_headroom(512, 128, "l3h");
+ l3->l3h = l3->data;
+ msgb_v_put(l3, 0x23);
+ msgb_v_put(l3, 0x42);
+ msgb_v_put(l3, 0x21);
+
+ /* with l3 data */
+ msg = gsm0808_create_cipher_complete(l3, 4);
+ VERIFY(msg, res1, ARRAY_SIZE(res1));
+ msgb_free(msg);
+
+ /* with l3 data but short */
+ l3->len -= 1;
+ l3->tail -= 1;
+ msg = gsm0808_create_cipher_complete(l3, 4);
+ VERIFY(msg, res2, ARRAY_SIZE(res2));
+ msgb_free(msg);
+
+ /* without l3 data */
+ msg = gsm0808_create_cipher_complete(NULL, 4);
+ VERIFY(msg, res2, ARRAY_SIZE(res2));
+ msgb_free(msg);
+
+
+ msgb_free(l3);
+}
+
+static void test_create_cipher_reject()
+{
+ static const uint8_t res[] = { 0x00, 0x02, 0x59, 0x23 };
+ struct msgb *msg;
+
+ printf("Testing creating Cipher Reject\n");
+ msg = gsm0808_create_cipher_reject(0x23);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_cm_u()
+{
+ static const uint8_t res[] = {
+ 0x00, 0x07, 0x54, 0x12, 0x01, 0x23, 0x13, 0x01, 0x42 };
+ static const uint8_t res2o[] = {
+ 0x00, 0x04, 0x54, 0x12, 0x01, 0x23 };
+ struct msgb *msg;
+ const uint8_t cm2 = 0x23;
+ const uint8_t cm3 = 0x42;
+
+ printf("Testing creating CM U\n");
+ msg = gsm0808_create_classmark_update(&cm2, 1, &cm3, 1);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+
+ msg = gsm0808_create_classmark_update(&cm2, 1, NULL, 0);
+ VERIFY(msg, res2o, ARRAY_SIZE(res2o));
+
+ msgb_free(msg);
+}
+
+static void test_create_sapi_reject()
+{
+ static const uint8_t res[] = { 0x00, 0x03, 0x25, 0x03, 0x25 };
+ struct msgb *msg;
+
+ printf("Testing creating SAPI Reject\n");
+ msg = gsm0808_create_sapi_reject(3);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_ass_compl()
+{
+ static const uint8_t res1[] = {
+ 0x00, 0x09, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c,
+ 0x11, 0x40, 0x22 };
+ static const uint8_t res2[] = {
+ 0x00, 0x07, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11};
+ struct msgb *msg;
+
+ printf("Testing creating Assignment Complete\n");
+ msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0x22);
+ VERIFY(msg, res1, ARRAY_SIZE(res1));
+ msgb_free(msg);
+
+ msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0);
+ VERIFY(msg, res2, ARRAY_SIZE(res2));
+ msgb_free(msg);
+}
+
+static void test_create_ass_fail()
+{
+ static const uint8_t res1[] = { 0x00, 0x04, 0x03, 0x04, 0x01, 0x23 };
+ static const uint8_t res2[] = {
+ 0x00, 0x06, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02};
+ uint8_t rr_res = 2;
+ struct msgb *msg;
+
+ printf("Testing creating Assignment Failure\n");
+ msg = gsm0808_create_assignment_failure(0x23, NULL);
+ VERIFY(msg, res1, ARRAY_SIZE(res1));
+ msgb_free(msg);
+
+ msg = gsm0808_create_assignment_failure(0x23, &rr_res);
+ VERIFY(msg, res2, ARRAY_SIZE(res2));
+ msgb_free(msg);
+}
+
+static void test_create_clear_rqst()
+{
+ static const uint8_t res[] = { 0x00, 0x04, 0x22, 0x04, 0x01, 0x23 };
+ struct msgb *msg;
+
+ printf("Testing creating Clear Request\n");
+ msg = gsm0808_create_clear_rqst(0x23);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_dtap()
+{
+ static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
+ struct msgb *msg, *l3;
+
+ printf("Testing creating DTAP\n");
+ l3 = msgb_alloc_headroom(512, 128, "test");
+ l3->l3h = l3->data;
+ msgb_v_put(l3, 0x23);
+ msgb_v_put(l3, 0x42);
+
+ msg = gsm0808_create_dtap(l3, 0x3);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+ msgb_free(l3);
+}
+
+static void test_prepend_dtap()
+{
+ static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
+ struct msgb *in_msg;
+
+ printf("Testing prepend DTAP\n");
+
+ in_msg = msgb_alloc_headroom(512, 128, "test");
+ msgb_v_put(in_msg, 0x23);
+ msgb_v_put(in_msg, 0x42);
+
+ gsm0808_prepend_dtap_header(in_msg, 0x3);
+ in_msg->l3h = in_msg->data;
+ VERIFY(in_msg, res, ARRAY_SIZE(res));
+ msgb_free(in_msg);
+}
+
+int main(int argc, char **argv)
+{
+ printf("Testing generation of GSM0808 messages\n");
+ test_create_layer3();
+ test_create_reset();
+ test_create_clear_command();
+ test_create_clear_complete();
+ test_create_cipher_complete();
+ test_create_cipher_reject();
+ test_create_cm_u();
+ test_create_sapi_reject();
+ test_create_ass_compl();
+ test_create_ass_fail();
+ test_create_clear_rqst();
+ test_create_dtap();
+ test_prepend_dtap();
+
+ printf("Done\n");
+ return EXIT_SUCCESS;
+}
diff --git a/Src/osmolib/src/shared/libosmocore/tests/gsm0808/gsm0808_test.ok b/Src/osmolib/src/shared/libosmocore/tests/gsm0808/gsm0808_test.ok
new file mode 100644
index 0000000..eb43126
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/gsm0808/gsm0808_test.ok
@@ -0,0 +1,15 @@
+Testing generation of GSM0808 messages
+Testing creating Layer3
+Testing creating Reset
+Testing creating Clear Command
+Testing creating Clear Complete
+Testing creating Cipher Complete
+Testing creating Cipher Reject
+Testing creating CM U
+Testing creating SAPI Reject
+Testing creating Assignment Complete
+Testing creating Assignment Failure
+Testing creating Clear Request
+Testing creating DTAP
+Testing prepend DTAP
+Done
diff --git a/Src/osmolib/src/shared/libosmocore/tests/lapd/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/lapd/Makefile.am
new file mode 100644
index 0000000..f7e2ab0
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/lapd/Makefile.am
@@ -0,0 +1,9 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+AM_FLAGS = -Wall -O0
+noinst_PROGRAMS = lapd_test
+EXTRA_DIST = lapd_test.ok
+
+lapd_test_SOURCES = lapd_test.c
+lapd_test_LDADD = \
+ $(top_builddir)/src/libosmocore.la \
+ $(top_builddir)/src/gsm/libosmogsm.la
diff --git a/Src/osmolib/src/shared/libosmocore/tests/lapd/lapd_test.c b/Src/osmolib/src/shared/libosmocore/tests/lapd/lapd_test.c
new file mode 100644
index 0000000..d58bec6
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/lapd/lapd_test.c
@@ -0,0 +1,319 @@
+/*
+ * (C) 2011 by Holger Hans Peter Freyther
+ * (C) 2011 by On-Waves
+ * 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/logging.h>
+#include <osmocom/gsm/lapdm.h>
+#include <osmocom/gsm/rsl.h>
+
+#include <errno.h>
+
+#include <string.h>
+
+#define CHECK_RC(rc) \
+ if (rc != 0) { \
+ printf("Operation failed rc=%d on %s:%d\n", rc, __FILE__, __LINE__); \
+ abort(); \
+ }
+
+#define ASSERT(exp) \
+ if (!(exp)) { \
+ printf("Assert failed %s %s:%d\n", #exp, __FILE__, __LINE__); \
+ abort(); \
+ }
+
+
+static struct log_info info = {};
+
+struct lapdm_polling_state {
+ struct lapdm_channel *bts;
+ int bts_read;
+
+ struct lapdm_channel *ms;
+ int ms_read;
+};
+
+static struct msgb *msgb_from_array(const uint8_t *data, int len)
+{
+ struct msgb *msg = msgb_alloc_headroom(4096, 128, "data");
+ msg->l3h = msgb_put(msg, len);
+ memcpy(msg->l3h, data, len);
+ return msg;
+}
+
+/*
+ * Test data is below...
+ */
+static const uint8_t cm[] = {
+ 0x05, 0x24, 0x31, 0x03, 0x50, 0x18, 0x93, 0x08,
+ 0x29, 0x47, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+};
+
+static const uint8_t cm_padded[] = {
+ 0x05, 0x24, 0x31, 0x03, 0x50, 0x18, 0x93, 0x08,
+ 0x29, 0x47, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x2b, 0x2b, 0x2b, 0x2b
+};
+
+static const uint8_t mm[] = {
+ 0x00, 0x0c, 0x00, 0x03, 0x01, 0x01, 0x20, 0x02,
+ 0x00, 0x0b, 0x00, 0x03, 0x05, 0x04, 0x0d
+};
+
+static const uint8_t dummy1[] = {
+ 0xab, 0x03, 0x30, 0x60, 0x06,
+};
+
+static struct msgb *create_cm_serv_req(void)
+{
+ struct msgb *msg;
+
+ msg = msgb_from_array(cm, sizeof(cm));
+ rsl_rll_push_l3(msg, RSL_MT_EST_REQ, 0, 0, 1);
+ return msg;
+}
+
+static struct msgb *create_mm_id_req(void)
+{
+ struct msgb *msg;
+
+ msg = msgb_from_array(mm, sizeof(mm));
+ msg->l2h = msg->data + 3;
+ ASSERT(msgb_l2len(msg) == 12);
+ msg->l3h = msg->l2h + 6;
+ ASSERT(msgb_l3len(msg) == 6);
+
+ return msg;
+}
+
+static struct msgb *create_empty_msg(void)
+{
+ struct msgb *msg;
+
+ msg = msgb_from_array(NULL, 0);
+ ASSERT(msgb_l3len(msg) == 0);
+ rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, 0, 0, 1);
+ return msg;
+}
+
+static struct msgb *create_dummy_data_req(void)
+{
+ struct msgb *msg;
+
+ msg = msgb_from_array(dummy1, sizeof(dummy1));
+ rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, 0, 0, 1);
+ return msg;
+}
+
+static int send(struct msgb *in_msg, struct lapdm_channel *chan)
+{
+ struct osmo_phsap_prim pp;
+ struct msgb *msg;
+ int rc;
+
+ msg = msgb_alloc_headroom(128, 64, "PH-DATA.ind");
+ osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA,
+ PRIM_OP_INDICATION, msg);
+ /* copy over actual MAC block */
+ msg->l2h = msgb_put(msg, msgb_l2len(in_msg));
+ memcpy(msg->l2h, in_msg->l2h, msgb_l2len(in_msg));
+
+ /* LAPDm requires those... */
+ pp.u.data.chan_nr = 0;
+ pp.u.data.link_id = 0;
+ /* feed into the LAPDm code of libosmogsm */
+ rc = lapdm_phsap_up(&pp.oph, &chan->lapdm_dcch);
+ ASSERT(rc == 0 || rc == -EBUSY);
+ return 0;
+}
+
+/*
+ * I get called from the LAPDm code when something was sent my way...
+ */
+static int bts_to_ms_tx_cb(struct msgb *in_msg, struct lapdm_entity *le, void *_ctx)
+{
+ struct lapdm_polling_state *state = _ctx;
+
+
+ printf("%s: MS->BTS(us) message %d\n", __func__, msgb_length(in_msg));
+
+
+ if (state->bts_read == 0) {
+ printf("BTS: Verifying CM request.\n");
+ ASSERT(msgb_l3len(in_msg) == ARRAY_SIZE(cm_padded));
+ ASSERT(memcmp(in_msg->l3h, cm_padded, ARRAY_SIZE(cm_padded)) == 0);
+ } else if (state->bts_read == 1) {
+ printf("BTS: Verifying dummy message.\n");
+ ASSERT(msgb_l3len(in_msg) == ARRAY_SIZE(dummy1));
+ ASSERT(memcmp(in_msg->l3h, dummy1, ARRAY_SIZE(dummy1)) == 0);
+ } else {
+ printf("BTS: Do not know to verify: %d\n", state->bts_read);
+ }
+
+ state->bts_read += 1;
+ msgb_free(in_msg);
+
+ return 0;
+}
+
+static int ms_to_bts_l1_cb(struct osmo_prim_hdr *oph, void *_ctx)
+{
+ int rc;
+ struct lapdm_polling_state *state = _ctx;
+ printf("%s: MS(us) -> BTS prim message\n", __func__);
+
+ /* i stuff it into the LAPDm channel of the BTS */
+ rc = send(oph->msg, state->bts);
+ msgb_free(oph->msg);
+}
+
+static int ms_to_bts_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *_ctx)
+{
+ struct lapdm_polling_state *state = _ctx;
+
+ printf("%s: BTS->MS(us) message %d\n", __func__, msgb_length(msg));
+
+ if (state->ms_read == 0) {
+ struct abis_rsl_rll_hdr hdr;
+
+ printf("MS: Verifying incoming primitive.\n");
+ ASSERT(msg->len == sizeof(struct abis_rsl_rll_hdr) + 3);
+
+ /* verify the header */
+ memset(&hdr, 0, sizeof(hdr));
+ rsl_init_rll_hdr(&hdr, RSL_MT_EST_CONF);
+ hdr.c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
+ ASSERT(memcmp(msg->data, &hdr, sizeof(hdr)) == 0);
+
+ /* Verify the added RSL_IE_L3_INFO but we have a bug here */
+ ASSERT(msg->data[6] == RSL_IE_L3_INFO);
+ #warning "RSL_IE_L3_INFO 16 bit length is wrong"
+ /* ASSERT(msg->data[7] == 0x0 && msg->data[8] == 0x9c); */
+ /* this should be 0x0 and 0x0... but we have a bug */
+ } else if (state->ms_read == 1) {
+ printf("MS: Verifying incoming MM message: %d\n", msgb_l3len(msg));
+ ASSERT(msgb_l3len(msg) == 3);
+ ASSERT(memcmp(msg->l3h, &mm[12], msgb_l3len(msg)) == 0);
+ } else {
+ printf("MS: Do not know to verify: %d\n", state->ms_read);
+ }
+
+ state->ms_read += 1;
+ msgb_free(msg);
+ return 0;
+}
+
+static void test_lapdm_polling()
+{
+ printf("I do some very simple LAPDm test.\n");
+
+ int rc;
+ struct lapdm_polling_state test_state;
+ struct osmo_phsap_prim pp;
+
+ /* Configure LAPDm on both sides */
+ struct lapdm_channel bts_to_ms_channel;
+ struct lapdm_channel ms_to_bts_channel;
+ memset(&bts_to_ms_channel, 0, sizeof(bts_to_ms_channel));
+ memset(&ms_to_bts_channel, 0, sizeof(ms_to_bts_channel));
+
+ memset(&test_state, 0, sizeof(test_state));
+ test_state.bts = &bts_to_ms_channel;
+ test_state.ms = &ms_to_bts_channel;
+
+ /* BTS to MS in polling mode */
+ lapdm_channel_init(&bts_to_ms_channel, LAPDM_MODE_BTS);
+ lapdm_channel_set_flags(&bts_to_ms_channel, LAPDM_ENT_F_POLLING_ONLY);
+ lapdm_channel_set_l1(&bts_to_ms_channel, NULL, &test_state);
+ lapdm_channel_set_l3(&bts_to_ms_channel, bts_to_ms_tx_cb, &test_state);
+
+ /* MS to BTS in direct mode */
+ lapdm_channel_init(&ms_to_bts_channel, LAPDM_MODE_MS);
+ lapdm_channel_set_l1(&ms_to_bts_channel, ms_to_bts_l1_cb, &test_state);
+ lapdm_channel_set_l3(&ms_to_bts_channel, ms_to_bts_tx_cb, &test_state);
+
+ /*
+ * We try to send messages from the MS to the BTS to the MS..
+ */
+ /* 1. Start with MS -> BTS, BTS should have a pending message */
+ printf("Establishing link.\n");
+ lapdm_rslms_recvmsg(create_cm_serv_req(), &ms_to_bts_channel);
+
+ /* 2. Poll on the BTS for sending out a confirmation */
+ printf("\nConfirming\n");
+ ASSERT(test_state.bts_read == 1)
+ rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
+ CHECK_RC(rc);
+ ASSERT(pp.oph.msg->data == pp.oph.msg->l2h);
+ send(pp.oph.msg, &ms_to_bts_channel);
+ msgb_free(pp.oph.msg);
+ ASSERT(test_state.ms_read == 1);
+
+ /* 3. Send some data to the MS */
+ printf("\nSending back to MS\n");
+ lapdm_rslms_recvmsg(create_mm_id_req(), &bts_to_ms_channel);
+ rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
+ CHECK_RC(rc);
+ send(pp.oph.msg, &ms_to_bts_channel);
+ msgb_free(pp.oph.msg);
+ ASSERT(test_state.ms_read == 2);
+
+ /* verify that there is nothing more to poll */
+ rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
+ ASSERT(rc < 0);
+
+ /* 3. And back to the BTS */
+ printf("\nSending back to BTS\n");
+ ASSERT(test_state.ms_read == 2);
+ lapdm_rslms_recvmsg(create_dummy_data_req(), &ms_to_bts_channel);
+
+
+ /* 4. And back to the MS, but let's move data/l2h apart */
+ ASSERT(test_state.bts_read == 2)
+ ASSERT(test_state.ms_read == 2);
+ rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
+ CHECK_RC(rc);
+ send(pp.oph.msg, &ms_to_bts_channel);
+ ASSERT(test_state.ms_read == 2);
+ msgb_free(pp.oph.msg);
+
+ /* verify that there is nothing more to poll */
+ rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
+ ASSERT(rc < 0);
+
+ /* check sending an empty L3 message fails */
+ rc = lapdm_rslms_recvmsg(create_empty_msg(), &bts_to_ms_channel);
+ ASSERT(rc == -1);
+ ASSERT(test_state.ms_read == 2);
+
+ /* clean up */
+ lapdm_channel_exit(&bts_to_ms_channel);
+ lapdm_channel_exit(&ms_to_bts_channel);
+}
+
+int main(int argc, char **argv)
+{
+ osmo_init_logging(&info);
+
+ test_lapdm_polling();
+ printf("Success.\n");
+
+ return 0;
+}
diff --git a/Src/osmolib/src/shared/libosmocore/tests/lapd/lapd_test.ok b/Src/osmolib/src/shared/libosmocore/tests/lapd/lapd_test.ok
new file mode 100644
index 0000000..d67a0a8
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/lapd/lapd_test.ok
@@ -0,0 +1,20 @@
+I do some very simple LAPDm test.
+Establishing link.
+ms_to_bts_l1_cb: MS(us) -> BTS prim message
+bts_to_ms_tx_cb: MS->BTS(us) message 29
+BTS: Verifying CM request.
+
+Confirming
+ms_to_bts_tx_cb: BTS->MS(us) message 9
+MS: Verifying incoming primitive.
+
+Sending back to MS
+ms_to_bts_tx_cb: BTS->MS(us) message 12
+MS: Verifying incoming MM message: 3
+ms_to_bts_l1_cb: MS(us) -> BTS prim message
+
+Sending back to BTS
+ms_to_bts_l1_cb: MS(us) -> BTS prim message
+bts_to_ms_tx_cb: MS->BTS(us) message 14
+BTS: Verifying dummy message.
+Success.
diff --git a/Src/osmolib/src/shared/libosmocore/tests/msgfile/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/msgfile/Makefile.am
index c9f4bec..88c355d 100644
--- a/Src/osmolib/src/shared/libosmocore/tests/msgfile/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/tests/msgfile/Makefile.am
@@ -1,5 +1,6 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include
noinst_PROGRAMS = msgfile_test
+EXTRA_DIST = msgfile_test.ok msgconfig.cfg
msgfile_test_SOURCES = msgfile_test.c
msgfile_test_LDADD = $(top_builddir)/src/libosmocore.la
diff --git a/Src/osmolib/src/shared/libosmocore/tests/msgfile/msgfile_test.ok b/Src/osmolib/src/shared/libosmocore/tests/msgfile/msgfile_test.ok
new file mode 100644
index 0000000..c47cd74
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/msgfile/msgfile_test.ok
@@ -0,0 +1 @@
+Entry '*:*::Hello Welt'
diff --git a/Src/osmolib/src/shared/libosmocore/tests/sms/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/sms/Makefile.am
index fa4e387..02860af 100644
--- a/Src/osmolib/src/shared/libosmocore/tests/sms/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/tests/sms/Makefile.am
@@ -1,5 +1,6 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include
noinst_PROGRAMS = sms_test
+EXTRA_DIST = sms_test.ok
sms_test_SOURCES = sms_test.c
sms_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
diff --git a/Src/osmolib/src/shared/libosmocore/tests/sms/sms_test.ok b/Src/osmolib/src/shared/libosmocore/tests/sms/sms_test.ok
new file mode 100644
index 0000000..d0e0983
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/sms/sms_test.ok
@@ -0,0 +1,2 @@
+SMS testing
+OK
diff --git a/Src/osmolib/src/shared/libosmocore/tests/smscb/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/smscb/Makefile.am
index 9a6fb4f..7045ea7 100644
--- a/Src/osmolib/src/shared/libosmocore/tests/smscb/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/tests/smscb/Makefile.am
@@ -1,5 +1,6 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include
noinst_PROGRAMS = smscb_test
+EXTRA_DIST = smscb_test.ok
smscb_test_SOURCES = smscb_test.c
smscb_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
diff --git a/Src/osmolib/src/shared/libosmocore/tests/smscb/smscb_test.ok b/Src/osmolib/src/shared/libosmocore/tests/smscb/smscb_test.ok
new file mode 100644
index 0000000..347037f
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/smscb/smscb_test.ok
@@ -0,0 +1,4 @@
+(srl) GS: 1 MSG_CODE: 1 UPDATE: 0
+(msg) msg_id: 1293
+(dcs) group: 1 language: 0
+(pge) page total: 1 current: 1
diff --git a/Src/osmolib/src/shared/libosmocore/tests/testsuite.at b/Src/osmolib/src/shared/libosmocore/tests/testsuite.at
new file mode 100644
index 0000000..69624c1
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/testsuite.at
@@ -0,0 +1,73 @@
+AT_INIT
+AT_BANNER([Regression tests.])
+
+
+# todo.. create one macro for it
+AT_SETUP([a5])
+AT_KEYWORDS([a5])
+cat $abs_srcdir/a5/a5_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/a5/a5_test], [], [expout])
+AT_CLEANUP
+
+AT_SETUP([bits])
+AT_KEYWORDS([bits])
+cat $abs_srcdir/bits/bitrev_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/bits/bitrev_test], [], [expout])
+AT_CLEANUP
+
+AT_SETUP([conv])
+AT_KEYWORDS([conv])
+cat $abs_srcdir/conv/conv_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/conv/conv_test], [], [expout])
+AT_CLEANUP
+
+if ENABLE_MSGFILE
+AT_SETUP([msgfile])
+AT_KEYWORDS([msgfile])
+cp $abs_srcdir/msgfile/msgconfig.cfg .
+cat $abs_srcdir/msgfile/msgfile_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/msgfile/msgfile_test], [], [expout])
+AT_CLEANUP
+endif
+
+AT_SETUP([sms])
+AT_KEYWORDS([sms])
+cat $abs_srcdir/sms/sms_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/sms/sms_test], [], [expout])
+AT_CLEANUP
+
+AT_SETUP([smscb])
+AT_KEYWORDS([smscb])
+cat $abs_srcdir/smscb/smscb_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/smscb/smscb_test], [], [expout])
+AT_CLEANUP
+
+AT_SETUP([timer])
+AT_KEYWORDS([timer])
+cat $abs_srcdir/timer/timer_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/timer/timer_test -s 5], [], [expout], [ignore])
+AT_CLEANUP
+
+AT_SETUP([ussd])
+AT_KEYWORDS([ussd])
+cat $abs_srcdir/ussd/ussd_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/ussd/ussd_test], [], [expout], [ignore])
+AT_CLEANUP
+
+AT_SETUP([auth])
+AT_KEYWORDS([auth])
+cat $abs_srcdir/auth/milenage_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/auth/milenage_test], [], [expout], [ignore])
+AT_CLEANUP
+
+AT_SETUP([lapd])
+AT_KEYWORDS([lapd])
+cat $abs_srcdir/lapd/lapd_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/lapd/lapd_test], [], [expout], [ignore])
+AT_CLEANUP
+
+AT_SETUP([gsm0808])
+AT_KEYWORDS([gsm0808])
+cat $abs_srcdir/gsm0808/gsm0808_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/gsm0808/gsm0808_test], [], [expout], [ignore])
+AT_CLEANUP
diff --git a/Src/osmolib/src/shared/libosmocore/tests/timer/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/timer/Makefile.am
index d3decf5..062d81b 100644
--- a/Src/osmolib/src/shared/libosmocore/tests/timer/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/tests/timer/Makefile.am
@@ -1,5 +1,6 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include
noinst_PROGRAMS = timer_test
+EXTRA_DIST = timer_test.ok
timer_test_SOURCES = timer_test.c
timer_test_LDADD = $(top_builddir)/src/libosmocore.la
diff --git a/Src/osmolib/src/shared/libosmocore/tests/timer/timer_test.c b/Src/osmolib/src/shared/libosmocore/tests/timer/timer_test.c
index 240bc48..3775151 100644
--- a/Src/osmolib/src/shared/libosmocore/tests/timer/timer_test.c
+++ b/Src/osmolib/src/shared/libosmocore/tests/timer/timer_test.c
@@ -1,7 +1,11 @@
/*
* (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2011 by Harald Welte <laforge@gnumonks.org>
* All Rights Reserved
*
+ * Authors: Holger Hans Peter Freyther <zecke@selfish.org>
+ * Pablo Neira Ayuso <pablo@gnumonks.org>
+ *
* 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
@@ -19,59 +23,169 @@
*/
#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <getopt.h>
+#include <osmocom/core/talloc.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/select.h>
+#include <osmocom/core/linuxlist.h>
#include "../../config.h"
-static void timer_fired(void *data);
+static void main_timer_fired(void *data);
+static void secondary_timer_fired(void *data);
-static struct osmo_timer_list timer_one = {
- .cb = timer_fired,
- .data = (void*)1,
+static unsigned int main_timer_step = 0;
+static struct osmo_timer_list main_timer = {
+ .cb = main_timer_fired,
+ .data = &main_timer_step,
};
-static struct osmo_timer_list timer_two = {
- .cb = timer_fired,
- .data = (void*)2,
-};
+static LLIST_HEAD(timer_test_list);
-static struct osmo_timer_list timer_three = {
- .cb = timer_fired,
- .data = (void*)3,
+struct test_timer {
+ struct llist_head head;
+ struct osmo_timer_list timer;
+ struct timeval start;
+ struct timeval stop;
};
-static void timer_fired(void *_data)
+/* number of test steps. We add fact(steps) timers in the whole test. */
+#define MAIN_TIMER_NSTEPS 16
+
+/* time between two steps, in secs. */
+#define TIME_BETWEEN_STEPS 1
+
+/* timer imprecision that we accept for this test: 10 milliseconds. */
+#define TIMER_PRES_SECS 0
+#define TIMER_PRES_USECS 10000
+
+static int timer_nsteps = MAIN_TIMER_NSTEPS;
+static unsigned int expired_timers = 0;
+static unsigned int total_timers = 0;
+static unsigned int too_late = 0;
+
+static void main_timer_fired(void *data)
{
- unsigned long data = (unsigned long) _data;
- printf("Fired timer: %lu\n", data);
-
- if (data == 1) {
- osmo_timer_schedule(&timer_one, 3, 0);
- osmo_timer_del(&timer_two);
- } else if (data == 2) {
- printf("Should not be fired... bug in del_timer\n");
- } else if (data == 3) {
- printf("Timer fired not registering again\n");
- } else {
- printf("wtf... wrong data\n");
- }
+ unsigned int *step = data;
+ unsigned int add_in_this_step;
+ int i;
+
+ if (*step == timer_nsteps) {
+ fprintf(stderr, "Main timer has finished, please, "
+ "wait a bit for the final report.\n");
+ return;
+ }
+ /* add 2^step pair of timers per step. */
+ add_in_this_step = (1 << *step);
+
+ for (i=0; i<add_in_this_step; i++) {
+ struct test_timer *v;
+
+ v = talloc_zero(NULL, struct test_timer);
+ if (v == NULL) {
+ fprintf(stderr, "timer_test: OOM!\n");
+ return;
+ }
+ gettimeofday(&v->start, NULL);
+ v->timer.cb = secondary_timer_fired;
+ v->timer.data = v;
+ unsigned int seconds = (random() % 10) + 1;
+ v->stop.tv_sec = v->start.tv_sec + seconds;
+ osmo_timer_schedule(&v->timer, seconds, 0);
+ llist_add(&v->head, &timer_test_list);
+ }
+ fprintf(stderr, "added %d timers in step %u (expired=%u)\n",
+ add_in_this_step, *step, expired_timers);
+ total_timers += add_in_this_step;
+ osmo_timer_schedule(&main_timer, TIME_BETWEEN_STEPS, 0);
+ (*step)++;
}
-int main(int argc, char** argv)
+static void secondary_timer_fired(void *data)
{
- printf("Starting... timer\n");
+ struct test_timer *v = data, *this, *tmp;
+ struct timeval current, res, precision = { 1, 0 };
+
+ gettimeofday(&current, NULL);
+
+ timersub(&current, &v->stop, &res);
+ if (timercmp(&res, &precision, >)) {
+ fprintf(stderr, "ERROR: timer %p has expired too late!\n",
+ v->timer);
+ too_late++;
+ }
+
+ llist_del(&v->head);
+ talloc_free(data);
+ expired_timers++;
+ if (expired_timers == total_timers) {
+ fprintf(stdout, "test over: added=%u expired=%u too_late=%u \n",
+ total_timers, expired_timers, too_late);
+ exit(EXIT_SUCCESS);
+ }
+
+ /* randomly (10%) deletion of timers. */
+ llist_for_each_entry_safe(this, tmp, &timer_test_list, head) {
+ if ((random() % 100) < 10) {
+ osmo_timer_del(&this->timer);
+ llist_del(&this->head);
+ talloc_free(this);
+ expired_timers++;
+ }
+ }
+}
+
+static void alarm_handler(int signum)
+{
+ fprintf(stderr, "ERROR: We took too long to run the timer test, "
+ "something seems broken, aborting.\n");
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char *argv[])
+{
+ int c;
+
+ if (signal(SIGALRM, alarm_handler) == SIG_ERR) {
+ perror("cannot register signal handler");
+ exit(EXIT_FAILURE);
+ }
+
+ while ((c = getopt_long(argc, argv, "s:", NULL, NULL)) != -1) {
+ switch(c) {
+ case 's':
+ timer_nsteps = atoi(optarg);
+ if (timer_nsteps <= 0) {
+ fprintf(stderr, "%s: steps must be > 0\n",
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ default:
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ fprintf(stdout, "Running timer test for %u steps, accepting "
+ "imprecision of %u.%.6u seconds\n",
+ timer_nsteps, TIMER_PRES_SECS, TIMER_PRES_USECS);
+
+ osmo_timer_schedule(&main_timer, 1, 0);
- osmo_timer_schedule(&timer_one, 3, 0);
- osmo_timer_schedule(&timer_two, 5, 0);
- osmo_timer_schedule(&timer_three, 4, 0);
+ /* if the test takes too long, we may consider that the timer scheduler
+ * has hung. We set some maximum wait time which is the double of the
+ * maximum timeout randomly set (10 seconds, worst case) plus the
+ * number of steps (since some of them are reset each step). */
+ alarm(2 * (10 + timer_nsteps));
#ifdef HAVE_SYS_SELECT_H
- while (1) {
- osmo_select_main(0);
- }
+ while (1) {
+ osmo_select_main(0);
+ }
#else
- printf("Select not supported on this platform!\n");
+ fprintf(stdout, "Select not supported on this platform!\n");
#endif
}
diff --git a/Src/osmolib/src/shared/libosmocore/tests/timer/timer_test.ok b/Src/osmolib/src/shared/libosmocore/tests/timer/timer_test.ok
new file mode 100644
index 0000000..b4e0e11
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/timer/timer_test.ok
@@ -0,0 +1,2 @@
+Running timer test for 5 steps, accepting imprecision of 0.010000 seconds
+test over: added=31 expired=31 too_late=0
diff --git a/Src/osmolib/src/shared/libosmocore/tests/ussd/Makefile.am b/Src/osmolib/src/shared/libosmocore/tests/ussd/Makefile.am
index ef9aa49..de9ff89 100644
--- a/Src/osmolib/src/shared/libosmocore/tests/ussd/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/tests/ussd/Makefile.am
@@ -1,5 +1,6 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include
noinst_PROGRAMS = ussd_test
+EXTRA_DIST = ussd_test.ok
ussd_test_SOURCES = ussd_test.c
ussd_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
diff --git a/Src/osmolib/src/shared/libosmocore/tests/ussd/ussd_test.c b/Src/osmolib/src/shared/libosmocore/tests/ussd/ussd_test.c
index 6d2a8c9..55384f1 100644
--- a/Src/osmolib/src/shared/libosmocore/tests/ussd/ussd_test.c
+++ b/Src/osmolib/src/shared/libosmocore/tests/ussd/ussd_test.c
@@ -19,6 +19,8 @@
*
*/
+#include <osmocom/core/application.h>
+#include <osmocom/core/logging.h>
#include <osmocom/gsm/gsm0480.h>
#include <stdio.h>
#include <stdlib.h>
@@ -64,12 +66,16 @@ static int parse_mangle_ussd(const uint8_t *_data, int len)
return rc;
}
+struct log_info info = {};
+
int main(int argc, char **argv)
{
struct ussd_request req;
const int size = sizeof(ussd_request);
int i;
+ osmo_init_logging(&info);
+
gsm0480_decode_ussd_request((struct gsm48_hdr *) ussd_request, size, &req);
printf("Tested if it still works. Text was: %s\n", req.text);
diff --git a/Src/osmolib/src/shared/libosmocore/tests/ussd/ussd_test.ok b/Src/osmolib/src/shared/libosmocore/tests/ussd/ussd_test.ok
new file mode 100644
index 0000000..1b6316e
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/tests/ussd/ussd_test.ok
@@ -0,0 +1,53 @@
+Tested if it still works. Text was: **321#
+Testing parsing a USSD request and truncated versions
+Result for 1 is 28
+Result for 1 is 27
+Result for 1 is 26
+Result for 1 is 25
+Result for 0 is 24
+Result for 0 is 23
+Result for 0 is 22
+Result for 0 is 21
+Result for 0 is 20
+Result for 0 is 19
+Result for 0 is 18
+Result for 0 is 17
+Result for 0 is 16
+Result for 0 is 15
+Result for 0 is 14
+Result for 0 is 13
+Result for 0 is 12
+Result for 0 is 11
+Result for 0 is 10
+Result for 0 is 9
+Result for 0 is 8
+Result for 0 is 7
+Result for 0 is 6
+Result for 0 is 5
+Result for 0 is 4
+Result for 0 is 3
+Mangling the container now
+Result for 0 is 28
+Result for 0 is 27
+Result for 1 is 26
+Result for 1 is 25
+Result for 0 is 24
+Result for 0 is 23
+Result for 0 is 22
+Result for 0 is 21
+Result for 0 is 20
+Result for 0 is 19
+Result for 0 is 18
+Result for 0 is 17
+Result for 0 is 16
+Result for 0 is 15
+Result for 0 is 14
+Result for 0 is 13
+Result for 0 is 12
+Result for 0 is 11
+Result for 0 is 10
+Result for 0 is 9
+Result for 0 is 8
+Result for 0 is 7
+Result for 0 is 6
+Result for 1 is 5
diff --git a/Src/osmolib/src/shared/libosmocore/utils/Makefile.am b/Src/osmolib/src/shared/libosmocore/utils/Makefile.am
index 22903d9..4e7869e 100644
--- a/Src/osmolib/src/shared/libosmocore/utils/Makefile.am
+++ b/Src/osmolib/src/shared/libosmocore/utils/Makefile.am
@@ -1,7 +1,10 @@
if ENABLE_UTILITIES
INCLUDES = $(all_includes) -I$(top_srcdir)/include
-noinst_PROGRAMS = osmo-arfcn
+noinst_PROGRAMS = osmo-arfcn osmo-auc-gen
osmo_arfcn_SOURCES = osmo-arfcn.c
osmo_arfcn_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
+
+osmo_auc_gen_SOURCES = osmo-auc-gen.c
+osmo_auc_gen_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
endif
diff --git a/Src/osmolib/src/shared/libosmocore/utils/gen_website_doc_tree.sh b/Src/osmolib/src/shared/libosmocore/utils/gen_website_doc_tree.sh
index 622db56..622db56 100644..100755
--- a/Src/osmolib/src/shared/libosmocore/utils/gen_website_doc_tree.sh
+++ b/Src/osmolib/src/shared/libosmocore/utils/gen_website_doc_tree.sh
diff --git a/Src/osmolib/src/shared/libosmocore/utils/osmo-auc-gen.c b/Src/osmolib/src/shared/libosmocore/utils/osmo-auc-gen.c
new file mode 100644
index 0000000..62b5128
--- /dev/null
+++ b/Src/osmolib/src/shared/libosmocore/utils/osmo-auc-gen.c
@@ -0,0 +1,183 @@
+/* GSM/GPRS/3G authentication testing tool */
+
+/* (C) 2010-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 <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <osmocom/crypt/auth.h>
+#include <osmocom/core/utils.h>
+
+static void dump_auth_vec(struct osmo_auth_vector *vec)
+{
+ printf("RAND:\t%s\n", osmo_hexdump(vec->rand, sizeof(vec->rand)));
+
+ if (vec->auth_types & OSMO_AUTH_TYPE_UMTS) {
+ printf("AUTN:\t%s\n", osmo_hexdump(vec->autn, sizeof(vec->autn)));
+ printf("IK:\t%s\n", osmo_hexdump(vec->ik, sizeof(vec->ik)));
+ printf("CK:\t%s\n", osmo_hexdump(vec->ck, sizeof(vec->ck)));
+ printf("RES:\t%s\n", osmo_hexdump(vec->res, vec->res_len));
+ }
+
+ if (vec->auth_types & OSMO_AUTH_TYPE_GSM) {
+ printf("SRES:\t%s\n", osmo_hexdump(vec->sres, sizeof(vec->sres)));
+ printf("Kc:\t%s\n", osmo_hexdump(vec->kc, sizeof(vec->kc)));
+ }
+}
+
+static struct osmo_sub_auth_data test_aud = {
+ .type = OSMO_AUTH_TYPE_NONE,
+ .algo = OSMO_AUTH_ALG_NONE,
+};
+
+int main(int argc, char **argv)
+{
+ struct osmo_auth_vector _vec;
+ struct osmo_auth_vector *vec = &_vec;
+ uint8_t _rand[16];
+ int rc, option_index;
+ int rand_is_set = 0;
+
+ printf("osmo-auc-gen (C) 2011 by Harald Welte\n");
+ printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
+
+ while (1) {
+ int c;
+ unsigned long ul;
+ static struct option long_options[] = {
+ { "2g", 0, 0, '2' },
+ { "3g", 0, 0, '3' },
+ { "algorithm", 1, 0, 'a' },
+ { "key", 1, 0, 'k' },
+ { "opc", 1, 0, 'o' },
+ { "amf", 1, 0, 'f' },
+ { "sqn", 1, 0, 's' },
+ { "rand", 1, 0, 'r' },
+ { 0, 0, 0, 0 }
+ };
+
+ rc = 0;
+
+ c = getopt_long(argc, argv, "23a:k:o:f:s:r:", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case '2':
+ test_aud.type = OSMO_AUTH_TYPE_GSM;
+ break;
+ case '3':
+ test_aud.type = OSMO_AUTH_TYPE_UMTS;
+ break;
+ case 'a':
+ rc = osmo_auth_alg_parse(optarg);
+ if (rc < 0)
+ break;
+ test_aud.algo = rc;
+ break;
+ case 'k':
+ switch (test_aud.type) {
+ case OSMO_AUTH_TYPE_GSM:
+ rc = osmo_hexparse(optarg, test_aud.u.gsm.ki,
+ sizeof(test_aud.u.gsm.ki));
+ break;
+ case OSMO_AUTH_TYPE_UMTS:
+ rc = osmo_hexparse(optarg, test_aud.u.umts.k,
+ sizeof(test_aud.u.umts.k));
+ break;
+ default:
+ fprintf(stderr, "please specify 2g/3g first!\n");
+ }
+ break;
+ case 'o':
+ if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
+ fprintf(stderr, "Only UMTS has OPC\n");
+ exit(2);
+ }
+ rc = osmo_hexparse(optarg, test_aud.u.umts.opc,
+ sizeof(test_aud.u.umts.opc));
+ break;
+ case 'f':
+ if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
+ fprintf(stderr, "Only UMTS has AMF\n");
+ exit(2);
+ }
+ rc = osmo_hexparse(optarg, test_aud.u.umts.amf,
+ sizeof(test_aud.u.umts.amf));
+ break;
+ case 's':
+ if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
+ fprintf(stderr, "Only UMTS has SQN\n");
+ exit(2);
+ }
+ ul = strtoul(optarg, 0, 10);
+ test_aud.u.umts.sqn = ul;
+ break;
+ case 'r':
+ rc = osmo_hexparse(optarg, _rand, sizeof(_rand));
+ rand_is_set = 1;
+ break;
+ }
+
+ if (rc < 0) {
+ fprintf(stderr, "Error parsing argument of option `%c'\n", c);
+ exit(2);
+ }
+ }
+
+ if (!rand_is_set) {
+ printf("WARNING: We're using really weak random numbers!\n\n");
+ srand(time(NULL));
+ *(uint32_t *)&_rand[0] = rand();
+ *(uint32_t *)(&_rand[4]) = rand();
+ *(uint32_t *)(&_rand[8]) = rand();
+ *(uint32_t *)(&_rand[12]) = rand();
+ }
+
+ memset(vec, 0, sizeof(*vec));
+
+ rc = osmo_auth_gen_vec(vec, &test_aud, _rand);
+ if (rc < 0) {
+ fprintf(stderr, "error generating auth vector\n");
+ exit(1);
+ }
+
+ dump_auth_vec(vec);
+#if 0
+ const uint8_t auts[14] = { 0x87, 0x11, 0xa0, 0xec, 0x9e, 0x16, 0x37, 0xdf,
+ 0x17, 0xf8, 0x0b, 0x38, 0x4e, 0xe4 };
+
+ rc = osmo_auth_gen_vec_auts(vec, &test_aud, auts, _rand, _rand);
+ if (rc < 0) {
+ printf("AUTS failed\n");
+ } else {
+ printf("AUTS success: SEQ.MS = %lu\n", test_aud.u.umts.sqn);
+ }
+#endif
+ exit(0);
+
+}
diff --git a/Src/osmolib/src/shared/update-libosmocore.sh b/Src/osmolib/src/shared/update-libosmocore.sh
index 69dfbe1..69dfbe1 100644..100755
--- a/Src/osmolib/src/shared/update-libosmocore.sh
+++ b/Src/osmolib/src/shared/update-libosmocore.sh
diff --git a/Src/osmolib/src/target/firmware/Makefile b/Src/osmolib/src/target/firmware/Makefile
index 4ccd395..3af2f67 100644
--- a/Src/osmolib/src/target/firmware/Makefile
+++ b/Src/osmolib/src/target/firmware/Makefile
@@ -4,8 +4,19 @@
BOARDS?=compal_e88 compal_e86 compal_e99 se_j100 gta0x pirelli_dpl10
# List of all applications (meant to be overridden on command line)
-APPLICATIONS?=hello_world compal_dsp_dump layer1 loader simtest chainload
+APPLICATIONS?=hello_world compal_dsp_dump layer1 loader chainload rssi
+# Framebuffer support, board specific drivers
+#
+
+FB_OBJS=fb/framebuffer.o fb/font.o fb/helvR08.o fb/helvB14.o fb/c64.o
+
+FB_e88_OBJS=$(FB_OBJS) fb/fb_bw8.o fb/fb_st7558.o
+FB_e99_OBJS=$(FB_OBJS) fb/fb_rgb332.o fb/fb_ssd1783.o
+FB_e86_OBJS=$(FB_OBJS) fb/fb_rgb332.o fb/fb_td014.o
+FB_j100_OBJS=$(FB_OBJS) fb/fb_rgb332.o fb/fb_ssd1963.o
+FB_dpl10_OBJS=$(FB_OBJS) fb/fb_rgb332.o fb/fb_s6b33b1x.o
+FB_dummy_OBJS=$(FB_OBJS) fb/fb_dummy.o
# TI Calypso
@@ -13,12 +24,12 @@ calypso_COMMON_OBJS=board/common/calypso_uart.o board/common/calypso_pwl.o
# OpenMoko GTA0x
-gta0x_OBJS=$(calypso_COMMON_OBJS) board/gta0x/rffe_gta0x_triband.o board/gta0x/init.o board/gta0x/rf_power.o
+gta0x_OBJS=$(calypso_COMMON_OBJS) board/gta0x/rffe_gta0x_triband.o board/gta0x/init.o board/gta0x/rf_power.o $(FB_dummy_OBJS)
gta0x_ENVIRONMENTS=highram
# Pirelli DP-L10
-pirelli_dpl10_OBJS=$(calypso_COMMON_OBJS) board/pirelli_dpl10/rffe_dpl10_triband.o board/pirelli_dpl10/init.o board/pirelli_dpl10/rf_power.o
+pirelli_dpl10_OBJS=$(calypso_COMMON_OBJS) board/pirelli_dpl10/rffe_dpl10_triband.o board/pirelli_dpl10/init.o board/pirelli_dpl10/rf_power.o $(FB_dpl10_OBJS)
pirelli_dpl10_ENVIRONMENTS=highram
# Compal Generic
@@ -34,7 +45,7 @@ highram_OBJS=board/compal/start.ram.o board/compal/exceptions_redirected.o board
# Compal E88
-compal_e88_OBJS=$(compal_COMMON_OBJS) board/compal_e88/init.o
+compal_e88_OBJS=$(compal_COMMON_OBJS) board/compal_e88/init.o $(FB_e88_OBJS)
compal_e88_ENVIRONMENTS=$(compal_COMMON_ENVIRONMENTS) e88loader e88flash
e88loader_LDS=board/compal_e88/loader.lds
@@ -45,12 +56,12 @@ e88flash_OBJS=board/compal/start.rom.o board/compal/header.o board/compal/except
# Compal E86 (has a different RFFE configuration)
-compal_e86_OBJS=$(calypso_COMMON_OBJS) board/compal_e86/rffe_dualband_e86.o board/compal/rf_power.o board/compal_e86/init.o
+compal_e86_OBJS=$(calypso_COMMON_OBJS) board/compal_e86/rffe_dualband_e86.o board/compal/rf_power.o board/compal_e86/init.o $(FB_e86_OBJS)
compal_e86_ENVIRONMENTS=$(compal_COMMON_ENVIRONMENTS)
# Compal E99
-compal_e99_OBJS=$(compal_COMMON_OBJS) board/compal_e99/init.o
+compal_e99_OBJS=$(compal_COMMON_OBJS) board/compal_e99/init.o $(FB_e99_OBJS)
compal_e99_ENVIRONMENTS=$(compal_COMMON_ENVIRONMENTS)
e99loader_LDS=board/compal_e99/loader.lds
@@ -59,7 +70,7 @@ e99flash_LDS=board/compal_e99/flash.lds
# Sony Ericsson J100 (made by Compal)
-se_j100_OBJS=$(compal_COMMON_OBJS) board/se_j100/init.o
+se_j100_OBJS=$(compal_COMMON_OBJS) board/se_j100/init.o $(FB_j100_OBJS)
se_j100_ENVIRONMENTS=$(compal_COMMON_ENVIRONMENTS)
# Global include path
@@ -67,12 +78,11 @@ INCLUDES=-Iinclude/ -I../../../include -I../../shared/libosmocore/include
# Various objects that are currently linked into all applications
FLASH_OBJS=flash/cfi_flash.o
-DISPLAY_OBJS=display/font_r8x8.o display/font_r8x8_horiz.o display/st7558.o display/td014.o display/ssd1783.o display/ssd1963.o display/display.o
ABB_OBJS=abb/twl3025.o
RF_OBJS=rf/trf6151.o
# Objects that go in all applications
-ANY_APP_OBJS+=$(ABB_OBJS) $(RF_OBJS) $(DISPLAY_OBJS) $(FLASH_OBJS)
+ANY_APP_OBJS+=$(ABB_OBJS) $(RF_OBJS) $(FLASH_OBJS)
ANY_APP_LIBS+=calypso/libcalypso.a layer1/liblayer1.a lib/libmini.a comm/libcomm.a ../../shared/libosmocore/build-target/src/.libs/libosmocore.a ../../shared/libosmocore/build-target/src/gsm/.libs/libosmogsm.a
# Libraries are defined in subdirectories
diff --git a/Src/osmolib/src/target/firmware/abb/twl3025.c b/Src/osmolib/src/target/firmware/abb/twl3025.c
index 564c34b..e4fcf4f 100644
--- a/Src/osmolib/src/target/firmware/abb/twl3025.c
+++ b/Src/osmolib/src/target/firmware/abb/twl3025.c
@@ -31,6 +31,7 @@
#include <calypso/tsp.h>
#include <calypso/tpu.h>
#include <abb/twl3025.h>
+#include <asm/system.h>
/* TWL3025 */
#define REG_PAGE(n) (n >> 7)
@@ -105,13 +106,6 @@ static void twl3025_irq(enum irq_nr nr)
case IRQ_EXTERNAL: // charger in/out, pwrbtn, adc done
src = twl3025_reg_read(ITSTATREG);
// printd("itstatreg 0x%02x\n", src);
- if (src & 0x04) {
- /* poll PWON status and power off the phone when the
- * powerbutton has been released (otherwise it will
- * poweron immediately again) */
- while (!(twl3025_reg_read(VRPCSTS) & 0x10)) { };
- twl3025_power_off();
- }
if (src & 0x08)
handle_charger();
if (src & 0x20)
@@ -193,6 +187,17 @@ static void twl3025_wait_ibic_access(void)
void twl3025_power_off(void)
{
+ unsigned long flags;
+
+ /* turn off all IRQs, since received frames cannot be
+ * handled form here. (otherwise the message allocation
+ * runs out of memory) */
+ local_firq_save(flags);
+
+ /* poll PWON status and power off the phone when the
+ * powerbutton has been released (otherwise it will
+ * poweron immediately again) */
+ while (!(twl3025_reg_read(VRPCSTS) & 0x10)) { };
twl3025_reg_write(VRPCDEV, 0x01);
}
diff --git a/Src/osmolib/src/target/firmware/apps/chainload/main.c b/Src/osmolib/src/target/firmware/apps/chainload/main.c
index 5121837..9dfa217 100644
--- a/Src/osmolib/src/target/firmware/apps/chainload/main.c
+++ b/Src/osmolib/src/target/firmware/apps/chainload/main.c
@@ -29,6 +29,7 @@
#include <delay.h>
#include <calypso/clock.h>
+#include <calypso/timer.h>
/* Main Program */
diff --git a/Src/osmolib/src/target/firmware/apps/compal_dsp_dump/main.c b/Src/osmolib/src/target/firmware/apps/compal_dsp_dump/main.c
index c823d0a..f148d50 100644
--- a/Src/osmolib/src/target/firmware/apps/compal_dsp_dump/main.c
+++ b/Src/osmolib/src/target/firmware/apps/compal_dsp_dump/main.c
@@ -37,6 +37,7 @@
#include <calypso/irq.h>
#include <calypso/misc.h>
#include <comm/timer.h>
+#include <fb/framebuffer.h>
/* Main Program */
const char *hr = "======================================================================\n";
@@ -52,11 +53,33 @@ int main(void)
dump_dev_id();
puts(hr);
+ fb_clear();
+
+ fb_setfg(FB_COLOR_BLACK);
+ fb_setbg(FB_COLOR_WHITE);
+ fb_setfont(FB_FONT_HELVB14);
+
+ fb_gotoxy(2,20);
+ fb_putstr("DSP Dump",framebuffer->width-4);
+
+ fb_setfg(FB_COLOR_RED);
+ fb_setbg(FB_COLOR_BLUE);
+
+ fb_gotoxy(2,25);
+ fb_boxto(framebuffer->width-3,38);
+
+ fb_setfg(FB_COLOR_WHITE);
+ fb_setfont(FB_FONT_HELVR08);
+ fb_gotoxy(8,33);
+ fb_putstr("osmocom-bb",framebuffer->width-4);
+
+ fb_flush();
+
/* Dump DSP content */
dsp_dump();
while (1) {
- update_timers();
+ osmo_timers_update();
}
}
diff --git a/Src/osmolib/src/target/firmware/apps/hello_world/main.c b/Src/osmolib/src/target/firmware/apps/hello_world/main.c
index 5e3ed85..cdf4dae 100644
--- a/Src/osmolib/src/target/firmware/apps/hello_world/main.c
+++ b/Src/osmolib/src/target/firmware/apps/hello_world/main.c
@@ -31,7 +31,6 @@
#include <keypad.h>
#include <board.h>
#include <abb/twl3025.h>
-#include <display.h>
#include <rf/trf6151.h>
#include <calypso/clock.h>
#include <calypso/tpu.h>
@@ -41,6 +40,7 @@
#include <calypso/misc.h>
#include <comm/sercomm.h>
#include <comm/timer.h>
+#include <fb/framebuffer.h>
/* Main Program */
const char *hr = "======================================================================\n";
@@ -55,7 +55,6 @@ static void console_rx_cb(uint8_t dlci, struct msgb *msg)
}
printf("Message on console DLCI: '%s'\n", msg->data);
- display_puts((char *) msg->data);
msgb_free(msg);
}
@@ -89,6 +88,30 @@ int main(void)
calypso_clk_dump();
puts(hr);
+ fb_clear();
+
+ fb_setfg(FB_COLOR_BLACK);
+ fb_setbg(FB_COLOR_WHITE);
+ fb_setfont(FB_FONT_HELVB14);
+
+ fb_gotoxy(2,20);
+ fb_putstr("Hello World!",framebuffer->width-4);
+
+ fb_setfg(FB_COLOR_RED);
+ fb_setbg(FB_COLOR_BLUE);
+
+ fb_gotoxy(2,25);
+ fb_boxto(framebuffer->width-3,38);
+
+ fb_setfg(FB_COLOR_WHITE);
+ fb_setfont(FB_FONT_HELVR08);
+ fb_gotoxy(8,33);
+ fb_putstr("osmocom-bb",framebuffer->width-4);
+
+ fb_flush();
+
+
+
/* Dump all memory */
//dump_mem();
#if 0
@@ -97,16 +120,13 @@ int main(void)
puts(hr);
#endif
- display_set_attr(DISP_ATTR_INVERT);
- display_puts("Hello World");
-
sercomm_register_rx_cb(SC_DLCI_CONSOLE, console_rx_cb);
sercomm_register_rx_cb(SC_DLCI_L1A_L23, l1a_l23_rx_cb);
/* beyond this point we only react to interrupts */
puts("entering interrupt loop\n");
while (1) {
- update_timers();
+ osmo_timers_update();
}
twl3025_power_off();
@@ -132,16 +152,13 @@ void key_handler(enum key_codes code, enum key_states state)
case KEY_7:
case KEY_8:
case KEY_9:
- sprintf(test, "%d", code - KEY_0);
- display_puts(test);
+ // used to be display_puts...
break;
case KEY_STAR:
- sprintf(test, "*", 0);
- display_puts(test);
+ // used to be display puts...
break;
case KEY_HASH:
- sprintf(test, "#", 0);
- display_puts(test);
+ // used to be display puts...
break;
default:
break;
diff --git a/Src/osmolib/src/target/firmware/apps/layer1/main.c b/Src/osmolib/src/target/firmware/apps/layer1/main.c
index 8eaf4a6..a8d4f5d 100644
--- a/Src/osmolib/src/target/firmware/apps/layer1/main.c
+++ b/Src/osmolib/src/target/firmware/apps/layer1/main.c
@@ -25,13 +25,13 @@
#include <debug.h>
#include <memory.h>
+#include <string.h>
#include <delay.h>
#include <rffe.h>
#include <keypad.h>
#include <board.h>
#include <abb/twl3025.h>
-#include <display.h>
#include <rf/trf6151.h>
#include <comm/sercomm.h>
@@ -42,9 +42,14 @@
#include <calypso/tsp.h>
#include <calypso/irq.h>
#include <calypso/misc.h>
+#include <calypso/sim.h>
#include <layer1/sync.h>
+#include <layer1/async.h>
#include <layer1/tpu_window.h>
+#include <layer1/l23_api.h>
+
+#include <fb/framebuffer.h>
const char *hr = "======================================================================\n";
@@ -54,6 +59,9 @@ static void key_handler(enum key_codes code, enum key_states state);
int main(void)
{
+ uint8_t atr[20];
+ uint8_t atrLength = 0;
+
board_init();
puts("\n\nOSMOCOM Layer 1 (revision " GIT_REVISION ")\n");
@@ -69,17 +77,44 @@ int main(void)
calypso_clk_dump();
puts(hr);
- display_puts("layer1.bin");
+ fb_clear();
- layer1_init();
+ fb_setfg(FB_COLOR_BLACK);
+ fb_setbg(FB_COLOR_WHITE);
+ fb_setfont(FB_FONT_HELVB14);
+
+ fb_gotoxy(2,20);
+ fb_putstr("Layer 1",framebuffer->width-4);
+
+ fb_setfg(FB_COLOR_RED);
+ fb_setbg(FB_COLOR_BLUE);
+
+ fb_gotoxy(2,25);
+ fb_boxto(framebuffer->width-3,38);
- display_unset_attr(DISP_ATTR_INVERT);
+ fb_setfg(FB_COLOR_WHITE);
+ fb_setfont(FB_FONT_HELVR08);
+ fb_gotoxy(8,33);
+ fb_putstr("osmocom-bb",framebuffer->width-4);
+
+ fb_flush();
+
+ /* initialize SIM */
+ calypso_sim_init();
+
+ puts("Power up simcard:\n");
+ memset(atr,0,sizeof(atr));
+ atrLength = calypso_sim_powerup(atr);
+
+ layer1_init();
tpu_frame_irq_en(1, 1);
while (1) {
l1a_compl_execute();
- update_timers();
+ osmo_timers_update();
+ sim_handler();
+ l1a_l23_handler();
}
/* NOT REACHED */
@@ -130,6 +165,9 @@ static void key_handler(enum key_codes code, enum key_states state)
default:
break;
}
+ /* power down SIM, TODO: this will happen with every key pressed,
+ put it somewhere else ! */
+ calypso_sim_powerdown();
}
diff --git a/Src/osmolib/src/target/firmware/apps/loader/main.c b/Src/osmolib/src/target/firmware/apps/loader/main.c
index 2ff6f9c..c55c56c 100644
--- a/Src/osmolib/src/target/firmware/apps/loader/main.c
+++ b/Src/osmolib/src/target/firmware/apps/loader/main.c
@@ -45,6 +45,7 @@
#include <calypso/tsp.h>
#include <calypso/irq.h>
#include <calypso/misc.h>
+#include <calypso/backlight.h>
#include <uart.h>
#include <calypso/timer.h>
diff --git a/Src/osmolib/src/target/firmware/apps/rssi/main.c b/Src/osmolib/src/target/firmware/apps/rssi/main.c
new file mode 100644
index 0000000..a189740
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/apps/rssi/main.c
@@ -0,0 +1,1544 @@
+/* Cell Monitor of Free Software for Calypso Phone */
+
+/* (C) 2012 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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <debug.h>
+#include <memory.h>
+#include <delay.h>
+#include <byteorder.h>
+#include <rffe.h>
+#include <keypad.h>
+#include <board.h>
+#include <abb/twl3025.h>
+#include <rf/trf6151.h>
+#include <calypso/clock.h>
+#include <calypso/tpu.h>
+#include <calypso/tsp.h>
+#include <calypso/dsp.h>
+#include <calypso/irq.h>
+#include <calypso/misc.h>
+#include <calypso/buzzer.h>
+#include <comm/sercomm.h>
+#include <comm/timer.h>
+#include <fb/framebuffer.h>
+#include <layer1/sync.h>
+#include <layer1/async.h>
+#include <layer1/l23_api.h>
+#include <osmocom/gsm/rsl.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/gsm48_ie.h>
+
+enum key_codes key_code = KEY_INV;
+int key_pressed = 0;
+enum key_codes key_pressed_code;
+unsigned long key_pressed_when;
+unsigned int key_pressed_delay;
+
+enum mode {
+ MODE_MAIN,
+ MODE_SPECTRUM,
+ MODE_ARFCN,
+ MODE_SYNC,
+ MODE_RACH,
+} mode = MODE_MAIN;
+enum mode last_mode; /* where to return after entering ARFCN */
+
+static uint16_t arfcn = 0, ul_arfcn;
+int pcs = 0;
+int uplink = 0;
+int max = 0;
+uint8_t power, max_power;
+char input[5];
+int cursor;
+
+char *sync_result = NULL;
+char *sync_msg = "";
+
+static struct band {
+ int min, max, prev, next, freq_ul, freq_dl;
+} bands[] = {
+ { 128, 251, 124, 512, 8242, 8692 }, /* GSM 850 */
+ { 955, 124, 885, 128, 8762, 9212 }, /* P,E,R GSM */
+ { 512, 885, 251, 955, 17102, 18052 }, /* DCS 1800 */
+ { 0, 0, 0, 0, 0, 0},
+};
+
+struct band *band;
+
+#define PCS_MIN 512
+#define PCS_MAX 810
+#define DCS_MIN 512
+#define DCS_MAX 885
+#define PCS_UL 18502
+#define PCS_DL 19302
+
+enum pm_mode {
+ PM_IDLE,
+ PM_SENT,
+ PM_RANGE_SENT,
+ PM_RANGE_RESULT,
+ PM_RESULT,
+} pm_mode = PM_IDLE;
+
+#define NUM_PM_DL 2
+#define NUM_PM_UL 10
+int pm_meas[NUM_PM_UL];
+int pm_count = 0;
+int pm_max = 2;
+uint8_t pm_spectrum[1024];
+int pm_scale = 1; /* scale measured power level */
+
+#define TONE_JIFFIES ((HZ < 25) ? 1 : HZ / 25)
+int tone = 0;
+unsigned long tone_time;
+int tone_on = 0;
+
+uint8_t bsic;
+uint8_t ul_levels[8], ul_max[8]; /* 8 uplink levels */
+uint8_t si_1[23];
+uint8_t si_2[23];
+uint8_t si_2bis[23];
+uint8_t si_2ter[23];
+uint8_t si_3[23];
+uint8_t si_4[23];
+uint16_t si_new = 0, ul_new;
+uint16_t mcc, mnc, lac, cell_id;
+int ccch_conf;
+int nb_num;
+struct gsm_sysinfo_freq freq[1024];
+#define NEIGH_LINES ((framebuffer->height - 25) / 8)
+
+#define FREQ_TYPE_SERV 0x01 /* frequency of the serving cell */
+#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 */
+
+int rach = 0;
+struct gsm48_req_ref rach_ref;
+uint8_t rach_ra;
+unsigned long rach_when;
+uint8_t ta;
+
+enum assign {
+ ASSIGN_NONE,
+ ASSIGN_NO_TX,
+ ASSIGN_RESULT,
+ ASSIGN_REJECT,
+ ASSIGN_TIMEOUT,
+} assign;
+
+/* UI */
+
+static void print_display(char *text, int *y, int c)
+{
+ /* skip lines, given by cursor */
+ (*y)++;
+ if (c >= (*y))
+ return;
+ /* skip, if end of display area is reached */
+ if ((*y) - c > NEIGH_LINES)
+ return;
+
+ fb_gotoxy(0, 20 + (((*y) - c - 1) << 3));
+ fb_putstr(text, framebuffer->width);
+}
+
+static void refresh_display(void)
+{
+ char text[16];
+
+ fb_clear();
+
+ /* header */
+ fb_setbg(FB_COLOR_WHITE);
+ if (mode != MODE_SPECTRUM && !(mode == MODE_SYNC && cursor < 0)) {
+ fb_setfg(FB_COLOR_BLUE);
+ fb_setfont(FB_FONT_HELVR08);
+ fb_gotoxy(0, 7);
+ fb_putstr("Osmocom Monitor Tool", -1);
+ fb_gotoxy(0, 10);
+ fb_setfg(FB_COLOR_GREEN);
+ fb_boxto(framebuffer->width - 1, 10);
+ }
+ fb_setfg(FB_COLOR_BLACK);
+ fb_setfont(FB_FONT_C64);
+
+ /* RACH */
+ if (mode == MODE_RACH) {
+ unsigned long elapsed = jiffies - rach_when;
+
+ fb_gotoxy(0,28);
+ switch (assign) {
+ case ASSIGN_NONE:
+ fb_putstr("Rach sent...", -1);
+ break;
+ case ASSIGN_RESULT:
+ sprintf(text, "TA = %d", ta);
+ fb_putstr(text, -1);
+ fb_gotoxy(0,36);
+ sprintf(text, "(%dm)", ta * 554);
+ fb_putstr(text, -1);
+ break;
+ case ASSIGN_REJECT:
+ fb_putstr("Rejected!", -1);
+ break;
+ case ASSIGN_NO_TX:
+ fb_putstr("TX disabled", -1);
+ break;
+ case ASSIGN_TIMEOUT:
+ fb_putstr("Timeout", -1);
+ break;
+ }
+ switch (assign) {
+ case ASSIGN_RESULT:
+ case ASSIGN_REJECT:
+ fb_gotoxy(0,44);
+ sprintf(text, "Delay:%ldms", elapsed * 1000 / HZ);
+ fb_putstr(text, -1);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* SYNC / UL levels */
+ if (mode == MODE_SYNC && cursor < 0) {
+ int i, tn, l;
+ int offset = (framebuffer->width - 96) >> 1;
+ int height = framebuffer->height - 25;
+
+ fb_setfont(FB_FONT_HELVR08);
+ for (i = 0; i < 8; i++) {
+ if (uplink)
+ tn = (i + 3) & 7; /* UL is shifted by 3 */
+ else
+ tn = i;
+ fb_setbg(FB_COLOR_WHITE);
+ fb_gotoxy(offset + 12 * i, 7);
+ l = (max) ? ul_max[tn] : ul_levels[tn];
+ l = 110 - l;
+ if (l >= 100)
+ l -= 100;
+ sprintf(text, "%02d", l);
+ fb_putstr(text, framebuffer->width);
+ fb_setbg(FB_COLOR_BLACK);
+ fb_gotoxy(offset + 3 + 12 * i, height + 10);
+ fb_boxto(offset + 3 + 12 * i + 5, height + 10 - ul_levels[tn] * height / 64);
+ if (max) {
+ fb_gotoxy(offset + 3 + 12 * i, height + 10 - ul_max[tn] * height / 64);
+ fb_boxto(offset + 3 + 12 * i + 5, height + 10 - ul_max[tn] * height / 64);
+ }
+ }
+ fb_setbg(FB_COLOR_TRANSP);
+ if (max) {
+ fb_setfg(FB_COLOR_RED);
+ fb_gotoxy(framebuffer->width - 16, 15);
+ fb_putstr("max", framebuffer->width);
+ }
+ fb_setfont(FB_FONT_C64);
+ fb_setfg(FB_COLOR_BLUE);
+ fb_gotoxy(0, 16);
+ if (pcs && ul_arfcn >= PCS_MIN && ul_arfcn <= PCS_MAX)
+ sprintf(text, "%4dP", ul_arfcn);
+ else if (ul_arfcn >= DCS_MIN && ul_arfcn <= DCS_MAX)
+ sprintf(text, "%4dD", ul_arfcn);
+ else
+ sprintf(text, "%4d ", ul_arfcn);
+ fb_putstr(text, framebuffer->width);
+ fb_setbg(FB_COLOR_WHITE);
+ fb_setfg(FB_COLOR_BLACK);
+ }
+
+ /* SYNC / SI */
+ if (mode == MODE_SYNC && cursor == 0) {
+ fb_gotoxy(0, 20);
+ if (sync_msg[0] == 'o')
+ sprintf(text, "BSIC%d/%d %4d", bsic >> 3, bsic & 7,
+ power - 110);
+ else
+ sprintf(text, "Sync %s", sync_msg);
+ fb_putstr(text, -1);
+
+ fb_gotoxy(0,28);
+ text[0] = si_1[2] ? '1' : '-';
+ text[1] = ' ';
+ text[2] = si_2[2] ? '2' : '-';
+ text[3] = ' ';
+ text[4] = si_2bis[2] ? '2' : '-';
+ text[5] = si_2bis[2] ? 'b' : ' ';
+ text[6] = si_2ter[2] ? '2' : '-';
+ text[7] = si_2ter[2] ? 't' : ' ';
+ text[8] = ' ';
+ text[9] = si_3[2] ? '3' : '-';
+ text[10] = ' ';
+ text[11] = si_4[2] ? '4' : '-';
+ text[12] = '\0';
+ fb_putstr(text, -1);
+
+ fb_gotoxy(0, 36);
+ fb_putstr("MCC MNC LAC ", -1);
+ fb_gotoxy(0, 44);
+ if (mcc) {
+ if ((mnc & 0x00f) == 0x00f)
+ sprintf(text, "%3x %02x %04x", mcc, mnc >> 4, lac);
+ else
+ sprintf(text, "%3x %03x %04x", mcc, mnc, lac);
+ fb_putstr(text, -1);
+ } else
+ fb_putstr("--- --- ----", -1);
+ fb_gotoxy(0, 52);
+ if (si_3[2]) {
+ sprintf(text, "cell id:%04x", cell_id);
+ fb_putstr(text, -1);
+ } else
+ fb_putstr("cell id:----", -1);
+ }
+
+ /* SYNC / neighbour cells */
+ if (mode == MODE_SYNC && cursor > 0) {
+ int i, y = 0;
+
+ text[0] = '\0';
+ for (i = 0; i < 1024; i++) {
+ if (freq[i].mask & FREQ_TYPE_SERV) {
+ if (!text[0])
+ sprintf(text, "S: %4d", i);
+ else {
+ sprintf(text + 7, " %4d", i);
+ print_display(text, &y, cursor - 1);
+ text[0] = '\0';
+ }
+ }
+ }
+ if (text[0])
+ print_display(text, &y, cursor - 1);
+ text[0] = '\0';
+ for (i = 0; i < 1024; i++) {
+ if (freq[i].mask & FREQ_TYPE_NCELL) {
+ if (!text[0])
+ sprintf(text, "N: %4d", i);
+ else {
+ sprintf(text + 7, " %4d", i);
+ print_display(text, &y, cursor - 1);
+ text[0] = '\0';
+ }
+ }
+ }
+ if (text[0])
+ print_display(text, &y, cursor - 1);
+ nb_num = y;
+ }
+
+ /* ARFCN */
+ if (mode == MODE_MAIN || mode == MODE_ARFCN) {
+ fb_gotoxy(0, 20);
+ if (mode == MODE_ARFCN)
+ sprintf(text, "ARFCN %s", input);
+ else if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX)
+ sprintf(text, "ARFCN %dPCS", arfcn);
+ else if (arfcn >= DCS_MIN && arfcn <= DCS_MAX)
+ sprintf(text, "ARFCN %dDCS", arfcn);
+ else
+ sprintf(text, "ARFCN %d", arfcn);
+ fb_putstr(text,framebuffer->width);
+ }
+
+ /* cursor */
+ if (mode == MODE_ARFCN) {
+ fb_setfg(FB_COLOR_WHITE);
+ fb_setbg(FB_COLOR_BLUE);
+ fb_putstr(" ", framebuffer->width);
+ fb_setfg(FB_COLOR_BLACK);
+ fb_setbg(FB_COLOR_WHITE);
+ }
+
+ /* Frequency / power */
+ if (mode == MODE_MAIN) {
+ int f;
+
+ if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX) {
+ if (uplink)
+ f = PCS_UL;
+ else
+ f = PCS_DL;
+ } else if (uplink)
+ f = band->freq_ul;
+ else
+ f = band->freq_dl;
+ f += ((arfcn - band->min) & 1023) << 1;
+
+ fb_gotoxy(0, 30);
+ sprintf(text, "Freq. %d.%d", f / 10, f % 10);
+ fb_putstr(text,framebuffer->width);
+
+ fb_gotoxy(0, 40);
+ sprintf(text, "Power %d", ((max) ? max_power : power) - 110);
+ fb_putstr(text, framebuffer->width);
+ if (max) {
+ fb_setfont(FB_FONT_HELVR08);
+ fb_setfg(FB_COLOR_RED);
+ fb_gotoxy(framebuffer->width - 16, 39);
+ fb_putstr("max", framebuffer->width);
+ fb_setfont(FB_FONT_C64);
+ fb_setfg(FB_COLOR_BLACK);
+ }
+ fb_setbg(FB_COLOR_BLACK);
+ fb_gotoxy(0, 45);
+ fb_boxto(framebuffer->width * power / 64, 50);
+ if (max) {
+ fb_gotoxy(framebuffer->width * max_power / 64 ,45);
+ fb_boxto(framebuffer->width * max_power / 64, 50);
+ }
+ fb_setbg(FB_COLOR_WHITE);
+ }
+
+ /* spectrum */
+ if (mode == MODE_SPECTRUM) {
+ int i;
+ uint16_t a, e, p;
+ int height = framebuffer->height - 25;
+
+ fb_gotoxy(0, 8);
+ if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX)
+ sprintf(text, "%4dP", arfcn);
+ else if (arfcn >= DCS_MIN && arfcn <= DCS_MAX)
+ sprintf(text, "%4dD", arfcn);
+ else
+ sprintf(text, "%4d ", arfcn);
+ sprintf(text + 5, " %4d", pm_spectrum[arfcn & 1023] - 110);
+ fb_putstr(text, -1);
+ fb_setfg(FB_COLOR_RED);
+ if (max) {
+ fb_setfont(FB_FONT_HELVR08);
+ fb_gotoxy(framebuffer->width - 16,15);
+ fb_putstr("max", framebuffer->width);
+ fb_setfont(FB_FONT_C64);
+ }
+ if (pm_scale != 1) {
+ fb_setfont(FB_FONT_HELVR08);
+ fb_gotoxy(1, 15);
+ sprintf(text, "x%d", pm_scale);
+ fb_putstr(text, framebuffer->width);
+ fb_setfont(FB_FONT_C64);
+ }
+ fb_setfg(FB_COLOR_BLACK);
+ if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX) {
+ a = PCS_MIN;
+ e = PCS_MAX;
+ } else {
+ a = band->min;
+ e = band->max;
+ }
+ for (i = 0; i < framebuffer->width; i++) {
+ p = (arfcn + i - (framebuffer->width >> 1)) & 1023;
+ if ((((p - a) & 1023) & 512))
+ continue;
+ if ((((e - p) & 1023) & 512))
+ continue;
+ p = (pm_spectrum[p] * pm_scale * height / 64);
+ if (p > height)
+ p = height;
+ if (i == (framebuffer->width >> 1))
+ fb_setfg(FB_COLOR_RED);
+ fb_gotoxy(i, height + 10 - p);
+ fb_boxto(i, height + 10);
+ if (i == (framebuffer->width >> 1))
+ fb_setfg(FB_COLOR_BLACK);
+ }
+ i = framebuffer->width >> 1;
+ fb_gotoxy(i, 0);
+ fb_boxto(i, 4);
+ fb_gotoxy(i, height + 10);
+ fb_boxto(i, height + 14);
+ }
+
+ /* footer */
+ fb_setfg(FB_COLOR_GREEN);
+ fb_gotoxy(0, framebuffer->height - 10);
+ fb_boxto(framebuffer->width-1, framebuffer->height - 10);
+ fb_gotoxy(0, framebuffer->height - 1);
+ fb_setfg(FB_COLOR_RED);
+ if (mode == MODE_ARFCN)
+ sprintf(text, "%s %s", (cursor) ? "del " : "back",
+ (cursor) ? "enter" : " ");
+ else if (mode == MODE_SYNC && cursor < 0)
+ sprintf(text, "%s %s", "back",
+ (uplink) ? "UL" : "DL");
+ else if (mode == MODE_SYNC || mode == MODE_RACH)
+ sprintf(text, "%s ", "back");
+ else
+ sprintf(text, "%s %s", (pcs) ? "PCS" : "DCS",
+ (uplink) ? "UL" : "DL");
+ fb_putstr(text, -1);
+ fb_setfg(FB_COLOR_BLACK);
+ fb_setfont(FB_FONT_HELVR08);
+ fb_gotoxy(0, framebuffer->height - 2);
+ sprintf(text, "%d", tone / 25);
+ fb_putstr(text, -1);
+
+ fb_flush();
+}
+
+static void exit_arfcn(void)
+{
+ mode = last_mode;
+ refresh_display();
+}
+
+static void enter_arfcn(enum key_codes code)
+{
+ /* enter mode */
+ if (mode != MODE_ARFCN) {
+ last_mode = mode;
+ mode = MODE_ARFCN;
+ input[0] = code - KEY_0 + '0';
+ input[1] = '\0';
+ cursor = 1;
+ refresh_display();
+ return;
+ }
+
+ if (code == KEY_LEFT_SB) {
+ /* back */
+ if (cursor == 0) {
+ exit_arfcn();
+ return;
+ }
+ /* delete */
+ cursor--;
+ input[cursor] = '\0';
+ refresh_display();
+ return;
+ }
+
+ if (code == KEY_RIGHT_SB) {
+ int check = 0;
+ int i;
+ struct band *temp = NULL;
+
+ /* nothing entered */
+ if (cursor == 0) {
+ return;
+ }
+ for (i = 0; i < cursor; i++)
+ check = (check << 3) + (check << 1) + input[i] - '0';
+
+ /* check */
+ for (i = 0; bands[i].max; i++) {
+ temp = &bands[i];
+ if (temp->min < temp->max) {
+ if (check >= temp->min && check <= temp->max)
+ break;
+ } else {
+ if (check >= temp->min || check <= temp->max)
+ break;
+ }
+ }
+ if (!bands[i].max)
+ return;
+ if (check > 1023)
+ return;
+ arfcn = check;
+ band = temp;
+ mode = last_mode;
+ refresh_display();
+ return;
+ }
+
+ if (cursor == 4)
+ return;
+
+ input[cursor] = code - KEY_0 + '0';
+ cursor++;
+ input[cursor] = '\0';
+ refresh_display();
+}
+
+static int inc_dec_arfcn(int inc)
+{
+ int i;
+
+ /* select current band */
+ for (i = 0; bands[i].max; i++) {
+ band = &bands[i];
+ if (band->min < band->max) {
+ if (arfcn >= band->min && arfcn <= band->max)
+ break;
+ } else {
+ if (arfcn >= band->min || arfcn <= band->max)
+ break;
+ }
+ }
+ if (!bands[i].max)
+ return -EINVAL;
+
+ if (inc) {
+ if (arfcn == band->max)
+ arfcn = band->next;
+ else if (arfcn == 1023)
+ arfcn = 0;
+ else
+ arfcn++;
+ } else {
+ if (arfcn == band->min)
+ arfcn = band->prev;
+ else if (arfcn == 0)
+ arfcn = 1023;
+ else
+ arfcn--;
+ }
+ /* select next band */
+ for (i = 0; bands[i].max; i++) {
+ band = &bands[i];
+ if (band->min < band->max) {
+ if (arfcn >= band->min && arfcn <= band->max)
+ break;
+ } else {
+ if (arfcn >= band->min || arfcn <= band->max)
+ break;
+ }
+ }
+ if (!bands[i].max)
+ return -EINVAL;
+
+ refresh_display();
+
+ return 0;
+}
+
+static void request_ul_levels(uint16_t a);
+
+static int inc_dec_ul_arfcn(int inc)
+{
+ uint16_t a;
+
+ /* loop until we hit a serving cell or our current bcch arfcn */
+ if (inc) {
+ for (a = (ul_arfcn + 1) & 1023; a != (arfcn & 1023);
+ a = (a + 1) & 1023) {
+ if ((freq[a].mask & FREQ_TYPE_SERV))
+ break;
+ }
+ } else {
+ for (a = (ul_arfcn - 1) & 1023; a != (arfcn & 1023);
+ a = (a - 1) & 1023) {
+ if ((freq[a].mask & FREQ_TYPE_SERV))
+ break;
+ }
+ }
+ ul_arfcn = a;
+
+ refresh_display();
+
+ request_ul_levels(a);
+
+ return 0;
+}
+
+static void toggle_dcs_pcs(void)
+{
+ pcs = !pcs;
+ refresh_display();
+}
+
+static void toggle_up_down(void)
+{
+ uplink = !uplink;
+ refresh_display();
+
+ if (mode == MODE_SYNC && cursor < 0)
+ request_ul_levels(ul_arfcn);
+}
+
+static void toggle_spectrum(void)
+{
+ if (mode == MODE_MAIN) {
+ mode = MODE_SPECTRUM;
+ pm_mode = PM_IDLE;
+ } else if (mode == MODE_SPECTRUM) {
+ mode = MODE_MAIN;
+ pm_mode = PM_IDLE;
+ }
+ l1s_reset();
+ l1s_reset_hw();
+ pm_count = 0;
+ refresh_display();
+}
+
+static void tone_inc_dec(int inc)
+{
+ if (inc) {
+ if (tone + 25 <= 255)
+ tone += 25;
+ } else {
+ if (tone - 25 >= 0)
+ tone -= 25;
+ }
+
+ refresh_display();
+}
+
+static void hold_max(void)
+{
+ max = !max;
+ max_power = power;
+ refresh_display();
+}
+
+static int inc_dec_neighbour(int inc)
+{
+ if (inc) {
+ if (cursor > 0 && cursor - 1 >= (nb_num - NEIGH_LINES))
+ return -EINVAL;
+ cursor++;
+ } else {
+ if (cursor < 0)
+ return -EINVAL;
+ cursor--;
+ }
+
+ refresh_display();
+
+ return 0;
+}
+
+static int inc_dec_spectrum(int inc)
+{
+ if (inc) {
+ pm_scale <<= 1;
+ if (pm_scale > 8)
+ pm_scale = 8;
+ } else {
+ pm_scale >>= 1;
+ if (pm_scale < 1)
+ pm_scale = 1;
+ }
+
+ refresh_display();
+
+ return 0;
+}
+
+static void enter_sync(void);
+static void exit_sync(void);
+
+static void enter_rach(void);
+static void exit_rach(void);
+
+static void handle_key_code()
+{
+ /* key repeat */
+ if (key_pressed) {
+ unsigned long elapsed = jiffies - key_pressed_when;
+ if (elapsed > key_pressed_delay) {
+ key_pressed_when = jiffies;
+ key_pressed_delay = HZ / 10;
+ /* only repeat these keys */
+ if (key_pressed_code == KEY_LEFT
+ || key_pressed_code == KEY_RIGHT)
+ key_code = key_pressed_code;
+ }
+ }
+
+ if (key_code == KEY_INV)
+ return;
+
+ /* do later, do not disturb tone */
+ if (tone_on)
+ return;
+
+ switch (key_code) {
+ case KEY_0:
+ case KEY_1:
+ case KEY_2:
+ case KEY_3:
+ case KEY_4:
+ case KEY_5:
+ case KEY_6:
+ case KEY_7:
+ case KEY_8:
+ case KEY_9:
+ if (mode == MODE_MAIN || mode == MODE_SPECTRUM || mode == MODE_ARFCN)
+ enter_arfcn(key_code);
+ break;
+ case KEY_UP:
+ if (mode == MODE_MAIN)
+ tone_inc_dec(1);
+ else if (mode == MODE_SYNC)
+ inc_dec_neighbour(0);
+ else if (mode == MODE_SPECTRUM)
+ inc_dec_spectrum(1);
+ break;
+ case KEY_DOWN:
+ if (mode == MODE_MAIN)
+ tone_inc_dec(0);
+ else if (mode == MODE_SYNC)
+ inc_dec_neighbour(1);
+ else if (mode == MODE_SPECTRUM)
+ inc_dec_spectrum(0);
+ break;
+ case KEY_RIGHT:
+ if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
+ inc_dec_arfcn(1);
+ else if (mode == MODE_SYNC && cursor < 0)
+ inc_dec_ul_arfcn(1);
+ break;
+ case KEY_LEFT:
+ if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
+ inc_dec_arfcn(0);
+ else if (mode == MODE_SYNC && cursor < 0)
+ inc_dec_ul_arfcn(0);
+ break;
+ case KEY_LEFT_SB:
+ if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
+ toggle_dcs_pcs();
+ else if (mode == MODE_ARFCN)
+ enter_arfcn(key_code);
+ else if (mode == MODE_SYNC)
+ exit_sync();
+ else if (mode == MODE_RACH)
+ exit_rach();
+ break;
+ case KEY_RIGHT_SB:
+ if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
+ toggle_up_down();
+ else if (mode == MODE_ARFCN)
+ enter_arfcn(key_code);
+ else if (mode == MODE_SYNC && cursor < 0)
+ toggle_up_down();
+ break;
+ case KEY_OK:
+ if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
+ enter_sync();
+ else if (mode == MODE_SYNC || mode == MODE_RACH)
+ enter_rach();
+ break;
+ case KEY_MENU:
+ hold_max();
+ break;
+ case KEY_POWER:
+ if (mode == MODE_ARFCN)
+ exit_arfcn();
+ else if (mode == MODE_SYNC)
+ exit_sync();
+ else if (mode == MODE_RACH)
+ exit_rach();
+ else if (mode == MODE_SPECTRUM)
+ toggle_spectrum();
+ break;
+ case KEY_STAR:
+ if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
+ toggle_spectrum();
+ break;
+ default:
+ break;
+ }
+
+ key_code = KEY_INV;
+}
+
+static void handle_tone(void)
+{
+ unsigned long elapsed = jiffies - tone_time;
+
+ if (!tone_on) {
+ if (!tone || mode != MODE_MAIN)
+ return;
+ /* wait depending on power level */
+ if (elapsed < (uint8_t)(63-power))
+ return;
+ buzzer_volume(tone);
+ buzzer_note(NOTE(NOTE_C, OCTAVE_5));
+ tone_time = jiffies;
+ tone_on = 1;
+ return;
+ }
+
+ if (elapsed >= TONE_JIFFIES) {
+ tone_on = 0;
+ tone_time = jiffies;
+ buzzer_volume(0);
+ }
+}
+
+/* PM handling */
+
+static void handle_pm(void)
+{
+ /* start power measurement */
+ if (pm_mode == PM_IDLE && (mode == MODE_MAIN || mode == MODE_SPECTRUM)) {
+ struct msgb *msg = l1ctl_msgb_alloc(L1CTL_PM_REQ);
+ struct l1ctl_pm_req *pm;
+ uint16_t a, e;
+
+ pm = (struct l1ctl_pm_req *) msgb_put(msg, sizeof(*pm));
+ pm->type = 1;
+ if (mode == MODE_MAIN) {
+ a = arfcn;
+ if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX)
+ a |= ARFCN_PCS;
+ if (uplink)
+ a |= ARFCN_UPLINK;
+ e = a;
+ pm_mode = PM_SENT;
+ }
+ if (mode == MODE_SPECTRUM) {
+ if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX) {
+ a = PCS_MIN | ARFCN_PCS;
+ e = PCS_MAX | ARFCN_PCS;
+ } else {
+ a = band->min;
+ e = band->max;
+ }
+ pm_mode = PM_RANGE_SENT;
+ }
+ if (uplink) {
+ a |= ARFCN_UPLINK;
+ e |= ARFCN_UPLINK;
+ }
+ pm->range.band_arfcn_from = htons(a);
+ pm->range.band_arfcn_to = htons(e);
+
+ l1a_l23_rx(SC_DLCI_L1A_L23, msg);
+
+ return;
+ }
+
+ if (pm_mode == PM_RESULT) {
+ pm_mode = PM_IDLE;
+ if (pm_count == pm_max) {
+ int i = 0;
+ int sum = 0;
+
+ if (uplink) {
+ /* find max */
+ for (i = 0; i < pm_count; i++) {
+ if (pm_meas[i] > sum)
+ sum = pm_meas[i];
+ }
+ power = sum;
+ } else {
+ for (i = 0; i < pm_count; i++)
+ sum += pm_meas[i];
+ power = sum / pm_count;
+ }
+ if (power > max_power)
+ max_power = power;
+ pm_count = 0;
+ pm_max = (uplink) ? NUM_PM_UL : NUM_PM_DL;
+ if (!tone_on)
+ refresh_display();
+ }
+ return;
+ }
+
+ if (pm_mode == PM_RANGE_RESULT) {
+ pm_mode = PM_IDLE;
+ refresh_display();
+ buzzer_volume(tone);
+ buzzer_note(NOTE(NOTE_C, OCTAVE_5));
+ tone_time = jiffies;
+ tone_on = 1;
+ return;
+ }
+}
+
+/* sync / SI */
+
+static void enter_sync(void)
+{
+ struct msgb *msg = l1ctl_msgb_alloc(L1CTL_FBSB_REQ);
+ struct l1ctl_fbsb_req *req;
+ uint16_t a = arfcn;
+
+ l1s_reset();
+ l1s_reset_hw();
+ pm_count = 0;
+ pm_mode = PM_IDLE;
+
+ req = (struct l1ctl_fbsb_req *) msgb_put(msg, sizeof(*req));
+ if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX)
+ a |= ARFCN_PCS;
+ req->band_arfcn = htons(a);
+ req->timeout = htons(100);
+ /* 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 = L1CTL_FBSB_F_FB01SB;
+ req->sync_info_idx = 0;
+ req->ccch_mode = CCCH_MODE_NONE;
+ l1a_l23_rx(SC_DLCI_L1A_L23, msg);
+
+ mode = MODE_SYNC;
+ memset(ul_levels, 0, sizeof(ul_levels));
+ si_new = 0;
+ ul_new = 0;
+ ul_arfcn = arfcn;
+ si_1[2] = 0;
+ si_2[2] = 0;
+ si_2bis[2] = 0;
+ si_2ter[2] = 0;
+ si_3[2] = 0;
+ si_4[2] = 0;
+ mcc = mnc = lac = 0;
+ ccch_conf = -1;
+ memset(freq, 0, sizeof(freq));
+ cursor = 0;
+ nb_num = 0;
+ sync_msg = "trying";
+ refresh_display();
+}
+
+static void exit_sync(void)
+{
+ l1s_reset();
+ l1s_reset_hw();
+ pm_count = 0;
+ pm_mode = PM_IDLE;
+ mode = MODE_MAIN;
+}
+
+int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *_mcc,
+uint16_t *_mnc, uint16_t *_lac)
+{
+ *_mcc = ((lai->digits[0] & 0x0f) << 8)
+ | (lai->digits[0] & 0xf0)
+ | (lai->digits[1] & 0x0f);
+ *_mnc = ((lai->digits[2] & 0x0f) << 8)
+ | (lai->digits[2] & 0xf0)
+ | ((lai->digits[1] & 0xf0) >> 4);
+ *_lac = ntohs(lai->lac);
+
+ return 0;
+}
+
+static void request_ul_levels(uint16_t a)
+{
+ struct msgb *msg = l1ctl_msgb_alloc(L1CTL_NEIGH_PM_REQ);
+ struct l1ctl_neigh_pm_req *pm_req =
+ (struct l1ctl_neigh_pm_req *) msgb_put(msg, sizeof(*pm_req));
+ int i;
+
+ if (pcs && a >= PCS_MIN && a <= PCS_MAX)
+ a |= ARFCN_PCS;
+ if (uplink)
+ a |= ARFCN_UPLINK;
+ pm_req->n = 8;
+ for (i = 0; i < 8; i++) {
+ pm_req->band_arfcn[i] = htons(a);
+ pm_req->tn[i] = i;
+ }
+ l1a_l23_rx(SC_DLCI_L1A_L23, msg);
+}
+
+static void handle_sync(void)
+{
+ struct gsm48_system_information_type_1 *si1;
+ struct gsm48_system_information_type_2 *si2;
+ struct gsm48_system_information_type_2bis *si2bis;
+ struct gsm48_system_information_type_2ter *si2ter;
+ struct gsm48_system_information_type_3 *si3;
+ struct gsm48_system_information_type_4 *si4;
+
+ if (mode != MODE_SYNC)
+ return;
+
+ /* once we synced, we take the result and request UL measurement */
+ if (sync_result) {
+ uint16_t a = ul_arfcn;
+
+ sync_msg = sync_result;
+ sync_result = NULL;
+ refresh_display();
+
+ if (sync_msg[0] != 'o')
+ return;
+
+ request_ul_levels(a);
+
+ return;
+ }
+
+ if (tone_on)
+ return;
+
+ /* no UL result, no SI result */
+ if (!ul_new && !(si_new & 0x100))
+ return;
+
+ /* new UL result */
+ if (ul_new) {
+ ul_new = 0;
+ if (cursor < 0)
+ refresh_display();
+ return;
+ }
+
+ /* decode si */
+ switch (si_new & 0xff) {
+ case GSM48_MT_RR_SYSINFO_1:
+ si1 = (struct gsm48_system_information_type_1 *)si_1;
+ gsm48_decode_freq_list(freq, si1->cell_channel_description,
+ sizeof(si1->cell_channel_description), 0xce,
+ FREQ_TYPE_SERV);
+ break;
+ case GSM48_MT_RR_SYSINFO_2:
+ si2 = (struct gsm48_system_information_type_2 *)si_2;
+ gsm48_decode_freq_list(freq, si2->bcch_frequency_list,
+ sizeof(si2->bcch_frequency_list), 0xce,
+ FREQ_TYPE_NCELL_2);
+ break;
+ case GSM48_MT_RR_SYSINFO_2bis:
+ si2bis = (struct gsm48_system_information_type_2bis *)si_2bis;
+ gsm48_decode_freq_list(freq, si2bis->bcch_frequency_list,
+ sizeof(si2bis->bcch_frequency_list), 0xce,
+ FREQ_TYPE_NCELL_2bis);
+ break;
+ case GSM48_MT_RR_SYSINFO_2ter:
+ si2ter = (struct gsm48_system_information_type_2ter *)si_2ter;
+ gsm48_decode_freq_list(freq, si2ter->ext_bcch_frequency_list,
+ sizeof(si2ter->ext_bcch_frequency_list), 0x8e,
+ FREQ_TYPE_NCELL_2ter);
+ break;
+ case GSM48_MT_RR_SYSINFO_3:
+ si3 = (struct gsm48_system_information_type_3 *)si_3;
+ gsm48_decode_lai(&si3->lai, &mcc, &mnc, &lac);
+ cell_id = ntohs(si3->cell_identity);
+ if (ccch_conf < 0) {
+ struct msgb *msg =
+ l1ctl_msgb_alloc(L1CTL_CCCH_MODE_REQ);
+ struct l1ctl_ccch_mode_req *req =
+ (struct l1ctl_ccch_mode_req *)
+ msgb_put(msg, sizeof(*req));
+
+ ccch_conf = si3->control_channel_desc.ccch_conf;
+ req->ccch_mode = (ccch_conf == 1)
+ ? CCCH_MODE_COMBINED
+ : CCCH_MODE_NON_COMBINED;
+ printf("ccch_mode=%d\n", ccch_conf);
+
+ l1a_l23_rx(SC_DLCI_L1A_L23, msg);
+ }
+ break;
+ case GSM48_MT_RR_SYSINFO_4:
+ si4 = (struct gsm48_system_information_type_4 *)si_4;
+ gsm48_decode_lai(&si4->lai, &mcc, &mnc, &lac);
+ break;
+ }
+
+ if (cursor >= 0)
+ refresh_display();
+
+ /* tone depends on successfully received BCCH */
+ buzzer_volume(tone);
+ tone_time = jiffies;
+ tone_on = 1;
+ if ((si_new & 0xff) == 0xff)
+ buzzer_note(NOTE(NOTE_C, OCTAVE_2));
+ else
+ buzzer_note(NOTE(NOTE_C, OCTAVE_5));
+ si_new = 0;
+}
+
+static void enter_rach(void)
+{
+ if (ccch_conf < 0)
+ return;
+
+ if (rach)
+ return;
+
+#ifndef CONFIG_TX_ENABLE
+ assign = ASSIGN_NO_TX;
+ mode = MODE_RACH;
+ /* display refresh is done by rach handler */
+#else
+ struct msgb *msg1 = l1ctl_msgb_alloc(L1CTL_NEIGH_PM_REQ);
+ struct msgb *msg2 = l1ctl_msgb_alloc(L1CTL_RACH_REQ);
+ struct l1ctl_neigh_pm_req *pm_req = (struct l1ctl_neigh_pm_req *)
+ msgb_put(msg1, sizeof(*pm_req));
+ struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *)
+ msgb_put(msg2, sizeof(*ul));;
+ struct l1ctl_rach_req *rach_req = (struct l1ctl_rach_req *)
+ msgb_put(msg2, sizeof(*rach_req));
+
+ l1s.tx_power = 0;
+
+ pm_req->n = 0; /* disable */
+
+ rach_ra = 0x00;
+ rach_req->ra = rach_ra;
+ rach_req->offset = 0;
+ rach_req->combined = (ccch_conf == 1);
+
+ l1a_l23_rx(SC_DLCI_L1A_L23, msg1);
+ l1a_l23_rx(SC_DLCI_L1A_L23, msg2);
+ rach = 1;
+ rach_when = jiffies;
+ assign = ASSIGN_NONE;
+ mode = MODE_RACH;
+ refresh_display();
+#endif
+
+}
+
+static void exit_rach(void)
+{
+ rach = 0;
+
+ request_ul_levels(ul_arfcn);
+
+ mode = MODE_SYNC;
+ refresh_display();
+}
+
+static void handle_assign(void)
+{
+ if (mode != MODE_RACH)
+ return;
+
+ if (assign == ASSIGN_NONE) {
+ unsigned long elapsed = jiffies - rach_when;
+
+ if (!rach)
+ return;
+ if (elapsed < HZ * 2)
+ return;
+ assign = ASSIGN_TIMEOUT;
+ rach = 0;
+ }
+
+ refresh_display();
+ assign = ASSIGN_NONE;
+}
+
+/* Main Program */
+const char *hr = "======================================================================\n";
+
+/* match request reference agains request history */
+static int gsm48_match_ra(struct gsm48_req_ref *ref)
+{
+ uint8_t ia_t1, ia_t2, ia_t3;
+ uint8_t cr_t1, cr_t2, cr_t3;
+
+ if (rach && ref->ra == rach_ra) {
+ ia_t1 = ref->t1;
+ ia_t2 = ref->t2;
+ ia_t3 = (ref->t3_high << 3) | ref->t3_low;
+ ref = &rach_ref;
+ cr_t1 = ref->t1;
+ cr_t2 = ref->t2;
+ cr_t3 = (ref->t3_high << 3) | ref->t3_low;
+ if (ia_t1 == cr_t1 && ia_t2 == cr_t2 && ia_t3 == cr_t3)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* note: called from IRQ context */
+static void rx_imm_ass(struct msgb *msg)
+{
+ struct gsm48_imm_ass *ia = msgb_l3(msg);
+
+ if (gsm48_match_ra(&ia->req_ref)) {
+ assign = ASSIGN_RESULT;
+ ta = ia->timing_advance;
+ rach = 0;
+ }
+}
+
+/* note: called from IRQ context */
+static void rx_imm_ass_ext(struct msgb *msg)
+{
+ struct gsm48_imm_ass_ext *ia = msgb_l3(msg);
+
+ if (gsm48_match_ra(&ia->req_ref1)) {
+ assign = ASSIGN_RESULT;
+ ta = ia->timing_advance1;
+ rach = 0;
+ }
+ if (gsm48_match_ra(&ia->req_ref2)) {
+ assign = ASSIGN_RESULT;
+ ta = ia->timing_advance2;
+ rach = 0;
+ }
+}
+
+/* note: called from IRQ context */
+static void rx_imm_ass_rej(struct msgb *msg)
+{
+ struct gsm48_imm_ass_rej *ia = msgb_l3(msg);
+ struct gsm48_req_ref *req_ref;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ /* request reference */
+ req_ref = (struct gsm48_req_ref *)
+ (((uint8_t *)&ia->req_ref1) + i * 4);
+ if (gsm48_match_ra(req_ref)) {
+ assign = ASSIGN_REJECT;
+ rach = 0;
+ }
+ }
+}
+
+/* note: called from IRQ context */
+static void rx_pch_agch(struct msgb *msg)
+{
+ struct gsm48_system_information_type_header *sih;
+
+ /* store SI */
+ sih = msgb_l3(msg);
+ switch (sih->system_information) {
+ case GSM48_MT_RR_IMM_ASS:
+ rx_imm_ass(msg);
+ break;
+ case GSM48_MT_RR_IMM_ASS_EXT:
+ rx_imm_ass_ext(msg);
+ break;
+ case GSM48_MT_RR_IMM_ASS_REJ:
+ rx_imm_ass_rej(msg);
+ break;
+ }
+}
+
+/* note: called from IRQ context */
+static void rx_bcch(struct msgb *msg)
+{
+ struct gsm48_system_information_type_header *sih;
+
+ /* store SI */
+ sih = msgb_l3(msg);
+ switch (sih->system_information) {
+ case GSM48_MT_RR_SYSINFO_1:
+ memcpy(si_1, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ case GSM48_MT_RR_SYSINFO_2:
+ memcpy(si_2, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ case GSM48_MT_RR_SYSINFO_2bis:
+ memcpy(si_2bis, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ case GSM48_MT_RR_SYSINFO_2ter:
+ memcpy(si_2ter, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ case GSM48_MT_RR_SYSINFO_3:
+ memcpy(si_3, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ case GSM48_MT_RR_SYSINFO_4:
+ memcpy(si_4, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ }
+ si_new = sih->system_information | 0x100;
+}
+
+/* note: called from IRQ context */
+static void l1a_l23_tx(struct msgb *msg)
+{
+ struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->l1h;
+ struct l1ctl_pm_conf *pmr;
+ struct l1ctl_info_dl *dl;
+ struct l1ctl_fbsb_conf *sb;
+ uint8_t chan_type, chan_ts, chan_ss;
+ struct l1ctl_neigh_pm_ind *pm_ind;
+ struct gsm_time tm;
+
+ switch (l1h->msg_type) {
+ case L1CTL_PM_CONF:
+ if (pm_mode == PM_SENT) {
+ pmr = (struct l1ctl_pm_conf *) l1h->data;
+ pm_meas[pm_count] = pmr->pm[0];
+ pm_count++;
+ pm_mode = PM_RESULT;
+ }
+ if (pm_mode == PM_RANGE_SENT) {
+ for (pmr = (struct l1ctl_pm_conf *) l1h->data;
+ (uint8_t *) pmr < msg->tail; pmr++) {
+ if (!max || pm_spectrum[ntohs(pmr->band_arfcn) & 1023] < pmr->pm[0])
+ pm_spectrum[ntohs(pmr->band_arfcn) & 1023] = pmr->pm[0];
+ }
+ if ((l1h->flags & L1CTL_F_DONE))
+ pm_mode = PM_RANGE_RESULT;
+ }
+ l1s.tpu_offset_correction += 5000 / NUM_PM_UL;
+ break;
+ case L1CTL_FBSB_CONF:
+ dl = (struct l1ctl_info_dl *) l1h->data;
+ sb = (struct l1ctl_fbsb_conf *) dl->payload;
+ if (sb->result == 0)
+ sync_result = "ok";
+ else
+ sync_result = "error";
+ bsic = sb->bsic;
+ break;
+ case L1CTL_DATA_IND:
+ dl = (struct l1ctl_info_dl *) l1h->data;
+ msg->l2h = dl->payload;
+ rsl_dec_chan_nr(dl->chan_nr, &chan_type, &chan_ss, &chan_ts);
+
+ power = dl->rx_level;
+ if (dl->fire_crc >= 2) {
+ if (chan_type == RSL_CHAN_BCCH)
+ si_new = 0x1ff; /* error frame indication */
+ break; /* free, but don't send to sercom */
+ }
+
+ switch (chan_type) {
+ case RSL_CHAN_BCCH:
+ msg->l3h = msg->l2h;
+ rx_bcch(msg);
+ break;
+ case RSL_CHAN_PCH_AGCH:
+ msg->l3h = msg->l2h;
+ rx_pch_agch(msg);
+ break;
+ }
+ sercomm_sendmsg(SC_DLCI_L1A_L23, msg);
+ return; /* msg is freed by sercom */
+ case L1CTL_NEIGH_PM_IND:
+ for (pm_ind = (struct l1ctl_neigh_pm_ind *) l1h->data;
+ (uint8_t *) pm_ind < msg->tail; pm_ind++) {
+ ul_levels[pm_ind->tn] = pm_ind->pm[0];
+ /* hold max only, if max enabled and level is lower */
+ if (!max || ul_levels[pm_ind->tn] > ul_max[pm_ind->tn])
+ ul_max[pm_ind->tn] = ul_levels[pm_ind->tn];
+ if (pm_ind->tn == 7)
+ ul_new = 1;
+ }
+ break;
+ case L1CTL_RACH_CONF:
+ dl = (struct l1ctl_info_dl *) l1h->data;
+ gsm_fn2gsmtime(&tm, ntohl(dl->frame_nr));
+ rach_ref.t1 = tm.t1;
+ rach_ref.t2 = tm.t2;
+ rach_ref.t3_low = tm.t3 & 0x7;
+ rach_ref.t3_high = tm.t3 >> 3;
+ break;
+ }
+
+ msgb_free(msg);
+
+}
+
+static void console_rx_cb(uint8_t dlci, struct msgb *msg)
+{
+ if (dlci != SC_DLCI_CONSOLE) {
+ printf("Message for unknown DLCI %u\n", dlci);
+ return;
+ }
+
+ printf("Message on console DLCI: '%s'\n", msg->data);
+ msgb_free(msg);
+}
+
+static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
+{
+ int i;
+ printf("l1a_l23_rx_cb (DLCI %d): ", dlci);
+ for (i = 0; i < msg->len; i++)
+ printf("%02x ", msg->data[i]);
+ puts("\n");
+}
+
+static void key_handler(enum key_codes code, enum key_states state)
+{
+ if (state != PRESSED) {
+ key_pressed = 0;
+ return;
+ }
+ /* key repeat */
+ if (!key_pressed) {
+ key_pressed = 1;
+ key_pressed_when = jiffies;
+ key_pressed_code = code;
+ key_pressed_delay = HZ * 6 / 10;
+ }
+
+ key_code = code;
+}
+
+int main(void)
+{
+ board_init();
+
+ puts("\n\nOSMOCOM Monitor Tool (revision " GIT_REVISION ")\n");
+ puts(hr);
+
+ /* Dump device identification */
+ dump_dev_id();
+ puts(hr);
+
+ /* Dump clock config before PLL set */
+ calypso_clk_dump();
+ puts(hr);
+
+ keypad_set_handler(&key_handler);
+
+ /* Dump clock config after PLL set */
+ calypso_clk_dump();
+ puts(hr);
+
+ sercomm_register_rx_cb(SC_DLCI_CONSOLE, console_rx_cb);
+ sercomm_register_rx_cb(SC_DLCI_L1A_L23, l1a_l23_rx_cb);
+
+ layer1_init();
+ l1a_l23_tx_cb = l1a_l23_tx;
+
+// display_unset_attr(DISP_ATTR_INVERT);
+
+ tpu_frame_irq_en(1, 1);
+
+ buzzer_mode_pwt(1);
+ buzzer_volume(0);
+
+ memset(pm_spectrum, 0, sizeof(pm_spectrum));
+ memset(ul_max, 0, sizeof(ul_max));
+
+ /* inc 0 to 1 and refresh */
+ inc_dec_arfcn(1);
+
+ while (1) {
+ l1a_compl_execute();
+ osmo_timers_update();
+ handle_key_code();
+ l1a_l23_handler();
+ handle_pm();
+ handle_sync();
+ handle_assign();
+ handle_tone();
+ }
+
+ /* NOT REACHED */
+
+ twl3025_power_off();
+}
+
diff --git a/Src/osmolib/src/target/firmware/apps/simtest/main.c b/Src/osmolib/src/target/firmware/apps/simtest/main.c
index 83f708e..3272b57 100644..100755
--- a/Src/osmolib/src/target/firmware/apps/simtest/main.c
+++ b/Src/osmolib/src/target/firmware/apps/simtest/main.c
@@ -31,7 +31,6 @@
#include <keypad.h>
#include <board.h>
#include <abb/twl3025.h>
-#include <display.h>
#include <rf/trf6151.h>
#include <calypso/clock.h>
#include <calypso/tpu.h>
@@ -52,14 +51,14 @@ static void myHexdump(uint8_t *data, int len)
int i;
for(i=0;i<len;i++)
- printf("%x ",data[i]);
+ printf("%02x ",data[i]);
printf("(%i bytes)\n", len);
return;
}
-/* SIM instructions
+/* SIM instructions
All instructions a standard sim card must feature: */
#define SIM_CLASS 0xA0 /* Class that contains the following instructions */
#define SIM_SELECT 0xA4 /* Select a file on the card */
@@ -135,7 +134,7 @@ uint16_t sim_select(uint16_t fid)
}
/* Get the status of the currently selected file */
-uint16_t sim_status(void)
+uint16_t sim_status(void)
{
uint8_t status_word[2];
@@ -158,6 +157,55 @@ uint16_t sim_readbinary(uint8_t offset_high, uint8_t offset_low, uint8_t length,
return (status_word[0] << 8) | status_word[1];
}
+uint16_t sim_verify(char *pin)
+{
+ uint8_t txBuffer[8];
+ uint8_t status_word[2];
+
+ memset(txBuffer, 0xFF, 8);
+ memcpy(txBuffer, pin, strlen(pin));
+
+ if(calypso_sim_transceive(SIM_CLASS, SIM_VERIFY_CHV, 0x00, 0x01, 0x08, txBuffer,status_word, SIM_APDU_PUT) != 0)
+ return 0xFFFF;
+
+ return (status_word[0] << 8) | status_word[1];
+}
+
+uint16_t sim_run_gsm_algorith(uint8_t *data)
+{
+ uint8_t status_word[2];
+
+ if(calypso_sim_transceive(SIM_CLASS, SIM_RUN_GSM_ALGORITHM, 0x00, 0x00, 0x10, data, status_word, SIM_APDU_PUT) != 0)
+ return 0xFFFF;
+
+ printf(" ==> Status word: %x\n", (status_word[0] << 8) | status_word[1]);
+
+ if(status_word[0] != 0x9F || status_word[1] != 0x0C)
+ return (status_word[0] << 8) | status_word[1];
+
+ /* GET RESPONSE */
+
+ if(calypso_sim_transceive(SIM_CLASS, SIM_GET_RESPONSE, 0, 0, 0x0C, data ,status_word, SIM_APDU_GET) != 0)
+ return 0xFFFF;
+
+ return (status_word[0] << 8) | status_word[1];
+}
+
+
+/* FIXME: We need proper calibrated delay loops at some point! */
+void delay_us(unsigned int us)
+{
+ volatile unsigned int i;
+
+ for (i= 0; i < us*4; i++) { i; }
+}
+
+void delay_ms(unsigned int ms)
+{
+ volatile unsigned int i;
+ for (i= 0; i < ms*1300; i++) { i; }
+}
+
/* Execute my (dexter's) personal test */
void do_sim_test(void)
{
@@ -171,7 +219,7 @@ void do_sim_test(void)
uint8_t atr[20];
uint8_t atrLength = 0;
-
+
memset(atr,0,sizeof(atr));
@@ -185,7 +233,7 @@ void do_sim_test(void)
/* Initialize Sim-Controller driver */
puts("Initializing driver:\n");
- calypso_sim_init();
+ calypso_sim_init(NULL);
/* Power up sim and display ATR */
puts("Power up simcard:\n");
@@ -215,6 +263,9 @@ void do_sim_test(void)
puts(" * Testing SELECT: Selecting DF_GSM\n");
printf(" ==> Status word: %x\n", sim_select(SIM_DF_GSM));
+ puts(" * Testing PIN VERIFY\n");
+ printf(" ==> Status word: %x\n", sim_verify("1234"));
+
puts(" * Testing SELECT: Selecting EF_IMSI\n");
printf(" ==> Status word: %x\n", sim_select(SIM_EF_IMSI));
@@ -222,11 +273,18 @@ void do_sim_test(void)
printf(" ==> Status word: %x\n", sim_status());
memset(buffer,0,sizeof(buffer));
- puts(" * Testing READ BINARY:\n");
+ puts(" * Testing READ BINARY:\n");
printf(" ==> Status word: %x\n", sim_readbinary(0,0,9,buffer));
printf(" Data: ");
myHexdump(buffer,9);
+ memset(buffer,0,sizeof(buffer));
+ memcpy(buffer,"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff",16);
+ puts(" * Testing RUN GSM ALGORITHM\n");
+ printf(" ==> Status word: %x\n", sim_run_gsm_algorith(buffer));
+ printf(" Result: ");
+ myHexdump(buffer,12);
+
delay_ms(5000);
calypso_sim_powerdown();
@@ -279,9 +337,6 @@ int main(void)
puts(hr);
#endif
- display_set_attr(DISP_ATTR_INVERT);
- display_puts("SIM-TEST");
-
sercomm_register_rx_cb(SC_DLCI_CONSOLE, console_rx_cb);
do_sim_test();
diff --git a/Src/osmolib/src/target/firmware/board/compal/highram.lds b/Src/osmolib/src/target/firmware/board/compal/highram.lds
index 1f0a5a6..498a2fa 100644
--- a/Src/osmolib/src/target/firmware/board/compal/highram.lds
+++ b/Src/osmolib/src/target/firmware/board/compal/highram.lds
@@ -16,9 +16,9 @@ MEMORY
/* lowram: could be anything, we place exception vectors here */
XRAM (rw) : ORIGIN = 0x00800000, LENGTH = 0x00020000
/* highram binary: our text, initialized data */
- LRAM (rw) : ORIGIN = 0x00820000, LENGTH = 0x00010000
+ LRAM (rw) : ORIGIN = 0x00820000, LENGTH = 0x00014000
/* highram binary: our unitialized data, stacks, heap */
- IRAM (rw) : ORIGIN = 0x00830000, LENGTH = 0x00010000
+ IRAM (rw) : ORIGIN = 0x00834000, LENGTH = 0x0000c000
}
SECTIONS
{
diff --git a/Src/osmolib/src/target/firmware/board/compal/ram.lds b/Src/osmolib/src/target/firmware/board/compal/ram.lds
index 342870d..9503ede 100644
--- a/Src/osmolib/src/target/firmware/board/compal/ram.lds
+++ b/Src/osmolib/src/target/firmware/board/compal/ram.lds
@@ -11,9 +11,9 @@ ENTRY(_start)
MEMORY
{
/* compal-loaded binary: our text, initialized data */
- LRAM (rw) : ORIGIN = 0x00800000, LENGTH = 0x00010000
+ LRAM (rw) : ORIGIN = 0x00800000, LENGTH = 0x00014000
/* compal-loaded binary: our unitialized data, stacks, heap */
- IRAM (rw) : ORIGIN = 0x00810000, LENGTH = 0x00010000
+ IRAM (rw) : ORIGIN = 0x00814000, LENGTH = 0x0000c000
}
SECTIONS
{
diff --git a/Src/osmolib/src/target/firmware/board/compal_e86/init.c b/Src/osmolib/src/target/firmware/board/compal_e86/init.c
index 1de6193..2d463cb 100644
--- a/Src/osmolib/src/target/firmware/board/compal_e86/init.c
+++ b/Src/osmolib/src/target/firmware/board/compal_e86/init.c
@@ -41,10 +41,12 @@
#include <calypso/backlight.h>
#include <comm/sercomm.h>
+#include <comm/timer.h>
#include <abb/twl3025.h>
#include <rf/trf6151.h>
-#include <display.h>
+
+#include <fb/framebuffer.h>
#define ARMIO_LATCH_OUT 0xfffe4802
#define IO_CNTL_REG 0xfffe4804
@@ -127,8 +129,7 @@ void board_init(void)
timer_init();
/* Initialize LCD driver (uses UWire) */
- display = &td014_display;
- display_init();
+ fb_init();
bl_mode_pwl(1);
bl_level(0);
diff --git a/Src/osmolib/src/target/firmware/board/compal_e88/init.c b/Src/osmolib/src/target/firmware/board/compal_e88/init.c
index a5bf880..fe3fd72 100644
--- a/Src/osmolib/src/target/firmware/board/compal_e88/init.c
+++ b/Src/osmolib/src/target/firmware/board/compal_e88/init.c
@@ -44,7 +44,7 @@
#include <abb/twl3025.h>
#include <rf/trf6151.h>
-#include <display.h>
+#include <fb/framebuffer.h>
#define ARMIO_LATCH_OUT 0xfffe4802
#define IO_CNTL_REG 0xfffe4804
@@ -123,8 +123,8 @@ void board_init(void)
timer_init();
/* Initialize LCD driver (uses I2C) and backlight */
- display = &st7558_display;
- display_init();
+ fb_init();
+
bl_mode_pwl(1);
bl_level(50);
diff --git a/Src/osmolib/src/target/firmware/board/compal_e99/init.c b/Src/osmolib/src/target/firmware/board/compal_e99/init.c
index 0c218a8..31eb978 100644
--- a/Src/osmolib/src/target/firmware/board/compal_e99/init.c
+++ b/Src/osmolib/src/target/firmware/board/compal_e99/init.c
@@ -41,10 +41,12 @@
#include <calypso/backlight.h>
#include <comm/sercomm.h>
+#include <comm/timer.h>
#include <abb/twl3025.h>
#include <rf/trf6151.h>
-#include <display.h>
+
+#include <fb/framebuffer.h>
#define ARMIO_LATCH_OUT 0xfffe4802
#define IO_CNTL_REG 0xfffe4804
@@ -127,11 +129,11 @@ void board_init(void)
timer_init();
/* Initialize LCD driver (uses UWire) and backlight */
- display = &ssd1783_display;
- display_init();
bl_mode_pwl(1);
bl_level(50);
+ fb_init();
+
/* Initialize keypad driver */
keypad_init(1);
diff --git a/Src/osmolib/src/target/firmware/board/gta0x/init.c b/Src/osmolib/src/target/firmware/board/gta0x/init.c
index 4f256ea..d125e15 100644
--- a/Src/osmolib/src/target/firmware/board/gta0x/init.c
+++ b/Src/osmolib/src/target/firmware/board/gta0x/init.c
@@ -44,7 +44,6 @@
#include <abb/twl3025.h>
#include <rf/trf6151.h>
-#include <display.h>
#define ARMIO_LATCH_OUT 0xfffe4802
#define IO_CNTL_REG 0xfffe4804
@@ -123,8 +122,6 @@ void board_init(void)
timer_init();
/* Initialize LCD driver (uses I2C) and backlight */
- display = &st7558_display;
- display_init();
bl_mode_pwl(1);
bl_level(50);
diff --git a/Src/osmolib/src/target/firmware/board/pirelli_dpl10/init.c b/Src/osmolib/src/target/firmware/board/pirelli_dpl10/init.c
index 53fb257..ef18403 100644
--- a/Src/osmolib/src/target/firmware/board/pirelli_dpl10/init.c
+++ b/Src/osmolib/src/target/firmware/board/pirelli_dpl10/init.c
@@ -1,7 +1,7 @@
/* Initialization for the Pirelli DP-L10 */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2011 by Steve Markgraf <steve@steve-m.de>
+ * (C) 2011-12 by Steve Markgraf <steve@steve-m.de>
*
* All Rights Reserved
*
@@ -45,10 +45,13 @@
#include <abb/twl3025.h>
#include <rf/trf6151.h>
-#include <display.h>
+
+#include <fb/framebuffer.h>
#define ARMIO_LATCH_OUT 0xfffe4802
+#define IO_CNTL_REG 0xfffe4804
#define ASIC_CONF_REG 0xfffef008
+#define IO_CONF_REG 0xfffef00a
static void board_io_init(void)
{
@@ -59,17 +62,36 @@ static void board_io_init(void)
reg |= ((1 << 12) | (1 << 7)); /* SCL / SDA */
/* TWL3025: Set SPI+RIF RX clock to rising edge */
reg |= (1 << 13) | (1 << 14);
+ reg &= ~(1 << 1);
writew(reg, ASIC_CONF_REG);
+
+ /* enable IO functionality */
+ reg = readw(IO_CONF_REG);
+ reg |= (1 << 9) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
+ writew(reg, IO_CONF_REG);
+
+ /* set IO directions */
+ reg = readw(IO_CNTL_REG);
+ reg &= ~((1 << 7) | (1 << 4) | (1 << 1));
+ writew(reg, IO_CNTL_REG);
+
+ /* reset display controller, disable bypass mode, set nCS4 to display */
+ reg = readw(ARMIO_LATCH_OUT);
+ reg &= ~(1 << 4);
+ writew(reg, ARMIO_LATCH_OUT);
+ reg &= ~(1 << 7);
+ reg |= (1 << 4) | (1 << 1);
+ writew(reg, ARMIO_LATCH_OUT);
}
void board_init(void)
{
/* Configure the memory interface */
- calypso_mem_cfg(CALYPSO_nCS0, 3, CALYPSO_MEM_16bit, 1);
- calypso_mem_cfg(CALYPSO_nCS1, 3, CALYPSO_MEM_16bit, 1);
+ calypso_mem_cfg(CALYPSO_nCS0, 4, CALYPSO_MEM_16bit, 1);
+ calypso_mem_cfg(CALYPSO_nCS1, 4, CALYPSO_MEM_16bit, 1);
calypso_mem_cfg(CALYPSO_nCS2, 5, CALYPSO_MEM_16bit, 1);
- calypso_mem_cfg(CALYPSO_nCS3, 5, CALYPSO_MEM_16bit, 1);
- calypso_mem_cfg(CALYPSO_CS4, 0, CALYPSO_MEM_8bit, 1);
+ calypso_mem_cfg(CALYPSO_nCS3, 4, CALYPSO_MEM_16bit, 1);
+ calypso_mem_cfg(CALYPSO_CS4, 7, CALYPSO_MEM_16bit, 1);
calypso_mem_cfg(CALYPSO_nCS6, 0, CALYPSO_MEM_32bit, 1);
calypso_mem_cfg(CALYPSO_nCS7, 0, CALYPSO_MEM_32bit, 0);
@@ -110,11 +132,11 @@ void board_init(void)
/* Initialize system timers (uses hwtimer 2) */
timer_init();
- /* Initialize LCD driver (uses I2C) and backlight */
- display = &st7558_display;
- display_init();
+ /* Initialize LCD driver and backlight (0 is max, 255 min brightness) */
bl_mode_pwl(1);
- bl_level(0);
+ bl_level(50);
+
+ fb_init();
/* Initialize keypad driver */
keypad_init(1);
diff --git a/Src/osmolib/src/target/firmware/board/se_j100/init.c b/Src/osmolib/src/target/firmware/board/se_j100/init.c
index 30c3e6b..2a3de0e 100644
--- a/Src/osmolib/src/target/firmware/board/se_j100/init.c
+++ b/Src/osmolib/src/target/firmware/board/se_j100/init.c
@@ -41,10 +41,12 @@
#include <calypso/backlight.h>
#include <comm/sercomm.h>
+#include <comm/timer.h>
#include <abb/twl3025.h>
#include <rf/trf6151.h>
-#include <display.h>
+
+#include <fb/framebuffer.h>
#define ARMIO_LATCH_OUT 0xfffe4802
#define IO_CNTL_REG 0xfffe4804
@@ -127,8 +129,7 @@ void board_init(void)
timer_init();
/* Initialize LCD driver (uses UWire) and backlight */
- display = &ssd1963_display;
- display_init();
+ fb_init();
bl_mode_pwl(1);
bl_level(50);
diff --git a/Src/osmolib/src/target/firmware/calypso/backlight.c b/Src/osmolib/src/target/firmware/calypso/backlight.c
index a18dcb9..cf29984 100644
--- a/Src/osmolib/src/target/firmware/calypso/backlight.c
+++ b/Src/osmolib/src/target/firmware/calypso/backlight.c
@@ -50,7 +50,7 @@ void bl_mode_pwl(int on)
writew(reg, ASIC_CONF_REG);
} else {
/* Switch pin from PWL to LT */
- reg |= ~ASCONF_PWL_ENA;
+ reg &= ~ASCONF_PWL_ENA;
writew(reg, ASIC_CONF_REG);
/* Disable pwl */
writeb(0x00, PWL_REG(PWL_CTRL));
diff --git a/Src/osmolib/src/target/firmware/calypso/i2c.c b/Src/osmolib/src/target/firmware/calypso/i2c.c
index 344424d..bf44178 100644
--- a/Src/osmolib/src/target/firmware/calypso/i2c.c
+++ b/Src/osmolib/src/target/firmware/calypso/i2c.c
@@ -67,9 +67,9 @@ int i2c_write(uint8_t chip, uint32_t addr, int alen, const uint8_t *buffer, int
if (len > 16)
return -1;
- printd("i2c_write(chip=0x%02u, addr=0x%02u): ", chip, addr)
+ printd("i2c_write(chip=0x%02u, addr=0x%02u): ", chip, addr);
- writeb(chip & 0x3f, I2C_REG(DEVICE_REG));
+ writeb(chip & 0x7f, I2C_REG(DEVICE_REG));
writeb(addr & 0xff, I2C_REG(ADDRESS_REG));
/* we have to tell the controller how many bits we'll put into the fifo ?!? */
@@ -91,7 +91,7 @@ int i2c_write(uint8_t chip, uint32_t addr, int alen, const uint8_t *buffer, int
/* wait until transfer completes */
while (1) {
uint8_t reg = readb(I2C_REG(STATUS_ACTIVITY_REG));
- printd("I2C Status: 0x%02x\n", rerg & 0xf);
+ printd("I2C Status: 0x%02x\n", reg & 0xf);
if (!(reg & I2C_STATUS_IDLE)) // 0: idle 1: not idle
break;
}
diff --git a/Src/osmolib/src/target/firmware/calypso/keypad.c b/Src/osmolib/src/target/firmware/calypso/keypad.c
index fd4e0ff..f2dea9d 100644
--- a/Src/osmolib/src/target/firmware/calypso/keypad.c
+++ b/Src/osmolib/src/target/firmware/calypso/keypad.c
@@ -31,6 +31,7 @@
#include <calypso/irq.h>
#include <abb/twl3025.h>
+#include <comm/timer.h>
#define KBR_LATCH_REG 0xfffe480a
@@ -44,16 +45,13 @@ void emit_key(uint8_t key, uint8_t state)
{
printf("key=%u %s\n", key, state == PRESSED ? "pressed" : "released");
- if (state == RELEASED)
- if (key == KEY_POWER)
- twl3025_power_off();
-
if(key_handler) {
key_handler(key, state);
}
}
volatile uint32_t lastbuttons = 0;
+unsigned long power_hold = 0;
#define BTN_TO_KEY(name) \
((diff & BTN_##name) == BTN_##name) \
@@ -67,6 +65,17 @@ void dispatch_buttons(uint32_t buttons)
{
uint8_t state;
+ if ((buttons & BTN_POWER)) {
+ /* hold button 500ms to shut down */
+ if ((lastbuttons & BTN_POWER)) {
+ unsigned long elapsed = jiffies - power_hold;
+ if (elapsed > 50)
+ twl3025_power_off();
+ power_hold++;
+ } else
+ power_hold = jiffies;
+ }
+
if (buttons == lastbuttons)
return;
diff --git a/Src/osmolib/src/target/firmware/calypso/rtc.c b/Src/osmolib/src/target/firmware/calypso/rtc.c
index ce750c2..45d759f 100644
--- a/Src/osmolib/src/target/firmware/calypso/rtc.c
+++ b/Src/osmolib/src/target/firmware/calypso/rtc.c
@@ -26,7 +26,6 @@
#include <defines.h>
#include <debug.h>
#include <memory.h>
-#include <display.h>
#include <calypso/irq.h>
#define BASE_ADDR_RTC 0xfffe1800
@@ -61,10 +60,6 @@ static int tick_ctr;
static void rtc_irq_tick(__unused enum irq_nr nr)
{
- if (tick_ctr & 1)
- display_set_attr(DISP_ATTR_INVERT);
- else
- display_unset_attr(DISP_ATTR_INVERT);
tick_ctr++;
}
diff --git a/Src/osmolib/src/target/firmware/calypso/sim.c b/Src/osmolib/src/target/firmware/calypso/sim.c
index a539cf8..752628f 100644
--- a/Src/osmolib/src/target/firmware/calypso/sim.c
+++ b/Src/osmolib/src/target/firmware/calypso/sim.c
@@ -1,6 +1,7 @@
/* Driver for Simcard Controller inside TI Calypso/Iota */
/* (C) 2010 by Philipp Fabian Benedikt Maier <philipp-maier@runningserver.com>
+ * (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
*
* All Rights Reserved
*
@@ -20,34 +21,76 @@
*
*/
+/* Uncomment to debug sim */
+/* #define DEBUG */
+
#include <stdint.h>
#include <stdio.h>
#include <debug.h>
#include <memory.h>
+#include <string.h>
+#include <delay.h>
+#include <osmocom/core/msgb.h>
+#include <layer1/l23_api.h>
#include <abb/twl3025.h>
#include <calypso/sim.h>
#include <calypso/irq.h>
-static int sim_rx_character_count = 0; /* How many bytes have been received by calypso_sim_receive() */
-static int sim_tx_character_count = 0; /* How many bytes have been transmitted by calypso_sim_transmit() */
-static int sim_tx_character_length = 0; /* How many bytes have to be transmitted by calypso_sim_transmit() */
-static uint8_t *rx_buffer = 0; /* RX-Buffer that is issued by calypso_sim_receive() */
-static uint8_t *tx_buffer = 0; /* TX-Buffer that is issued by calypso_sim_transmit() */
-volatile static int rxDoneFlag = 0; /* Used for rx synchronization instead of a semaphore in calypso_sim_receive() */
-volatile static int txDoneFlag = 0; /* Used for rx synchronization instead of a semaphore in calypso_sim_transmit() */
+#include <l1ctl_proto.h>
+
+#define SIM_CLASS 0xA0
+ /* Class that contains the following instructions */
+#define SIM_GET_RESPONSE 0xC0
+ /* Get the response of a command from the card */
+#define SIM_READ_BINARY 0xB0 /* Read file in binary mode */
+#define SIM_READ_RECORD 0xB2 /* Read record in binary mode */
+
+enum {
+ SIM_STATE_IDLE,
+ SIM_STATE_TX_HEADER,
+ SIM_STATE_RX_STATUS,
+ SIM_STATE_RX_ACK,
+ SIM_STATE_RX_ACK_DATA,
+ SIM_STATE_TX_DATA,
+};
+
+#define L3_MSG_HEAD 4
+
+static uint8_t sim_data[256]; /* buffer for SIM command */
+static volatile uint16_t sim_len = 0; /* lenght of data in sim_data[] */
+static volatile uint8_t sim_state = SIM_STATE_IDLE;
+ /* current state of SIM process */
+static volatile uint8_t sim_ignore_waiting_char = 0;
+ /* signal ignoring of NULL procedure byte */
+static volatile int sim_rx_character_count = 0;
+ /* How many bytes have been received by calypso_sim_receive() */
+static volatile int sim_rx_max_character_count = 0;
+ /* How many bytes have been received by calypso_sim_receive() */
+static volatile int sim_tx_character_count = 0;
+ /* How many bytes have been transmitted by calypso_sim_transmit() */
+static volatile int sim_tx_character_length = 0;
+ /* How many bytes have to be transmitted by calypso_sim_transmit() */
+static uint8_t *rx_buffer = 0;
+ /* RX-Buffer that is issued by calypso_sim_receive() */
+static uint8_t *tx_buffer = 0;
+ /* TX-Buffer that is issued by calypso_sim_transmit() */
+static volatile int rxDoneFlag = 0;
+ /* Used for rx synchronization instead of a semaphore in calypso_sim_receive() */
+static volatile int txDoneFlag = 0;
+ /* Used for rx synchronization instead of a semaphore in calypso_sim_transmit() */
/* Display Register dump */
void calypso_sim_regdump(void)
{
-#if (SIM_DEBUG == 1)
+#ifdef DEBUG
unsigned int regVal;
+#define SIM_DEBUG_OUTPUTDELAY 200
- puts("\n\n\n");
- puts("====================== CALYPSO SIM REGISTER DUMP =====================\n");
- puts("Reg_sim_cmd register (R/W) - FFFE:0000\n");
-
+ puts("\n\n\n");
+ puts("====================== CALYPSO SIM REGISTER DUMP =====================\n");
+ puts("Reg_sim_cmd register (R/W) - FFFE:0000\n");
regVal = readw(REG_SIM_CMD);
printf(" |-REG_SIM_CMD = %04x\n", readw(REG_SIM_CMD));
@@ -149,25 +192,25 @@ void calypso_sim_regdump(void)
else
puts(" | |-REG_SIM_CONF1_CONFSCLKDIV = 0 ==> SIM clock frequency is 13/4 Mhz.\n");
delay_ms(SIM_DEBUG_OUTPUTDELAY);
-
+
if(regVal & REG_SIM_CONF1_CONFSCLKLEV)
puts(" | |-REG_SIM_CONF1_CONFSCLKLEV = 1 ==> SIM clock idle level is high.\n");
else
puts(" | |-REG_SIM_CONF1_CONFSCLKLEV = 0 ==> SIM clock idle level is low.\n");
delay_ms(SIM_DEBUG_OUTPUTDELAY);
-
+
if(regVal & REG_SIM_CONF1_CONFETUPERIOD)
puts(" | |-REG_SIM_CONF1_CONFETUPERIOD = 1 ==> ETU period is 512/8*1/Fsclk.\n");
else
puts(" | |-REG_SIM_CONF1_CONFETUPERIOD = 0 ==> ETU period is 372/8*1/Fsclk.\n");
delay_ms(SIM_DEBUG_OUTPUTDELAY);
-
+
if(regVal & REG_SIM_CONF1_CONFBYPASS)
puts(" | |-REG_SIM_CONF1_CONFBYPASS = 1 ==> Hardware timers and start and stop sequences are bypassed.\n");
else
puts(" | |-REG_SIM_CONF1_CONFBYPASS = 0 ==> Hardware timers and start and stop sequences are normal.\n");
delay_ms(SIM_DEBUG_OUTPUTDELAY);
-
+
if(regVal & REG_SIM_CONF1_CONFSVCCLEV)
puts(" | |-REG_SIM_CONF1_CONFSVCCLEV = 1 ==> SVCC Level is high (Only valid when CONFBYPASS = 1).\n");
else
@@ -301,122 +344,32 @@ void calypso_sim_regdump(void)
return;
}
-/* Apply power to the simcard (use nullpointer to ignore atr) */
-int calypso_sim_powerup(uint8_t *atr)
-{
- /* Enable level shifters and voltage regulator */
- twl3025_reg_write(VRPCSIM, VRPCSIM_SIMLEN | VRPCSIM_RSIMEN | VRPCSIM_SIMSEL);
-#if (SIM_DEBUG == 1)
- puts(" * Power enabled!\n");
-#endif
- delay_ms(SIM_OPERATION_DELAY);
-
- /* Enable clock */
- writew(REG_SIM_CMD_MODULE_CLK_EN | REG_SIM_CMD_CMDSTART, REG_SIM_CMD);
-#if (SIM_DEBUG == 1)
- puts(" * Clock enabled!\n");
-#endif
- delay_ms(SIM_OPERATION_DELAY);
-
- /* Release reset */
- writew(readw(REG_SIM_CONF1) | REG_SIM_CONF1_CONFBYPASS | REG_SIM_CONF1_CONFSRSTLEV | REG_SIM_CONF1_CONFSVCCLEV, REG_SIM_CONF1);
-#if (SIM_DEBUG == 1)
- puts(" * Reset released!\n");
-#endif
-
- /* Catch ATR */
- if(atr != 0)
- return calypso_sim_receive(atr);
- else
- return 0;
-}
-
-
-/* Powerdown simcard */
-void calypso_sim_powerdown(void)
-{
- writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFBYPASS, REG_SIM_CONF1);
-#if (SIM_DEBUG == 1)
- puts(" * Reset pulled down!\n");
-#endif
- delay_ms(SIM_OPERATION_DELAY);
-
- writew(REG_SIM_CMD_MODULE_CLK_EN | REG_SIM_CMD_CMDSTOP, REG_SIM_CMD);
-#if (SIM_DEBUG == 1)
- puts(" * Clock disabled!\n");
-#endif
- delay_ms(SIM_OPERATION_DELAY);
-
- writew(0, REG_SIM_CMD);
-#if (SIM_DEBUG == 1)
- puts(" * Module disabled!\n");
-#endif
- delay_ms(SIM_OPERATION_DELAY);
-
- /* Disable level shifters and voltage regulator */
- twl3025_reg_write(VRPCSIM, 0);
-#if (SIM_DEBUG == 1)
- puts(" * Power disabled!\n");
-#endif
- delay_ms(SIM_OPERATION_DELAY);
-
- return;
-}
-
-/* reset the simcard (see note 1) */
-int calypso_sim_reset(uint8_t *atr)
-{
-
- /* Pull reset down */
- writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFSRSTLEV , REG_SIM_CONF1);
-#if (SIM_DEBUG == 1)
- puts(" * Reset pulled down!\n");
-#endif
-
- delay_ms(SIM_OPERATION_DELAY);
-
- /* Pull reset down */
- writew(readw(REG_SIM_CONF1) | REG_SIM_CONF1_CONFSRSTLEV , REG_SIM_CONF1);
-#if (SIM_DEBUG == 1)
- puts(" * Reset released!\n");
-#endif
-
- /* Catch ATR */
- if(atr != 0)
- return calypso_sim_receive(atr);
- else
- return 0;
-}
-
/* Receive raw data through the sim interface */
-int calypso_sim_receive(uint8_t *data)
+int calypso_sim_receive(uint8_t *data, uint8_t len)
{
+ printd("Triggering SIM reception\n");
+
/* Prepare buffers and flags */
rx_buffer = data;
sim_rx_character_count = 0;
rxDoneFlag = 0;
+ sim_rx_max_character_count = len;
/* Switch I/O direction to input */
writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFTXRX, REG_SIM_CONF1);
/* Unmask the interrupts that are needed to perform this action */
- writew(~(REG_SIM_MASKIT_MASK_SIM_RX | REG_SIM_MASKIT_MASK_SIM_WT), REG_SIM_MASKIT);
-
- /* Wait till rxDoneFlag is set */
- while(rxDoneFlag == 0);
+ writew(~(REG_SIM_MASKIT_MASK_SIM_RX | REG_SIM_MASKIT_MASK_SIM_WT),
+ REG_SIM_MASKIT);
- /* Disable all interrupt driven functions by masking all interrupts */
- writew(0xFF, REG_SIM_MASKIT);
-
- /* Hand back the number of bytes received */
- return sim_rx_character_count;
-
- return;
+ return 0;
}
/* Transmit raw data through the sim interface */
int calypso_sim_transmit(uint8_t *data, int length)
{
+ printd("Triggering SIM transmission\n");
+
/* Prepare buffers and flags */
tx_buffer = data;
sim_tx_character_count = 0;
@@ -434,12 +387,6 @@ int calypso_sim_transmit(uint8_t *data, int length)
tx_buffer++;
sim_tx_character_count++;
- /* Wait till rxDoneFlag is set */
- while(txDoneFlag == 0);
-
- /* Disable all interrupt driven functions by masking all interrupts */
- writew(0xFF, REG_SIM_MASKIT);
-
return 0;
}
@@ -451,290 +398,344 @@ void sim_irq_handler(enum irq_nr irq)
/* Display interrupt information */
-#if (SIM_DEBUG == 1)
- puts("SIM-ISR: Interrupt caught: ");
-#endif
- if(regVal & REG_SIM_IT_SIM_NATR)
- {
-#if (SIM_DEBUG == 1)
- puts(" No answer to reset!\n");
-#endif
+ printd("SIM-ISR: ");
+
+ if(regVal & REG_SIM_IT_SIM_NATR) {
+ printd(" No answer to reset!\n");
}
- /* Used by: calypso_sim_receive() to determine when the transmission is over */
- if(regVal & REG_SIM_IT_SIM_WT)
- {
-#if (SIM_DEBUG == 1)
- puts(" Character underflow!\n");
-#endif
+ /* Used by: calypso_sim_receive() to determine when the transmission
+ * is over
+ */
+ if(regVal & REG_SIM_IT_SIM_WT) {
+ printd(" Character underflow!\n");
rxDoneFlag = 1;
+
}
- if(regVal & REG_SIM_IT_SIM_OV)
- {
-#if (SIM_DEBUG == 1)
- puts(" Receive overflow!\n");
-#endif
+ if(regVal & REG_SIM_IT_SIM_OV) {
+ printd(" Receive overflow!\n");
}
/* Used by: calypso_sim_transmit() to transmit the data */
- if(regVal & REG_SIM_IT_SIM_TX)
- {
-#if (SIM_DEBUG == 1)
- puts(" Waiting for character to transmit...\n");
-#endif
- if(sim_tx_character_count >= sim_tx_character_length)
+ if(regVal & REG_SIM_IT_SIM_TX) {
+ printd(" Waiting for transmit...\n");
+ if(sim_tx_character_count >= sim_tx_character_length) {
txDoneFlag = 1;
- else
- {
+ } else {
writew(*tx_buffer,REG_SIM_DTX);
tx_buffer++;
sim_tx_character_count++;
+
+ /* its essential to immediately switch to RX after TX
+ * is done
+ */
+ if(sim_tx_character_count >= sim_tx_character_length) {
+ /* TODO: set a proper delay here, 4 is to
+ long if not debugging and no delay is too
+ short */
+// delay_ms(1);
+ /* Switch I/O direction to input */
+ writew(readw(REG_SIM_CONF1) &
+ ~REG_SIM_CONF1_CONFTXRX, REG_SIM_CONF1);
+ }
}
}
/* Used by: calypso_sim_receive() to receive the incoming data */
- if(regVal & REG_SIM_IT_SIM_RX)
- {
-#if (SIM_DEBUG == 1)
- puts(" Waiting characters to be read...\n");
-#endif
- /* Increment character count - this is what calypso_sim_receive() hands back */
+ if(regVal & REG_SIM_IT_SIM_RX) {
+ uint8_t ch = (uint8_t) (readw(REG_SIM_DRX) & 0xFF);
+
+ /* ignore NULL procedure byte */
+ if(ch == 0x60 && sim_ignore_waiting_char) {
+ printd(" 0x60 received...\n");
+ return;
+ }
+
+ printd(" Waiting for read (%02X)...\n", ch);
+
+ /* Increment character count - this is what
+ * calypso_sim_receive() hands back
+ */
sim_rx_character_count++;
/* Read byte from rx-fifo and write it to the issued buffer */
- *rx_buffer = (uint8_t) (readw(REG_SIM_DRX) & 0xFF);
+ *rx_buffer = ch;
rx_buffer++;
+
+ /* to maximise SIM access speed, stop waiting after
+ all the expected characters have been received. */
+ if (sim_rx_max_character_count
+ && sim_rx_character_count >= sim_rx_max_character_count) {
+ printd(" Max characters received!\n");
+ rxDoneFlag = 1;
+ }
}
}
-/* Transceive T0 Apdu to sim acording to GSM 11.11 Page 34 */
-int calypso_sim_transceive(uint8_t cla, /* Class (in GSM context mostly 0xA0 */
- uint8_t ins, /* Instruction */
- uint8_t p1, /* First parameter */
- uint8_t p2, /* Second parameter */
- uint8_t p3le, /* Length of the data that should be transceived */
- uint8_t *data, /* Data payload */
- uint8_t *status, /* Status word (2 byte array, see note 1) */
- uint8_t mode) /* Mode of operation: 1=GET, 0=PUT */
-
- /* Note 1: You can use a null-pointer (0) if you are not interested in
- the status word */
+/* simm command from layer 23 */
+void sim_apdu(uint16_t len, uint8_t *data)
{
- uint8_t transmissionBuffer[256];
- uint8_t numberOfReceivedBytes;
-
-#if (SIM_DEBUG == 1)
- printf("SIM-T0: Transceiving APDU-Header: (%02x %02x %02x %02x %02x)\n",cla,ins,p1,p2,p3le);
-#endif
+ if (sim_state != SIM_STATE_IDLE) {
+ puts("Sim reader currently busy...\n");
+ return;
+ }
+ memcpy(sim_data, data, len);
+ sim_len = len;
+}
- /* Transmit APDU header */
- memset(transmissionBuffer,0,sizeof(transmissionBuffer));
- transmissionBuffer[0] = cla;
- transmissionBuffer[1] = ins;
- transmissionBuffer[2] = p1;
- transmissionBuffer[3] = p2;
- transmissionBuffer[4] = p3le;
- calypso_sim_transmit(transmissionBuffer,5);
-
- /* Case 1: No input, No Output */
- if(p3le == 0)
- {
-#if (SIM_DEBUG == 1)
- puts("SIM-T0: Case 1: No input, No Output (See also GSM 11.11 Page 34)\n");
-#endif
- numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
-
- if(numberOfReceivedBytes == 2)
- {
-#if (SIM_DEBUG == 1)
- printf("SIM-T0: Status-word received: %02x %02x\n", transmissionBuffer[0], transmissionBuffer[1]);
-#endif
- /* Hand back status word */
- if(status != 0)
- {
- status[0] = transmissionBuffer[0];
- status[1] = transmissionBuffer[1];
- }
-
- return 0;
- }
+/* handling sim events */
+void sim_handler(void)
+{
+ static struct msgb *msg;
+ struct l1ctl_hdr *l1h;
+ static uint8_t mode;
+ static uint8_t *response;
+ static uint16_t length;
+
+ switch (sim_state) {
+ case SIM_STATE_IDLE:
+ if (!sim_len)
+ break; /* wait for SIM command */
+ /* check if instructions expects a response */
+ if (/* GET RESPONSE needs SIM_APDU_GET */
+ (sim_len == 5 && sim_data[0] == SIM_CLASS &&
+ sim_data[1] == SIM_GET_RESPONSE && sim_data[2] == 0x00 &&
+ sim_data[3] == 0x00) ||
+ /* READ BINARY/RECORD needs SIM_APDU_GET */
+ (sim_len >= 5 && sim_data[0] == SIM_CLASS &&
+ (sim_data[1] == SIM_READ_BINARY ||
+ sim_data[1] == SIM_READ_RECORD)))
+ mode = SIM_APDU_GET;
else
- {
-#if (SIM_DEBUG == 1)
- puts("SIM-T0: T0 Protocol error -- aborting!\n");
-#endif
- return -1;
+ mode = SIM_APDU_PUT;
+
+ length = sim_data[4];
+
+ /* allocate space for expected response */
+ msg = msgb_alloc_headroom(256, L3_MSG_HEAD
+ + sizeof(struct l1ctl_hdr), "l1ctl1");
+ response = msgb_put(msg, length + 2 + 1);
+
+ sim_state = SIM_STATE_TX_HEADER;
+
+ /* send APDU header */
+ calypso_sim_transmit(sim_data, 5);
+ break;
+ case SIM_STATE_TX_HEADER:
+ if (!txDoneFlag)
+ break; /* wait until header is transmitted */
+ /* Disable all interrupt driven functions */
+ writew(0xFF, REG_SIM_MASKIT);
+ /* Case 1: No input, No Output */
+ if (length == 0) {
+ sim_state = SIM_STATE_RX_STATUS;
+ calypso_sim_receive(response + 1, 2);
+ break;
+ }
+ /* Case 2: No input / Output of known length */
+ if (mode == SIM_APDU_PUT) {
+ sim_state = SIM_STATE_RX_ACK;
+ calypso_sim_receive(response, 1);
+ break;
+ /* Case 4: Input / No output */
+ } else {
+ sim_state = SIM_STATE_RX_ACK_DATA;
+ calypso_sim_receive(response, length + 1 + 2);
+ }
+ break;
+ case SIM_STATE_RX_STATUS:
+ if (!rxDoneFlag)
+ break; /* wait until data is received */
+ /* Disable all interrupt driven functions */
+ writew(0xFF, REG_SIM_MASKIT);
+ /* disable special ignore case */
+ sim_ignore_waiting_char = 0;
+ /* wrong number of bytes received */
+ if (sim_rx_character_count != 2) {
+ puts("SIM: Failed to read status\n");
+ goto error;
+ }
+ msgb_pull(msg, length + 1); /* pull up to status info */
+ goto queue;
+ case SIM_STATE_RX_ACK:
+ if (!rxDoneFlag)
+ break; /* wait until data is received */
+ /* Disable all interrupt driven functions */
+ writew(0xFF, REG_SIM_MASKIT);
+ /* error received */
+ if (sim_rx_character_count == 2) {
+ puts("SIM: command failed\n");
+ msgb_pull(msg, msg->len - 2);
+ msg->data[0] = response[0];
+ msg->data[1] = response[1];
+ goto queue;
+ }
+ /* wrong number of bytes received */
+ if (sim_rx_character_count != 1) {
+ puts("SIM: ACK read failed\n");
+ goto error;
+ }
+ if (response[0] != sim_data[1]) {
+ puts("SIM: ACK does not match request\n");
+ goto error;
+ }
+ sim_state = SIM_STATE_TX_DATA;
+ calypso_sim_transmit(sim_data + 5, length);
+ break;
+ case SIM_STATE_TX_DATA:
+ if (!txDoneFlag)
+ break; /* wait until data is transmitted */
+ /* Disable all interrupt driven functions */
+ writew(0xFF, REG_SIM_MASKIT);
+ /* Ignore waiting char for RUN GSM ALGORITHM */
+ /* TODO: implement proper handling of the "Procedure Bytes"
+ than this is no longer needed */
+ if(sim_data[1] == 0x88)
+ sim_ignore_waiting_char = 1;
+ sim_state = SIM_STATE_RX_STATUS;
+ calypso_sim_receive(response + length + 1, 2);
+ break;
+ case SIM_STATE_RX_ACK_DATA:
+ if (!rxDoneFlag)
+ break; /* wait until data is received */
+ /* Disable all interrupt driven functions */
+ writew(0xFF, REG_SIM_MASKIT);
+ /* error received */
+ if (sim_rx_character_count == 2) {
+ puts("SIM: command failed\n");
+ msgb_pull(msg, msg->len - 2);
+ msg->data[0] = response[0];
+ msg->data[1] = response[1];
+ goto queue;
+ }
+ /* wrong number of bytes received */
+ if (sim_rx_character_count != length + 1 + 2) {
+ puts("SIM: Failed to read data\n");
+ goto error;
}
+ msgb_pull(msg, 1); /* pull ACK byte */
+ goto queue;
}
- /* Case 2: No input / Output of known length */
- else if(mode == SIM_APDU_PUT)
- {
-#if (SIM_DEBUG == 1)
- puts("SIM-T0: Case 2: No input / Output of known length (See also GSM 11.11 Page 34)\n");
-#endif
+ return;
- numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
+error:
+ msgb_pull(msg, msg->len - 2);
+ msg->data[0] = 0;
+ msg->data[1] = 0;
+queue:
+ printf("SIM Response (%d): %s\n", msg->len,
+ osmo_hexdump(msg->data, msg->len));
+ l1h = (struct l1ctl_hdr *) msgb_push(msg, sizeof(*l1h));
+ l1h->msg_type = L1CTL_SIM_CONF;
+ l1h->flags = 0;
+ msg->l1h = (uint8_t *)l1h;
+ l1_queue_for_l2(msg);
+ /* go IDLE */
+ sim_state = SIM_STATE_IDLE;
+ sim_len = 0;
- /* Error situation: The card has aborted, sends no data but a status word */
- if(numberOfReceivedBytes == 2)
- {
-#if (SIM_DEBUG == 1)
- printf("SIM-T0: Status-word received (ERROR): %02x %02x\n", transmissionBuffer[0], transmissionBuffer[1]);
-#endif
- /* Hand back status word */
- if(status != 0)
- {
- status[0] = transmissionBuffer[0];
- status[1] = transmissionBuffer[1];
- }
-
- return 0;
- }
- /* Acknoledge byte received */
- else if(numberOfReceivedBytes == 1)
- {
-#if (SIM_DEBUG == 1)
- printf("SIM-T0: ACK received: %02x\n", transmissionBuffer[0]);
-#endif
- /* Check if ACK is valid */
- if(transmissionBuffer[0] != ins)
- {
-#if (SIM_DEBUG == 1)
- puts("SIM-T0: T0 Protocol error: Invalid ACK byte -- aborting!\n");
-#endif
- return -1;
- }
-
- /* Transmit body */
- calypso_sim_transmit(data,p3le);
-
- /* Receive status word */
- numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
-
- /* Check status word */
- if(numberOfReceivedBytes == 2)
- {
-#if (SIM_DEBUG == 1)
- printf("SIM-T0: Status-word received: %02x %02x\n", transmissionBuffer[0], transmissionBuffer[1]);
-#endif
+ return;
+}
- /* Hand back status word */
- if(status != 0)
- {
- status[0] = transmissionBuffer[0];
- status[1] = transmissionBuffer[1];
- }
+/* Initialize simcard interface */
+void calypso_sim_init(void)
+{
+ /* Register IRQ handler and turn interrupts on */
+ printd("SIM: Registering interrupt handler for simcard-interface\n");
- return 0;
- }
- else
- {
-#if (SIM_DEBUG == 1)
- puts("SIM-T0: T0 Protocol error: Missing or invalid status word -- aborting!\n");
-#endif
- return -1;
- }
- }
- else
- {
-#if (SIM_DEBUG == 1)
- puts("SIM-T0: T0 Protocol error: Missing ACK byte -- aborting!\n");
-#endif
- return -1;
- }
- }
+ irq_register_handler(IRQ_SIMCARD, &sim_irq_handler);
- /* Case 4: Input / No output */
- else if(mode == SIM_APDU_GET)
- {
-#if (SIM_DEBUG == 1)
- puts("SIM-T0: Case 4: Input / No output (See also GSM 11.11 Page 34)\n");
+#if 1
+ irq_config(IRQ_SIMCARD, 0, 0, 0xff);
+#else
+ irq_config(IRQ_SIMCARD, 0, 0, 1);
#endif
- numberOfReceivedBytes = calypso_sim_receive(data);
-
- /* Error situation: The card has aborted, sends no data but a status word */
- if(numberOfReceivedBytes == 2)
- {
+ irq_enable(IRQ_SIMCARD);
+}
-#if (SIM_DEBUG == 1)
- printf("SIM-T0: Status-word received (ERROR): %02x %02x\n", data[0], data[1]);
+/* Apply power to the simcard (use nullpointer to ignore atr) */
+int calypso_sim_powerup(uint8_t *atr)
+{
+ /* Enable level shifters and voltage regulator */
+#if 1 // 2.9V
+ twl3025_reg_write(VRPCSIM, VRPCSIM_SIMLEN | VRPCSIM_RSIMEN
+ | VRPCSIM_SIMSEL);
+#else // 1.8V
+ twl3025_reg_write(VRPCSIM, VRPCSIM_SIMLEN | VRPCSIM_RSIMEN);
#endif
- /* Hand back status word */
- if(status != 0)
- {
- status[0] = data[0];
- status[1] = data[1];
- }
-
- return 0;
- }
+ printd(" * Power enabled!\n");
+ delay_ms(SIM_OPERATION_DELAY);
- /* Data correctly received */
- else if(numberOfReceivedBytes == p3le + 1 + 2)
- {
-#if (SIM_DEBUG == 1)
- printf("SIM-T0: ACK received: %02x\n", data[0]);
-#endif
- /* Check if ACK is valid */
- if(data[0] != ins)
- {
-#if (SIM_DEBUG == 1)
- puts("SIM-T0: T0 Protocol error: Invalid ACK byte -- aborting!\n");
-#endif
- return -1;
- }
+ /* Enable clock */
+ writew(REG_SIM_CMD_MODULE_CLK_EN | REG_SIM_CMD_CMDSTART, REG_SIM_CMD);
+ printd(" * Clock enabled!\n");
+ delay_ms(SIM_OPERATION_DELAY);
-#if (SIM_DEBUG == 1)
- printf("SIM-T0: Status-word received: %02x %02x\n", data[p3le + 1], data[p3le + 2]);
-#endif
- /* Hand back status word */
- if(status != 0)
- {
- status[0] = data[p3le + 1];
- status[1] = data[p3le + 2];
- }
-
- /* Move data one position left to cut away the ACK-Byte */
- memcpy(data,data+1,p3le);
-
- return 0;
- }
- else
- {
-#if (SIM_DEBUG == 1)
- puts("SIM-T0: T0 Protocol error: Incorrect or missing answer -- aborting!\n");
-#endif
- return -1;
- }
- }
+ /* Release reset */
+ writew(readw(REG_SIM_CONF1) | REG_SIM_CONF1_CONFBYPASS
+ | REG_SIM_CONF1_CONFSRSTLEV
+ | REG_SIM_CONF1_CONFSVCCLEV, REG_SIM_CONF1);
+ printd(" * Reset released!\n");
- /* Should not happen, if it happens then the programmer has submitted invalid parameters! */
- else
- {
-#if (SIM_DEBUG == 1)
- puts("SIM-T0: T0 Protocol error: Invalid case (program bug!) -- aborting!\n");
-#endif
+ /* Catch ATR */
+ if(atr != 0) {
+ calypso_sim_receive(atr, 0);
+ while (!rxDoneFlag)
+ ;
}
- /* Note: The other cases are not implemented because they are already covered
- by the CASE 1,2 and 4. */
-
return 0;
}
-/* Initialize simcard interface */
-void calypso_sim_init(void)
+/* Powerdown simcard */
+void calypso_sim_powerdown(void)
{
- /* Register IRQ handler and turn interrupts on */
-#if (SIM_DEBUG == 1)
- puts("SIM: Registering interrupt handler for simcard-interface\n");
-#endif
- irq_register_handler(IRQ_SIMCARD, &sim_irq_handler);
- irq_config(IRQ_SIMCARD, 0, 0, 0xff);
- irq_enable(IRQ_SIMCARD);
+ writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFBYPASS, REG_SIM_CONF1);
+ printd(" * Reset pulled down!\n");
+ delay_ms(SIM_OPERATION_DELAY);
+
+ writew(REG_SIM_CMD_MODULE_CLK_EN | REG_SIM_CMD_CMDSTOP, REG_SIM_CMD);
+ printd(" * Clock disabled!\n");
+ delay_ms(SIM_OPERATION_DELAY);
+
+ writew(0, REG_SIM_CMD);
+ printd(" * Module disabled!\n");
+ delay_ms(SIM_OPERATION_DELAY);
+
+ /* Disable level shifters and voltage regulator */
+ twl3025_reg_write(VRPCSIM, 0);
+ printd(" * Power disabled!\n");
+ delay_ms(SIM_OPERATION_DELAY);
+
+ return;
+}
+
+/* reset the simcard (see note 1) */
+int calypso_sim_reset(uint8_t *atr)
+{
+
+ /* Pull reset down */
+ writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFSRSTLEV,
+ REG_SIM_CONF1);
+ printd(" * Reset pulled down!\n");
+
+ delay_ms(SIM_OPERATION_DELAY);
+
+ /* Pull reset down */
+ writew(readw(REG_SIM_CONF1) | REG_SIM_CONF1_CONFSRSTLEV, REG_SIM_CONF1);
+ printd(" * Reset released!\n");
+
+ /* Catch ATR */
+ if(atr != 0) {
+ calypso_sim_receive(atr, 0);
+ while (!rxDoneFlag)
+ ;
+ }
+
+ return 0;
}
diff --git a/Src/osmolib/src/target/firmware/comm/msgb.c b/Src/osmolib/src/target/firmware/comm/msgb.c
index 4215d24..3524ba5 100644
--- a/Src/osmolib/src/target/firmware/comm/msgb.c
+++ b/Src/osmolib/src/target/firmware/comm/msgb.c
@@ -26,6 +26,7 @@
#include <debug.h>
#include <delay.h>
+#include <console.h>
#include <osmocom/core/msgb.h>
diff --git a/Src/osmolib/src/target/firmware/comm/timer.c b/Src/osmolib/src/target/firmware/comm/timer.c
index 6a649ae..ce4f06d 100644
--- a/Src/osmolib/src/target/firmware/comm/timer.c
+++ b/Src/osmolib/src/target/firmware/comm/timer.c
@@ -33,22 +33,20 @@ static LLIST_HEAD(timer_list);
unsigned long volatile jiffies;
-#define TIMER_HZ 100
-
#define time_after(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long, b) && \
((long)(b) - (long)(a) < 0))
#define time_before(a,b) time_after(b,a)
-void add_timer(struct osmo_timer_list *timer)
+void osmo_timer_add(struct osmo_timer_list *timer)
{
struct osmo_timer_list *list_timer;
/* TODO: Optimize and remember the closest item... */
timer->active = 1;
- /* this might be called from within update_timers */
+ /* this might be called from within osmo_timers_update */
llist_for_each_entry(list_timer, &timer_list, entry)
if (timer == list_timer)
return;
@@ -57,13 +55,13 @@ void add_timer(struct osmo_timer_list *timer)
llist_add(&timer->entry, &timer_list);
}
-void schedule_timer(struct osmo_timer_list *timer, int milliseconds)
+void osmo_timer_schedule(struct osmo_timer_list *timer, int milliseconds)
{
- timer->expires = jiffies + ((milliseconds * TIMER_HZ) / 1000);
- add_timer(timer);
+ timer->expires = jiffies + ((milliseconds * HZ) / 1000);
+ osmo_timer_add(timer);
}
-void del_timer(struct osmo_timer_list *timer)
+void osmo_timer_del(struct osmo_timer_list *timer)
{
if (timer->in_list) {
timer->active = 0;
@@ -72,7 +70,7 @@ void del_timer(struct osmo_timer_list *timer)
}
}
-int timer_pending(struct osmo_timer_list *timer)
+int osmo_timer_pending(struct osmo_timer_list *timer)
{
return timer->active;
}
@@ -131,7 +129,7 @@ void prepare_timers()
/*
* fire all timers... and remove them
*/
-int update_timers(void)
+int osmo_timers_update(void)
{
struct osmo_timer_list *timer, *tmp;
int work = 0;
@@ -139,7 +137,7 @@ int update_timers(void)
/*
* The callbacks might mess with our list and in this case
* even llist_for_each_entry_safe is not safe to use. To allow
- * del_timer, add_timer, schedule_timer to be called from within
+ * osmo_timer_del, osmo_timer_add, osmo_timer_schedule to be called from within
* the callback we jump through some loops.
*
* First we set the handled flag of each active timer to zero,
@@ -149,7 +147,7 @@ int update_timers(void)
* is dispatched we will remove the non-active from the list.
*
* TODO: If this is a performance issue we can poison a global
- * variable in add_timer and del_timer and only then restart.
+ * variable in osmo_timer_add and osmo_timer_del and only then restart.
*/
llist_for_each_entry(timer, &timer_list, entry) {
timer->handled = 0;
@@ -169,14 +167,14 @@ restart:
llist_for_each_entry_safe(timer, tmp, &timer_list, entry) {
timer->handled = 0;
if (!timer->active) {
- del_timer(timer);
+ osmo_timer_del(timer);
}
}
return work;
}
-int timer_check(void)
+int osmo_timers_check(void)
{
struct osmo_timer_list *timer;
int i = 0;
@@ -200,10 +198,10 @@ void timer_init(void)
/* configure TIMER2 for our purpose */
hwtimer_enable(2, 1);
/* The timer runs at 13MHz / 32, i.e. 406.25kHz */
-#if (TIMER_HZ == 100)
+#if (HZ == 100)
hwtimer_load(2, 4062);
hwtimer_config(2, 0, 1);
-#elif (TIMER_HZ == 10)
+#elif (HZ == 10)
/* prescaler 4, 1015 ticks until expiry */
hwtimer_load(2, 1015);
hwtimer_config(2, 4, 1);
diff --git a/Src/osmolib/src/target/firmware/fb/4x6.c b/Src/osmolib/src/target/firmware/fb/4x6.c
new file mode 100644
index 0000000..2a35eba
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/4x6.c
@@ -0,0 +1,731 @@
+#include <fb/font.h>
+static const uint8_t font_4x6_data[] = {
+/* --- new character space (32) starting at offset 0x0000 --- */
+ /*0000:*/ 4, 4, 1, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0005:*/ 0x00, /* ........ */
+/* --- new character exclam (33) starting at offset 0x0006 --- */
+ /*0006:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*000b:*/ 0x40, /* .#...... */
+ /*000c:*/ 0x40, /* .#...... */
+ /*000d:*/ 0x40, /* .#...... */
+ /*000e:*/ 0x00, /* ........ */
+ /*000f:*/ 0x40, /* .#...... */
+/* --- new character quotedbl (34) starting at offset 0x0010 --- */
+ /*0010:*/ 4, 4, 2, 0, 3, /* width and bbox (w,h,x,y) */
+ /*0015:*/ 0xa0, /* #.#..... */
+ /*0016:*/ 0xa0, /* #.#..... */
+/* --- new character numbersign (35) starting at offset 0x0017 --- */
+ /*0017:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*001c:*/ 0xa0, /* #.#..... */
+ /*001d:*/ 0xf0, /* ####.... */
+ /*001e:*/ 0xa0, /* #.#..... */
+ /*001f:*/ 0xf0, /* ####.... */
+ /*0020:*/ 0xa0, /* #.#..... */
+/* --- new character dollar (36) starting at offset 0x0021 --- */
+ /*0021:*/ 4, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0026:*/ 0x40, /* .#...... */
+ /*0027:*/ 0xe0, /* ###..... */
+ /*0028:*/ 0xc0, /* ##...... */
+ /*0029:*/ 0x20, /* ..#..... */
+ /*002a:*/ 0xe0, /* ###..... */
+ /*002b:*/ 0x40, /* .#...... */
+/* --- new character percent (37) starting at offset 0x002c --- */
+ /*002c:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0031:*/ 0x80, /* #....... */
+ /*0032:*/ 0x20, /* ..#..... */
+ /*0033:*/ 0x40, /* .#...... */
+ /*0034:*/ 0x80, /* #....... */
+ /*0035:*/ 0x20, /* ..#..... */
+/* --- new character ampersand (38) starting at offset 0x0036 --- */
+ /*0036:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*003b:*/ 0x40, /* .#...... */
+ /*003c:*/ 0xa0, /* #.#..... */
+ /*003d:*/ 0x40, /* .#...... */
+ /*003e:*/ 0xa0, /* #.#..... */
+ /*003f:*/ 0x50, /* .#.#.... */
+/* --- new character quotesingle (39) starting at offset 0x0040 --- */
+ /*0040:*/ 4, 4, 2, 0, 3, /* width and bbox (w,h,x,y) */
+ /*0045:*/ 0x40, /* .#...... */
+ /*0046:*/ 0x40, /* .#...... */
+/* --- new character parenleft (40) starting at offset 0x0047 --- */
+ /*0047:*/ 4, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*004c:*/ 0x20, /* ..#..... */
+ /*004d:*/ 0x40, /* .#...... */
+ /*004e:*/ 0x40, /* .#...... */
+ /*004f:*/ 0x40, /* .#...... */
+ /*0050:*/ 0x40, /* .#...... */
+ /*0051:*/ 0x20, /* ..#..... */
+/* --- new character parenright (41) starting at offset 0x0052 --- */
+ /*0052:*/ 4, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0057:*/ 0x80, /* #....... */
+ /*0058:*/ 0x40, /* .#...... */
+ /*0059:*/ 0x40, /* .#...... */
+ /*005a:*/ 0x40, /* .#...... */
+ /*005b:*/ 0x40, /* .#...... */
+ /*005c:*/ 0x80, /* #....... */
+/* --- new character asterisk (42) starting at offset 0x005d --- */
+ /*005d:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0062:*/ 0xa0, /* #.#..... */
+ /*0063:*/ 0x40, /* .#...... */
+ /*0064:*/ 0xe0, /* ###..... */
+ /*0065:*/ 0x40, /* .#...... */
+ /*0066:*/ 0xa0, /* #.#..... */
+/* --- new character plus (43) starting at offset 0x0067 --- */
+ /*0067:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*006c:*/ 0x40, /* .#...... */
+ /*006d:*/ 0x40, /* .#...... */
+ /*006e:*/ 0xe0, /* ###..... */
+ /*006f:*/ 0x40, /* .#...... */
+ /*0070:*/ 0x40, /* .#...... */
+/* --- new character comma (44) starting at offset 0x0071 --- */
+ /*0071:*/ 4, 4, 2, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0076:*/ 0x40, /* .#...... */
+ /*0077:*/ 0x80, /* #....... */
+/* --- new character hyphen (45) starting at offset 0x0078 --- */
+ /*0078:*/ 4, 4, 1, 0, 2, /* width and bbox (w,h,x,y) */
+ /*007d:*/ 0xe0, /* ###..... */
+/* --- new character period (46) starting at offset 0x007e --- */
+ /*007e:*/ 4, 4, 1, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0083:*/ 0x40, /* .#...... */
+/* --- new character slash (47) starting at offset 0x0084 --- */
+ /*0084:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0089:*/ 0x20, /* ..#..... */
+ /*008a:*/ 0x20, /* ..#..... */
+ /*008b:*/ 0x40, /* .#...... */
+ /*008c:*/ 0x80, /* #....... */
+ /*008d:*/ 0x80, /* #....... */
+/* --- new character zero (48) starting at offset 0x008e --- */
+ /*008e:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0093:*/ 0x40, /* .#...... */
+ /*0094:*/ 0xa0, /* #.#..... */
+ /*0095:*/ 0xe0, /* ###..... */
+ /*0096:*/ 0xa0, /* #.#..... */
+ /*0097:*/ 0x40, /* .#...... */
+/* --- new character one (49) starting at offset 0x0098 --- */
+ /*0098:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*009d:*/ 0x40, /* .#...... */
+ /*009e:*/ 0xc0, /* ##...... */
+ /*009f:*/ 0x40, /* .#...... */
+ /*00a0:*/ 0x40, /* .#...... */
+ /*00a1:*/ 0xe0, /* ###..... */
+/* --- new character two (50) starting at offset 0x00a2 --- */
+ /*00a2:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00a7:*/ 0x40, /* .#...... */
+ /*00a8:*/ 0xa0, /* #.#..... */
+ /*00a9:*/ 0x20, /* ..#..... */
+ /*00aa:*/ 0x40, /* .#...... */
+ /*00ab:*/ 0xe0, /* ###..... */
+/* --- new character three (51) starting at offset 0x00ac --- */
+ /*00ac:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00b1:*/ 0xe0, /* ###..... */
+ /*00b2:*/ 0x20, /* ..#..... */
+ /*00b3:*/ 0x40, /* .#...... */
+ /*00b4:*/ 0x20, /* ..#..... */
+ /*00b5:*/ 0xc0, /* ##...... */
+/* --- new character four (52) starting at offset 0x00b6 --- */
+ /*00b6:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00bb:*/ 0xa0, /* #.#..... */
+ /*00bc:*/ 0xa0, /* #.#..... */
+ /*00bd:*/ 0xe0, /* ###..... */
+ /*00be:*/ 0x20, /* ..#..... */
+ /*00bf:*/ 0x20, /* ..#..... */
+/* --- new character five (53) starting at offset 0x00c0 --- */
+ /*00c0:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00c5:*/ 0xe0, /* ###..... */
+ /*00c6:*/ 0x80, /* #....... */
+ /*00c7:*/ 0xc0, /* ##...... */
+ /*00c8:*/ 0x20, /* ..#..... */
+ /*00c9:*/ 0xc0, /* ##...... */
+/* --- new character six (54) starting at offset 0x00ca --- */
+ /*00ca:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00cf:*/ 0x60, /* .##..... */
+ /*00d0:*/ 0x80, /* #....... */
+ /*00d1:*/ 0xc0, /* ##...... */
+ /*00d2:*/ 0xa0, /* #.#..... */
+ /*00d3:*/ 0x40, /* .#...... */
+/* --- new character seven (55) starting at offset 0x00d4 --- */
+ /*00d4:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00d9:*/ 0xe0, /* ###..... */
+ /*00da:*/ 0x20, /* ..#..... */
+ /*00db:*/ 0x40, /* .#...... */
+ /*00dc:*/ 0x80, /* #....... */
+ /*00dd:*/ 0x80, /* #....... */
+/* --- new character eight (56) starting at offset 0x00de --- */
+ /*00de:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00e3:*/ 0x60, /* .##..... */
+ /*00e4:*/ 0xa0, /* #.#..... */
+ /*00e5:*/ 0x40, /* .#...... */
+ /*00e6:*/ 0xa0, /* #.#..... */
+ /*00e7:*/ 0xc0, /* ##...... */
+/* --- new character nine (57) starting at offset 0x00e8 --- */
+ /*00e8:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00ed:*/ 0x40, /* .#...... */
+ /*00ee:*/ 0xa0, /* #.#..... */
+ /*00ef:*/ 0x60, /* .##..... */
+ /*00f0:*/ 0x20, /* ..#..... */
+ /*00f1:*/ 0xc0, /* ##...... */
+/* --- new character colon (58) starting at offset 0x00f2 --- */
+ /*00f2:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00f7:*/ 0x40, /* .#...... */
+ /*00f8:*/ 0x00, /* ........ */
+ /*00f9:*/ 0x00, /* ........ */
+ /*00fa:*/ 0x40, /* .#...... */
+/* --- new character semicolon (59) starting at offset 0x00fb --- */
+ /*00fb:*/ 4, 4, 5, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0100:*/ 0x40, /* .#...... */
+ /*0101:*/ 0x00, /* ........ */
+ /*0102:*/ 0x00, /* ........ */
+ /*0103:*/ 0x40, /* .#...... */
+ /*0104:*/ 0x80, /* #....... */
+/* --- new character less (60) starting at offset 0x0105 --- */
+ /*0105:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*010a:*/ 0x20, /* ..#..... */
+ /*010b:*/ 0x40, /* .#...... */
+ /*010c:*/ 0x80, /* #....... */
+ /*010d:*/ 0x40, /* .#...... */
+ /*010e:*/ 0x20, /* ..#..... */
+/* --- new character equal (61) starting at offset 0x010f --- */
+ /*010f:*/ 4, 4, 3, 0, 1, /* width and bbox (w,h,x,y) */
+ /*0114:*/ 0xe0, /* ###..... */
+ /*0115:*/ 0x00, /* ........ */
+ /*0116:*/ 0xe0, /* ###..... */
+/* --- new character greater (62) starting at offset 0x0117 --- */
+ /*0117:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*011c:*/ 0x80, /* #....... */
+ /*011d:*/ 0x40, /* .#...... */
+ /*011e:*/ 0x20, /* ..#..... */
+ /*011f:*/ 0x40, /* .#...... */
+ /*0120:*/ 0x80, /* #....... */
+/* --- new character question (63) starting at offset 0x0121 --- */
+ /*0121:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0126:*/ 0xc0, /* ##...... */
+ /*0127:*/ 0x20, /* ..#..... */
+ /*0128:*/ 0x40, /* .#...... */
+ /*0129:*/ 0x00, /* ........ */
+ /*012a:*/ 0x40, /* .#...... */
+/* --- new character at (64) starting at offset 0x012b --- */
+ /*012b:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0130:*/ 0x60, /* .##..... */
+ /*0131:*/ 0xa0, /* #.#..... */
+ /*0132:*/ 0xa0, /* #.#..... */
+ /*0133:*/ 0x80, /* #....... */
+ /*0134:*/ 0x60, /* .##..... */
+/* --- new character A (65) starting at offset 0x0135 --- */
+ /*0135:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*013a:*/ 0x40, /* .#...... */
+ /*013b:*/ 0xa0, /* #.#..... */
+ /*013c:*/ 0xe0, /* ###..... */
+ /*013d:*/ 0xa0, /* #.#..... */
+ /*013e:*/ 0xa0, /* #.#..... */
+/* --- new character B (66) starting at offset 0x013f --- */
+ /*013f:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0144:*/ 0xc0, /* ##...... */
+ /*0145:*/ 0xa0, /* #.#..... */
+ /*0146:*/ 0xc0, /* ##...... */
+ /*0147:*/ 0xa0, /* #.#..... */
+ /*0148:*/ 0xc0, /* ##...... */
+/* --- new character C (67) starting at offset 0x0149 --- */
+ /*0149:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*014e:*/ 0x40, /* .#...... */
+ /*014f:*/ 0xa0, /* #.#..... */
+ /*0150:*/ 0x80, /* #....... */
+ /*0151:*/ 0xa0, /* #.#..... */
+ /*0152:*/ 0x40, /* .#...... */
+/* --- new character D (68) starting at offset 0x0153 --- */
+ /*0153:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0158:*/ 0xc0, /* ##...... */
+ /*0159:*/ 0xa0, /* #.#..... */
+ /*015a:*/ 0xa0, /* #.#..... */
+ /*015b:*/ 0xa0, /* #.#..... */
+ /*015c:*/ 0xc0, /* ##...... */
+/* --- new character E (69) starting at offset 0x015d --- */
+ /*015d:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0162:*/ 0xe0, /* ###..... */
+ /*0163:*/ 0x80, /* #....... */
+ /*0164:*/ 0xc0, /* ##...... */
+ /*0165:*/ 0x80, /* #....... */
+ /*0166:*/ 0xe0, /* ###..... */
+/* --- new character F (70) starting at offset 0x0167 --- */
+ /*0167:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*016c:*/ 0xe0, /* ###..... */
+ /*016d:*/ 0x80, /* #....... */
+ /*016e:*/ 0xc0, /* ##...... */
+ /*016f:*/ 0x80, /* #....... */
+ /*0170:*/ 0x80, /* #....... */
+/* --- new character G (71) starting at offset 0x0171 --- */
+ /*0171:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0176:*/ 0x60, /* .##..... */
+ /*0177:*/ 0x80, /* #....... */
+ /*0178:*/ 0xa0, /* #.#..... */
+ /*0179:*/ 0xa0, /* #.#..... */
+ /*017a:*/ 0x60, /* .##..... */
+/* --- new character H (72) starting at offset 0x017b --- */
+ /*017b:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0180:*/ 0xa0, /* #.#..... */
+ /*0181:*/ 0xa0, /* #.#..... */
+ /*0182:*/ 0xe0, /* ###..... */
+ /*0183:*/ 0xa0, /* #.#..... */
+ /*0184:*/ 0xa0, /* #.#..... */
+/* --- new character I (73) starting at offset 0x0185 --- */
+ /*0185:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*018a:*/ 0xe0, /* ###..... */
+ /*018b:*/ 0x40, /* .#...... */
+ /*018c:*/ 0x40, /* .#...... */
+ /*018d:*/ 0x40, /* .#...... */
+ /*018e:*/ 0xe0, /* ###..... */
+/* --- new character J (74) starting at offset 0x018f --- */
+ /*018f:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0194:*/ 0x20, /* ..#..... */
+ /*0195:*/ 0x20, /* ..#..... */
+ /*0196:*/ 0x20, /* ..#..... */
+ /*0197:*/ 0xa0, /* #.#..... */
+ /*0198:*/ 0x40, /* .#...... */
+/* --- new character K (75) starting at offset 0x0199 --- */
+ /*0199:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*019e:*/ 0xa0, /* #.#..... */
+ /*019f:*/ 0xa0, /* #.#..... */
+ /*01a0:*/ 0xc0, /* ##...... */
+ /*01a1:*/ 0xa0, /* #.#..... */
+ /*01a2:*/ 0xa0, /* #.#..... */
+/* --- new character L (76) starting at offset 0x01a3 --- */
+ /*01a3:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01a8:*/ 0x80, /* #....... */
+ /*01a9:*/ 0x80, /* #....... */
+ /*01aa:*/ 0x80, /* #....... */
+ /*01ab:*/ 0x80, /* #....... */
+ /*01ac:*/ 0xe0, /* ###..... */
+/* --- new character M (77) starting at offset 0x01ad --- */
+ /*01ad:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01b2:*/ 0xa0, /* #.#..... */
+ /*01b3:*/ 0xe0, /* ###..... */
+ /*01b4:*/ 0xe0, /* ###..... */
+ /*01b5:*/ 0xa0, /* #.#..... */
+ /*01b6:*/ 0xa0, /* #.#..... */
+/* --- new character N (78) starting at offset 0x01b7 --- */
+ /*01b7:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01bc:*/ 0x20, /* ..#..... */
+ /*01bd:*/ 0xa0, /* #.#..... */
+ /*01be:*/ 0xe0, /* ###..... */
+ /*01bf:*/ 0xa0, /* #.#..... */
+ /*01c0:*/ 0x80, /* #....... */
+/* --- new character O (79) starting at offset 0x01c1 --- */
+ /*01c1:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01c6:*/ 0x40, /* .#...... */
+ /*01c7:*/ 0xa0, /* #.#..... */
+ /*01c8:*/ 0xa0, /* #.#..... */
+ /*01c9:*/ 0xa0, /* #.#..... */
+ /*01ca:*/ 0x40, /* .#...... */
+/* --- new character P (80) starting at offset 0x01cb --- */
+ /*01cb:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01d0:*/ 0xc0, /* ##...... */
+ /*01d1:*/ 0xa0, /* #.#..... */
+ /*01d2:*/ 0xc0, /* ##...... */
+ /*01d3:*/ 0x80, /* #....... */
+ /*01d4:*/ 0x80, /* #....... */
+/* --- new character Q (81) starting at offset 0x01d5 --- */
+ /*01d5:*/ 4, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*01da:*/ 0x40, /* .#...... */
+ /*01db:*/ 0xa0, /* #.#..... */
+ /*01dc:*/ 0xa0, /* #.#..... */
+ /*01dd:*/ 0xa0, /* #.#..... */
+ /*01de:*/ 0x40, /* .#...... */
+ /*01df:*/ 0x20, /* ..#..... */
+/* --- new character R (82) starting at offset 0x01e0 --- */
+ /*01e0:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01e5:*/ 0xc0, /* ##...... */
+ /*01e6:*/ 0xa0, /* #.#..... */
+ /*01e7:*/ 0xc0, /* ##...... */
+ /*01e8:*/ 0xa0, /* #.#..... */
+ /*01e9:*/ 0xa0, /* #.#..... */
+/* --- new character S (83) starting at offset 0x01ea --- */
+ /*01ea:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01ef:*/ 0x60, /* .##..... */
+ /*01f0:*/ 0x80, /* #....... */
+ /*01f1:*/ 0x40, /* .#...... */
+ /*01f2:*/ 0x20, /* ..#..... */
+ /*01f3:*/ 0xc0, /* ##...... */
+/* --- new character T (84) starting at offset 0x01f4 --- */
+ /*01f4:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01f9:*/ 0xe0, /* ###..... */
+ /*01fa:*/ 0x40, /* .#...... */
+ /*01fb:*/ 0x40, /* .#...... */
+ /*01fc:*/ 0x40, /* .#...... */
+ /*01fd:*/ 0x40, /* .#...... */
+/* --- new character U (85) starting at offset 0x01fe --- */
+ /*01fe:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0203:*/ 0xa0, /* #.#..... */
+ /*0204:*/ 0xa0, /* #.#..... */
+ /*0205:*/ 0xa0, /* #.#..... */
+ /*0206:*/ 0xa0, /* #.#..... */
+ /*0207:*/ 0xe0, /* ###..... */
+/* --- new character V (86) starting at offset 0x0208 --- */
+ /*0208:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*020d:*/ 0xa0, /* #.#..... */
+ /*020e:*/ 0xa0, /* #.#..... */
+ /*020f:*/ 0xa0, /* #.#..... */
+ /*0210:*/ 0xe0, /* ###..... */
+ /*0211:*/ 0x40, /* .#...... */
+/* --- new character W (87) starting at offset 0x0212 --- */
+ /*0212:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0217:*/ 0xa0, /* #.#..... */
+ /*0218:*/ 0xa0, /* #.#..... */
+ /*0219:*/ 0xe0, /* ###..... */
+ /*021a:*/ 0xe0, /* ###..... */
+ /*021b:*/ 0xa0, /* #.#..... */
+/* --- new character X (88) starting at offset 0x021c --- */
+ /*021c:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0221:*/ 0xa0, /* #.#..... */
+ /*0222:*/ 0xa0, /* #.#..... */
+ /*0223:*/ 0x40, /* .#...... */
+ /*0224:*/ 0xa0, /* #.#..... */
+ /*0225:*/ 0xa0, /* #.#..... */
+/* --- new character Y (89) starting at offset 0x0226 --- */
+ /*0226:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*022b:*/ 0xa0, /* #.#..... */
+ /*022c:*/ 0xa0, /* #.#..... */
+ /*022d:*/ 0x40, /* .#...... */
+ /*022e:*/ 0x40, /* .#...... */
+ /*022f:*/ 0x40, /* .#...... */
+/* --- new character Z (90) starting at offset 0x0230 --- */
+ /*0230:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0235:*/ 0xe0, /* ###..... */
+ /*0236:*/ 0x20, /* ..#..... */
+ /*0237:*/ 0x40, /* .#...... */
+ /*0238:*/ 0x80, /* #....... */
+ /*0239:*/ 0xe0, /* ###..... */
+/* --- new character bracketleft (91) starting at offset 0x023a --- */
+ /*023a:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*023f:*/ 0x60, /* .##..... */
+ /*0240:*/ 0x40, /* .#...... */
+ /*0241:*/ 0x40, /* .#...... */
+ /*0242:*/ 0x40, /* .#...... */
+ /*0243:*/ 0x60, /* .##..... */
+/* --- new character backslash (92) starting at offset 0x0244 --- */
+ /*0244:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0249:*/ 0x80, /* #....... */
+ /*024a:*/ 0x80, /* #....... */
+ /*024b:*/ 0x40, /* .#...... */
+ /*024c:*/ 0x20, /* ..#..... */
+ /*024d:*/ 0x20, /* ..#..... */
+/* --- new character bracketright (93) starting at offset 0x024e --- */
+ /*024e:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0253:*/ 0xc0, /* ##...... */
+ /*0254:*/ 0x40, /* .#...... */
+ /*0255:*/ 0x40, /* .#...... */
+ /*0256:*/ 0x40, /* .#...... */
+ /*0257:*/ 0xc0, /* ##...... */
+/* --- new character asciicircum (94) starting at offset 0x0258 --- */
+ /*0258:*/ 4, 4, 2, 0, 3, /* width and bbox (w,h,x,y) */
+ /*025d:*/ 0x40, /* .#...... */
+ /*025e:*/ 0xa0, /* #.#..... */
+/* --- new character underscore (95) starting at offset 0x025f --- */
+ /*025f:*/ 4, 4, 1, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0264:*/ 0xe0, /* ###..... */
+/* --- new character grave (96) starting at offset 0x0265 --- */
+ /*0265:*/ 4, 4, 2, 0, 3, /* width and bbox (w,h,x,y) */
+ /*026a:*/ 0x40, /* .#...... */
+ /*026b:*/ 0x20, /* ..#..... */
+/* --- new character a (97) starting at offset 0x026c --- */
+ /*026c:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0271:*/ 0x60, /* .##..... */
+ /*0272:*/ 0xa0, /* #.#..... */
+ /*0273:*/ 0xa0, /* #.#..... */
+ /*0274:*/ 0x60, /* .##..... */
+/* --- new character b (98) starting at offset 0x0275 --- */
+ /*0275:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*027a:*/ 0x80, /* #....... */
+ /*027b:*/ 0xc0, /* ##...... */
+ /*027c:*/ 0xa0, /* #.#..... */
+ /*027d:*/ 0xa0, /* #.#..... */
+ /*027e:*/ 0xc0, /* ##...... */
+/* --- new character c (99) starting at offset 0x027f --- */
+ /*027f:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0284:*/ 0x60, /* .##..... */
+ /*0285:*/ 0x80, /* #....... */
+ /*0286:*/ 0x80, /* #....... */
+ /*0287:*/ 0x60, /* .##..... */
+/* --- new character d (100) starting at offset 0x0288 --- */
+ /*0288:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*028d:*/ 0x20, /* ..#..... */
+ /*028e:*/ 0x60, /* .##..... */
+ /*028f:*/ 0xa0, /* #.#..... */
+ /*0290:*/ 0xa0, /* #.#..... */
+ /*0291:*/ 0x60, /* .##..... */
+/* --- new character e (101) starting at offset 0x0292 --- */
+ /*0292:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0297:*/ 0x40, /* .#...... */
+ /*0298:*/ 0xa0, /* #.#..... */
+ /*0299:*/ 0xc0, /* ##...... */
+ /*029a:*/ 0x60, /* .##..... */
+/* --- new character f (102) starting at offset 0x029b --- */
+ /*029b:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02a0:*/ 0x20, /* ..#..... */
+ /*02a1:*/ 0x40, /* .#...... */
+ /*02a2:*/ 0xe0, /* ###..... */
+ /*02a3:*/ 0x40, /* .#...... */
+ /*02a4:*/ 0x40, /* .#...... */
+/* --- new character g (103) starting at offset 0x02a5 --- */
+ /*02a5:*/ 4, 4, 5, 0, -1, /* width and bbox (w,h,x,y) */
+ /*02aa:*/ 0x60, /* .##..... */
+ /*02ab:*/ 0xa0, /* #.#..... */
+ /*02ac:*/ 0x60, /* .##..... */
+ /*02ad:*/ 0x20, /* ..#..... */
+ /*02ae:*/ 0xc0, /* ##...... */
+/* --- new character h (104) starting at offset 0x02af --- */
+ /*02af:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02b4:*/ 0x80, /* #....... */
+ /*02b5:*/ 0xc0, /* ##...... */
+ /*02b6:*/ 0xa0, /* #.#..... */
+ /*02b7:*/ 0xa0, /* #.#..... */
+ /*02b8:*/ 0xa0, /* #.#..... */
+/* --- new character i (105) starting at offset 0x02b9 --- */
+ /*02b9:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02be:*/ 0x40, /* .#...... */
+ /*02bf:*/ 0x00, /* ........ */
+ /*02c0:*/ 0xc0, /* ##...... */
+ /*02c1:*/ 0x40, /* .#...... */
+ /*02c2:*/ 0xe0, /* ###..... */
+/* --- new character j (106) starting at offset 0x02c3 --- */
+ /*02c3:*/ 4, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*02c8:*/ 0x20, /* ..#..... */
+ /*02c9:*/ 0x00, /* ........ */
+ /*02ca:*/ 0x20, /* ..#..... */
+ /*02cb:*/ 0x20, /* ..#..... */
+ /*02cc:*/ 0x20, /* ..#..... */
+ /*02cd:*/ 0xc0, /* ##...... */
+/* --- new character k (107) starting at offset 0x02ce --- */
+ /*02ce:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02d3:*/ 0x80, /* #....... */
+ /*02d4:*/ 0xa0, /* #.#..... */
+ /*02d5:*/ 0xc0, /* ##...... */
+ /*02d6:*/ 0xa0, /* #.#..... */
+ /*02d7:*/ 0xa0, /* #.#..... */
+/* --- new character l (108) starting at offset 0x02d8 --- */
+ /*02d8:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02dd:*/ 0xc0, /* ##...... */
+ /*02de:*/ 0x40, /* .#...... */
+ /*02df:*/ 0x40, /* .#...... */
+ /*02e0:*/ 0x40, /* .#...... */
+ /*02e1:*/ 0xe0, /* ###..... */
+/* --- new character m (109) starting at offset 0x02e2 --- */
+ /*02e2:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02e7:*/ 0xa0, /* #.#..... */
+ /*02e8:*/ 0xe0, /* ###..... */
+ /*02e9:*/ 0xa0, /* #.#..... */
+ /*02ea:*/ 0xa0, /* #.#..... */
+/* --- new character n (110) starting at offset 0x02eb --- */
+ /*02eb:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02f0:*/ 0xc0, /* ##...... */
+ /*02f1:*/ 0xa0, /* #.#..... */
+ /*02f2:*/ 0xa0, /* #.#..... */
+ /*02f3:*/ 0xa0, /* #.#..... */
+/* --- new character o (111) starting at offset 0x02f4 --- */
+ /*02f4:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02f9:*/ 0x40, /* .#...... */
+ /*02fa:*/ 0xa0, /* #.#..... */
+ /*02fb:*/ 0xa0, /* #.#..... */
+ /*02fc:*/ 0x40, /* .#...... */
+/* --- new character p (112) starting at offset 0x02fd --- */
+ /*02fd:*/ 4, 4, 5, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0302:*/ 0xc0, /* ##...... */
+ /*0303:*/ 0xa0, /* #.#..... */
+ /*0304:*/ 0xc0, /* ##...... */
+ /*0305:*/ 0x80, /* #....... */
+ /*0306:*/ 0x80, /* #....... */
+/* --- new character q (113) starting at offset 0x0307 --- */
+ /*0307:*/ 4, 4, 5, 0, -1, /* width and bbox (w,h,x,y) */
+ /*030c:*/ 0x60, /* .##..... */
+ /*030d:*/ 0xa0, /* #.#..... */
+ /*030e:*/ 0xa0, /* #.#..... */
+ /*030f:*/ 0x60, /* .##..... */
+ /*0310:*/ 0x20, /* ..#..... */
+/* --- new character r (114) starting at offset 0x0311 --- */
+ /*0311:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0316:*/ 0xa0, /* #.#..... */
+ /*0317:*/ 0xc0, /* ##...... */
+ /*0318:*/ 0x80, /* #....... */
+ /*0319:*/ 0x80, /* #....... */
+/* --- new character s (115) starting at offset 0x031a --- */
+ /*031a:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*031f:*/ 0x60, /* .##..... */
+ /*0320:*/ 0xc0, /* ##...... */
+ /*0321:*/ 0x20, /* ..#..... */
+ /*0322:*/ 0xc0, /* ##...... */
+/* --- new character t (116) starting at offset 0x0323 --- */
+ /*0323:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0328:*/ 0x40, /* .#...... */
+ /*0329:*/ 0xe0, /* ###..... */
+ /*032a:*/ 0x40, /* .#...... */
+ /*032b:*/ 0x40, /* .#...... */
+ /*032c:*/ 0x20, /* ..#..... */
+/* --- new character u (117) starting at offset 0x032d --- */
+ /*032d:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0332:*/ 0xa0, /* #.#..... */
+ /*0333:*/ 0xa0, /* #.#..... */
+ /*0334:*/ 0xa0, /* #.#..... */
+ /*0335:*/ 0x60, /* .##..... */
+/* --- new character v (118) starting at offset 0x0336 --- */
+ /*0336:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*033b:*/ 0xa0, /* #.#..... */
+ /*033c:*/ 0xa0, /* #.#..... */
+ /*033d:*/ 0xa0, /* #.#..... */
+ /*033e:*/ 0x40, /* .#...... */
+/* --- new character w (119) starting at offset 0x033f --- */
+ /*033f:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0344:*/ 0xa0, /* #.#..... */
+ /*0345:*/ 0xa0, /* #.#..... */
+ /*0346:*/ 0xe0, /* ###..... */
+ /*0347:*/ 0xa0, /* #.#..... */
+/* --- new character x (120) starting at offset 0x0348 --- */
+ /*0348:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*034d:*/ 0xa0, /* #.#..... */
+ /*034e:*/ 0x40, /* .#...... */
+ /*034f:*/ 0x40, /* .#...... */
+ /*0350:*/ 0xa0, /* #.#..... */
+/* --- new character y (121) starting at offset 0x0351 --- */
+ /*0351:*/ 4, 4, 5, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0356:*/ 0xa0, /* #.#..... */
+ /*0357:*/ 0xa0, /* #.#..... */
+ /*0358:*/ 0x60, /* .##..... */
+ /*0359:*/ 0x20, /* ..#..... */
+ /*035a:*/ 0xc0, /* ##...... */
+/* --- new character z (122) starting at offset 0x035b --- */
+ /*035b:*/ 4, 4, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0360:*/ 0xe0, /* ###..... */
+ /*0361:*/ 0x20, /* ..#..... */
+ /*0362:*/ 0x40, /* .#...... */
+ /*0363:*/ 0xe0, /* ###..... */
+/* --- new character braceleft (123) starting at offset 0x0364 --- */
+ /*0364:*/ 4, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0369:*/ 0x20, /* ..#..... */
+ /*036a:*/ 0x40, /* .#...... */
+ /*036b:*/ 0xc0, /* ##...... */
+ /*036c:*/ 0x40, /* .#...... */
+ /*036d:*/ 0x40, /* .#...... */
+ /*036e:*/ 0x20, /* ..#..... */
+/* --- new character bar (124) starting at offset 0x036f --- */
+ /*036f:*/ 4, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0374:*/ 0x40, /* .#...... */
+ /*0375:*/ 0x40, /* .#...... */
+ /*0376:*/ 0x40, /* .#...... */
+ /*0377:*/ 0x40, /* .#...... */
+ /*0378:*/ 0x40, /* .#...... */
+/* --- new character braceright (125) starting at offset 0x0379 --- */
+ /*0379:*/ 4, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*037e:*/ 0x80, /* #....... */
+ /*037f:*/ 0x40, /* .#...... */
+ /*0380:*/ 0x60, /* .##..... */
+ /*0381:*/ 0x40, /* .#...... */
+ /*0382:*/ 0x40, /* .#...... */
+ /*0383:*/ 0x80, /* #....... */
+/* --- new character asciitilde (126) starting at offset 0x0384 --- */
+ /*0384:*/ 4, 4, 2, 0, 3, /* width and bbox (w,h,x,y) */
+ /*0389:*/ 0x50, /* .#.#.... */
+ /*038a:*/ 0xa0, /* #.#..... */
+};
+static const uint16_t font_4x6_offsets[] = {
+0x0000 /* space */,
+ 0x0006 /* exclam */,
+ 0x0010 /* quotedbl */,
+ 0x0017 /* numbersign */,
+ 0x0021 /* dollar */,
+ 0x002c /* percent */,
+ 0x0036 /* ampersand */,
+ 0x0040 /* quotesingle */,
+ 0x0047 /* parenleft */,
+ 0x0052 /* parenright */,
+ 0x005d /* asterisk */,
+ 0x0067 /* plus */,
+ 0x0071 /* comma */,
+ 0x0078 /* hyphen */,
+ 0x007e /* period */,
+ 0x0084 /* slash */,
+ 0x008e /* zero */,
+ 0x0098 /* one */,
+ 0x00a2 /* two */,
+ 0x00ac /* three */,
+ 0x00b6 /* four */,
+ 0x00c0 /* five */,
+ 0x00ca /* six */,
+ 0x00d4 /* seven */,
+ 0x00de /* eight */,
+ 0x00e8 /* nine */,
+ 0x00f2 /* colon */,
+ 0x00fb /* semicolon */,
+ 0x0105 /* less */,
+ 0x010f /* equal */,
+ 0x0117 /* greater */,
+ 0x0121 /* question */,
+ 0x012b /* at */,
+ 0x0135 /* A */,
+ 0x013f /* B */,
+ 0x0149 /* C */,
+ 0x0153 /* D */,
+ 0x015d /* E */,
+ 0x0167 /* F */,
+ 0x0171 /* G */,
+ 0x017b /* H */,
+ 0x0185 /* I */,
+ 0x018f /* J */,
+ 0x0199 /* K */,
+ 0x01a3 /* L */,
+ 0x01ad /* M */,
+ 0x01b7 /* N */,
+ 0x01c1 /* O */,
+ 0x01cb /* P */,
+ 0x01d5 /* Q */,
+ 0x01e0 /* R */,
+ 0x01ea /* S */,
+ 0x01f4 /* T */,
+ 0x01fe /* U */,
+ 0x0208 /* V */,
+ 0x0212 /* W */,
+ 0x021c /* X */,
+ 0x0226 /* Y */,
+ 0x0230 /* Z */,
+ 0x023a /* bracketleft */,
+ 0x0244 /* backslash */,
+ 0x024e /* bracketright */,
+ 0x0258 /* asciicircum */,
+ 0x025f /* underscore */,
+ 0x0265 /* grave */,
+ 0x026c /* a */,
+ 0x0275 /* b */,
+ 0x027f /* c */,
+ 0x0288 /* d */,
+ 0x0292 /* e */,
+ 0x029b /* f */,
+ 0x02a5 /* g */,
+ 0x02af /* h */,
+ 0x02b9 /* i */,
+ 0x02c3 /* j */,
+ 0x02ce /* k */,
+ 0x02d8 /* l */,
+ 0x02e2 /* m */,
+ 0x02eb /* n */,
+ 0x02f4 /* o */,
+ 0x02fd /* p */,
+ 0x0307 /* q */,
+ 0x0311 /* r */,
+ 0x031a /* s */,
+ 0x0323 /* t */,
+ 0x032d /* u */,
+ 0x0336 /* v */,
+ 0x033f /* w */,
+ 0x0348 /* x */,
+ 0x0351 /* y */,
+ 0x035b /* z */,
+ 0x0364 /* braceleft */,
+ 0x036f /* bar */,
+ 0x0379 /* braceright */,
+ 0x0384 /* asciitilde */,
+ 0xffff /* (no glyph) */
+};
+const struct fb_font font_4x6 = {
+ .height = 6,
+ .ascent = 5,
+ .firstchar = 32, /* space */
+ .lastchar = 127, /* ? */
+ .chardata = font_4x6_data,
+ .charoffs = font_4x6_offsets,
+};
diff --git a/Src/osmolib/src/target/firmware/fb/5x8.c b/Src/osmolib/src/target/firmware/fb/5x8.c
new file mode 100644
index 0000000..e200329
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/5x8.c
@@ -0,0 +1,802 @@
+#include <fb/font.h>
+static const uint8_t font_5x8_data[] = {
+/* --- new character space (32) starting at offset 0x0000 --- */
+ /*0000:*/ 5, 5, 1, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0005:*/ 0x00, /* ........ */
+/* --- new character exclam (33) starting at offset 0x0006 --- */
+ /*0006:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*000b:*/ 0x20, /* ..#..... */
+ /*000c:*/ 0x20, /* ..#..... */
+ /*000d:*/ 0x20, /* ..#..... */
+ /*000e:*/ 0x20, /* ..#..... */
+ /*000f:*/ 0x00, /* ........ */
+ /*0010:*/ 0x20, /* ..#..... */
+/* --- new character quotedbl (34) starting at offset 0x0011 --- */
+ /*0011:*/ 5, 5, 3, 0, 3, /* width and bbox (w,h,x,y) */
+ /*0016:*/ 0x50, /* .#.#.... */
+ /*0017:*/ 0x50, /* .#.#.... */
+ /*0018:*/ 0x50, /* .#.#.... */
+/* --- new character numbersign (35) starting at offset 0x0019 --- */
+ /*0019:*/ 5, 5, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*001e:*/ 0x50, /* .#.#.... */
+ /*001f:*/ 0x50, /* .#.#.... */
+ /*0020:*/ 0xf8, /* #####... */
+ /*0021:*/ 0x50, /* .#.#.... */
+ /*0022:*/ 0xf8, /* #####... */
+ /*0023:*/ 0x50, /* .#.#.... */
+ /*0024:*/ 0x50, /* .#.#.... */
+/* --- new character dollar (36) starting at offset 0x0025 --- */
+ /*0025:*/ 5, 5, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*002a:*/ 0x20, /* ..#..... */
+ /*002b:*/ 0x70, /* .###.... */
+ /*002c:*/ 0xa0, /* #.#..... */
+ /*002d:*/ 0x70, /* .###.... */
+ /*002e:*/ 0x28, /* ..#.#... */
+ /*002f:*/ 0x70, /* .###.... */
+ /*0030:*/ 0x20, /* ..#..... */
+/* --- new character percent (37) starting at offset 0x0031 --- */
+ /*0031:*/ 5, 5, 5, 0, 1, /* width and bbox (w,h,x,y) */
+ /*0036:*/ 0x40, /* .#...... */
+ /*0037:*/ 0x50, /* .#.#.... */
+ /*0038:*/ 0x20, /* ..#..... */
+ /*0039:*/ 0x50, /* .#.#.... */
+ /*003a:*/ 0x10, /* ...#.... */
+/* --- new character ampersand (38) starting at offset 0x003b --- */
+ /*003b:*/ 5, 5, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0040:*/ 0x40, /* .#...... */
+ /*0041:*/ 0xa0, /* #.#..... */
+ /*0042:*/ 0xa0, /* #.#..... */
+ /*0043:*/ 0x40, /* .#...... */
+ /*0044:*/ 0xa0, /* #.#..... */
+ /*0045:*/ 0xa0, /* #.#..... */
+ /*0046:*/ 0x50, /* .#.#.... */
+/* --- new character quotesingle (39) starting at offset 0x0047 --- */
+ /*0047:*/ 5, 5, 3, 0, 3, /* width and bbox (w,h,x,y) */
+ /*004c:*/ 0x20, /* ..#..... */
+ /*004d:*/ 0x20, /* ..#..... */
+ /*004e:*/ 0x20, /* ..#..... */
+/* --- new character parenleft (40) starting at offset 0x004f --- */
+ /*004f:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0054:*/ 0x20, /* ..#..... */
+ /*0055:*/ 0x40, /* .#...... */
+ /*0056:*/ 0x40, /* .#...... */
+ /*0057:*/ 0x40, /* .#...... */
+ /*0058:*/ 0x40, /* .#...... */
+ /*0059:*/ 0x20, /* ..#..... */
+/* --- new character parenright (41) starting at offset 0x005a --- */
+ /*005a:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*005f:*/ 0x40, /* .#...... */
+ /*0060:*/ 0x20, /* ..#..... */
+ /*0061:*/ 0x20, /* ..#..... */
+ /*0062:*/ 0x20, /* ..#..... */
+ /*0063:*/ 0x20, /* ..#..... */
+ /*0064:*/ 0x40, /* .#...... */
+/* --- new character asterisk (42) starting at offset 0x0065 --- */
+ /*0065:*/ 5, 5, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*006a:*/ 0x90, /* #..#.... */
+ /*006b:*/ 0x60, /* .##..... */
+ /*006c:*/ 0xf0, /* ####.... */
+ /*006d:*/ 0x60, /* .##..... */
+ /*006e:*/ 0x90, /* #..#.... */
+/* --- new character plus (43) starting at offset 0x006f --- */
+ /*006f:*/ 5, 5, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0074:*/ 0x20, /* ..#..... */
+ /*0075:*/ 0x20, /* ..#..... */
+ /*0076:*/ 0xf8, /* #####... */
+ /*0077:*/ 0x20, /* ..#..... */
+ /*0078:*/ 0x20, /* ..#..... */
+/* --- new character comma (44) starting at offset 0x0079 --- */
+ /*0079:*/ 5, 5, 3, 0, -1, /* width and bbox (w,h,x,y) */
+ /*007e:*/ 0x30, /* ..##.... */
+ /*007f:*/ 0x20, /* ..#..... */
+ /*0080:*/ 0x40, /* .#...... */
+/* --- new character hyphen (45) starting at offset 0x0081 --- */
+ /*0081:*/ 5, 5, 1, 0, 2, /* width and bbox (w,h,x,y) */
+ /*0086:*/ 0x70, /* .###.... */
+/* --- new character period (46) starting at offset 0x0087 --- */
+ /*0087:*/ 5, 5, 3, 0, -1, /* width and bbox (w,h,x,y) */
+ /*008c:*/ 0x20, /* ..#..... */
+ /*008d:*/ 0x70, /* .###.... */
+ /*008e:*/ 0x20, /* ..#..... */
+/* --- new character slash (47) starting at offset 0x008f --- */
+ /*008f:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0094:*/ 0x10, /* ...#.... */
+ /*0095:*/ 0x10, /* ...#.... */
+ /*0096:*/ 0x20, /* ..#..... */
+ /*0097:*/ 0x40, /* .#...... */
+ /*0098:*/ 0x80, /* #....... */
+ /*0099:*/ 0x80, /* #....... */
+/* --- new character zero (48) starting at offset 0x009a --- */
+ /*009a:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*009f:*/ 0x20, /* ..#..... */
+ /*00a0:*/ 0x50, /* .#.#.... */
+ /*00a1:*/ 0x50, /* .#.#.... */
+ /*00a2:*/ 0x50, /* .#.#.... */
+ /*00a3:*/ 0x50, /* .#.#.... */
+ /*00a4:*/ 0x20, /* ..#..... */
+/* --- new character one (49) starting at offset 0x00a5 --- */
+ /*00a5:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00aa:*/ 0x20, /* ..#..... */
+ /*00ab:*/ 0x60, /* .##..... */
+ /*00ac:*/ 0x20, /* ..#..... */
+ /*00ad:*/ 0x20, /* ..#..... */
+ /*00ae:*/ 0x20, /* ..#..... */
+ /*00af:*/ 0x70, /* .###.... */
+/* --- new character two (50) starting at offset 0x00b0 --- */
+ /*00b0:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00b5:*/ 0x60, /* .##..... */
+ /*00b6:*/ 0x90, /* #..#.... */
+ /*00b7:*/ 0x10, /* ...#.... */
+ /*00b8:*/ 0x60, /* .##..... */
+ /*00b9:*/ 0x80, /* #....... */
+ /*00ba:*/ 0xf0, /* ####.... */
+/* --- new character three (51) starting at offset 0x00bb --- */
+ /*00bb:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00c0:*/ 0xf0, /* ####.... */
+ /*00c1:*/ 0x20, /* ..#..... */
+ /*00c2:*/ 0x60, /* .##..... */
+ /*00c3:*/ 0x10, /* ...#.... */
+ /*00c4:*/ 0x90, /* #..#.... */
+ /*00c5:*/ 0x60, /* .##..... */
+/* --- new character four (52) starting at offset 0x00c6 --- */
+ /*00c6:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00cb:*/ 0x20, /* ..#..... */
+ /*00cc:*/ 0x60, /* .##..... */
+ /*00cd:*/ 0xa0, /* #.#..... */
+ /*00ce:*/ 0xf0, /* ####.... */
+ /*00cf:*/ 0x20, /* ..#..... */
+ /*00d0:*/ 0x20, /* ..#..... */
+/* --- new character five (53) starting at offset 0x00d1 --- */
+ /*00d1:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00d6:*/ 0xf0, /* ####.... */
+ /*00d7:*/ 0x80, /* #....... */
+ /*00d8:*/ 0xe0, /* ###..... */
+ /*00d9:*/ 0x10, /* ...#.... */
+ /*00da:*/ 0x90, /* #..#.... */
+ /*00db:*/ 0x60, /* .##..... */
+/* --- new character six (54) starting at offset 0x00dc --- */
+ /*00dc:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00e1:*/ 0x60, /* .##..... */
+ /*00e2:*/ 0x80, /* #....... */
+ /*00e3:*/ 0xe0, /* ###..... */
+ /*00e4:*/ 0x90, /* #..#.... */
+ /*00e5:*/ 0x90, /* #..#.... */
+ /*00e6:*/ 0x60, /* .##..... */
+/* --- new character seven (55) starting at offset 0x00e7 --- */
+ /*00e7:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00ec:*/ 0xf0, /* ####.... */
+ /*00ed:*/ 0x10, /* ...#.... */
+ /*00ee:*/ 0x20, /* ..#..... */
+ /*00ef:*/ 0x20, /* ..#..... */
+ /*00f0:*/ 0x40, /* .#...... */
+ /*00f1:*/ 0x40, /* .#...... */
+/* --- new character eight (56) starting at offset 0x00f2 --- */
+ /*00f2:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00f7:*/ 0x60, /* .##..... */
+ /*00f8:*/ 0x90, /* #..#.... */
+ /*00f9:*/ 0x60, /* .##..... */
+ /*00fa:*/ 0x90, /* #..#.... */
+ /*00fb:*/ 0x90, /* #..#.... */
+ /*00fc:*/ 0x60, /* .##..... */
+/* --- new character nine (57) starting at offset 0x00fd --- */
+ /*00fd:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0102:*/ 0x60, /* .##..... */
+ /*0103:*/ 0x90, /* #..#.... */
+ /*0104:*/ 0x90, /* #..#.... */
+ /*0105:*/ 0x70, /* .###.... */
+ /*0106:*/ 0x10, /* ...#.... */
+ /*0107:*/ 0x60, /* .##..... */
+/* --- new character colon (58) starting at offset 0x0108 --- */
+ /*0108:*/ 5, 5, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*010d:*/ 0x60, /* .##..... */
+ /*010e:*/ 0x60, /* .##..... */
+ /*010f:*/ 0x00, /* ........ */
+ /*0110:*/ 0x60, /* .##..... */
+ /*0111:*/ 0x60, /* .##..... */
+/* --- new character semicolon (59) starting at offset 0x0112 --- */
+ /*0112:*/ 5, 5, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0117:*/ 0x30, /* ..##.... */
+ /*0118:*/ 0x30, /* ..##.... */
+ /*0119:*/ 0x00, /* ........ */
+ /*011a:*/ 0x30, /* ..##.... */
+ /*011b:*/ 0x20, /* ..#..... */
+ /*011c:*/ 0x40, /* .#...... */
+/* --- new character less (60) starting at offset 0x011d --- */
+ /*011d:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0122:*/ 0x10, /* ...#.... */
+ /*0123:*/ 0x20, /* ..#..... */
+ /*0124:*/ 0x40, /* .#...... */
+ /*0125:*/ 0x40, /* .#...... */
+ /*0126:*/ 0x20, /* ..#..... */
+ /*0127:*/ 0x10, /* ...#.... */
+/* --- new character equal (61) starting at offset 0x0128 --- */
+ /*0128:*/ 5, 5, 3, 0, 1, /* width and bbox (w,h,x,y) */
+ /*012d:*/ 0xf0, /* ####.... */
+ /*012e:*/ 0x00, /* ........ */
+ /*012f:*/ 0xf0, /* ####.... */
+/* --- new character greater (62) starting at offset 0x0130 --- */
+ /*0130:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0135:*/ 0x40, /* .#...... */
+ /*0136:*/ 0x20, /* ..#..... */
+ /*0137:*/ 0x10, /* ...#.... */
+ /*0138:*/ 0x10, /* ...#.... */
+ /*0139:*/ 0x20, /* ..#..... */
+ /*013a:*/ 0x40, /* .#...... */
+/* --- new character question (63) starting at offset 0x013b --- */
+ /*013b:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0140:*/ 0x20, /* ..#..... */
+ /*0141:*/ 0x50, /* .#.#.... */
+ /*0142:*/ 0x10, /* ...#.... */
+ /*0143:*/ 0x20, /* ..#..... */
+ /*0144:*/ 0x00, /* ........ */
+ /*0145:*/ 0x20, /* ..#..... */
+/* --- new character at (64) starting at offset 0x0146 --- */
+ /*0146:*/ 5, 5, 8, 0, -1, /* width and bbox (w,h,x,y) */
+ /*014b:*/ 0x30, /* ..##.... */
+ /*014c:*/ 0x48, /* .#..#... */
+ /*014d:*/ 0x98, /* #..##... */
+ /*014e:*/ 0xa8, /* #.#.#... */
+ /*014f:*/ 0xa8, /* #.#.#... */
+ /*0150:*/ 0x90, /* #..#.... */
+ /*0151:*/ 0x40, /* .#...... */
+ /*0152:*/ 0x30, /* ..##.... */
+/* --- new character A (65) starting at offset 0x0153 --- */
+ /*0153:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0158:*/ 0x60, /* .##..... */
+ /*0159:*/ 0x90, /* #..#.... */
+ /*015a:*/ 0x90, /* #..#.... */
+ /*015b:*/ 0xf0, /* ####.... */
+ /*015c:*/ 0x90, /* #..#.... */
+ /*015d:*/ 0x90, /* #..#.... */
+/* --- new character B (66) starting at offset 0x015e --- */
+ /*015e:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0163:*/ 0xe0, /* ###..... */
+ /*0164:*/ 0x90, /* #..#.... */
+ /*0165:*/ 0xe0, /* ###..... */
+ /*0166:*/ 0x90, /* #..#.... */
+ /*0167:*/ 0x90, /* #..#.... */
+ /*0168:*/ 0xe0, /* ###..... */
+/* --- new character C (67) starting at offset 0x0169 --- */
+ /*0169:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*016e:*/ 0x60, /* .##..... */
+ /*016f:*/ 0x90, /* #..#.... */
+ /*0170:*/ 0x80, /* #....... */
+ /*0171:*/ 0x80, /* #....... */
+ /*0172:*/ 0x90, /* #..#.... */
+ /*0173:*/ 0x60, /* .##..... */
+/* --- new character D (68) starting at offset 0x0174 --- */
+ /*0174:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0179:*/ 0xe0, /* ###..... */
+ /*017a:*/ 0x90, /* #..#.... */
+ /*017b:*/ 0x90, /* #..#.... */
+ /*017c:*/ 0x90, /* #..#.... */
+ /*017d:*/ 0x90, /* #..#.... */
+ /*017e:*/ 0xe0, /* ###..... */
+/* --- new character E (69) starting at offset 0x017f --- */
+ /*017f:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0184:*/ 0xf0, /* ####.... */
+ /*0185:*/ 0x80, /* #....... */
+ /*0186:*/ 0xe0, /* ###..... */
+ /*0187:*/ 0x80, /* #....... */
+ /*0188:*/ 0x80, /* #....... */
+ /*0189:*/ 0xf0, /* ####.... */
+/* --- new character F (70) starting at offset 0x018a --- */
+ /*018a:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*018f:*/ 0xf0, /* ####.... */
+ /*0190:*/ 0x80, /* #....... */
+ /*0191:*/ 0xe0, /* ###..... */
+ /*0192:*/ 0x80, /* #....... */
+ /*0193:*/ 0x80, /* #....... */
+ /*0194:*/ 0x80, /* #....... */
+/* --- new character G (71) starting at offset 0x0195 --- */
+ /*0195:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*019a:*/ 0x60, /* .##..... */
+ /*019b:*/ 0x90, /* #..#.... */
+ /*019c:*/ 0x80, /* #....... */
+ /*019d:*/ 0xb0, /* #.##.... */
+ /*019e:*/ 0x90, /* #..#.... */
+ /*019f:*/ 0x60, /* .##..... */
+/* --- new character H (72) starting at offset 0x01a0 --- */
+ /*01a0:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01a5:*/ 0x90, /* #..#.... */
+ /*01a6:*/ 0x90, /* #..#.... */
+ /*01a7:*/ 0xf0, /* ####.... */
+ /*01a8:*/ 0x90, /* #..#.... */
+ /*01a9:*/ 0x90, /* #..#.... */
+ /*01aa:*/ 0x90, /* #..#.... */
+/* --- new character I (73) starting at offset 0x01ab --- */
+ /*01ab:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01b0:*/ 0x70, /* .###.... */
+ /*01b1:*/ 0x20, /* ..#..... */
+ /*01b2:*/ 0x20, /* ..#..... */
+ /*01b3:*/ 0x20, /* ..#..... */
+ /*01b4:*/ 0x20, /* ..#..... */
+ /*01b5:*/ 0x70, /* .###.... */
+/* --- new character J (74) starting at offset 0x01b6 --- */
+ /*01b6:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01bb:*/ 0x70, /* .###.... */
+ /*01bc:*/ 0x20, /* ..#..... */
+ /*01bd:*/ 0x20, /* ..#..... */
+ /*01be:*/ 0x20, /* ..#..... */
+ /*01bf:*/ 0xa0, /* #.#..... */
+ /*01c0:*/ 0x40, /* .#...... */
+/* --- new character K (75) starting at offset 0x01c1 --- */
+ /*01c1:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01c6:*/ 0x90, /* #..#.... */
+ /*01c7:*/ 0xa0, /* #.#..... */
+ /*01c8:*/ 0xc0, /* ##...... */
+ /*01c9:*/ 0xa0, /* #.#..... */
+ /*01ca:*/ 0xa0, /* #.#..... */
+ /*01cb:*/ 0x90, /* #..#.... */
+/* --- new character L (76) starting at offset 0x01cc --- */
+ /*01cc:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01d1:*/ 0x80, /* #....... */
+ /*01d2:*/ 0x80, /* #....... */
+ /*01d3:*/ 0x80, /* #....... */
+ /*01d4:*/ 0x80, /* #....... */
+ /*01d5:*/ 0x80, /* #....... */
+ /*01d6:*/ 0xf0, /* ####.... */
+/* --- new character M (77) starting at offset 0x01d7 --- */
+ /*01d7:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01dc:*/ 0x90, /* #..#.... */
+ /*01dd:*/ 0xf0, /* ####.... */
+ /*01de:*/ 0xf0, /* ####.... */
+ /*01df:*/ 0x90, /* #..#.... */
+ /*01e0:*/ 0x90, /* #..#.... */
+ /*01e1:*/ 0x90, /* #..#.... */
+/* --- new character N (78) starting at offset 0x01e2 --- */
+ /*01e2:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01e7:*/ 0x90, /* #..#.... */
+ /*01e8:*/ 0xd0, /* ##.#.... */
+ /*01e9:*/ 0xf0, /* ####.... */
+ /*01ea:*/ 0xb0, /* #.##.... */
+ /*01eb:*/ 0xb0, /* #.##.... */
+ /*01ec:*/ 0x90, /* #..#.... */
+/* --- new character O (79) starting at offset 0x01ed --- */
+ /*01ed:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01f2:*/ 0x60, /* .##..... */
+ /*01f3:*/ 0x90, /* #..#.... */
+ /*01f4:*/ 0x90, /* #..#.... */
+ /*01f5:*/ 0x90, /* #..#.... */
+ /*01f6:*/ 0x90, /* #..#.... */
+ /*01f7:*/ 0x60, /* .##..... */
+/* --- new character P (80) starting at offset 0x01f8 --- */
+ /*01f8:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01fd:*/ 0xe0, /* ###..... */
+ /*01fe:*/ 0x90, /* #..#.... */
+ /*01ff:*/ 0x90, /* #..#.... */
+ /*0200:*/ 0xe0, /* ###..... */
+ /*0201:*/ 0x80, /* #....... */
+ /*0202:*/ 0x80, /* #....... */
+/* --- new character Q (81) starting at offset 0x0203 --- */
+ /*0203:*/ 5, 5, 7, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0208:*/ 0x60, /* .##..... */
+ /*0209:*/ 0x90, /* #..#.... */
+ /*020a:*/ 0x90, /* #..#.... */
+ /*020b:*/ 0xd0, /* ##.#.... */
+ /*020c:*/ 0xb0, /* #.##.... */
+ /*020d:*/ 0x60, /* .##..... */
+ /*020e:*/ 0x10, /* ...#.... */
+/* --- new character R (82) starting at offset 0x020f --- */
+ /*020f:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0214:*/ 0xe0, /* ###..... */
+ /*0215:*/ 0x90, /* #..#.... */
+ /*0216:*/ 0x90, /* #..#.... */
+ /*0217:*/ 0xe0, /* ###..... */
+ /*0218:*/ 0x90, /* #..#.... */
+ /*0219:*/ 0x90, /* #..#.... */
+/* --- new character S (83) starting at offset 0x021a --- */
+ /*021a:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*021f:*/ 0x60, /* .##..... */
+ /*0220:*/ 0x90, /* #..#.... */
+ /*0221:*/ 0x40, /* .#...... */
+ /*0222:*/ 0x20, /* ..#..... */
+ /*0223:*/ 0x90, /* #..#.... */
+ /*0224:*/ 0x60, /* .##..... */
+/* --- new character T (84) starting at offset 0x0225 --- */
+ /*0225:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*022a:*/ 0x70, /* .###.... */
+ /*022b:*/ 0x20, /* ..#..... */
+ /*022c:*/ 0x20, /* ..#..... */
+ /*022d:*/ 0x20, /* ..#..... */
+ /*022e:*/ 0x20, /* ..#..... */
+ /*022f:*/ 0x20, /* ..#..... */
+/* --- new character U (85) starting at offset 0x0230 --- */
+ /*0230:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0235:*/ 0x90, /* #..#.... */
+ /*0236:*/ 0x90, /* #..#.... */
+ /*0237:*/ 0x90, /* #..#.... */
+ /*0238:*/ 0x90, /* #..#.... */
+ /*0239:*/ 0x90, /* #..#.... */
+ /*023a:*/ 0x60, /* .##..... */
+/* --- new character V (86) starting at offset 0x023b --- */
+ /*023b:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0240:*/ 0x90, /* #..#.... */
+ /*0241:*/ 0x90, /* #..#.... */
+ /*0242:*/ 0x90, /* #..#.... */
+ /*0243:*/ 0x90, /* #..#.... */
+ /*0244:*/ 0x60, /* .##..... */
+ /*0245:*/ 0x60, /* .##..... */
+/* --- new character W (87) starting at offset 0x0246 --- */
+ /*0246:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*024b:*/ 0x90, /* #..#.... */
+ /*024c:*/ 0x90, /* #..#.... */
+ /*024d:*/ 0x90, /* #..#.... */
+ /*024e:*/ 0xf0, /* ####.... */
+ /*024f:*/ 0xf0, /* ####.... */
+ /*0250:*/ 0x90, /* #..#.... */
+/* --- new character X (88) starting at offset 0x0251 --- */
+ /*0251:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0256:*/ 0x90, /* #..#.... */
+ /*0257:*/ 0x90, /* #..#.... */
+ /*0258:*/ 0x60, /* .##..... */
+ /*0259:*/ 0x60, /* .##..... */
+ /*025a:*/ 0x90, /* #..#.... */
+ /*025b:*/ 0x90, /* #..#.... */
+/* --- new character Y (89) starting at offset 0x025c --- */
+ /*025c:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0261:*/ 0x88, /* #...#... */
+ /*0262:*/ 0x88, /* #...#... */
+ /*0263:*/ 0x50, /* .#.#.... */
+ /*0264:*/ 0x20, /* ..#..... */
+ /*0265:*/ 0x20, /* ..#..... */
+ /*0266:*/ 0x20, /* ..#..... */
+/* --- new character Z (90) starting at offset 0x0267 --- */
+ /*0267:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*026c:*/ 0xf0, /* ####.... */
+ /*026d:*/ 0x10, /* ...#.... */
+ /*026e:*/ 0x20, /* ..#..... */
+ /*026f:*/ 0x40, /* .#...... */
+ /*0270:*/ 0x80, /* #....... */
+ /*0271:*/ 0xf0, /* ####.... */
+/* --- new character bracketleft (91) starting at offset 0x0272 --- */
+ /*0272:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0277:*/ 0x70, /* .###.... */
+ /*0278:*/ 0x40, /* .#...... */
+ /*0279:*/ 0x40, /* .#...... */
+ /*027a:*/ 0x40, /* .#...... */
+ /*027b:*/ 0x40, /* .#...... */
+ /*027c:*/ 0x70, /* .###.... */
+/* --- new character backslash (92) starting at offset 0x027d --- */
+ /*027d:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0282:*/ 0x80, /* #....... */
+ /*0283:*/ 0x80, /* #....... */
+ /*0284:*/ 0x40, /* .#...... */
+ /*0285:*/ 0x20, /* ..#..... */
+ /*0286:*/ 0x10, /* ...#.... */
+ /*0287:*/ 0x10, /* ...#.... */
+/* --- new character bracketright (93) starting at offset 0x0288 --- */
+ /*0288:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*028d:*/ 0x70, /* .###.... */
+ /*028e:*/ 0x10, /* ...#.... */
+ /*028f:*/ 0x10, /* ...#.... */
+ /*0290:*/ 0x10, /* ...#.... */
+ /*0291:*/ 0x10, /* ...#.... */
+ /*0292:*/ 0x70, /* .###.... */
+/* --- new character asciicircum (94) starting at offset 0x0293 --- */
+ /*0293:*/ 5, 5, 2, 0, 4, /* width and bbox (w,h,x,y) */
+ /*0298:*/ 0x20, /* ..#..... */
+ /*0299:*/ 0x50, /* .#.#.... */
+/* --- new character underscore (95) starting at offset 0x029a --- */
+ /*029a:*/ 5, 5, 1, 0, -1, /* width and bbox (w,h,x,y) */
+ /*029f:*/ 0xf0, /* ####.... */
+/* --- new character grave (96) starting at offset 0x02a0 --- */
+ /*02a0:*/ 5, 5, 2, 0, 4, /* width and bbox (w,h,x,y) */
+ /*02a5:*/ 0x40, /* .#...... */
+ /*02a6:*/ 0x20, /* ..#..... */
+/* --- new character a (97) starting at offset 0x02a7 --- */
+ /*02a7:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02ac:*/ 0x70, /* .###.... */
+ /*02ad:*/ 0x90, /* #..#.... */
+ /*02ae:*/ 0x90, /* #..#.... */
+ /*02af:*/ 0x70, /* .###.... */
+/* --- new character b (98) starting at offset 0x02b0 --- */
+ /*02b0:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02b5:*/ 0x80, /* #....... */
+ /*02b6:*/ 0x80, /* #....... */
+ /*02b7:*/ 0xe0, /* ###..... */
+ /*02b8:*/ 0x90, /* #..#.... */
+ /*02b9:*/ 0x90, /* #..#.... */
+ /*02ba:*/ 0xe0, /* ###..... */
+/* --- new character c (99) starting at offset 0x02bb --- */
+ /*02bb:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02c0:*/ 0x30, /* ..##.... */
+ /*02c1:*/ 0x40, /* .#...... */
+ /*02c2:*/ 0x40, /* .#...... */
+ /*02c3:*/ 0x30, /* ..##.... */
+/* --- new character d (100) starting at offset 0x02c4 --- */
+ /*02c4:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02c9:*/ 0x10, /* ...#.... */
+ /*02ca:*/ 0x10, /* ...#.... */
+ /*02cb:*/ 0x70, /* .###.... */
+ /*02cc:*/ 0x90, /* #..#.... */
+ /*02cd:*/ 0x90, /* #..#.... */
+ /*02ce:*/ 0x70, /* .###.... */
+/* --- new character e (101) starting at offset 0x02cf --- */
+ /*02cf:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02d4:*/ 0x60, /* .##..... */
+ /*02d5:*/ 0xb0, /* #.##.... */
+ /*02d6:*/ 0xc0, /* ##...... */
+ /*02d7:*/ 0x60, /* .##..... */
+/* --- new character f (102) starting at offset 0x02d8 --- */
+ /*02d8:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02dd:*/ 0x20, /* ..#..... */
+ /*02de:*/ 0x50, /* .#.#.... */
+ /*02df:*/ 0x40, /* .#...... */
+ /*02e0:*/ 0xe0, /* ###..... */
+ /*02e1:*/ 0x40, /* .#...... */
+ /*02e2:*/ 0x40, /* .#...... */
+/* --- new character g (103) starting at offset 0x02e3 --- */
+ /*02e3:*/ 5, 5, 5, 0, -1, /* width and bbox (w,h,x,y) */
+ /*02e8:*/ 0x60, /* .##..... */
+ /*02e9:*/ 0x90, /* #..#.... */
+ /*02ea:*/ 0x70, /* .###.... */
+ /*02eb:*/ 0x10, /* ...#.... */
+ /*02ec:*/ 0x60, /* .##..... */
+/* --- new character h (104) starting at offset 0x02ed --- */
+ /*02ed:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02f2:*/ 0x80, /* #....... */
+ /*02f3:*/ 0x80, /* #....... */
+ /*02f4:*/ 0xe0, /* ###..... */
+ /*02f5:*/ 0x90, /* #..#.... */
+ /*02f6:*/ 0x90, /* #..#.... */
+ /*02f7:*/ 0x90, /* #..#.... */
+/* --- new character i (105) starting at offset 0x02f8 --- */
+ /*02f8:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02fd:*/ 0x20, /* ..#..... */
+ /*02fe:*/ 0x00, /* ........ */
+ /*02ff:*/ 0x60, /* .##..... */
+ /*0300:*/ 0x20, /* ..#..... */
+ /*0301:*/ 0x20, /* ..#..... */
+ /*0302:*/ 0x70, /* .###.... */
+/* --- new character j (106) starting at offset 0x0303 --- */
+ /*0303:*/ 5, 5, 7, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0308:*/ 0x10, /* ...#.... */
+ /*0309:*/ 0x00, /* ........ */
+ /*030a:*/ 0x10, /* ...#.... */
+ /*030b:*/ 0x10, /* ...#.... */
+ /*030c:*/ 0x10, /* ...#.... */
+ /*030d:*/ 0x50, /* .#.#.... */
+ /*030e:*/ 0x20, /* ..#..... */
+/* --- new character k (107) starting at offset 0x030f --- */
+ /*030f:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0314:*/ 0x80, /* #....... */
+ /*0315:*/ 0x80, /* #....... */
+ /*0316:*/ 0x90, /* #..#.... */
+ /*0317:*/ 0xe0, /* ###..... */
+ /*0318:*/ 0x90, /* #..#.... */
+ /*0319:*/ 0x90, /* #..#.... */
+/* --- new character l (108) starting at offset 0x031a --- */
+ /*031a:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*031f:*/ 0x60, /* .##..... */
+ /*0320:*/ 0x20, /* ..#..... */
+ /*0321:*/ 0x20, /* ..#..... */
+ /*0322:*/ 0x20, /* ..#..... */
+ /*0323:*/ 0x20, /* ..#..... */
+ /*0324:*/ 0x70, /* .###.... */
+/* --- new character m (109) starting at offset 0x0325 --- */
+ /*0325:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*032a:*/ 0xd0, /* ##.#.... */
+ /*032b:*/ 0xa8, /* #.#.#... */
+ /*032c:*/ 0xa8, /* #.#.#... */
+ /*032d:*/ 0xa8, /* #.#.#... */
+/* --- new character n (110) starting at offset 0x032e --- */
+ /*032e:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0333:*/ 0xe0, /* ###..... */
+ /*0334:*/ 0x90, /* #..#.... */
+ /*0335:*/ 0x90, /* #..#.... */
+ /*0336:*/ 0x90, /* #..#.... */
+/* --- new character o (111) starting at offset 0x0337 --- */
+ /*0337:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*033c:*/ 0x60, /* .##..... */
+ /*033d:*/ 0x90, /* #..#.... */
+ /*033e:*/ 0x90, /* #..#.... */
+ /*033f:*/ 0x60, /* .##..... */
+/* --- new character p (112) starting at offset 0x0340 --- */
+ /*0340:*/ 5, 5, 5, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0345:*/ 0xe0, /* ###..... */
+ /*0346:*/ 0x90, /* #..#.... */
+ /*0347:*/ 0xe0, /* ###..... */
+ /*0348:*/ 0x80, /* #....... */
+ /*0349:*/ 0x80, /* #....... */
+/* --- new character q (113) starting at offset 0x034a --- */
+ /*034a:*/ 5, 5, 5, 0, -1, /* width and bbox (w,h,x,y) */
+ /*034f:*/ 0x70, /* .###.... */
+ /*0350:*/ 0x90, /* #..#.... */
+ /*0351:*/ 0x70, /* .###.... */
+ /*0352:*/ 0x10, /* ...#.... */
+ /*0353:*/ 0x10, /* ...#.... */
+/* --- new character r (114) starting at offset 0x0354 --- */
+ /*0354:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0359:*/ 0xa0, /* #.#..... */
+ /*035a:*/ 0xd0, /* ##.#.... */
+ /*035b:*/ 0x80, /* #....... */
+ /*035c:*/ 0x80, /* #....... */
+/* --- new character s (115) starting at offset 0x035d --- */
+ /*035d:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0362:*/ 0x30, /* ..##.... */
+ /*0363:*/ 0x60, /* .##..... */
+ /*0364:*/ 0x10, /* ...#.... */
+ /*0365:*/ 0x60, /* .##..... */
+/* --- new character t (116) starting at offset 0x0366 --- */
+ /*0366:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*036b:*/ 0x40, /* .#...... */
+ /*036c:*/ 0x40, /* .#...... */
+ /*036d:*/ 0xe0, /* ###..... */
+ /*036e:*/ 0x40, /* .#...... */
+ /*036f:*/ 0x50, /* .#.#.... */
+ /*0370:*/ 0x20, /* ..#..... */
+/* --- new character u (117) starting at offset 0x0371 --- */
+ /*0371:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0376:*/ 0x90, /* #..#.... */
+ /*0377:*/ 0x90, /* #..#.... */
+ /*0378:*/ 0x90, /* #..#.... */
+ /*0379:*/ 0x70, /* .###.... */
+/* --- new character v (118) starting at offset 0x037a --- */
+ /*037a:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*037f:*/ 0x50, /* .#.#.... */
+ /*0380:*/ 0x50, /* .#.#.... */
+ /*0381:*/ 0x50, /* .#.#.... */
+ /*0382:*/ 0x20, /* ..#..... */
+/* --- new character w (119) starting at offset 0x0383 --- */
+ /*0383:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0388:*/ 0x88, /* #...#... */
+ /*0389:*/ 0xa8, /* #.#.#... */
+ /*038a:*/ 0xa8, /* #.#.#... */
+ /*038b:*/ 0x50, /* .#.#.... */
+/* --- new character x (120) starting at offset 0x038c --- */
+ /*038c:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0391:*/ 0x90, /* #..#.... */
+ /*0392:*/ 0x60, /* .##..... */
+ /*0393:*/ 0x60, /* .##..... */
+ /*0394:*/ 0x90, /* #..#.... */
+/* --- new character y (121) starting at offset 0x0395 --- */
+ /*0395:*/ 5, 5, 5, 0, -1, /* width and bbox (w,h,x,y) */
+ /*039a:*/ 0x90, /* #..#.... */
+ /*039b:*/ 0x90, /* #..#.... */
+ /*039c:*/ 0x70, /* .###.... */
+ /*039d:*/ 0x90, /* #..#.... */
+ /*039e:*/ 0x60, /* .##..... */
+/* --- new character z (122) starting at offset 0x039f --- */
+ /*039f:*/ 5, 5, 4, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03a4:*/ 0xf0, /* ####.... */
+ /*03a5:*/ 0x20, /* ..#..... */
+ /*03a6:*/ 0x40, /* .#...... */
+ /*03a7:*/ 0xf0, /* ####.... */
+/* --- new character braceleft (123) starting at offset 0x03a8 --- */
+ /*03a8:*/ 5, 5, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03ad:*/ 0x30, /* ..##.... */
+ /*03ae:*/ 0x40, /* .#...... */
+ /*03af:*/ 0x20, /* ..#..... */
+ /*03b0:*/ 0xc0, /* ##...... */
+ /*03b1:*/ 0x20, /* ..#..... */
+ /*03b2:*/ 0x40, /* .#...... */
+ /*03b3:*/ 0x30, /* ..##.... */
+/* --- new character bar (124) starting at offset 0x03b4 --- */
+ /*03b4:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03b9:*/ 0x20, /* ..#..... */
+ /*03ba:*/ 0x20, /* ..#..... */
+ /*03bb:*/ 0x20, /* ..#..... */
+ /*03bc:*/ 0x20, /* ..#..... */
+ /*03bd:*/ 0x20, /* ..#..... */
+ /*03be:*/ 0x20, /* ..#..... */
+/* --- new character braceright (125) starting at offset 0x03bf --- */
+ /*03bf:*/ 5, 5, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03c4:*/ 0xc0, /* ##...... */
+ /*03c5:*/ 0x20, /* ..#..... */
+ /*03c6:*/ 0x40, /* .#...... */
+ /*03c7:*/ 0x30, /* ..##.... */
+ /*03c8:*/ 0x40, /* .#...... */
+ /*03c9:*/ 0x20, /* ..#..... */
+ /*03ca:*/ 0xc0, /* ##...... */
+/* --- new character asciitilde (126) starting at offset 0x03cb --- */
+ /*03cb:*/ 5, 5, 2, 0, 4, /* width and bbox (w,h,x,y) */
+ /*03d0:*/ 0x50, /* .#.#.... */
+ /*03d1:*/ 0xa0, /* #.#..... */
+};
+static const uint16_t font_5x8_offsets[] = {
+0x0000 /* space */,
+ 0x0006 /* exclam */,
+ 0x0011 /* quotedbl */,
+ 0x0019 /* numbersign */,
+ 0x0025 /* dollar */,
+ 0x0031 /* percent */,
+ 0x003b /* ampersand */,
+ 0x0047 /* quotesingle */,
+ 0x004f /* parenleft */,
+ 0x005a /* parenright */,
+ 0x0065 /* asterisk */,
+ 0x006f /* plus */,
+ 0x0079 /* comma */,
+ 0x0081 /* hyphen */,
+ 0x0087 /* period */,
+ 0x008f /* slash */,
+ 0x009a /* zero */,
+ 0x00a5 /* one */,
+ 0x00b0 /* two */,
+ 0x00bb /* three */,
+ 0x00c6 /* four */,
+ 0x00d1 /* five */,
+ 0x00dc /* six */,
+ 0x00e7 /* seven */,
+ 0x00f2 /* eight */,
+ 0x00fd /* nine */,
+ 0x0108 /* colon */,
+ 0x0112 /* semicolon */,
+ 0x011d /* less */,
+ 0x0128 /* equal */,
+ 0x0130 /* greater */,
+ 0x013b /* question */,
+ 0x0146 /* at */,
+ 0x0153 /* A */,
+ 0x015e /* B */,
+ 0x0169 /* C */,
+ 0x0174 /* D */,
+ 0x017f /* E */,
+ 0x018a /* F */,
+ 0x0195 /* G */,
+ 0x01a0 /* H */,
+ 0x01ab /* I */,
+ 0x01b6 /* J */,
+ 0x01c1 /* K */,
+ 0x01cc /* L */,
+ 0x01d7 /* M */,
+ 0x01e2 /* N */,
+ 0x01ed /* O */,
+ 0x01f8 /* P */,
+ 0x0203 /* Q */,
+ 0x020f /* R */,
+ 0x021a /* S */,
+ 0x0225 /* T */,
+ 0x0230 /* U */,
+ 0x023b /* V */,
+ 0x0246 /* W */,
+ 0x0251 /* X */,
+ 0x025c /* Y */,
+ 0x0267 /* Z */,
+ 0x0272 /* bracketleft */,
+ 0x027d /* backslash */,
+ 0x0288 /* bracketright */,
+ 0x0293 /* asciicircum */,
+ 0x029a /* underscore */,
+ 0x02a0 /* grave */,
+ 0x02a7 /* a */,
+ 0x02b0 /* b */,
+ 0x02bb /* c */,
+ 0x02c4 /* d */,
+ 0x02cf /* e */,
+ 0x02d8 /* f */,
+ 0x02e3 /* g */,
+ 0x02ed /* h */,
+ 0x02f8 /* i */,
+ 0x0303 /* j */,
+ 0x030f /* k */,
+ 0x031a /* l */,
+ 0x0325 /* m */,
+ 0x032e /* n */,
+ 0x0337 /* o */,
+ 0x0340 /* p */,
+ 0x034a /* q */,
+ 0x0354 /* r */,
+ 0x035d /* s */,
+ 0x0366 /* t */,
+ 0x0371 /* u */,
+ 0x037a /* v */,
+ 0x0383 /* w */,
+ 0x038c /* x */,
+ 0x0395 /* y */,
+ 0x039f /* z */,
+ 0x03a8 /* braceleft */,
+ 0x03b4 /* bar */,
+ 0x03bf /* braceright */,
+ 0x03cb /* asciitilde */,
+ 0xffff /* (no glyph) */
+};
+const struct fb_font font_5x8 = {
+ .height = 8,
+ .ascent = 7,
+ .firstchar = 32, /* space */
+ .lastchar = 127, /* ? */
+ .chardata = font_5x8_data,
+ .charoffs = font_5x8_offsets,
+};
diff --git a/Src/osmolib/src/target/firmware/fb/c64.c b/Src/osmolib/src/target/firmware/fb/c64.c
new file mode 100644
index 0000000..82ebfa3
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/c64.c
@@ -0,0 +1,1069 @@
+#include <fb/font.h>
+static const uint8_t font_c64_data[] = {
+/* --- new character ' ' (32) starting at offset 0x0000 --- */
+ /*0000:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0005:*/ 0x00, /* ........ */
+ /*0006:*/ 0x00, /* ........ */
+ /*0007:*/ 0x00, /* ........ */
+ /*0008:*/ 0x00, /* ........ */
+ /*0009:*/ 0x00, /* ........ */
+ /*000a:*/ 0x00, /* ........ */
+ /*000b:*/ 0x00, /* ........ */
+ /*000c:*/ 0x00, /* ........ */
+/* --- new character '!' (33) starting at offset 0x000d --- */
+ /*000d:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0012:*/ 0x18, /* ...##... */
+ /*0013:*/ 0x18, /* ...##... */
+ /*0014:*/ 0x18, /* ...##... */
+ /*0015:*/ 0x18, /* ...##... */
+ /*0016:*/ 0x00, /* ........ */
+ /*0017:*/ 0x00, /* ........ */
+ /*0018:*/ 0x18, /* ...##... */
+ /*0019:*/ 0x00, /* ........ */
+/* --- new character '"' (34) starting at offset 0x001a --- */
+ /*001a:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*001f:*/ 0x66, /* .##..##. */
+ /*0020:*/ 0x66, /* .##..##. */
+ /*0021:*/ 0x66, /* .##..##. */
+ /*0022:*/ 0x00, /* ........ */
+ /*0023:*/ 0x00, /* ........ */
+ /*0024:*/ 0x00, /* ........ */
+ /*0025:*/ 0x00, /* ........ */
+ /*0026:*/ 0x00, /* ........ */
+/* --- new character '#' (35) starting at offset 0x0027 --- */
+ /*0027:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*002c:*/ 0x66, /* .##..##. */
+ /*002d:*/ 0x66, /* .##..##. */
+ /*002e:*/ 0xff, /* ######## */
+ /*002f:*/ 0x66, /* .##..##. */
+ /*0030:*/ 0xff, /* ######## */
+ /*0031:*/ 0x66, /* .##..##. */
+ /*0032:*/ 0x66, /* .##..##. */
+ /*0033:*/ 0x00, /* ........ */
+/* --- new character '$' (36) starting at offset 0x0034 --- */
+ /*0034:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0039:*/ 0x18, /* ...##... */
+ /*003a:*/ 0x3e, /* ..#####. */
+ /*003b:*/ 0x60, /* .##..... */
+ /*003c:*/ 0x3c, /* ..####.. */
+ /*003d:*/ 0x06, /* .....##. */
+ /*003e:*/ 0x7c, /* .#####.. */
+ /*003f:*/ 0x18, /* ...##... */
+ /*0040:*/ 0x00, /* ........ */
+/* --- new character '%' (37) starting at offset 0x0041 --- */
+ /*0041:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0046:*/ 0x62, /* .##...#. */
+ /*0047:*/ 0x66, /* .##..##. */
+ /*0048:*/ 0x0c, /* ....##.. */
+ /*0049:*/ 0x18, /* ...##... */
+ /*004a:*/ 0x30, /* ..##.... */
+ /*004b:*/ 0x66, /* .##..##. */
+ /*004c:*/ 0x46, /* .#...##. */
+ /*004d:*/ 0x00, /* ........ */
+/* --- new character '&' (38) starting at offset 0x004e --- */
+ /*004e:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0053:*/ 0x3c, /* ..####.. */
+ /*0054:*/ 0x66, /* .##..##. */
+ /*0055:*/ 0x3c, /* ..####.. */
+ /*0056:*/ 0x38, /* ..###... */
+ /*0057:*/ 0x67, /* .##..### */
+ /*0058:*/ 0x66, /* .##..##. */
+ /*0059:*/ 0x3f, /* ..###### */
+ /*005a:*/ 0x00, /* ........ */
+/* --- new character ''' (39) starting at offset 0x005b --- */
+ /*005b:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0060:*/ 0x06, /* .....##. */
+ /*0061:*/ 0x0c, /* ....##.. */
+ /*0062:*/ 0x18, /* ...##... */
+ /*0063:*/ 0x00, /* ........ */
+ /*0064:*/ 0x00, /* ........ */
+ /*0065:*/ 0x00, /* ........ */
+ /*0066:*/ 0x00, /* ........ */
+ /*0067:*/ 0x00, /* ........ */
+/* --- new character '(' (40) starting at offset 0x0068 --- */
+ /*0068:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*006d:*/ 0x0c, /* ....##.. */
+ /*006e:*/ 0x18, /* ...##... */
+ /*006f:*/ 0x30, /* ..##.... */
+ /*0070:*/ 0x30, /* ..##.... */
+ /*0071:*/ 0x30, /* ..##.... */
+ /*0072:*/ 0x18, /* ...##... */
+ /*0073:*/ 0x0c, /* ....##.. */
+ /*0074:*/ 0x00, /* ........ */
+/* --- new character ')' (41) starting at offset 0x0075 --- */
+ /*0075:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*007a:*/ 0x30, /* ..##.... */
+ /*007b:*/ 0x18, /* ...##... */
+ /*007c:*/ 0x0c, /* ....##.. */
+ /*007d:*/ 0x0c, /* ....##.. */
+ /*007e:*/ 0x0c, /* ....##.. */
+ /*007f:*/ 0x18, /* ...##... */
+ /*0080:*/ 0x30, /* ..##.... */
+ /*0081:*/ 0x00, /* ........ */
+/* --- new character '*' (42) starting at offset 0x0082 --- */
+ /*0082:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0087:*/ 0x00, /* ........ */
+ /*0088:*/ 0x66, /* .##..##. */
+ /*0089:*/ 0x3c, /* ..####.. */
+ /*008a:*/ 0xff, /* ######## */
+ /*008b:*/ 0x3c, /* ..####.. */
+ /*008c:*/ 0x66, /* .##..##. */
+ /*008d:*/ 0x00, /* ........ */
+ /*008e:*/ 0x00, /* ........ */
+/* --- new character '+' (43) starting at offset 0x008f --- */
+ /*008f:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0094:*/ 0x00, /* ........ */
+ /*0095:*/ 0x18, /* ...##... */
+ /*0096:*/ 0x18, /* ...##... */
+ /*0097:*/ 0x7e, /* .######. */
+ /*0098:*/ 0x18, /* ...##... */
+ /*0099:*/ 0x18, /* ...##... */
+ /*009a:*/ 0x00, /* ........ */
+ /*009b:*/ 0x00, /* ........ */
+/* --- new character ',' (44) starting at offset 0x009c --- */
+ /*009c:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00a1:*/ 0x00, /* ........ */
+ /*00a2:*/ 0x00, /* ........ */
+ /*00a3:*/ 0x00, /* ........ */
+ /*00a4:*/ 0x00, /* ........ */
+ /*00a5:*/ 0x00, /* ........ */
+ /*00a6:*/ 0x18, /* ...##... */
+ /*00a7:*/ 0x18, /* ...##... */
+ /*00a8:*/ 0x30, /* ..##.... */
+/* --- new character '-' (45) starting at offset 0x00a9 --- */
+ /*00a9:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00ae:*/ 0x00, /* ........ */
+ /*00af:*/ 0x00, /* ........ */
+ /*00b0:*/ 0x00, /* ........ */
+ /*00b1:*/ 0x7e, /* .######. */
+ /*00b2:*/ 0x00, /* ........ */
+ /*00b3:*/ 0x00, /* ........ */
+ /*00b4:*/ 0x00, /* ........ */
+ /*00b5:*/ 0x00, /* ........ */
+/* --- new character '.' (46) starting at offset 0x00b6 --- */
+ /*00b6:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00bb:*/ 0x00, /* ........ */
+ /*00bc:*/ 0x00, /* ........ */
+ /*00bd:*/ 0x00, /* ........ */
+ /*00be:*/ 0x00, /* ........ */
+ /*00bf:*/ 0x00, /* ........ */
+ /*00c0:*/ 0x18, /* ...##... */
+ /*00c1:*/ 0x18, /* ...##... */
+ /*00c2:*/ 0x00, /* ........ */
+/* --- new character '/' (47) starting at offset 0x00c3 --- */
+ /*00c3:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00c8:*/ 0x00, /* ........ */
+ /*00c9:*/ 0x03, /* ......## */
+ /*00ca:*/ 0x06, /* .....##. */
+ /*00cb:*/ 0x0c, /* ....##.. */
+ /*00cc:*/ 0x18, /* ...##... */
+ /*00cd:*/ 0x30, /* ..##.... */
+ /*00ce:*/ 0x60, /* .##..... */
+ /*00cf:*/ 0x00, /* ........ */
+/* --- new character '0' (48) starting at offset 0x00d0 --- */
+ /*00d0:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00d5:*/ 0x3c, /* ..####.. */
+ /*00d6:*/ 0x66, /* .##..##. */
+ /*00d7:*/ 0x6e, /* .##.###. */
+ /*00d8:*/ 0x76, /* .###.##. */
+ /*00d9:*/ 0x66, /* .##..##. */
+ /*00da:*/ 0x66, /* .##..##. */
+ /*00db:*/ 0x3c, /* ..####.. */
+ /*00dc:*/ 0x00, /* ........ */
+/* --- new character '1' (49) starting at offset 0x00dd --- */
+ /*00dd:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00e2:*/ 0x18, /* ...##... */
+ /*00e3:*/ 0x18, /* ...##... */
+ /*00e4:*/ 0x38, /* ..###... */
+ /*00e5:*/ 0x18, /* ...##... */
+ /*00e6:*/ 0x18, /* ...##... */
+ /*00e7:*/ 0x18, /* ...##... */
+ /*00e8:*/ 0x7e, /* .######. */
+ /*00e9:*/ 0x00, /* ........ */
+/* --- new character '2' (50) starting at offset 0x00ea --- */
+ /*00ea:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00ef:*/ 0x3c, /* ..####.. */
+ /*00f0:*/ 0x66, /* .##..##. */
+ /*00f1:*/ 0x06, /* .....##. */
+ /*00f2:*/ 0x0c, /* ....##.. */
+ /*00f3:*/ 0x30, /* ..##.... */
+ /*00f4:*/ 0x60, /* .##..... */
+ /*00f5:*/ 0x7e, /* .######. */
+ /*00f6:*/ 0x00, /* ........ */
+/* --- new character '3' (51) starting at offset 0x00f7 --- */
+ /*00f7:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00fc:*/ 0x3c, /* ..####.. */
+ /*00fd:*/ 0x66, /* .##..##. */
+ /*00fe:*/ 0x06, /* .....##. */
+ /*00ff:*/ 0x1c, /* ...###.. */
+ /*0100:*/ 0x06, /* .....##. */
+ /*0101:*/ 0x66, /* .##..##. */
+ /*0102:*/ 0x3c, /* ..####.. */
+ /*0103:*/ 0x00, /* ........ */
+/* --- new character '4' (52) starting at offset 0x0104 --- */
+ /*0104:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0109:*/ 0x06, /* .....##. */
+ /*010a:*/ 0x0e, /* ....###. */
+ /*010b:*/ 0x1e, /* ...####. */
+ /*010c:*/ 0x66, /* .##..##. */
+ /*010d:*/ 0x7f, /* .####### */
+ /*010e:*/ 0x06, /* .....##. */
+ /*010f:*/ 0x06, /* .....##. */
+ /*0110:*/ 0x00, /* ........ */
+/* --- new character '5' (53) starting at offset 0x0111 --- */
+ /*0111:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0116:*/ 0x7e, /* .######. */
+ /*0117:*/ 0x60, /* .##..... */
+ /*0118:*/ 0x7c, /* .#####.. */
+ /*0119:*/ 0x06, /* .....##. */
+ /*011a:*/ 0x06, /* .....##. */
+ /*011b:*/ 0x66, /* .##..##. */
+ /*011c:*/ 0x3c, /* ..####.. */
+ /*011d:*/ 0x00, /* ........ */
+/* --- new character '6' (54) starting at offset 0x011e --- */
+ /*011e:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0123:*/ 0x3c, /* ..####.. */
+ /*0124:*/ 0x66, /* .##..##. */
+ /*0125:*/ 0x60, /* .##..... */
+ /*0126:*/ 0x7c, /* .#####.. */
+ /*0127:*/ 0x66, /* .##..##. */
+ /*0128:*/ 0x66, /* .##..##. */
+ /*0129:*/ 0x3c, /* ..####.. */
+ /*012a:*/ 0x00, /* ........ */
+/* --- new character '7' (55) starting at offset 0x012b --- */
+ /*012b:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0130:*/ 0x7e, /* .######. */
+ /*0131:*/ 0x66, /* .##..##. */
+ /*0132:*/ 0x0c, /* ....##.. */
+ /*0133:*/ 0x18, /* ...##... */
+ /*0134:*/ 0x18, /* ...##... */
+ /*0135:*/ 0x18, /* ...##... */
+ /*0136:*/ 0x18, /* ...##... */
+ /*0137:*/ 0x00, /* ........ */
+/* --- new character '8' (56) starting at offset 0x0138 --- */
+ /*0138:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*013d:*/ 0x3c, /* ..####.. */
+ /*013e:*/ 0x66, /* .##..##. */
+ /*013f:*/ 0x66, /* .##..##. */
+ /*0140:*/ 0x3c, /* ..####.. */
+ /*0141:*/ 0x66, /* .##..##. */
+ /*0142:*/ 0x66, /* .##..##. */
+ /*0143:*/ 0x3c, /* ..####.. */
+ /*0144:*/ 0x00, /* ........ */
+/* --- new character '9' (57) starting at offset 0x0145 --- */
+ /*0145:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*014a:*/ 0x3c, /* ..####.. */
+ /*014b:*/ 0x66, /* .##..##. */
+ /*014c:*/ 0x66, /* .##..##. */
+ /*014d:*/ 0x3e, /* ..#####. */
+ /*014e:*/ 0x06, /* .....##. */
+ /*014f:*/ 0x66, /* .##..##. */
+ /*0150:*/ 0x3c, /* ..####.. */
+ /*0151:*/ 0x00, /* ........ */
+/* --- new character ':' (58) starting at offset 0x0152 --- */
+ /*0152:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0157:*/ 0x00, /* ........ */
+ /*0158:*/ 0x00, /* ........ */
+ /*0159:*/ 0x18, /* ...##... */
+ /*015a:*/ 0x00, /* ........ */
+ /*015b:*/ 0x00, /* ........ */
+ /*015c:*/ 0x18, /* ...##... */
+ /*015d:*/ 0x00, /* ........ */
+ /*015e:*/ 0x00, /* ........ */
+/* --- new character ';' (59) starting at offset 0x015f --- */
+ /*015f:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0164:*/ 0x00, /* ........ */
+ /*0165:*/ 0x00, /* ........ */
+ /*0166:*/ 0x18, /* ...##... */
+ /*0167:*/ 0x00, /* ........ */
+ /*0168:*/ 0x00, /* ........ */
+ /*0169:*/ 0x18, /* ...##... */
+ /*016a:*/ 0x18, /* ...##... */
+ /*016b:*/ 0x30, /* ..##.... */
+/* --- new character '<' (60) starting at offset 0x016c --- */
+ /*016c:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0171:*/ 0x0e, /* ....###. */
+ /*0172:*/ 0x18, /* ...##... */
+ /*0173:*/ 0x30, /* ..##.... */
+ /*0174:*/ 0x60, /* .##..... */
+ /*0175:*/ 0x30, /* ..##.... */
+ /*0176:*/ 0x18, /* ...##... */
+ /*0177:*/ 0x0e, /* ....###. */
+ /*0178:*/ 0x00, /* ........ */
+/* --- new character '=' (61) starting at offset 0x0179 --- */
+ /*0179:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*017e:*/ 0x00, /* ........ */
+ /*017f:*/ 0x00, /* ........ */
+ /*0180:*/ 0x7e, /* .######. */
+ /*0181:*/ 0x00, /* ........ */
+ /*0182:*/ 0x7e, /* .######. */
+ /*0183:*/ 0x00, /* ........ */
+ /*0184:*/ 0x00, /* ........ */
+ /*0185:*/ 0x00, /* ........ */
+/* --- new character '>' (62) starting at offset 0x0186 --- */
+ /*0186:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*018b:*/ 0x70, /* .###.... */
+ /*018c:*/ 0x18, /* ...##... */
+ /*018d:*/ 0x0c, /* ....##.. */
+ /*018e:*/ 0x06, /* .....##. */
+ /*018f:*/ 0x0c, /* ....##.. */
+ /*0190:*/ 0x18, /* ...##... */
+ /*0191:*/ 0x70, /* .###.... */
+ /*0192:*/ 0x00, /* ........ */
+/* --- new character '?' (63) starting at offset 0x0193 --- */
+ /*0193:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0198:*/ 0x3c, /* ..####.. */
+ /*0199:*/ 0x66, /* .##..##. */
+ /*019a:*/ 0x06, /* .....##. */
+ /*019b:*/ 0x0c, /* ....##.. */
+ /*019c:*/ 0x18, /* ...##... */
+ /*019d:*/ 0x00, /* ........ */
+ /*019e:*/ 0x18, /* ...##... */
+ /*019f:*/ 0x00, /* ........ */
+/* --- new character '@' (64) starting at offset 0x01a0 --- */
+ /*01a0:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01a5:*/ 0x3c, /* ..####.. */
+ /*01a6:*/ 0x66, /* .##..##. */
+ /*01a7:*/ 0x6e, /* .##.###. */
+ /*01a8:*/ 0x6e, /* .##.###. */
+ /*01a9:*/ 0x60, /* .##..... */
+ /*01aa:*/ 0x62, /* .##...#. */
+ /*01ab:*/ 0x3c, /* ..####.. */
+ /*01ac:*/ 0x00, /* ........ */
+/* --- new character 'A' (65) starting at offset 0x01ad --- */
+ /*01ad:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01b2:*/ 0x18, /* ...##... */
+ /*01b3:*/ 0x3c, /* ..####.. */
+ /*01b4:*/ 0x66, /* .##..##. */
+ /*01b5:*/ 0x7e, /* .######. */
+ /*01b6:*/ 0x66, /* .##..##. */
+ /*01b7:*/ 0x66, /* .##..##. */
+ /*01b8:*/ 0x66, /* .##..##. */
+ /*01b9:*/ 0x00, /* ........ */
+/* --- new character 'B' (66) starting at offset 0x01ba --- */
+ /*01ba:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01bf:*/ 0x7c, /* .#####.. */
+ /*01c0:*/ 0x66, /* .##..##. */
+ /*01c1:*/ 0x66, /* .##..##. */
+ /*01c2:*/ 0x7c, /* .#####.. */
+ /*01c3:*/ 0x66, /* .##..##. */
+ /*01c4:*/ 0x66, /* .##..##. */
+ /*01c5:*/ 0x7c, /* .#####.. */
+ /*01c6:*/ 0x00, /* ........ */
+/* --- new character 'C' (67) starting at offset 0x01c7 --- */
+ /*01c7:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01cc:*/ 0x3c, /* ..####.. */
+ /*01cd:*/ 0x66, /* .##..##. */
+ /*01ce:*/ 0x60, /* .##..... */
+ /*01cf:*/ 0x60, /* .##..... */
+ /*01d0:*/ 0x60, /* .##..... */
+ /*01d1:*/ 0x66, /* .##..##. */
+ /*01d2:*/ 0x3c, /* ..####.. */
+ /*01d3:*/ 0x00, /* ........ */
+/* --- new character 'D' (68) starting at offset 0x01d4 --- */
+ /*01d4:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01d9:*/ 0x78, /* .####... */
+ /*01da:*/ 0x6c, /* .##.##.. */
+ /*01db:*/ 0x66, /* .##..##. */
+ /*01dc:*/ 0x66, /* .##..##. */
+ /*01dd:*/ 0x66, /* .##..##. */
+ /*01de:*/ 0x6c, /* .##.##.. */
+ /*01df:*/ 0x78, /* .####... */
+ /*01e0:*/ 0x00, /* ........ */
+/* --- new character 'E' (69) starting at offset 0x01e1 --- */
+ /*01e1:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01e6:*/ 0x7e, /* .######. */
+ /*01e7:*/ 0x60, /* .##..... */
+ /*01e8:*/ 0x60, /* .##..... */
+ /*01e9:*/ 0x78, /* .####... */
+ /*01ea:*/ 0x60, /* .##..... */
+ /*01eb:*/ 0x60, /* .##..... */
+ /*01ec:*/ 0x7e, /* .######. */
+ /*01ed:*/ 0x00, /* ........ */
+/* --- new character 'F' (70) starting at offset 0x01ee --- */
+ /*01ee:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01f3:*/ 0x7e, /* .######. */
+ /*01f4:*/ 0x60, /* .##..... */
+ /*01f5:*/ 0x60, /* .##..... */
+ /*01f6:*/ 0x78, /* .####... */
+ /*01f7:*/ 0x60, /* .##..... */
+ /*01f8:*/ 0x60, /* .##..... */
+ /*01f9:*/ 0x60, /* .##..... */
+ /*01fa:*/ 0x00, /* ........ */
+/* --- new character 'G' (71) starting at offset 0x01fb --- */
+ /*01fb:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0200:*/ 0x3c, /* ..####.. */
+ /*0201:*/ 0x66, /* .##..##. */
+ /*0202:*/ 0x60, /* .##..... */
+ /*0203:*/ 0x6e, /* .##.###. */
+ /*0204:*/ 0x66, /* .##..##. */
+ /*0205:*/ 0x66, /* .##..##. */
+ /*0206:*/ 0x3c, /* ..####.. */
+ /*0207:*/ 0x00, /* ........ */
+/* --- new character 'H' (72) starting at offset 0x0208 --- */
+ /*0208:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*020d:*/ 0x66, /* .##..##. */
+ /*020e:*/ 0x66, /* .##..##. */
+ /*020f:*/ 0x66, /* .##..##. */
+ /*0210:*/ 0x7e, /* .######. */
+ /*0211:*/ 0x66, /* .##..##. */
+ /*0212:*/ 0x66, /* .##..##. */
+ /*0213:*/ 0x66, /* .##..##. */
+ /*0214:*/ 0x00, /* ........ */
+/* --- new character 'I' (73) starting at offset 0x0215 --- */
+ /*0215:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*021a:*/ 0x3c, /* ..####.. */
+ /*021b:*/ 0x18, /* ...##... */
+ /*021c:*/ 0x18, /* ...##... */
+ /*021d:*/ 0x18, /* ...##... */
+ /*021e:*/ 0x18, /* ...##... */
+ /*021f:*/ 0x18, /* ...##... */
+ /*0220:*/ 0x3c, /* ..####.. */
+ /*0221:*/ 0x00, /* ........ */
+/* --- new character 'J' (74) starting at offset 0x0222 --- */
+ /*0222:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0227:*/ 0x1e, /* ...####. */
+ /*0228:*/ 0x0c, /* ....##.. */
+ /*0229:*/ 0x0c, /* ....##.. */
+ /*022a:*/ 0x0c, /* ....##.. */
+ /*022b:*/ 0x0c, /* ....##.. */
+ /*022c:*/ 0x6c, /* .##.##.. */
+ /*022d:*/ 0x38, /* ..###... */
+ /*022e:*/ 0x00, /* ........ */
+/* --- new character 'K' (75) starting at offset 0x022f --- */
+ /*022f:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0234:*/ 0x66, /* .##..##. */
+ /*0235:*/ 0x6c, /* .##.##.. */
+ /*0236:*/ 0x78, /* .####... */
+ /*0237:*/ 0x70, /* .###.... */
+ /*0238:*/ 0x78, /* .####... */
+ /*0239:*/ 0x6c, /* .##.##.. */
+ /*023a:*/ 0x66, /* .##..##. */
+ /*023b:*/ 0x00, /* ........ */
+/* --- new character 'L' (76) starting at offset 0x023c --- */
+ /*023c:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0241:*/ 0x60, /* .##..... */
+ /*0242:*/ 0x60, /* .##..... */
+ /*0243:*/ 0x60, /* .##..... */
+ /*0244:*/ 0x60, /* .##..... */
+ /*0245:*/ 0x60, /* .##..... */
+ /*0246:*/ 0x60, /* .##..... */
+ /*0247:*/ 0x7e, /* .######. */
+ /*0248:*/ 0x00, /* ........ */
+/* --- new character 'M' (77) starting at offset 0x0249 --- */
+ /*0249:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*024e:*/ 0x63, /* .##...## */
+ /*024f:*/ 0x77, /* .###.### */
+ /*0250:*/ 0x7f, /* .####### */
+ /*0251:*/ 0x6b, /* .##.#.## */
+ /*0252:*/ 0x63, /* .##...## */
+ /*0253:*/ 0x63, /* .##...## */
+ /*0254:*/ 0x63, /* .##...## */
+ /*0255:*/ 0x00, /* ........ */
+/* --- new character 'N' (78) starting at offset 0x0256 --- */
+ /*0256:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*025b:*/ 0x66, /* .##..##. */
+ /*025c:*/ 0x76, /* .###.##. */
+ /*025d:*/ 0x7e, /* .######. */
+ /*025e:*/ 0x7e, /* .######. */
+ /*025f:*/ 0x6e, /* .##.###. */
+ /*0260:*/ 0x66, /* .##..##. */
+ /*0261:*/ 0x66, /* .##..##. */
+ /*0262:*/ 0x00, /* ........ */
+/* --- new character 'O' (79) starting at offset 0x0263 --- */
+ /*0263:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0268:*/ 0x3c, /* ..####.. */
+ /*0269:*/ 0x66, /* .##..##. */
+ /*026a:*/ 0x66, /* .##..##. */
+ /*026b:*/ 0x66, /* .##..##. */
+ /*026c:*/ 0x66, /* .##..##. */
+ /*026d:*/ 0x66, /* .##..##. */
+ /*026e:*/ 0x3c, /* ..####.. */
+ /*026f:*/ 0x00, /* ........ */
+/* --- new character 'P' (80) starting at offset 0x0270 --- */
+ /*0270:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0275:*/ 0x7c, /* .#####.. */
+ /*0276:*/ 0x66, /* .##..##. */
+ /*0277:*/ 0x66, /* .##..##. */
+ /*0278:*/ 0x7c, /* .#####.. */
+ /*0279:*/ 0x60, /* .##..... */
+ /*027a:*/ 0x60, /* .##..... */
+ /*027b:*/ 0x60, /* .##..... */
+ /*027c:*/ 0x00, /* ........ */
+/* --- new character 'Q' (81) starting at offset 0x027d --- */
+ /*027d:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0282:*/ 0x3c, /* ..####.. */
+ /*0283:*/ 0x66, /* .##..##. */
+ /*0284:*/ 0x66, /* .##..##. */
+ /*0285:*/ 0x66, /* .##..##. */
+ /*0286:*/ 0x66, /* .##..##. */
+ /*0287:*/ 0x3c, /* ..####.. */
+ /*0288:*/ 0x0e, /* ....###. */
+ /*0289:*/ 0x00, /* ........ */
+/* --- new character 'R' (82) starting at offset 0x028a --- */
+ /*028a:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*028f:*/ 0x7c, /* .#####.. */
+ /*0290:*/ 0x66, /* .##..##. */
+ /*0291:*/ 0x66, /* .##..##. */
+ /*0292:*/ 0x7c, /* .#####.. */
+ /*0293:*/ 0x78, /* .####... */
+ /*0294:*/ 0x6c, /* .##.##.. */
+ /*0295:*/ 0x66, /* .##..##. */
+ /*0296:*/ 0x00, /* ........ */
+/* --- new character 'S' (83) starting at offset 0x0297 --- */
+ /*0297:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*029c:*/ 0x3c, /* ..####.. */
+ /*029d:*/ 0x66, /* .##..##. */
+ /*029e:*/ 0x60, /* .##..... */
+ /*029f:*/ 0x3c, /* ..####.. */
+ /*02a0:*/ 0x06, /* .....##. */
+ /*02a1:*/ 0x66, /* .##..##. */
+ /*02a2:*/ 0x3c, /* ..####.. */
+ /*02a3:*/ 0x00, /* ........ */
+/* --- new character 'T' (84) starting at offset 0x02a4 --- */
+ /*02a4:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02a9:*/ 0x7e, /* .######. */
+ /*02aa:*/ 0x18, /* ...##... */
+ /*02ab:*/ 0x18, /* ...##... */
+ /*02ac:*/ 0x18, /* ...##... */
+ /*02ad:*/ 0x18, /* ...##... */
+ /*02ae:*/ 0x18, /* ...##... */
+ /*02af:*/ 0x18, /* ...##... */
+ /*02b0:*/ 0x00, /* ........ */
+/* --- new character 'U' (85) starting at offset 0x02b1 --- */
+ /*02b1:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02b6:*/ 0x66, /* .##..##. */
+ /*02b7:*/ 0x66, /* .##..##. */
+ /*02b8:*/ 0x66, /* .##..##. */
+ /*02b9:*/ 0x66, /* .##..##. */
+ /*02ba:*/ 0x66, /* .##..##. */
+ /*02bb:*/ 0x66, /* .##..##. */
+ /*02bc:*/ 0x3c, /* ..####.. */
+ /*02bd:*/ 0x00, /* ........ */
+/* --- new character 'V' (86) starting at offset 0x02be --- */
+ /*02be:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02c3:*/ 0x66, /* .##..##. */
+ /*02c4:*/ 0x66, /* .##..##. */
+ /*02c5:*/ 0x66, /* .##..##. */
+ /*02c6:*/ 0x66, /* .##..##. */
+ /*02c7:*/ 0x66, /* .##..##. */
+ /*02c8:*/ 0x3c, /* ..####.. */
+ /*02c9:*/ 0x18, /* ...##... */
+ /*02ca:*/ 0x00, /* ........ */
+/* --- new character 'W' (87) starting at offset 0x02cb --- */
+ /*02cb:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02d0:*/ 0x63, /* .##...## */
+ /*02d1:*/ 0x63, /* .##...## */
+ /*02d2:*/ 0x63, /* .##...## */
+ /*02d3:*/ 0x6b, /* .##.#.## */
+ /*02d4:*/ 0x7f, /* .####### */
+ /*02d5:*/ 0x77, /* .###.### */
+ /*02d6:*/ 0x63, /* .##...## */
+ /*02d7:*/ 0x00, /* ........ */
+/* --- new character 'X' (88) starting at offset 0x02d8 --- */
+ /*02d8:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02dd:*/ 0x66, /* .##..##. */
+ /*02de:*/ 0x66, /* .##..##. */
+ /*02df:*/ 0x3c, /* ..####.. */
+ /*02e0:*/ 0x18, /* ...##... */
+ /*02e1:*/ 0x3c, /* ..####.. */
+ /*02e2:*/ 0x66, /* .##..##. */
+ /*02e3:*/ 0x66, /* .##..##. */
+ /*02e4:*/ 0x00, /* ........ */
+/* --- new character 'Y' (89) starting at offset 0x02e5 --- */
+ /*02e5:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02ea:*/ 0x66, /* .##..##. */
+ /*02eb:*/ 0x66, /* .##..##. */
+ /*02ec:*/ 0x66, /* .##..##. */
+ /*02ed:*/ 0x3c, /* ..####.. */
+ /*02ee:*/ 0x18, /* ...##... */
+ /*02ef:*/ 0x18, /* ...##... */
+ /*02f0:*/ 0x18, /* ...##... */
+ /*02f1:*/ 0x00, /* ........ */
+/* --- new character 'Z' (90) starting at offset 0x02f2 --- */
+ /*02f2:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02f7:*/ 0x7e, /* .######. */
+ /*02f8:*/ 0x06, /* .....##. */
+ /*02f9:*/ 0x0c, /* ....##.. */
+ /*02fa:*/ 0x18, /* ...##... */
+ /*02fb:*/ 0x30, /* ..##.... */
+ /*02fc:*/ 0x60, /* .##..... */
+ /*02fd:*/ 0x7e, /* .######. */
+ /*02fe:*/ 0x00, /* ........ */
+/* --- new character '[' (91) starting at offset 0x02ff --- */
+ /*02ff:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0304:*/ 0x3c, /* ..####.. */
+ /*0305:*/ 0x30, /* ..##.... */
+ /*0306:*/ 0x30, /* ..##.... */
+ /*0307:*/ 0x30, /* ..##.... */
+ /*0308:*/ 0x30, /* ..##.... */
+ /*0309:*/ 0x30, /* ..##.... */
+ /*030a:*/ 0x3c, /* ..####.. */
+ /*030b:*/ 0x00, /* ........ */
+/* --- new character '\' (92) starting at offset 0x030c --- */
+ /*030c:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0311:*/ 0x00, /* ........ */
+ /*0312:*/ 0xc0, /* ##...... */
+ /*0313:*/ 0x60, /* .##..... */
+ /*0314:*/ 0x30, /* ..##.... */
+ /*0315:*/ 0x18, /* ...##... */
+ /*0316:*/ 0x0c, /* ....##.. */
+ /*0317:*/ 0x06, /* .....##. */
+ /*0318:*/ 0x00, /* ........ */
+/* --- new character ']' (93) starting at offset 0x0319 --- */
+ /*0319:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*031e:*/ 0x3c, /* ..####.. */
+ /*031f:*/ 0x0c, /* ....##.. */
+ /*0320:*/ 0x0c, /* ....##.. */
+ /*0321:*/ 0x0c, /* ....##.. */
+ /*0322:*/ 0x0c, /* ....##.. */
+ /*0323:*/ 0x0c, /* ....##.. */
+ /*0324:*/ 0x3c, /* ..####.. */
+ /*0325:*/ 0x00, /* ........ */
+/* --- new character '^' (94) starting at offset 0x0326 --- */
+ /*0326:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*032b:*/ 0x18, /* ...##... */
+ /*032c:*/ 0x3c, /* ..####.. */
+ /*032d:*/ 0x66, /* .##..##. */
+ /*032e:*/ 0x00, /* ........ */
+ /*032f:*/ 0x00, /* ........ */
+ /*0330:*/ 0x00, /* ........ */
+ /*0331:*/ 0x00, /* ........ */
+ /*0332:*/ 0x00, /* ........ */
+/* --- new character '_' (95) starting at offset 0x0333 --- */
+ /*0333:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0338:*/ 0x00, /* ........ */
+ /*0339:*/ 0x00, /* ........ */
+ /*033a:*/ 0x00, /* ........ */
+ /*033b:*/ 0x00, /* ........ */
+ /*033c:*/ 0x00, /* ........ */
+ /*033d:*/ 0x00, /* ........ */
+ /*033e:*/ 0x00, /* ........ */
+ /*033f:*/ 0xff, /* ######## */
+/* --- new character '`' (96) starting at offset 0x0340 --- */
+ /*0340:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0345:*/ 0x60, /* .##..... */
+ /*0346:*/ 0x30, /* ..##.... */
+ /*0347:*/ 0x18, /* ...##... */
+ /*0348:*/ 0x00, /* ........ */
+ /*0349:*/ 0x00, /* ........ */
+ /*034a:*/ 0x00, /* ........ */
+ /*034b:*/ 0x00, /* ........ */
+ /*034c:*/ 0x00, /* ........ */
+/* --- new character 'a' (97) starting at offset 0x034d --- */
+ /*034d:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0352:*/ 0x00, /* ........ */
+ /*0353:*/ 0x00, /* ........ */
+ /*0354:*/ 0x3c, /* ..####.. */
+ /*0355:*/ 0x06, /* .....##. */
+ /*0356:*/ 0x3e, /* ..#####. */
+ /*0357:*/ 0x66, /* .##..##. */
+ /*0358:*/ 0x3e, /* ..#####. */
+ /*0359:*/ 0x00, /* ........ */
+/* --- new character 'b' (98) starting at offset 0x035a --- */
+ /*035a:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*035f:*/ 0x00, /* ........ */
+ /*0360:*/ 0x60, /* .##..... */
+ /*0361:*/ 0x60, /* .##..... */
+ /*0362:*/ 0x7c, /* .#####.. */
+ /*0363:*/ 0x66, /* .##..##. */
+ /*0364:*/ 0x66, /* .##..##. */
+ /*0365:*/ 0x7c, /* .#####.. */
+ /*0366:*/ 0x00, /* ........ */
+/* --- new character 'c' (99) starting at offset 0x0367 --- */
+ /*0367:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*036c:*/ 0x00, /* ........ */
+ /*036d:*/ 0x00, /* ........ */
+ /*036e:*/ 0x3c, /* ..####.. */
+ /*036f:*/ 0x60, /* .##..... */
+ /*0370:*/ 0x60, /* .##..... */
+ /*0371:*/ 0x60, /* .##..... */
+ /*0372:*/ 0x3c, /* ..####.. */
+ /*0373:*/ 0x00, /* ........ */
+/* --- new character 'd' (100) starting at offset 0x0374 --- */
+ /*0374:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0379:*/ 0x00, /* ........ */
+ /*037a:*/ 0x06, /* .....##. */
+ /*037b:*/ 0x06, /* .....##. */
+ /*037c:*/ 0x3e, /* ..#####. */
+ /*037d:*/ 0x66, /* .##..##. */
+ /*037e:*/ 0x66, /* .##..##. */
+ /*037f:*/ 0x3e, /* ..#####. */
+ /*0380:*/ 0x00, /* ........ */
+/* --- new character 'e' (101) starting at offset 0x0381 --- */
+ /*0381:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0386:*/ 0x00, /* ........ */
+ /*0387:*/ 0x00, /* ........ */
+ /*0388:*/ 0x3c, /* ..####.. */
+ /*0389:*/ 0x66, /* .##..##. */
+ /*038a:*/ 0x7e, /* .######. */
+ /*038b:*/ 0x60, /* .##..... */
+ /*038c:*/ 0x3c, /* ..####.. */
+ /*038d:*/ 0x00, /* ........ */
+/* --- new character 'f' (102) starting at offset 0x038e --- */
+ /*038e:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0393:*/ 0x00, /* ........ */
+ /*0394:*/ 0x0e, /* ....###. */
+ /*0395:*/ 0x18, /* ...##... */
+ /*0396:*/ 0x3e, /* ..#####. */
+ /*0397:*/ 0x18, /* ...##... */
+ /*0398:*/ 0x18, /* ...##... */
+ /*0399:*/ 0x18, /* ...##... */
+ /*039a:*/ 0x00, /* ........ */
+/* --- new character 'g' (103) starting at offset 0x039b --- */
+ /*039b:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03a0:*/ 0x00, /* ........ */
+ /*03a1:*/ 0x00, /* ........ */
+ /*03a2:*/ 0x3e, /* ..#####. */
+ /*03a3:*/ 0x66, /* .##..##. */
+ /*03a4:*/ 0x66, /* .##..##. */
+ /*03a5:*/ 0x3e, /* ..#####. */
+ /*03a6:*/ 0x06, /* .....##. */
+ /*03a7:*/ 0x7c, /* .#####.. */
+/* --- new character 'h' (104) starting at offset 0x03a8 --- */
+ /*03a8:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03ad:*/ 0x00, /* ........ */
+ /*03ae:*/ 0x60, /* .##..... */
+ /*03af:*/ 0x60, /* .##..... */
+ /*03b0:*/ 0x7c, /* .#####.. */
+ /*03b1:*/ 0x66, /* .##..##. */
+ /*03b2:*/ 0x66, /* .##..##. */
+ /*03b3:*/ 0x66, /* .##..##. */
+ /*03b4:*/ 0x00, /* ........ */
+/* --- new character 'i' (105) starting at offset 0x03b5 --- */
+ /*03b5:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03ba:*/ 0x00, /* ........ */
+ /*03bb:*/ 0x18, /* ...##... */
+ /*03bc:*/ 0x00, /* ........ */
+ /*03bd:*/ 0x38, /* ..###... */
+ /*03be:*/ 0x18, /* ...##... */
+ /*03bf:*/ 0x18, /* ...##... */
+ /*03c0:*/ 0x3c, /* ..####.. */
+ /*03c1:*/ 0x00, /* ........ */
+/* --- new character 'j' (106) starting at offset 0x03c2 --- */
+ /*03c2:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03c7:*/ 0x00, /* ........ */
+ /*03c8:*/ 0x06, /* .....##. */
+ /*03c9:*/ 0x00, /* ........ */
+ /*03ca:*/ 0x06, /* .....##. */
+ /*03cb:*/ 0x06, /* .....##. */
+ /*03cc:*/ 0x06, /* .....##. */
+ /*03cd:*/ 0x06, /* .....##. */
+ /*03ce:*/ 0x3c, /* ..####.. */
+/* --- new character 'k' (107) starting at offset 0x03cf --- */
+ /*03cf:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03d4:*/ 0x00, /* ........ */
+ /*03d5:*/ 0x60, /* .##..... */
+ /*03d6:*/ 0x60, /* .##..... */
+ /*03d7:*/ 0x6c, /* .##.##.. */
+ /*03d8:*/ 0x78, /* .####... */
+ /*03d9:*/ 0x6c, /* .##.##.. */
+ /*03da:*/ 0x66, /* .##..##. */
+ /*03db:*/ 0x00, /* ........ */
+/* --- new character 'l' (108) starting at offset 0x03dc --- */
+ /*03dc:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03e1:*/ 0x00, /* ........ */
+ /*03e2:*/ 0x38, /* ..###... */
+ /*03e3:*/ 0x18, /* ...##... */
+ /*03e4:*/ 0x18, /* ...##... */
+ /*03e5:*/ 0x18, /* ...##... */
+ /*03e6:*/ 0x18, /* ...##... */
+ /*03e7:*/ 0x3c, /* ..####.. */
+ /*03e8:*/ 0x00, /* ........ */
+/* --- new character 'm' (109) starting at offset 0x03e9 --- */
+ /*03e9:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03ee:*/ 0x00, /* ........ */
+ /*03ef:*/ 0x00, /* ........ */
+ /*03f0:*/ 0x66, /* .##..##. */
+ /*03f1:*/ 0x7f, /* .####### */
+ /*03f2:*/ 0x7f, /* .####### */
+ /*03f3:*/ 0x6b, /* .##.#.## */
+ /*03f4:*/ 0x63, /* .##...## */
+ /*03f5:*/ 0x00, /* ........ */
+/* --- new character 'n' (110) starting at offset 0x03f6 --- */
+ /*03f6:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03fb:*/ 0x00, /* ........ */
+ /*03fc:*/ 0x00, /* ........ */
+ /*03fd:*/ 0x7c, /* .#####.. */
+ /*03fe:*/ 0x66, /* .##..##. */
+ /*03ff:*/ 0x66, /* .##..##. */
+ /*0400:*/ 0x66, /* .##..##. */
+ /*0401:*/ 0x66, /* .##..##. */
+ /*0402:*/ 0x00, /* ........ */
+/* --- new character 'o' (111) starting at offset 0x0403 --- */
+ /*0403:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0408:*/ 0x00, /* ........ */
+ /*0409:*/ 0x00, /* ........ */
+ /*040a:*/ 0x3c, /* ..####.. */
+ /*040b:*/ 0x66, /* .##..##. */
+ /*040c:*/ 0x66, /* .##..##. */
+ /*040d:*/ 0x66, /* .##..##. */
+ /*040e:*/ 0x3c, /* ..####.. */
+ /*040f:*/ 0x00, /* ........ */
+/* --- new character 'p' (112) starting at offset 0x0410 --- */
+ /*0410:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0415:*/ 0x00, /* ........ */
+ /*0416:*/ 0x00, /* ........ */
+ /*0417:*/ 0x7c, /* .#####.. */
+ /*0418:*/ 0x66, /* .##..##. */
+ /*0419:*/ 0x66, /* .##..##. */
+ /*041a:*/ 0x7c, /* .#####.. */
+ /*041b:*/ 0x60, /* .##..... */
+ /*041c:*/ 0x60, /* .##..... */
+/* --- new character 'q' (113) starting at offset 0x041d --- */
+ /*041d:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0422:*/ 0x00, /* ........ */
+ /*0423:*/ 0x00, /* ........ */
+ /*0424:*/ 0x3e, /* ..#####. */
+ /*0425:*/ 0x66, /* .##..##. */
+ /*0426:*/ 0x66, /* .##..##. */
+ /*0427:*/ 0x3e, /* ..#####. */
+ /*0428:*/ 0x06, /* .....##. */
+ /*0429:*/ 0x06, /* .....##. */
+/* --- new character 'r' (114) starting at offset 0x042a --- */
+ /*042a:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*042f:*/ 0x00, /* ........ */
+ /*0430:*/ 0x00, /* ........ */
+ /*0431:*/ 0x7c, /* .#####.. */
+ /*0432:*/ 0x66, /* .##..##. */
+ /*0433:*/ 0x60, /* .##..... */
+ /*0434:*/ 0x60, /* .##..... */
+ /*0435:*/ 0x60, /* .##..... */
+ /*0436:*/ 0x00, /* ........ */
+/* --- new character 's' (115) starting at offset 0x0437 --- */
+ /*0437:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*043c:*/ 0x00, /* ........ */
+ /*043d:*/ 0x00, /* ........ */
+ /*043e:*/ 0x3e, /* ..#####. */
+ /*043f:*/ 0x60, /* .##..... */
+ /*0440:*/ 0x3c, /* ..####.. */
+ /*0441:*/ 0x06, /* .....##. */
+ /*0442:*/ 0x7c, /* .#####.. */
+ /*0443:*/ 0x00, /* ........ */
+/* --- new character 't' (116) starting at offset 0x0444 --- */
+ /*0444:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0449:*/ 0x00, /* ........ */
+ /*044a:*/ 0x18, /* ...##... */
+ /*044b:*/ 0x7e, /* .######. */
+ /*044c:*/ 0x18, /* ...##... */
+ /*044d:*/ 0x18, /* ...##... */
+ /*044e:*/ 0x18, /* ...##... */
+ /*044f:*/ 0x0e, /* ....###. */
+ /*0450:*/ 0x00, /* ........ */
+/* --- new character 'u' (117) starting at offset 0x0451 --- */
+ /*0451:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0456:*/ 0x00, /* ........ */
+ /*0457:*/ 0x00, /* ........ */
+ /*0458:*/ 0x66, /* .##..##. */
+ /*0459:*/ 0x66, /* .##..##. */
+ /*045a:*/ 0x66, /* .##..##. */
+ /*045b:*/ 0x66, /* .##..##. */
+ /*045c:*/ 0x3e, /* ..#####. */
+ /*045d:*/ 0x00, /* ........ */
+/* --- new character 'v' (118) starting at offset 0x045e --- */
+ /*045e:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0463:*/ 0x00, /* ........ */
+ /*0464:*/ 0x00, /* ........ */
+ /*0465:*/ 0x66, /* .##..##. */
+ /*0466:*/ 0x66, /* .##..##. */
+ /*0467:*/ 0x66, /* .##..##. */
+ /*0468:*/ 0x3c, /* ..####.. */
+ /*0469:*/ 0x18, /* ...##... */
+ /*046a:*/ 0x00, /* ........ */
+/* --- new character 'w' (119) starting at offset 0x046b --- */
+ /*046b:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0470:*/ 0x00, /* ........ */
+ /*0471:*/ 0x00, /* ........ */
+ /*0472:*/ 0x63, /* .##...## */
+ /*0473:*/ 0x6b, /* .##.#.## */
+ /*0474:*/ 0x7f, /* .####### */
+ /*0475:*/ 0x3e, /* ..#####. */
+ /*0476:*/ 0x36, /* ..##.##. */
+ /*0477:*/ 0x00, /* ........ */
+/* --- new character 'x' (120) starting at offset 0x0478 --- */
+ /*0478:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*047d:*/ 0x00, /* ........ */
+ /*047e:*/ 0x00, /* ........ */
+ /*047f:*/ 0x66, /* .##..##. */
+ /*0480:*/ 0x3c, /* ..####.. */
+ /*0481:*/ 0x18, /* ...##... */
+ /*0482:*/ 0x3c, /* ..####.. */
+ /*0483:*/ 0x66, /* .##..##. */
+ /*0484:*/ 0x00, /* ........ */
+/* --- new character 'y' (121) starting at offset 0x0485 --- */
+ /*0485:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*048a:*/ 0x00, /* ........ */
+ /*048b:*/ 0x00, /* ........ */
+ /*048c:*/ 0x66, /* .##..##. */
+ /*048d:*/ 0x66, /* .##..##. */
+ /*048e:*/ 0x66, /* .##..##. */
+ /*048f:*/ 0x3e, /* ..#####. */
+ /*0490:*/ 0x0c, /* ....##.. */
+ /*0491:*/ 0x78, /* .####... */
+/* --- new character 'z' (122) starting at offset 0x0492 --- */
+ /*0492:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0497:*/ 0x00, /* ........ */
+ /*0498:*/ 0x00, /* ........ */
+ /*0499:*/ 0x7e, /* .######. */
+ /*049a:*/ 0x0c, /* ....##.. */
+ /*049b:*/ 0x18, /* ...##... */
+ /*049c:*/ 0x30, /* ..##.... */
+ /*049d:*/ 0x7e, /* .######. */
+ /*049e:*/ 0x00, /* ........ */
+/* --- new character '{' (123) starting at offset 0x049f --- */
+ /*049f:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*04a4:*/ 0x1c, /* ...###.. */
+ /*04a5:*/ 0x30, /* ..##.... */
+ /*04a6:*/ 0x30, /* ..##.... */
+ /*04a7:*/ 0x60, /* .##..... */
+ /*04a8:*/ 0x30, /* ..##.... */
+ /*04a9:*/ 0x30, /* ..##.... */
+ /*04aa:*/ 0x1c, /* ...###.. */
+ /*04ab:*/ 0x00, /* ........ */
+/* --- new character '|' (124) starting at offset 0x04ac --- */
+ /*04ac:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*04b1:*/ 0x18, /* ...##... */
+ /*04b2:*/ 0x18, /* ...##... */
+ /*04b3:*/ 0x18, /* ...##... */
+ /*04b4:*/ 0x18, /* ...##... */
+ /*04b5:*/ 0x18, /* ...##... */
+ /*04b6:*/ 0x18, /* ...##... */
+ /*04b7:*/ 0x18, /* ...##... */
+ /*04b8:*/ 0x00, /* ........ */
+/* --- new character '}' (125) starting at offset 0x04b9 --- */
+ /*04b9:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*04be:*/ 0x38, /* ..###... */
+ /*04bf:*/ 0x0c, /* ....##.. */
+ /*04c0:*/ 0x0c, /* ....##.. */
+ /*04c1:*/ 0x06, /* .....##. */
+ /*04c2:*/ 0x0c, /* ....##.. */
+ /*04c3:*/ 0x0c, /* ....##.. */
+ /*04c4:*/ 0x38, /* ..###... */
+ /*04c5:*/ 0x00, /* ........ */
+/* --- new character '~' (126) starting at offset 0x04c6 --- */
+ /*04c6:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*04cb:*/ 0x33, /* ..##..## */
+ /*04cc:*/ 0x7e, /* .######. */
+ /*04cd:*/ 0xcc, /* ##..##.. */
+ /*04ce:*/ 0x00, /* ........ */
+ /*04cf:*/ 0x00, /* ........ */
+ /*04d0:*/ 0x00, /* ........ */
+ /*04d1:*/ 0x00, /* ........ */
+ /*04d2:*/ 0x00, /* ........ */
+/* --- new character '' (127) starting at offset 0x04d3 --- */
+ /*04d3:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*04d8:*/ 0x00, /* ........ */
+ /*04d9:*/ 0x08, /* ....#... */
+ /*04da:*/ 0x0c, /* ....##.. */
+ /*04db:*/ 0xfe, /* #######. */
+ /*04dc:*/ 0xfe, /* #######. */
+ /*04dd:*/ 0x0c, /* ....##.. */
+ /*04de:*/ 0x08, /* ....#... */
+ /*04df:*/ 0x00, /* ........ */
+};
+static const uint16_t font_c64_offsets[] = {
+ 0x0000 /* ' ' */,
+ 0x000d /* '!' */,
+ 0x001a /* '"' */,
+ 0x0027 /* '#' */,
+ 0x0034 /* '$' */,
+ 0x0041 /* '%' */,
+ 0x004e /* '&' */,
+ 0x005b /* ''' */,
+ 0x0068 /* '(' */,
+ 0x0075 /* ')' */,
+ 0x0082 /* '*' */,
+ 0x008f /* '+' */,
+ 0x009c /* ',' */,
+ 0x00a9 /* '-' */,
+ 0x00b6 /* '.' */,
+ 0x00c3 /* '/' */,
+ 0x00d0 /* '0' */,
+ 0x00dd /* '1' */,
+ 0x00ea /* '2' */,
+ 0x00f7 /* '3' */,
+ 0x0104 /* '4' */,
+ 0x0111 /* '5' */,
+ 0x011e /* '6' */,
+ 0x012b /* '7' */,
+ 0x0138 /* '8' */,
+ 0x0145 /* '9' */,
+ 0x0152 /* ':' */,
+ 0x015f /* ';' */,
+ 0x016c /* '<' */,
+ 0x0179 /* '=' */,
+ 0x0186 /* '>' */,
+ 0x0193 /* '?' */,
+ 0x01a0 /* '@' */,
+ 0x01ad /* 'A' */,
+ 0x01ba /* 'B' */,
+ 0x01c7 /* 'C' */,
+ 0x01d4 /* 'D' */,
+ 0x01e1 /* 'E' */,
+ 0x01ee /* 'F' */,
+ 0x01fb /* 'G' */,
+ 0x0208 /* 'H' */,
+ 0x0215 /* 'I' */,
+ 0x0222 /* 'J' */,
+ 0x022f /* 'K' */,
+ 0x023c /* 'L' */,
+ 0x0249 /* 'M' */,
+ 0x0256 /* 'N' */,
+ 0x0263 /* 'O' */,
+ 0x0270 /* 'P' */,
+ 0x027d /* 'Q' */,
+ 0x028a /* 'R' */,
+ 0x0297 /* 'S' */,
+ 0x02a4 /* 'T' */,
+ 0x02b1 /* 'U' */,
+ 0x02be /* 'V' */,
+ 0x02cb /* 'W' */,
+ 0x02d8 /* 'X' */,
+ 0x02e5 /* 'Y' */,
+ 0x02f2 /* 'Z' */,
+ 0x02ff /* '[' */,
+ 0x030c /* '\' */,
+ 0x0319 /* ']' */,
+ 0x0326 /* '^' */,
+ 0x0333 /* '_' */,
+ 0x0340 /* '`' */,
+ 0x034d /* 'a' */,
+ 0x035a /* 'b' */,
+ 0x0367 /* 'c' */,
+ 0x0374 /* 'd' */,
+ 0x0381 /* 'e' */,
+ 0x038e /* 'f' */,
+ 0x039b /* 'g' */,
+ 0x03a8 /* 'h' */,
+ 0x03b5 /* 'i' */,
+ 0x03c2 /* 'j' */,
+ 0x03cf /* 'k' */,
+ 0x03dc /* 'l' */,
+ 0x03e9 /* 'm' */,
+ 0x03f6 /* 'n' */,
+ 0x0403 /* 'o' */,
+ 0x0410 /* 'p' */,
+ 0x041d /* 'q' */,
+ 0x042a /* 'r' */,
+ 0x0437 /* 's' */,
+ 0x0444 /* 't' */,
+ 0x0451 /* 'u' */,
+ 0x045e /* 'v' */,
+ 0x046b /* 'w' */,
+ 0x0478 /* 'x' */,
+ 0x0485 /* 'y' */,
+ 0x0492 /* 'z' */,
+ 0x049f /* '{' */,
+ 0x04ac /* '|' */,
+ 0x04b9 /* '}' */,
+ 0x04c6 /* '~' */,
+ 0x04d3 /* '' */,
+};
+const struct fb_font font_c64 = {
+ .height = 8,
+ .ascent = 8,
+ .firstchar = 32, /* space */
+ .lastchar = 127, /* ? */
+ .chardata = font_c64_data,
+ .charoffs = font_c64_offsets,
+};
diff --git a/Src/osmolib/src/target/firmware/fb/fb_bw8.c b/Src/osmolib/src/target/firmware/fb/fb_bw8.c
new file mode 100644
index 0000000..ffb59d8
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/fb_bw8.c
@@ -0,0 +1,311 @@
+/* utility functions for a black-and-white framebuffer organized
+ as 8-vertically-stacked-pixels per byte. This matches the
+ ST7558 LC Display Controller used on the Motorola C123 */
+
+/* (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.
+ *
+ */
+
+#include <fb/framebuffer.h>
+#include <fb/fb_bw8.h>
+
+#include <stdio.h> // debugging
+
+void fb_bw8_clear(){
+ int i,n;
+
+ /* bytes to clear */
+ n = (framebuffer->height+7)/8 * framebuffer->width;
+ for(i=0;i<n;i++)
+ fb_bw8->mem[i]=0;
+
+ /* mark everything as dirty */
+ fb_bw8->damage_x1 = 0;
+ fb_bw8->damage_x2 = framebuffer->width;
+ fb_bw8->damage_y1 = 0;
+ fb_bw8->damage_y2 = framebuffer->height;
+}
+
+/* update damage rectangle to include the area
+ x1,y1 (upper left) to x2,y2 (lower right)
+ Note that all pixels *including* x1y2 and x2y2 are
+ marked as dirty */
+static void fb_bw8_update_damage(
+ uint16_t x1,uint16_t y1, /* left upper corner (inclusive) */
+ uint16_t x2,uint16_t y2 /* right lower corner (inclusive) */
+){
+ fb_sanitize_box(&x1,&y1,&x2,&y2);
+
+ x2++; /* see definition of fb_bw8->damage_x2/y2 */
+ y2++;
+
+ /* maybe currently everything is clean? */
+ if(fb_bw8->damage_x1 == fb_bw8->damage_x2 ||
+ fb_bw8->damage_y1 == fb_bw8->damage_y2){
+ fb_bw8->damage_x1 = x1;
+ fb_bw8->damage_y1 = y1;
+ fb_bw8->damage_x2 = x2;
+ fb_bw8->damage_y2 = y2;
+/*
+ printf("%s: was clean! damage now %d %d %d %d\n",
+ __FUNCTION__,fb_bw8->damage_x1,fb_bw8->damage_y1,
+ fb_bw8->damage_x2,fb_bw8->damage_y2);
+*/
+ return;
+ }
+
+ /* grow damage box */
+ if(x1 < fb_bw8->damage_x1)
+ fb_bw8->damage_x1 = x1;
+ if(y1 < fb_bw8->damage_y1)
+ fb_bw8->damage_y1 = y1;
+ if(x2 > fb_bw8->damage_x2)
+ fb_bw8->damage_x2 = x2;
+ if(y2 > fb_bw8->damage_y2)
+ fb_bw8->damage_y2 = y2;
+#if 0
+ printf("%s: damage now %d %d %d %d\n",
+ __FUNCTION__,fb_bw8->damage_x1,fb_bw8->damage_y1,
+ fb_bw8->damage_x2,fb_bw8->damage_y2);
+#endif
+}
+
+static void fb_bw8_line(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2){
+ fb_sanitize_box(&x1,&y1,&x2,&y2);
+ /* FIXME : this is currently unimplemented! */
+}
+
+void fb_bw8_lineto(uint16_t x,uint16_t y){
+ fb_bw8_line(framebuffer->cursor_x,framebuffer->cursor_y,x,y);
+ framebuffer->cursor_x = x;
+ framebuffer->cursor_y = y;
+}
+
+/* depending on color set (add to or_mask) or clear
+ (remove from and_mask) bit number bitnum */
+static void set_pixel(uint8_t *and_mask,
+ uint8_t *or_mask,
+ int bitnum,
+ uint32_t color
+){
+ if(color == FB_COLOR_TRANSP)
+ return;
+ if(color == FB_COLOR_WHITE)
+ *and_mask &= ~(1<<bitnum);
+ else
+ *or_mask |= 1<<bitnum;
+}
+
+static void set_fg_pixel(uint8_t *and_mask,uint8_t *or_mask,int bitnum){
+ set_pixel(and_mask,or_mask,bitnum,framebuffer->fg_color);
+}
+
+static void set_bg_pixel(uint8_t *and_mask,uint8_t *or_mask,int bitnum){
+ set_pixel(and_mask,or_mask,bitnum,framebuffer->bg_color);
+}
+
+static void fb_bw8_box(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
+{
+ uint16_t y,w;
+ uint8_t *p;
+
+ uint8_t and_mask,or_mask; // filling
+ uint8_t and_mask_side,or_mask_side; // left and right side
+
+ fb_sanitize_box(&x1,&y1,&x2,&y2);
+ fb_bw8_update_damage(x1,y1,x2,y2);
+
+ for(y=y1&0xfff8;y<=y2;y+=8){
+ /* don't clear any pixels (white) */
+ and_mask = and_mask_side = 0xff;
+ or_mask = or_mask_side = 0;
+
+ for(w=0;w<8;w++){ /* check which pixels are affected */
+ if(y+w >= y1 && y+w <= y2){
+ set_bg_pixel(&and_mask,&or_mask,w);
+ set_fg_pixel(&and_mask_side,&or_mask_side,w);
+ }
+
+ if(y+w == y1 || y+w == y2){ /* top and bottom line */
+ set_fg_pixel(&and_mask,&or_mask,w);
+ }
+ }
+
+ p = fb_bw8->mem + (y/8)*framebuffer->width + x1;
+ for(w=x1;w<=x2;w++){
+ if(w == x1 || w == x2)
+ *p = (*p & and_mask_side)|or_mask_side;
+ else
+ *p = (*p & and_mask)|or_mask;
+ p++;
+ }
+ }
+}
+
+/* draw box from cursor to (x,y) */
+void
+fb_bw8_boxto(uint16_t x,uint16_t y){
+ fb_bw8_box(framebuffer->cursor_x,framebuffer->cursor_y,x,y);
+ framebuffer->cursor_x = x;
+ framebuffer->cursor_y = y;
+}
+
+/* this is the most ridiculous function ever, because it has to
+ fiddle with two braindead bitmaps at once, both being
+ organized differently */
+
+/* draw text at current position, with current font and colours up
+ to a width of maxwidth pixels, return pixelwidth consumed */
+
+int
+fb_bw8_putstr(char *str,int maxwidth){
+ const struct fb_font *font = fb_fonts[framebuffer->font];
+ const struct fb_char *fchr;
+
+ int x1,y1,x2,y2; // will become bounding box
+ int w; // 0..7 while building bits per byte
+ int y; // coordinates in display
+ int char_x,char_y; // coordinates in font character
+ int bitmap_x,bitmap_y; // coordinates in character's bitmap
+ int byte_per_line; // depending on character width in font
+ int bitmap_offs,bitmap_bit; // offset inside bitmap, bit number of pixel
+ int fb8_offs; // offset to current pixel in framebuffer
+ uint8_t and_mask,or_mask; // to draw on framebuffer
+ uint8_t *p; // pointer into framebuffer memorya
+ int total_w; // total width
+
+ /* center, if maxwidth < 0 */
+ if (maxwidth < 0) {
+ total_w = 0;
+ /* count width of string */
+ for(p=(uint8_t *)str;*p;p++){
+ fchr = fb_font_get_char(font,*p);
+ if(!fchr) /* FIXME: Does '?' exist in every font? */
+ fchr = fb_font_get_char(font,'?');
+ total_w += fchr->width;
+
+ } // str
+ if (total_w <= framebuffer->width)
+ framebuffer->cursor_x =
+ (framebuffer->width - total_w) >> 1;
+ maxwidth = framebuffer->width;
+ }
+
+ x1 = framebuffer->cursor_x; // first col (incl!)
+ x2 = x1 + maxwidth - 1; // last col (incl!)
+ if(x2 >= framebuffer->width)
+ x2 = framebuffer->width - 1;
+
+ y1 = framebuffer->cursor_y - font->ascent + 1; // first row
+ y2 = y1 + font->height - 1; // last row
+
+#if 0
+ printf("%s: %d %d %d %d\n",__FUNCTION__,x1,y1,x2,y2);
+#endif
+
+ if(y1 < 0) // sanitize in case of overflow
+ y1 = 0;
+ if(y2 >= framebuffer->height)
+ y2 = framebuffer->height - 1;
+
+ fb8_offs = x1 + (y1 & 0xfff8)/8;
+
+ /* iterate over all characters */
+ for(;*str && framebuffer->cursor_x <= x2;str++){
+ fchr = fb_font_get_char(font,*str);
+ if(!fchr) /* FIXME: Does '?' exist in every font? */
+ fchr = fb_font_get_char(font,'?');
+
+ byte_per_line = (fchr->bbox_w+7)/8;;
+
+ /* character pixels, left to right */
+ for(char_x=0;
+ char_x<fchr->width && char_x + framebuffer->cursor_x <= x2;
+ char_x++
+ ){
+ /* character pixels, top to bottom, in stripes
+ of 8 to match LCD RAM organisation */
+ for(y=y1&0xfff8;y<=y2;y+=8){ // display lines
+ /* bitmap coordinates, X= left to right */
+ bitmap_x = char_x - fchr->bbox_x;
+ /* character coords. Y increases from
+ cursor upwards */
+ char_y = framebuffer->cursor_y-y;
+ /* bitmap index = height-(bitmap coords)-1 */
+ bitmap_y = fchr->bbox_h -
+ (char_y - fchr->bbox_y) - 1;
+
+ fb8_offs = framebuffer->cursor_x +
+ char_x + (y/8)*framebuffer->width;
+
+ and_mask = 0xff;
+ or_mask = 0x00;
+
+ /* top to bottom inside of a 8bit column */
+ for(w=0;w<8;w++,bitmap_y++){
+ /* inside drawing area? */
+ if(y+w < y1 || y+w > y2)
+ continue;
+
+ /* outside pixel data of this
+ character? */
+ if(bitmap_x < 0 ||
+ bitmap_x >= fchr->bbox_w ||
+ bitmap_y < 0 ||
+ bitmap_y >= fchr->bbox_h
+ )
+ goto outside_char_bitmap;
+
+ /* check bit in pixel data for
+ this character */
+ bitmap_offs = bitmap_x/8+
+ bitmap_y*byte_per_line;
+ bitmap_bit = 7-(bitmap_x%8);
+
+ /* bit is set */
+ if(fchr->data[bitmap_offs] &
+ (1<<bitmap_bit)){
+ set_fg_pixel(&and_mask,
+ &or_mask,w);
+ } else { // unset, or outside bitmap
+outside_char_bitmap:
+ set_bg_pixel(&and_mask,
+ &or_mask,w);
+ }
+ } // for(w...)
+ /* adjust byte in framebuffer */
+ p = fb_bw8->mem + fb8_offs;
+ *p = ( *p & and_mask ) | or_mask;
+ } // for(y...)
+ } // for(char_x...)
+ framebuffer->cursor_x += char_x;
+ } // str
+
+ x2 = framebuffer->cursor_x;
+ fb_bw8_update_damage(x1,y1,x2,y2);
+ return x2-x1;
+}
+
+int
+fb_bw8_putchar(char c,int maxwidth){
+ char tmp[2];
+ tmp[0]=c;
+ tmp[1]=c;
+ return fb_bw8_putstr(tmp,maxwidth);
+}
diff --git a/Src/osmolib/src/target/firmware/fb/fb_dummy.c b/Src/osmolib/src/target/firmware/fb/fb_dummy.c
new file mode 100644
index 0000000..cb053de
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/fb_dummy.c
@@ -0,0 +1,70 @@
+/*
+ "hardware" driver for a dummy framebuffer. Used when no
+ display hardware is supported
+ */
+
+/* (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.
+ *
+ */
+
+#include <fb/framebuffer.h>
+#include <defines.h>
+
+static void
+fb_dummy_init(){
+}
+
+static void
+fb_dummy_clear(){
+}
+
+static void
+fb_dummy_boxto(uint16_t x,uint16_t y){
+ framebuffer->cursor_x = x;
+ framebuffer->cursor_y = y;
+}
+
+static void
+fb_dummy_lineto(uint16_t x,uint16_t y){
+ framebuffer->cursor_x = x;
+ framebuffer->cursor_y = y;
+}
+
+static int
+fb_dummy_putstr(__unused char *c, __unused int maxwidth){
+ return 0;
+}
+
+static void
+fb_dummy_flush(){
+}
+
+struct framebuffer fb_dummy_framebuffer = {
+ .name = "dummyfb",
+ .init = fb_dummy_init,
+ .clear = fb_dummy_clear,
+ .boxto = fb_dummy_boxto,
+ .lineto = fb_dummy_lineto,
+ .putstr = fb_dummy_putstr,
+ .flush = fb_dummy_flush,
+ .width = 128,
+ .height = 64
+};
+
+struct framebuffer *framebuffer = & fb_dummy_framebuffer;
diff --git a/Src/osmolib/src/target/firmware/fb/fb_rgb332.c b/Src/osmolib/src/target/firmware/fb/fb_rgb332.c
new file mode 100644
index 0000000..08d64e1
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/fb_rgb332.c
@@ -0,0 +1,305 @@
+/* utility functions for a color framebuffer organized
+ as one pixel per byte, with bits mapped as RRRGGGBB.
+ This matches the SSD1783 LC Display Controller used
+ on the Motorola C155 */
+
+/* (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.
+ *
+ */
+
+#include <fb/framebuffer.h>
+#include <fb/fb_rgb332.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+fb_rgb332_clear(){
+ int i,n;
+
+ /* bytes to clear */
+ n = framebuffer->height * framebuffer->width;
+ for(i=0;i<n;i++)
+ fb_rgb332->mem[i]=0xff; /* white */
+
+ /* mark everything as dirty */
+ fb_rgb332->damage_x1 = 0;
+ fb_rgb332->damage_x2 = framebuffer->width;
+ fb_rgb332->damage_y1 = 0;
+ fb_rgb332->damage_y2 = framebuffer->height;
+}
+
+/* update damage rectangle to include the area
+ x1,y1 (upper left) to x2,y2 (lower right)
+ Note that all pixels *including* x1y2 and x2y2 are
+ marked as dirty */
+static void
+fb_rgb332_update_damage(
+ uint16_t x1,uint16_t y1, /* left upper corner (inclusive) */
+ uint16_t x2,uint16_t y2 /* right lower corner (inclusive) */
+){
+ fb_sanitize_box(&x1,&y1,&x2,&y2);
+
+ x2++; /* see definition of fb_rgb332->damage_x2/y2 */
+ y2++;
+
+ /* maybe currently everything is clean? */
+ if(fb_rgb332->damage_x1 == fb_rgb332->damage_x2 ||
+ fb_rgb332->damage_y1 == fb_rgb332->damage_y2
+ ){
+ fb_rgb332->damage_x1 = x1;
+ fb_rgb332->damage_y1 = y1;
+ fb_rgb332->damage_x2 = x2;
+ fb_rgb332->damage_y2 = y2;
+ return;
+ }
+
+ /* grow damage box */
+ if(x1 < fb_rgb332->damage_x1)
+ fb_rgb332->damage_x1 = x1;
+ if(y1 < fb_rgb332->damage_y1)
+ fb_rgb332->damage_y1 = y1;
+ if(x2 > fb_rgb332->damage_x2)
+ fb_rgb332->damage_x2 = x2;
+ if(y2 > fb_rgb332->damage_y2)
+ fb_rgb332->damage_y2 = y2;
+#if 0
+ printf("%s: damage now %d %d %d %d\n",
+ __FUNCTION__,fb_rgb332->damage_x1,fb_rgb332->damage_y1,
+ fb_rgb332->damage_x2,fb_rgb332->damage_y2);
+#endif
+}
+
+/* we trust gcc to move this expensive bitshifting out of
+ the loops in the drawing funtcions */
+static uint8_t rgb_to_pixel(uint32_t color){
+ uint8_t ret;
+ ret = (FB_COLOR_TO_R(color) & 0xe0); /* 765 = RRR */
+ ret |= (FB_COLOR_TO_G(color) & 0xe0) >> 3; /* 432 = GGG */
+ ret |= (FB_COLOR_TO_B(color) & 0xc0) >> 6; /* 10 = BB */
+ return ret;
+}
+
+static void set_pix(uint8_t *pixel,uint32_t color){
+ if(color == FB_COLOR_TRANSP)
+ return;
+ *pixel = rgb_to_pixel(color);
+}
+
+static void set_fg(uint8_t *pixel){
+ set_pix(pixel,framebuffer->fg_color);
+}
+
+static void set_bg(uint8_t *pixel){
+ set_pix(pixel,framebuffer->bg_color);
+}
+
+void fb_rgb332_boxto(uint16_t x2,uint16_t y2)
+{
+ uint16_t x1 = framebuffer->cursor_x;
+ uint16_t y1 = framebuffer->cursor_y;
+ int x,y;
+ uint8_t *p;
+
+ framebuffer->cursor_x = x2;
+ framebuffer->cursor_y = y2;
+
+ fb_sanitize_box(&x1,&y1,&x2,&y2);
+ fb_rgb332_update_damage(x1,y1,x2,y2);
+
+ for(y=y1; y<=y2; y++){
+ p = & fb_rgb332->mem[x1 + framebuffer->width * y];
+ for(x=x1;x<=x2;x++){
+ set_bg(p);
+ if(y==y1 || y==y2 || x==x1 || x==x2) /* border */
+ set_fg(p);
+ p++;
+ }
+ }
+}
+
+/* draw a line like Brensenham did... (roughly) */
+void fb_rgb332_lineto(uint16_t x2,uint16_t y2){
+ uint8_t *p,pixel; /* framebuffer pointer */
+ int delta_regular; /* framebuffer offset per step */
+ int delta_step; /* " */
+
+ uint16_t x1 = framebuffer->cursor_x; /* start */
+ uint16_t y1 = framebuffer->cursor_y;
+
+ int t,tmax; /* counter for steps */
+ int err_inc,err_accu=0; /* error delta and accumulator for */
+ /* Brensenham's algorhithm */
+
+ fb_limit_fb_range(&x1,&y1);
+ fb_limit_fb_range(&x2,&y2);
+ fb_rgb332_update_damage(x1,y1,x2,y2);
+
+ framebuffer->cursor_x = x2; /* end pixel */
+ framebuffer->cursor_y = y2;
+
+ /* pointer to first pixel, pixel value in FB memory */
+ p = fb_rgb332->mem + framebuffer->width * y1 + x1;
+ pixel = rgb_to_pixel(framebuffer->fg_color);
+
+ if(abs(x2-x1) >= abs(y2-y1)){ /* shallow line */
+ /* set pointer deltas for directions */
+ delta_regular = 1; /* X */
+ if(x2 < x1)
+ delta_regular = -delta_regular;
+ delta_step = framebuffer->width; /* Y */
+ if(y2 < y1)
+ delta_step = -delta_step;
+ tmax = abs(x2-x1);
+ err_inc = abs(y2-y1);
+ } else { /* steep line */
+ delta_regular = framebuffer->width; /* Y */
+ if(y2 < y1)
+ delta_regular = -delta_regular;
+ delta_step = 1; /* X */
+ if(x2 < x1)
+ delta_step = -1;
+ tmax = abs(y2-y1);
+ err_inc = abs(x2-y1);
+ }
+
+#if 0
+ printf("%s: (%d,%d) -> (%d,%d) step=%d regular=%d err_inc=%d tmax=%d\n",
+ __FUNCTION__,x1,y1,x2,y2,delta_step,delta_regular,err_inc,tmax);
+#endif
+
+ for(t=0;t<=tmax;t++){
+ *p = pixel;
+ err_accu += err_inc;
+ if(err_accu >= tmax){
+ p += delta_step;
+ err_accu -= tmax;
+ }
+ p += delta_regular;
+ }
+}
+
+int fb_rgb332_putstr(char *str,int maxwidth){
+ const struct fb_font *font = fb_fonts[framebuffer->font];
+ const struct fb_char *fchr;
+
+ int x1,y1,x2,y2; // will become bounding box
+ int y; // coordinates in display
+ int char_x=0,char_y; // coordinates in font character
+ int bitmap_x,bitmap_y; // coordinates in character's bitmap
+ int byte_per_line; // depending on character width in font
+ int bitmap_offs,bitmap_bit; // offset inside bitmap, bit number of pixel
+ uint8_t *p,fgpixel,bgpixel,trans; // pointer into framebuffer memory
+ int total_w; // total width
+
+ /* center, if maxwidth < 0 */
+ if (maxwidth < 0) {
+ total_w = 0;
+ /* count width of string */
+ for(p=(uint8_t *)str;*p;p++){
+ fchr = fb_font_get_char(font,*p);
+ if(!fchr) /* FIXME: Does '?' exist in every font? */
+ fchr = fb_font_get_char(font,'?');
+ total_w += fchr->width;
+
+ } // str
+ if (total_w <= framebuffer->width)
+ framebuffer->cursor_x =
+ (framebuffer->width - total_w) >> 1;
+ else
+ framebuffer->cursor_x = 1;
+ maxwidth = framebuffer->width;
+ }
+
+ x1 = framebuffer->cursor_x; // first col (incl!)
+ x2 = x1 + maxwidth - 1; // last col (incl!)
+ if(x2 >= framebuffer->width)
+ x2 = framebuffer->width - 1;
+
+ y1 = framebuffer->cursor_y - font->ascent + 1; // first row
+ y2 = y1 + font->height - 1; // last row
+
+ fgpixel = rgb_to_pixel(framebuffer->fg_color);
+ bgpixel = rgb_to_pixel(framebuffer->bg_color);
+ trans = (framebuffer->bg_color == FB_COLOR_TRANSP);
+
+ if(y1 < 0) // sanitize in case of overflow
+ y1 = 0;
+ if(y2 >= framebuffer->height)
+ y2 = framebuffer->height - 1;
+
+ /* iterate over all characters */
+ for(;*str && framebuffer->cursor_x <= x2;str++){
+ fchr = fb_font_get_char(font,*str);
+ if(!fchr) /* FIXME: Does '?' exist in every font? */
+ fchr = fb_font_get_char(font,'?');
+ if(!fchr)
+ return 0;
+ byte_per_line = (fchr->bbox_w+7)/8;
+
+ for(y=y1;y<=y2;y++){
+ p=fb_rgb332->mem+y*framebuffer->width;
+ p+=framebuffer->cursor_x;
+
+ for(char_x=0;
+ char_x<fchr->width &&
+ char_x+framebuffer->cursor_x <= x2;
+ char_x++
+ ){
+ /* bitmap coordinates, X= left to right */
+ bitmap_x = char_x - fchr->bbox_x;
+ /* character coords. Y increases from
+ cursor upwards */
+ char_y = framebuffer->cursor_y-y;
+ /* bitmap index = height-(bitmap coords)-1 */
+ bitmap_y = fchr->bbox_h -
+ (char_y - fchr->bbox_y) - 1;
+
+ /* outside pixel data of this
+ character? */
+ if(bitmap_x < 0 ||
+ bitmap_x >= fchr->bbox_w ||
+ bitmap_y < 0 ||
+ bitmap_y >= fchr->bbox_h
+ )
+ goto outside_char_bitmap;
+
+ /* check bit in pixel data for
+ this character */
+ bitmap_offs=bitmap_x/8+bitmap_y*byte_per_line;
+ bitmap_bit=7-(bitmap_x%8);
+
+ /* bit is set */
+ if(fchr->data[bitmap_offs]&(1<<bitmap_bit)){
+ *p = fgpixel;
+ } else { // unset, or outside bitmap
+outside_char_bitmap:
+ if (!trans)
+ *p = bgpixel;
+ }
+ p++;
+ } // for(x...)
+ } // for(char_x...)
+ framebuffer->cursor_x += char_x;
+ } // str
+
+ x2 = framebuffer->cursor_x;
+ fb_rgb332_update_damage(x1,y1,x2,y2);
+ return x2-x1;
+}
+
diff --git a/Src/osmolib/src/target/firmware/fb/fb_s6b33b1x.c b/Src/osmolib/src/target/firmware/fb/fb_s6b33b1x.c
new file mode 100644
index 0000000..3629a10
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/fb_s6b33b1x.c
@@ -0,0 +1,193 @@
+/* Framebuffer implementation - combined Sunplus SPCA552E and
+ * Samsung S6B33B1X LCD driver - as used in the Pirelli DP-L10 */
+
+/* (C) 2012 by Steve Markgraf <steve@steve-m.de>
+ *
+ * based on fb_ssd1783.c:
+ * (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.
+ *
+ */
+
+#include <fb/framebuffer.h>
+#include <fb/fb_rgb332.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <delay.h>
+#include <memory.h>
+
+#define S6B33B1X_WIDTH 128
+#define S6B33B1X_HEIGHT 128
+#define LCD_INVIS_X_PIXELS 4
+
+#define ARMIO_LATCH_OUT 0xfffe4802
+#define nCS4_ADDR 0x02800000
+
+static uint8_t fb_s6b33b1x_mem[S6B33B1X_WIDTH * S6B33B1X_HEIGHT];
+
+enum s6b33b1x_cmdflag { CMD, DATA, END };
+
+struct s6b33b1x_cmdlist {
+ enum s6b33b1x_cmdflag is_cmd:8; /* 1: is a command, 0: is data, 2: end marker! */
+ uint8_t data; /* 8 bit to send to LC display */
+} __attribute__((packed));
+
+static const struct s6b33b1x_cmdlist
+s6b33b1x_initdata[] = {
+ { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */
+ { DATA, 0x00 }, /* DATA: everything off */
+ { CMD, 0x02 }, /* CMD Oscillation Mode Set */
+ { DATA, 0x00 }, /* DATA: oscillator off */
+ { CMD, 0x2c }, /* CMD Standby Mode off */
+ { CMD, 0x50 }, /* CMD Display off */
+ { CMD, 0x02 }, /* CMD Oscillation Mode Set */
+ { DATA, 0x01 }, /* DATA: oscillator on */
+ { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */
+ { DATA, 0x01 }, /* DATA: Booster 1 on */
+ { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */
+ { DATA, 0x09 }, /* DATA: Booster 1 on, OP-AMP on */
+ { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */
+ { DATA, 0x0b }, /* DATA: Booster 1 + 2 on, OP-AMP on */
+ { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */
+ { DATA, 0x0f }, /* DATA: Booster 1 + 2 + 3 on, OP-AMP on */
+ { CMD, 0x20 }, /* CMD DC-DC Select */
+ { DATA, 0x01 }, /* DATA: step up x1.5 */
+ { CMD, 0x24 }, /* CMD DCDC Clock Division Set */
+ { DATA, 0x0a }, /* DATA: fPCK = fOSC/6 */
+ { CMD, 0x2a }, /* CMD Contrast Control */
+ { DATA, 0x2d }, /* DATA: default contrast */
+ { CMD, 0x30 }, /* CMD Adressing mode set */
+ { DATA, 0x0b }, /* DATA: 65536 color mode */
+ { CMD, 0x10 }, /* CMD Driver output mode set */
+ { DATA, 0x03 }, /* DATA: Display duty: 1/132 */
+ { CMD, 0x34 }, /* CMD N-line inversion set */
+ { DATA, 0x88 }, /* DATA: inversion on, one frame, every 8 blocks */
+ { CMD, 0x40 }, /* CMD Entry mode set */
+ { DATA, 0x00 }, /* DATA: Y address counter mode */
+ { CMD, 0x28 }, /* CMD Temperature Compensation set */
+ { DATA, 0x01 }, /* DATA: slope -0.05%/degC */
+ { CMD, 0x32 }, /* CMD ROW vector mode set */
+ { DATA, 0x01 }, /* DATA: every 2 subgroup */
+ { CMD, 0x51 }, /* CMD Display on */
+ { END, 0x00 }, /* MARKER: end of list */
+};
+
+static void fb_s6b33b1x_send_cmdlist(const struct s6b33b1x_cmdlist *p)
+{
+ while(p->is_cmd != END){
+ writew(p->data, nCS4_ADDR);
+ p++;
+ }
+}
+
+static void fb_spca_write(uint16_t addr, uint16_t val)
+{
+ writew(addr, nCS4_ADDR);
+ writew(val , nCS4_ADDR | 2);
+}
+
+static void fb_spca_init(void)
+{
+ uint16_t reg;
+
+ /* Initialize Sunplus SPCA552E Media Controller for bypass mode */
+ fb_spca_write(0x7e, 0x00); /* internal register access */
+ delay_ms(10);
+ fb_spca_write(0x7a, 0x00); /* keep CPU in reset state */
+ delay_ms(10);
+ fb_spca_write(0x7f, 0x00); /* select main page */
+ delay_ms(5);
+ fb_spca_write(0x72, 0x07); /* don't reshape timing, 16 bit mode */
+ fb_spca_write(0x14, 0x03);
+ fb_spca_write(0x7f, 0x00); /* select main page */
+ delay_ms(5);
+ fb_spca_write(0x06, 0xff);
+ fb_spca_write(0x7f, 0x09);
+ fb_spca_write(0x19, 0x08); /* backlight: 0x08 is on, 0x0c is off */
+ fb_spca_write(0x23, 0x18);
+
+ /* enable bypass mode */
+ reg = readw(ARMIO_LATCH_OUT);
+ reg |= (1 << 7);
+ writew(reg, ARMIO_LATCH_OUT);
+}
+
+static void fb_s6b33b1x_init(void)
+{
+ printf("%s: initializing LCD.\n",__FUNCTION__);
+
+ fb_spca_init();
+ fb_s6b33b1x_send_cmdlist(s6b33b1x_initdata);
+}
+
+static void fb_s6b33b1x_flush(void)
+{
+ int x,y;
+ uint8_t *p;
+ struct s6b33b1x_cmdlist prepare_disp_write_cmds[] = {
+ { CMD, 0x42 }, /* set column address */
+ { DATA, fb_rgb332->damage_x1 + LCD_INVIS_X_PIXELS },
+ { DATA, fb_rgb332->damage_x2 + LCD_INVIS_X_PIXELS - 1 },
+ { CMD, 0x43 }, /* set page address (Y) */
+ { DATA, fb_rgb332->damage_y1 },
+ { DATA, fb_rgb332->damage_y2 - 1 },
+ { END, 0x00 }
+ };
+
+ /* If everything's clean, just return */
+ if(fb_rgb332->damage_x1 == fb_rgb332->damage_x2 ||
+ fb_rgb332->damage_y1 == fb_rgb332->damage_y2) {
+ printf("%s: no damage\n",__FUNCTION__);
+ return;
+ }
+
+ fb_s6b33b1x_send_cmdlist(prepare_disp_write_cmds);
+
+ for(y=fb_rgb332->damage_y1;y<fb_rgb332->damage_y2;y++) {
+ p = & fb_rgb332->mem[y * framebuffer->width]; // start of line
+ p += fb_rgb332->damage_x1; // start of damage area
+
+ for(x=fb_rgb332->damage_x1; x<fb_rgb332->damage_x2; x++) {
+ uint16_t data = rgb332_to_565(*p++);
+ writew(data , nCS4_ADDR | 2);
+ }
+ }
+
+ fb_rgb332->damage_x1 = fb_rgb332->damage_x2 = 0;
+ fb_rgb332->damage_y1 = fb_rgb332->damage_y2 = 0;
+}
+
+static struct framebuffer fb_s6b33b1x_framebuffer = {
+ .name = "s6b33b1x",
+ .init = fb_s6b33b1x_init,
+ .clear = fb_rgb332_clear,
+ .boxto = fb_rgb332_boxto,
+ .lineto = fb_rgb332_lineto,
+ .putstr = fb_rgb332_putstr,
+ .flush = fb_s6b33b1x_flush,
+ .width = S6B33B1X_WIDTH,
+ .height = S6B33B1X_HEIGHT
+};
+
+static struct fb_rgb332 fb_s6b33b1x_rgb332 = {
+ .mem = fb_s6b33b1x_mem
+};
+
+struct framebuffer *framebuffer = &fb_s6b33b1x_framebuffer;
+struct fb_rgb332 *fb_rgb332 = &fb_s6b33b1x_rgb332;
diff --git a/Src/osmolib/src/target/firmware/fb/fb_ssd1783.c b/Src/osmolib/src/target/firmware/fb/fb_ssd1783.c
new file mode 100644
index 0000000..cacdce0
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/fb_ssd1783.c
@@ -0,0 +1,204 @@
+/* Framebuffer implementation - SSD1783 LCD driver for C155 */
+/* Based on ssd1783.c by Steve Markgraf and Harald Welte */
+
+/* (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.
+ *
+ */
+
+#include <fb/framebuffer.h>
+#include <fb/fb_rgb332.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <delay.h>
+#include <uwire.h>
+#include <calypso/clock.h>
+
+#define SSD1783_WIDTH 98
+#define SSD1783_HEIGHT 67
+#define SSD1783_UWIRE_BITLEN 9
+#define SSD1783_DEV_ID 0
+
+#define LCD_TOP_FREE_ROWS 3
+#define LCD_LEFT_FREE_COLS 0
+#define PIXEL_BYTES 3
+#define FONT_HEIGHT 8
+#define FONT_WIDTH 8
+
+static uint8_t fb_ssd1783_mem[SSD1783_WIDTH * SSD1783_HEIGHT];
+
+enum ssd1783_cmdflag { CMD, DATA, END };
+
+struct ssd1783_cmdlist {
+ enum ssd1783_cmdflag is_cmd:8; /* 1: is a command, 0: is data, 2: end marker! */
+ uint8_t data; /* 8 bit to send to LC display */
+} __attribute__((packed));
+
+static const struct ssd1783_cmdlist
+ssd1783_initdata[] = {
+ { CMD, 0xD1 }, /* CMD set internal oscillator on */
+ { CMD, 0x94 }, /* CMD leave sleep mode */
+ { CMD, 0xbb }, /* CMD Set COM Output Scan Direction: */
+ { DATA, 0x01 }, /* DATA: 01: COM0-79, then COM159-80 */
+/* -------- DIFFERENT FROM ORIGINAL CODE: -------------- */
+/* we use 8bit per pixel packed RGB 332 */
+ { CMD, 0xbc }, /* CMD Set Data Output Scan Direction */
+ { DATA, 0x00 }, /* DATA: column scan, normal rotation, normal display */
+ { DATA, 0x00 }, /* DATA: RGB color arrangement R G B R G B ... */
+/*-->*/ { DATA, 0x01 }, /* DATA: 8 bit per pixel mode MSB <RRRGGGBB> LSB */
+/* --------- /DIFFERENT ---------- */
+ { CMD, 0xce }, /* CMD Set 256 Color Look Up Table LUT */
+ { DATA, 0x00 }, /* DATA red 000 */
+ { DATA, 0x03 }, /* DATA red 001 */
+ { DATA, 0x05 }, /* DATA red 010 */
+ { DATA, 0x07 }, /* DATA red 011 */
+ { DATA, 0x09 }, /* DATA red 100 */
+ { DATA, 0x0b }, /* DATA red 101 */
+ { DATA, 0x0d }, /* DATA red 110 */
+ { DATA, 0x0f }, /* DATA red 111 */
+ { DATA, 0x00 }, /* DATA green 000 */
+ { DATA, 0x03 }, /* DATA green 001 */
+ { DATA, 0x05 }, /* DATA green 010 */
+ { DATA, 0x07 }, /* DATA green 011 */
+ { DATA, 0x09 }, /* DATA green 100 */
+ { DATA, 0x0b }, /* DATA green 101 */
+ { DATA, 0x0d }, /* DATA green 110 */
+ { DATA, 0x0f }, /* DATA green 111 */
+ { DATA, 0x00 }, /* DATA blue 00 */
+ { DATA, 0x05 }, /* DATA blue 01 */
+ { DATA, 0x0a }, /* DATA blue 10 */
+ { DATA, 0x0f }, /* DATA blue 11 */
+ { CMD, 0xca }, /* CMD Set Display Control - Driver Duty Selection */
+ { DATA, 0xff }, // can't find description of the values in the original
+ { DATA, 0x10 }, // display/ssd1783.c in my datasheet :-(
+ { DATA, 0x01 }, //
+ { CMD, 0xab }, /* CMD Set Scroll Start */
+ { DATA, 0x00 }, /* DATA: Starting address at block 0 */
+ { CMD, 0x20 }, /* CMD Set power control register */
+ { DATA, 0x0b }, /* DATA: booster 6x, reference gen. & int regulator */
+ { CMD, 0x81 }, /* CMD Contrast Lvl & Int. Regul. Resistor Ratio */
+ { DATA, 0x29 }, /* DATA: contrast = 0x29 */
+ { DATA, 0x05 }, /* DATA: 0x05 = 0b101 -> 1+R2/R1 = 11.37 */
+ { CMD, 0xa7 }, /* CMD Invert Display */
+ { CMD, 0x82 }, /* CMD Set Temperature Compensation Coefficient */
+ { DATA, 0x00 }, /* DATA: Gradient is -0.10 % / degC */
+ { CMD, 0xfb }, /* CMD Set Biasing Ratio */
+ { DATA, 0x03 }, /* DATA: 1/10 bias */
+ { CMD, 0xf2 }, /* CMD Set Frame Frequency and N-line inversion */
+ { DATA, 0x08 }, /* DATA: 75 Hz (POR) */
+ { DATA, 0x06 }, /* DATA: n-line inversion: 6 lines */
+ { CMD, 0xf7 }, /* CMD Select PWM/FRC Select Full Col./8col mode */
+ { DATA, 0x28 }, /* DATA: always 0x28 */
+ { DATA, 0x8c }, /* DATA: 4bit PWM + 2 bit FRC */
+ { DATA, 0x05 }, /* DATA: full color mode */
+ { CMD, 0xaf }, /* CMD Display On */
+ { END, 0x00 }, /* MARKER: end of list */
+};
+
+static void
+fb_ssd1783_send_cmdlist(const struct ssd1783_cmdlist *p){
+ int i=0;
+ while(p->is_cmd != END){
+ uint16_t sendcmd = p->data;
+ if(p->is_cmd == DATA)
+ sendcmd |= 0x0100; /* 9th bit is cmd/data flag */
+ uwire_xfer(SSD1783_DEV_ID, SSD1783_UWIRE_BITLEN, &sendcmd, NULL);
+ p++;
+ i++;
+ }
+}
+
+static void
+fb_ssd1783_init(void){
+ printf("%s: initializing LCD.\n",__FUNCTION__);
+ calypso_reset_set(RESET_EXT, 0);
+ delay_ms(5);
+ uwire_init();
+ delay_ms(5);
+ fb_ssd1783_send_cmdlist(ssd1783_initdata);
+}
+
+/* somehow the palette is messed up, RRR seems to have the
+ bits reversed! R0 R1 R2 G G G B B ---> R2 R1 R0 G G G B B */
+static uint8_t fix_rrr(uint8_t v){
+ return (v & 0x5f) | (v & 0x80) >> 2 | (v & 0x20) << 2;
+}
+
+static void
+fb_ssd1783_flush(void){
+ int x,y;
+ uint8_t *p;
+ struct ssd1783_cmdlist prepare_disp_write_cmds[] = {
+ { CMD, 0x15 }, /* set column address */
+ { DATA, fb_rgb332->damage_x1 },
+ { DATA, fb_rgb332->damage_x2-1 },
+ { CMD, 0x75 }, /* set page address (Y) */
+ { DATA, fb_rgb332->damage_y1 },
+ { DATA, fb_rgb332->damage_y2-1 },
+ { CMD, 0x5c }, /* enter write display ram mode */
+ { END, 0x00 }
+ };
+ struct ssd1783_cmdlist nop[] = {
+ { CMD, 0x25 }, // NOP command
+ { END, 0x00 }
+ };
+
+ /* If everything's clean, just return */
+ if(fb_rgb332->damage_x1 == fb_rgb332->damage_x2 ||
+ fb_rgb332->damage_y1 == fb_rgb332->damage_y2){
+ printf("%s: no damage\n",__FUNCTION__);
+ return;
+ }
+
+ fb_ssd1783_send_cmdlist(prepare_disp_write_cmds);
+
+ for(y=fb_rgb332->damage_y1;y<fb_rgb332->damage_y2;y++){
+ p = & fb_rgb332->mem[y * framebuffer->width]; // start of line
+ p += fb_rgb332->damage_x1; // start of damage area
+
+ for(x=fb_rgb332->damage_x1;x<fb_rgb332->damage_x2;x++){
+ uint16_t data = 0x0100 | fix_rrr(*p++); // dummy data
+ uwire_xfer(SSD1783_DEV_ID, SSD1783_UWIRE_BITLEN,
+ &data, NULL);
+ }
+ }
+ fb_ssd1783_send_cmdlist(nop);
+
+ fb_rgb332->damage_x1 = fb_rgb332->damage_x2 = 0;
+ fb_rgb332->damage_y1 = fb_rgb332->damage_y2 = 0;
+}
+
+static struct framebuffer fb_ssd1783_framebuffer = {
+ .name = "ssd1783",
+ .init = fb_ssd1783_init,
+ .clear = fb_rgb332_clear,
+ .boxto = fb_rgb332_boxto,
+ .lineto = fb_rgb332_lineto,
+ .putstr = fb_rgb332_putstr,
+ .flush = fb_ssd1783_flush,
+ .width = SSD1783_WIDTH,
+ .height = SSD1783_HEIGHT
+};
+
+static struct fb_rgb332 fb_ssd1783_rgb332 = {
+ .mem = fb_ssd1783_mem
+};
+
+struct framebuffer *framebuffer = &fb_ssd1783_framebuffer;
+struct fb_rgb332 *fb_rgb332 = &fb_ssd1783_rgb332;
diff --git a/Src/osmolib/src/target/firmware/fb/fb_ssd1963.c b/Src/osmolib/src/target/firmware/fb/fb_ssd1963.c
new file mode 100644
index 0000000..361434e
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/fb_ssd1963.c
@@ -0,0 +1,196 @@
+/* Framebuffer implementation - SSD1963 (S1D15G14 clone) LCD driver for J100i */
+/* Based on ssd1963.c by Steve Markgraf and Harald Welte */
+
+/* (C) 2010 by Christian Vogel <vogelchr@vogel.cx>
+ * (C) 2012 by Steve Markgraf <steve@steve-m.de>
+ *
+ * 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 <fb/framebuffer.h>
+#include <fb/fb_rgb332.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <delay.h>
+#include <uwire.h>
+#include <calypso/clock.h>
+
+#define SSD1963_WIDTH 96
+#define SSD1963_HEIGHT 64
+#define SSD1963_UWIRE_BITLEN 9
+#define SSD1963_DEV_ID 0
+
+static uint8_t fb_ssd1963_mem[SSD1963_WIDTH * SSD1963_HEIGHT];
+
+enum ssd1963_cmdflag { CMD, DATA, END };
+
+struct ssd1963_cmdlist {
+ enum ssd1963_cmdflag is_cmd:8; /* 1: is a command, 0: is data, 2: end marker! */
+ uint8_t data; /* 8 bit to send to LC display */
+} __attribute__((packed));
+
+static const struct ssd1963_cmdlist
+ssd1963_initdata[] = {
+ { CMD, 0xb6 }, /* CMD Display Control, set panel parameters */
+ { DATA, 0x4b },
+ { DATA, 0xf1 },
+ { DATA, 0x40 },
+ { DATA, 0x40 },
+ { DATA, 0x00 },
+ { DATA, 0x8c },
+ { DATA, 0x00 },
+ { CMD, 0x3a }, /* CMD Set pixel format */
+ { DATA, 0x02 }, /* DATA: 8 bit per pixel */
+ { CMD, 0x2d }, /* Colour set, RGB332 -> RGB 565 mapping */
+ { DATA, 0x00 }, /* DATA red 000 */
+ { DATA, 0x04 }, /* DATA red 001 */
+ { DATA, 0x09 }, /* DATA red 010 */
+ { DATA, 0x0d }, /* DATA red 011 */
+ { DATA, 0x12 }, /* DATA red 100 */
+ { DATA, 0x16 }, /* DATA red 101 */
+ { DATA, 0x1b }, /* DATA red 110 */
+ { DATA, 0x1f }, /* DATA red 111 */
+ { DATA, 0x00 }, /* Those bytes are probably a second palette */
+ { DATA, 0x00 }, /* for an unused powersaving mode with reduced colors */
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 }, /* DATA green 000 */
+ { DATA, 0x09 }, /* DATA green 001 */
+ { DATA, 0x12 }, /* DATA green 010 */
+ { DATA, 0x1b }, /* DATA green 011 */
+ { DATA, 0x24 }, /* DATA green 100 */
+ { DATA, 0x2d }, /* DATA green 101 */
+ { DATA, 0x36 }, /* DATA green 110 */
+ { DATA, 0x3f }, /* DATA green 111 */
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 }, /* DATA blue 00 */
+ { DATA, 0x0a }, /* DATA blue 01 */
+ { DATA, 0x15 }, /* DATA blue 10 */
+ { DATA, 0x1f }, /* DATA blue 11 */
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { DATA, 0x00 },
+ { CMD, 0x11 }, /* CMD Exit sleep mode*/
+ { CMD, 0xba }, /* CMD Set contrast/Electronic Volume Control */
+ { DATA, 0x5b }, /* DATA: */
+ { DATA, 0x84 }, /* DATA: */
+ { CMD, 0x36 }, /* CMD Memory access control */
+ { DATA, 0x00 }, /* DATA: */
+ { CMD, 0x13 }, /* CMD Enter normal mode */
+ { CMD, 0x29 }, /* CMD Set display on */
+ { END, 0x00 }, /* MARKER: end of list */
+};
+
+static void
+fb_ssd1963_send_cmdlist(const struct ssd1963_cmdlist *p) {
+ int i=0;
+ while(p->is_cmd != END){
+ uint16_t sendcmd = p->data;
+ if(p->is_cmd == DATA)
+ sendcmd |= 0x0100; /* 9th bit is cmd/data flag */
+ uwire_xfer(SSD1963_DEV_ID, SSD1963_UWIRE_BITLEN, &sendcmd, NULL);
+ p++;
+ i++;
+ }
+}
+
+static void
+fb_ssd1963_init(void){
+ printf("%s: initializing LCD.\n",__FUNCTION__);
+ calypso_reset_set(RESET_EXT, 0);
+ delay_ms(5);
+ uwire_init();
+ delay_ms(5);
+ fb_ssd1963_send_cmdlist(ssd1963_initdata);
+}
+
+static void
+fb_ssd1963_flush(void){
+ int x,y;
+ uint8_t *p;
+ struct ssd1963_cmdlist prepare_disp_write_cmds[] = {
+ { CMD, 0x2a }, /* set column address */
+ { DATA, fb_rgb332->damage_x1 },
+ { DATA, fb_rgb332->damage_x2-1 },
+ { CMD, 0x2b }, /* set page address (Y) */
+ { DATA, fb_rgb332->damage_y1 },
+ { DATA, fb_rgb332->damage_y2-1 },
+ { CMD, 0x2c }, /* enter write display ram mode */
+ { END, 0x00 }
+ };
+ struct ssd1963_cmdlist nop[] = {
+ { CMD, 0x00 }, // NOP command
+ { END, 0x00 }
+ };
+
+ /* If everything's clean, just return */
+ if(fb_rgb332->damage_x1 == fb_rgb332->damage_x2 ||
+ fb_rgb332->damage_y1 == fb_rgb332->damage_y2) {
+ printf("%s: no damage\n",__FUNCTION__);
+ return;
+ }
+
+ fb_ssd1963_send_cmdlist(prepare_disp_write_cmds);
+
+ for(y=fb_rgb332->damage_y1;y<fb_rgb332->damage_y2;y++) {
+ p = & fb_rgb332->mem[y * framebuffer->width]; // start of line
+ p += fb_rgb332->damage_x1; // start of damage area
+
+ for(x=fb_rgb332->damage_x1;x<fb_rgb332->damage_x2;x++) {
+ uint16_t data = 0x0100 | *p++;
+ uwire_xfer(SSD1963_DEV_ID, SSD1963_UWIRE_BITLEN,
+ &data, NULL);
+ }
+ }
+ fb_ssd1963_send_cmdlist(nop);
+
+ fb_rgb332->damage_x1 = fb_rgb332->damage_x2 = 0;
+ fb_rgb332->damage_y1 = fb_rgb332->damage_y2 = 0;
+}
+
+static struct framebuffer fb_ssd1963_framebuffer = {
+ .name = "ssd1963",
+ .init = fb_ssd1963_init,
+ .clear = fb_rgb332_clear,
+ .boxto = fb_rgb332_boxto,
+ .lineto = fb_rgb332_lineto,
+ .putstr = fb_rgb332_putstr,
+ .flush = fb_ssd1963_flush,
+ .width = SSD1963_WIDTH,
+ .height = SSD1963_HEIGHT
+};
+
+static struct fb_rgb332 fb_ssd1963_rgb332 = {
+ .mem = fb_ssd1963_mem
+};
+
+struct framebuffer *framebuffer = &fb_ssd1963_framebuffer;
+struct fb_rgb332 *fb_rgb332 = &fb_ssd1963_rgb332;
diff --git a/Src/osmolib/src/target/firmware/fb/fb_st7558.c b/Src/osmolib/src/target/firmware/fb/fb_st7558.c
new file mode 100644
index 0000000..fdcd38f
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/fb_st7558.c
@@ -0,0 +1,132 @@
+/* Framebuffer implementation - ST1783 LCD driver for C123 */
+/* Based on st7558.c by Harald Welte */
+
+/* (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.
+ *
+ */
+
+#include <fb/framebuffer.h>
+#include <fb/fb_bw8.h>
+
+#include <i2c.h>
+#include <calypso/clock.h>
+#include <delay.h>
+
+#include <stdio.h>
+
+/* Sitronix ST7558 LCD Driver for OSMOCOM framebuffer interface. */
+/* (c) 2010 Christian Vogel <vogelchr@vogel.cx> */
+/* Based on the initial LCD driver by Harald Welte */
+
+#define CONTROL_RS_CMD
+
+#define ST7558_SLAVE_ADDR 0x3c
+#define ST7558_CMD_ADDR 0x00
+#define ST7558_RAM_ADDR 0x40
+
+#define ST7558_WIDTH 96 /* in pixels */
+#define ST7558_HEIGHT 65
+
+#define I2C_MAX_TRANSFER 16
+
+static uint8_t
+fb_st7558_mem[ST7558_WIDTH * ((ST7558_HEIGHT+7)/8)];
+
+/* setup as initially proposed by Harald in st7558.c */
+static const uint8_t st7558_setup[] = {
+ 0x2e, /* ext. display control, set mirror X, set mirror Y*/
+ 0x21, /* function set, enable extended instruction mode */
+ 0x12, /* bias system BS[2,1,0] = [0,1,0] */
+ 0xc0, /* set V_OP (V_OP6 = 1, V_OP[5:0] = 0) */
+ 0x0b, /* booster stages PC1=1, PC0=1 */
+ 0x20, /* function set, disable extended instruction mode */
+ 0x11, /* V_LCD L/H select, PRS=1 */
+ 0x00, /* NOP */
+ 0x0c, /* normal video mode */
+ 0x40, /* set X address to 0 */
+ 0x80 /* set Y address to 0 */
+};
+
+
+static void
+fb_st7558_init(){
+ calypso_reset_set(RESET_EXT, 0);
+ i2c_init(0,0);
+
+ /* initialize controller */
+ i2c_write(ST7558_SLAVE_ADDR,ST7558_CMD_ADDR,1,
+ st7558_setup,sizeof(st7558_setup));
+}
+
+static void
+fb_st7558_flush(){
+ uint16_t x;
+ int page,chunksize,nbytes;
+ uint8_t *p;
+ uint8_t cmd[2];
+
+ if(fb_bw8->damage_y1 == fb_bw8->damage_y2 ||
+ fb_bw8->damage_x1 == fb_bw8->damage_x2)
+ return; /* nothing to update */
+
+ /* update display in stripes of 8 rows, called "pages" */
+ for(page=fb_bw8->damage_y1 >> 3;page <= fb_bw8->damage_y2>>3;page++){
+ /* base offset in RAM framebuffer */
+ x = fb_bw8->damage_x1;
+ nbytes = fb_bw8->damage_x2 - fb_bw8->damage_x1;
+ p = fb_bw8->mem + (page * framebuffer->width + x);
+
+ /* i2c fifo can only handle a maximum of 16 bytes */
+ while(nbytes){
+ cmd[0]=0x40 | page; /* Set Y address of RAM. */
+ cmd[1]=0x80 | x;
+ chunksize = nbytes > I2C_MAX_TRANSFER ? I2C_MAX_TRANSFER : nbytes;
+
+ i2c_write(ST7558_SLAVE_ADDR,ST7558_CMD_ADDR,1,cmd,sizeof(cmd));
+ i2c_write(ST7558_SLAVE_ADDR,ST7558_RAM_ADDR,1,p,chunksize);
+
+ nbytes -= chunksize;
+ p+=I2C_MAX_TRANSFER;
+ x+=I2C_MAX_TRANSFER;
+ }
+ }
+
+ /* mark current buffer as unmodified! */
+ fb_bw8->damage_x1 = fb_bw8->damage_x2 = 0;
+ fb_bw8->damage_y1 = fb_bw8->damage_y2 = 0;
+}
+
+static struct framebuffer fb_st7558_framebuffer = {
+ .name = "st7558",
+ .init = fb_st7558_init,
+ .clear = fb_bw8_clear,
+ .boxto = fb_bw8_boxto,
+ .lineto = fb_bw8_lineto,
+ .putstr = fb_bw8_putstr,
+ .flush = fb_st7558_flush,
+ .width = ST7558_WIDTH,
+ .height = ST7558_HEIGHT
+};
+
+static struct fb_bw8 fb_st7558_bw8 = {
+ .mem = fb_st7558_mem
+};
+
+struct framebuffer *framebuffer = &fb_st7558_framebuffer;
+struct fb_bw8 *fb_bw8 = &fb_st7558_bw8;
diff --git a/Src/osmolib/src/target/firmware/fb/fb_td014.c b/Src/osmolib/src/target/firmware/fb/fb_td014.c
new file mode 100644
index 0000000..c7bde0c
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/fb_td014.c
@@ -0,0 +1,150 @@
+/* Framebuffer implementation - Toppoly TD014 LCD driver for Motorola C139/40 */
+/* Based on td014.c by Steve Markgraf and Harald Welte */
+
+/* (C) 2010 by Christian Vogel <vogelchr@vogel.cx>
+ * (C) 2012 by Steve Markgraf <steve@steve-m.de>
+ *
+ * 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 <fb/framebuffer.h>
+#include <fb/fb_rgb332.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <delay.h>
+#include <uwire.h>
+#include <calypso/clock.h>
+
+#define TD014_WIDTH 96
+#define TD014_HEIGHT 64
+#define TD014_UWIRE_BITLEN 9
+#define TD014_DEV_ID 0
+
+static uint8_t fb_td014_mem[TD014_WIDTH * TD014_HEIGHT];
+
+enum td014_cmdflag { CMD, DATA, END };
+
+struct td014_cmdlist {
+ enum td014_cmdflag is_cmd:8; /* 1: is a command, 0: is data, 2: end marker! */
+ uint8_t data; /* 8 bit to send to LC display */
+} __attribute__((packed));
+
+static const struct td014_cmdlist
+td014_initdata[] = {
+ { CMD, 0x3f },
+ { DATA, 0x01 },
+ { CMD, 0x20 },
+ { DATA, 0x03 },
+ { CMD, 0x31 },
+ { DATA, 0x03 },
+ { END, 0x00 }, /* MARKER: end of list */
+};
+
+static void
+fb_td014_send_cmdlist(const struct td014_cmdlist *p) {
+ int i=0;
+ while(p->is_cmd != END){
+ uint16_t sendcmd = p->data;
+ if(p->is_cmd == DATA)
+ sendcmd |= 0x0100; /* 9th bit is cmd/data flag */
+ uwire_xfer(TD014_DEV_ID, TD014_UWIRE_BITLEN, &sendcmd, NULL);
+ p++;
+ i++;
+ }
+}
+
+static void
+fb_td014_init(void) {
+ printf("%s: initializing LCD.\n",__FUNCTION__);
+ calypso_reset_set(RESET_EXT, 0);
+ delay_ms(5);
+ uwire_init();
+ delay_ms(5);
+
+ fb_td014_send_cmdlist(td014_initdata);
+}
+
+static void
+fb_td014_flush(void) {
+ int x,y;
+ uint8_t *p;
+ struct td014_cmdlist prepare_disp_write_cmds[] = {
+ { CMD, 0x10 },
+ { DATA, fb_rgb332->damage_x1 },
+ { CMD, 0x11 },
+ { DATA, fb_rgb332->damage_y1 },
+ { CMD, 0x12 },
+ { DATA, fb_rgb332->damage_x2-1 },
+ { CMD, 0x13 },
+ { DATA, fb_rgb332->damage_y2-1 },
+ { CMD, 0x14 },
+ { DATA, fb_rgb332->damage_x1 },
+ { CMD, 0x15 },
+ { DATA, fb_rgb332->damage_y1 },
+ { END, 0x00 }
+ };
+
+ /* If everything's clean, just return */
+ if(fb_rgb332->damage_x1 == fb_rgb332->damage_x2 ||
+ fb_rgb332->damage_y1 == fb_rgb332->damage_y2) {
+ printf("%s: no damage\n",__FUNCTION__);
+ return;
+ }
+
+ fb_td014_send_cmdlist(prepare_disp_write_cmds);
+
+ for(y=fb_rgb332->damage_y1;y<fb_rgb332->damage_y2;y++) {
+ p = & fb_rgb332->mem[y * framebuffer->width]; // start of line
+ p += fb_rgb332->damage_x1; // start of damage area
+
+ for(x=fb_rgb332->damage_x1; x<fb_rgb332->damage_x2; x++) {
+ uint16_t pixel = rgb332_to_565(*p++);
+ uint16_t data = 0x0100 | (pixel >> 8);
+
+ uwire_xfer(TD014_DEV_ID, TD014_UWIRE_BITLEN,
+ &data, NULL);
+
+ data = 0x0100 | (pixel & 0xff);
+ uwire_xfer(TD014_DEV_ID, TD014_UWIRE_BITLEN,
+ &data, NULL);
+ }
+ }
+
+ fb_rgb332->damage_x1 = fb_rgb332->damage_x2 = 0;
+ fb_rgb332->damage_y1 = fb_rgb332->damage_y2 = 0;
+}
+
+static struct framebuffer fb_td014_framebuffer = {
+ .name = "td014",
+ .init = fb_td014_init,
+ .clear = fb_rgb332_clear,
+ .boxto = fb_rgb332_boxto,
+ .lineto = fb_rgb332_lineto,
+ .putstr = fb_rgb332_putstr,
+ .flush = fb_td014_flush,
+ .width = TD014_WIDTH,
+ .height = TD014_HEIGHT
+};
+
+static struct fb_rgb332 fb_td014_rgb332 = {
+ .mem = fb_td014_mem
+};
+
+struct framebuffer *framebuffer = &fb_td014_framebuffer;
+struct fb_rgb332 *fb_rgb332 = &fb_td014_rgb332;
diff --git a/Src/osmolib/src/target/firmware/fb/font.c b/Src/osmolib/src/target/firmware/fb/font.c
new file mode 100644
index 0000000..d98096f
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/font.c
@@ -0,0 +1,57 @@
+/* Font Handling - Utility Functions */
+
+/* (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.
+ *
+ */
+
+#include <fb/font.h>
+
+/* what fonts are linked in? */
+extern const struct fb_font font_4x6;
+extern const struct fb_font font_5x8;
+extern const struct fb_font font_helvR08;
+extern const struct fb_font font_helvR14;
+//extern const struct fb_font font_helvR24;
+//extern const struct fb_font font_helvB08;
+extern const struct fb_font font_helvB14;
+// extern const struct fb_font font_helvB24;
+extern const struct fb_font font_c64;
+
+const struct fb_font *fb_fonts[]={
+// &font_4x6,
+// &font_5x8,
+ &font_helvR08,
+// &font_helvR14,
+// &font_helvR24,
+// &font_helvB08,
+ &font_helvB14,
+// &font_helvB24,
+ &font_c64,
+};
+
+const struct fb_char *
+fb_font_get_char(const struct fb_font *fnt,unsigned char c){
+ if(c < fnt->firstchar || c > fnt->lastchar)
+ return NULL;
+ uint16_t offs = fnt->charoffs[c-fnt->firstchar];
+ if(offs == FB_FONT_NOCHAR)
+ return NULL;
+ return (struct fb_char *)(fnt->chardata + offs);
+}
+
diff --git a/Src/osmolib/src/target/firmware/fb/framebuffer.c b/Src/osmolib/src/target/firmware/fb/framebuffer.c
new file mode 100644
index 0000000..ab54769
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/framebuffer.c
@@ -0,0 +1,28 @@
+/* Framebuffer - Utility Functions */
+
+/* (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.
+ *
+ */
+
+#include <fb/framebuffer.h>
+
+/* currently everything's inline in framebuffer .h */
+
+
+
diff --git a/Src/osmolib/src/target/firmware/fb/helvB08.c b/Src/osmolib/src/target/firmware/fb/helvB08.c
new file mode 100644
index 0000000..97dd92c
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/helvB08.c
@@ -0,0 +1,833 @@
+#include <fb/font.h>
+static const uint8_t font_helvB08_data[] = {
+/* --- new character space (32) starting at offset 0x0000 --- */
+ /*0000:*/ 2, 1, 1, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0005:*/ 0x00, /* ........ */
+/* --- new character exclam (33) starting at offset 0x0006 --- */
+ /*0006:*/ 3, 2, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*000b:*/ 0xc0, /* ##...... */
+ /*000c:*/ 0xc0, /* ##...... */
+ /*000d:*/ 0xc0, /* ##...... */
+ /*000e:*/ 0x80, /* #....... */
+ /*000f:*/ 0x00, /* ........ */
+ /*0010:*/ 0x80, /* #....... */
+ /*0011:*/ 0x80, /* #....... */
+/* --- new character quotedbl (34) starting at offset 0x0012 --- */
+ /*0012:*/ 4, 3, 2, 0, 4, /* width and bbox (w,h,x,y) */
+ /*0017:*/ 0xa0, /* #.#..... */
+ /*0018:*/ 0xa0, /* #.#..... */
+/* --- new character numbersign (35) starting at offset 0x0019 --- */
+ /*0019:*/ 5, 5, 6, -1, 0, /* width and bbox (w,h,x,y) */
+ /*001e:*/ 0x50, /* .#.#.... */
+ /*001f:*/ 0xf8, /* #####... */
+ /*0020:*/ 0x50, /* .#.#.... */
+ /*0021:*/ 0xf8, /* #####... */
+ /*0022:*/ 0xa0, /* #.#..... */
+ /*0023:*/ 0xa0, /* #.#..... */
+/* --- new character dollar (36) starting at offset 0x0024 --- */
+ /*0024:*/ 5, 4, 8, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0029:*/ 0x20, /* ..#..... */
+ /*002a:*/ 0x70, /* .###.... */
+ /*002b:*/ 0xc0, /* ##...... */
+ /*002c:*/ 0xe0, /* ###..... */
+ /*002d:*/ 0x70, /* .###.... */
+ /*002e:*/ 0x30, /* ..##.... */
+ /*002f:*/ 0xe0, /* ###..... */
+ /*0030:*/ 0x40, /* .#...... */
+/* --- new character percent (37) starting at offset 0x0031 --- */
+ /*0031:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0036:*/ 0x68, /* .##.#... */
+ /*0037:*/ 0xb0, /* #.##.... */
+ /*0038:*/ 0xe0, /* ###..... */
+ /*0039:*/ 0x38, /* ..###... */
+ /*003a:*/ 0x68, /* .##.#... */
+ /*003b:*/ 0xb0, /* #.##.... */
+/* --- new character ampersand (38) starting at offset 0x003c --- */
+ /*003c:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0041:*/ 0x70, /* .###.... */
+ /*0042:*/ 0x50, /* .#.#.... */
+ /*0043:*/ 0x60, /* .##..... */
+ /*0044:*/ 0xf8, /* #####... */
+ /*0045:*/ 0xd0, /* ##.#.... */
+ /*0046:*/ 0x68, /* .##.#... */
+/* --- new character quotesingle (39) starting at offset 0x0047 --- */
+ /*0047:*/ 3, 1, 3, 1, 5, /* width and bbox (w,h,x,y) */
+ /*004c:*/ 0x80, /* #....... */
+ /*004d:*/ 0x80, /* #....... */
+ /*004e:*/ 0x80, /* #....... */
+/* --- new character parenleft (40) starting at offset 0x004f --- */
+ /*004f:*/ 3, 2, 8, 0, -2, /* width and bbox (w,h,x,y) */
+ /*0054:*/ 0x40, /* .#...... */
+ /*0055:*/ 0x40, /* .#...... */
+ /*0056:*/ 0x80, /* #....... */
+ /*0057:*/ 0x80, /* #....... */
+ /*0058:*/ 0x80, /* #....... */
+ /*0059:*/ 0x80, /* #....... */
+ /*005a:*/ 0x40, /* .#...... */
+ /*005b:*/ 0x40, /* .#...... */
+/* --- new character parenright (41) starting at offset 0x005c --- */
+ /*005c:*/ 3, 2, 8, 0, -2, /* width and bbox (w,h,x,y) */
+ /*0061:*/ 0x80, /* #....... */
+ /*0062:*/ 0x80, /* #....... */
+ /*0063:*/ 0x40, /* .#...... */
+ /*0064:*/ 0x40, /* .#...... */
+ /*0065:*/ 0x40, /* .#...... */
+ /*0066:*/ 0x40, /* .#...... */
+ /*0067:*/ 0x80, /* #....... */
+ /*0068:*/ 0x80, /* #....... */
+/* --- new character asterisk (42) starting at offset 0x0069 --- */
+ /*0069:*/ 3, 3, 3, 0, 3, /* width and bbox (w,h,x,y) */
+ /*006e:*/ 0x40, /* .#...... */
+ /*006f:*/ 0xe0, /* ###..... */
+ /*0070:*/ 0x40, /* .#...... */
+/* --- new character plus (43) starting at offset 0x0071 --- */
+ /*0071:*/ 5, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0076:*/ 0x20, /* ..#..... */
+ /*0077:*/ 0x20, /* ..#..... */
+ /*0078:*/ 0xf0, /* ####.... */
+ /*0079:*/ 0x20, /* ..#..... */
+ /*007a:*/ 0x20, /* ..#..... */
+/* --- new character comma (44) starting at offset 0x007b --- */
+ /*007b:*/ 2, 2, 3, -1, -1, /* width and bbox (w,h,x,y) */
+ /*0080:*/ 0x40, /* .#...... */
+ /*0081:*/ 0x40, /* .#...... */
+ /*0082:*/ 0x80, /* #....... */
+/* --- new character hyphen (45) starting at offset 0x0083 --- */
+ /*0083:*/ 4, 3, 1, 0, 2, /* width and bbox (w,h,x,y) */
+ /*0088:*/ 0xe0, /* ###..... */
+/* --- new character period (46) starting at offset 0x0089 --- */
+ /*0089:*/ 2, 1, 2, 0, 0, /* width and bbox (w,h,x,y) */
+ /*008e:*/ 0x80, /* #....... */
+ /*008f:*/ 0x80, /* #....... */
+/* --- new character slash (47) starting at offset 0x0090 --- */
+ /*0090:*/ 3, 3, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0095:*/ 0x20, /* ..#..... */
+ /*0096:*/ 0x20, /* ..#..... */
+ /*0097:*/ 0x40, /* .#...... */
+ /*0098:*/ 0x40, /* .#...... */
+ /*0099:*/ 0x80, /* #....... */
+ /*009a:*/ 0x80, /* #....... */
+/* --- new character zero (48) starting at offset 0x009b --- */
+ /*009b:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00a0:*/ 0x60, /* .##..... */
+ /*00a1:*/ 0xd0, /* ##.#.... */
+ /*00a2:*/ 0xd0, /* ##.#.... */
+ /*00a3:*/ 0xd0, /* ##.#.... */
+ /*00a4:*/ 0xd0, /* ##.#.... */
+ /*00a5:*/ 0x60, /* .##..... */
+/* --- new character one (49) starting at offset 0x00a6 --- */
+ /*00a6:*/ 5, 3, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00ab:*/ 0x20, /* ..#..... */
+ /*00ac:*/ 0xe0, /* ###..... */
+ /*00ad:*/ 0x60, /* .##..... */
+ /*00ae:*/ 0x60, /* .##..... */
+ /*00af:*/ 0x60, /* .##..... */
+ /*00b0:*/ 0x60, /* .##..... */
+/* --- new character two (50) starting at offset 0x00b1 --- */
+ /*00b1:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00b6:*/ 0x60, /* .##..... */
+ /*00b7:*/ 0xb0, /* #.##.... */
+ /*00b8:*/ 0x30, /* ..##.... */
+ /*00b9:*/ 0x60, /* .##..... */
+ /*00ba:*/ 0xc0, /* ##...... */
+ /*00bb:*/ 0xf0, /* ####.... */
+/* --- new character three (51) starting at offset 0x00bc --- */
+ /*00bc:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00c1:*/ 0x60, /* .##..... */
+ /*00c2:*/ 0xb0, /* #.##.... */
+ /*00c3:*/ 0x60, /* .##..... */
+ /*00c4:*/ 0x30, /* ..##.... */
+ /*00c5:*/ 0xb0, /* #.##.... */
+ /*00c6:*/ 0x60, /* .##..... */
+/* --- new character four (52) starting at offset 0x00c7 --- */
+ /*00c7:*/ 5, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00cc:*/ 0x30, /* ..##.... */
+ /*00cd:*/ 0x50, /* .#.#.... */
+ /*00ce:*/ 0xd0, /* ##.#.... */
+ /*00cf:*/ 0xf8, /* #####... */
+ /*00d0:*/ 0x30, /* ..##.... */
+ /*00d1:*/ 0x30, /* ..##.... */
+/* --- new character five (53) starting at offset 0x00d2 --- */
+ /*00d2:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00d7:*/ 0x70, /* .###.... */
+ /*00d8:*/ 0xc0, /* ##...... */
+ /*00d9:*/ 0xe0, /* ###..... */
+ /*00da:*/ 0x30, /* ..##.... */
+ /*00db:*/ 0xb0, /* #.##.... */
+ /*00dc:*/ 0x60, /* .##..... */
+/* --- new character six (54) starting at offset 0x00dd --- */
+ /*00dd:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00e2:*/ 0x70, /* .###.... */
+ /*00e3:*/ 0xc0, /* ##...... */
+ /*00e4:*/ 0xe0, /* ###..... */
+ /*00e5:*/ 0xd0, /* ##.#.... */
+ /*00e6:*/ 0xd0, /* ##.#.... */
+ /*00e7:*/ 0x60, /* .##..... */
+/* --- new character seven (55) starting at offset 0x00e8 --- */
+ /*00e8:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00ed:*/ 0xf0, /* ####.... */
+ /*00ee:*/ 0x30, /* ..##.... */
+ /*00ef:*/ 0x30, /* ..##.... */
+ /*00f0:*/ 0x60, /* .##..... */
+ /*00f1:*/ 0x40, /* .#...... */
+ /*00f2:*/ 0xc0, /* ##...... */
+/* --- new character eight (56) starting at offset 0x00f3 --- */
+ /*00f3:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00f8:*/ 0x60, /* .##..... */
+ /*00f9:*/ 0xd0, /* ##.#.... */
+ /*00fa:*/ 0x60, /* .##..... */
+ /*00fb:*/ 0xd0, /* ##.#.... */
+ /*00fc:*/ 0xd0, /* ##.#.... */
+ /*00fd:*/ 0x60, /* .##..... */
+/* --- new character nine (57) starting at offset 0x00fe --- */
+ /*00fe:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0103:*/ 0x60, /* .##..... */
+ /*0104:*/ 0xb0, /* #.##.... */
+ /*0105:*/ 0xb0, /* #.##.... */
+ /*0106:*/ 0x70, /* .###.... */
+ /*0107:*/ 0x30, /* ..##.... */
+ /*0108:*/ 0xe0, /* ###..... */
+/* --- new character colon (58) starting at offset 0x0109 --- */
+ /*0109:*/ 2, 1, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*010e:*/ 0x80, /* #....... */
+ /*010f:*/ 0x80, /* #....... */
+ /*0110:*/ 0x00, /* ........ */
+ /*0111:*/ 0x80, /* #....... */
+ /*0112:*/ 0x80, /* #....... */
+/* --- new character semicolon (59) starting at offset 0x0113 --- */
+ /*0113:*/ 2, 2, 6, -1, -1, /* width and bbox (w,h,x,y) */
+ /*0118:*/ 0x40, /* .#...... */
+ /*0119:*/ 0x40, /* .#...... */
+ /*011a:*/ 0x00, /* ........ */
+ /*011b:*/ 0x40, /* .#...... */
+ /*011c:*/ 0x40, /* .#...... */
+ /*011d:*/ 0x80, /* #....... */
+/* --- new character less (60) starting at offset 0x011e --- */
+ /*011e:*/ 4, 3, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0123:*/ 0x20, /* ..#..... */
+ /*0124:*/ 0x40, /* .#...... */
+ /*0125:*/ 0x80, /* #....... */
+ /*0126:*/ 0x40, /* .#...... */
+ /*0127:*/ 0x20, /* ..#..... */
+/* --- new character equal (61) starting at offset 0x0128 --- */
+ /*0128:*/ 5, 4, 3, 0, 1, /* width and bbox (w,h,x,y) */
+ /*012d:*/ 0xf0, /* ####.... */
+ /*012e:*/ 0x00, /* ........ */
+ /*012f:*/ 0xf0, /* ####.... */
+/* --- new character greater (62) starting at offset 0x0130 --- */
+ /*0130:*/ 4, 3, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0135:*/ 0x80, /* #....... */
+ /*0136:*/ 0x40, /* .#...... */
+ /*0137:*/ 0x20, /* ..#..... */
+ /*0138:*/ 0x40, /* .#...... */
+ /*0139:*/ 0x80, /* #....... */
+/* --- new character question (63) starting at offset 0x013a --- */
+ /*013a:*/ 5, 4, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*013f:*/ 0xe0, /* ###..... */
+ /*0140:*/ 0x30, /* ..##.... */
+ /*0141:*/ 0x60, /* .##..... */
+ /*0142:*/ 0x40, /* .#...... */
+ /*0143:*/ 0x00, /* ........ */
+ /*0144:*/ 0x40, /* .#...... */
+ /*0145:*/ 0x40, /* .#...... */
+/* --- new character at (64) starting at offset 0x0146 --- */
+ /*0146:*/ 9, 8, 7, 0, -1, /* width and bbox (w,h,x,y) */
+ /*014b:*/ 0x7e, /* .######. */
+ /*014c:*/ 0xc3, /* ##....## */
+ /*014d:*/ 0x99, /* #..##..# */
+ /*014e:*/ 0xa9, /* #.#.#..# */
+ /*014f:*/ 0x99, /* #..##..# */
+ /*0150:*/ 0xce, /* ##..###. */
+ /*0151:*/ 0x60, /* .##..... */
+/* --- new character A (65) starting at offset 0x0152 --- */
+ /*0152:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0157:*/ 0x70, /* .###.... */
+ /*0158:*/ 0xd8, /* ##.##... */
+ /*0159:*/ 0xd8, /* ##.##... */
+ /*015a:*/ 0xf8, /* #####... */
+ /*015b:*/ 0xd8, /* ##.##... */
+ /*015c:*/ 0xd8, /* ##.##... */
+/* --- new character B (66) starting at offset 0x015d --- */
+ /*015d:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0162:*/ 0xf0, /* ####.... */
+ /*0163:*/ 0xd8, /* ##.##... */
+ /*0164:*/ 0xf0, /* ####.... */
+ /*0165:*/ 0xd8, /* ##.##... */
+ /*0166:*/ 0xd8, /* ##.##... */
+ /*0167:*/ 0xf0, /* ####.... */
+/* --- new character C (67) starting at offset 0x0168 --- */
+ /*0168:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*016d:*/ 0x78, /* .####... */
+ /*016e:*/ 0xc8, /* ##..#... */
+ /*016f:*/ 0xc0, /* ##...... */
+ /*0170:*/ 0xc0, /* ##...... */
+ /*0171:*/ 0xc8, /* ##..#... */
+ /*0172:*/ 0x78, /* .####... */
+/* --- new character D (68) starting at offset 0x0173 --- */
+ /*0173:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0178:*/ 0xf0, /* ####.... */
+ /*0179:*/ 0xd8, /* ##.##... */
+ /*017a:*/ 0xd8, /* ##.##... */
+ /*017b:*/ 0xd8, /* ##.##... */
+ /*017c:*/ 0xd8, /* ##.##... */
+ /*017d:*/ 0xf0, /* ####.... */
+/* --- new character E (69) starting at offset 0x017e --- */
+ /*017e:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0183:*/ 0xf0, /* ####.... */
+ /*0184:*/ 0xc0, /* ##...... */
+ /*0185:*/ 0xf0, /* ####.... */
+ /*0186:*/ 0xc0, /* ##...... */
+ /*0187:*/ 0xc0, /* ##...... */
+ /*0188:*/ 0xf0, /* ####.... */
+/* --- new character F (70) starting at offset 0x0189 --- */
+ /*0189:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*018e:*/ 0xf0, /* ####.... */
+ /*018f:*/ 0xc0, /* ##...... */
+ /*0190:*/ 0xf0, /* ####.... */
+ /*0191:*/ 0xc0, /* ##...... */
+ /*0192:*/ 0xc0, /* ##...... */
+ /*0193:*/ 0xc0, /* ##...... */
+/* --- new character G (71) starting at offset 0x0194 --- */
+ /*0194:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0199:*/ 0x78, /* .####... */
+ /*019a:*/ 0xc8, /* ##..#... */
+ /*019b:*/ 0xc0, /* ##...... */
+ /*019c:*/ 0xd8, /* ##.##... */
+ /*019d:*/ 0xc8, /* ##..#... */
+ /*019e:*/ 0x78, /* .####... */
+/* --- new character H (72) starting at offset 0x019f --- */
+ /*019f:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01a4:*/ 0xd8, /* ##.##... */
+ /*01a5:*/ 0xd8, /* ##.##... */
+ /*01a6:*/ 0xf8, /* #####... */
+ /*01a7:*/ 0xd8, /* ##.##... */
+ /*01a8:*/ 0xd8, /* ##.##... */
+ /*01a9:*/ 0xd8, /* ##.##... */
+/* --- new character I (73) starting at offset 0x01aa --- */
+ /*01aa:*/ 2, 1, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01af:*/ 0x80, /* #....... */
+ /*01b0:*/ 0x80, /* #....... */
+ /*01b1:*/ 0x80, /* #....... */
+ /*01b2:*/ 0x80, /* #....... */
+ /*01b3:*/ 0x80, /* #....... */
+ /*01b4:*/ 0x80, /* #....... */
+/* --- new character J (74) starting at offset 0x01b5 --- */
+ /*01b5:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01ba:*/ 0x30, /* ..##.... */
+ /*01bb:*/ 0x30, /* ..##.... */
+ /*01bc:*/ 0x30, /* ..##.... */
+ /*01bd:*/ 0x30, /* ..##.... */
+ /*01be:*/ 0xb0, /* #.##.... */
+ /*01bf:*/ 0x60, /* .##..... */
+/* --- new character K (75) starting at offset 0x01c0 --- */
+ /*01c0:*/ 6, 6, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01c5:*/ 0xd8, /* ##.##... */
+ /*01c6:*/ 0xd0, /* ##.#.... */
+ /*01c7:*/ 0xe0, /* ###..... */
+ /*01c8:*/ 0xf0, /* ####.... */
+ /*01c9:*/ 0xd8, /* ##.##... */
+ /*01ca:*/ 0xcc, /* ##..##.. */
+/* --- new character L (76) starting at offset 0x01cb --- */
+ /*01cb:*/ 5, 4, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01d0:*/ 0xc0, /* ##...... */
+ /*01d1:*/ 0xc0, /* ##...... */
+ /*01d2:*/ 0xc0, /* ##...... */
+ /*01d3:*/ 0xc0, /* ##...... */
+ /*01d4:*/ 0xc0, /* ##...... */
+ /*01d5:*/ 0xf0, /* ####.... */
+/* --- new character M (77) starting at offset 0x01d6 --- */
+ /*01d6:*/ 8, 7, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01db:*/ 0xc6, /* ##...##. */
+ /*01dc:*/ 0xc6, /* ##...##. */
+ /*01dd:*/ 0xee, /* ###.###. */
+ /*01de:*/ 0xfe, /* #######. */
+ /*01df:*/ 0xd6, /* ##.#.##. */
+ /*01e0:*/ 0xd6, /* ##.#.##. */
+/* --- new character N (78) starting at offset 0x01e1 --- */
+ /*01e1:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01e6:*/ 0xc8, /* ##..#... */
+ /*01e7:*/ 0xc8, /* ##..#... */
+ /*01e8:*/ 0xe8, /* ###.#... */
+ /*01e9:*/ 0xf8, /* #####... */
+ /*01ea:*/ 0xd8, /* ##.##... */
+ /*01eb:*/ 0xc8, /* ##..#... */
+/* --- new character O (79) starting at offset 0x01ec --- */
+ /*01ec:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01f1:*/ 0x70, /* .###.... */
+ /*01f2:*/ 0xd8, /* ##.##... */
+ /*01f3:*/ 0xc8, /* ##..#... */
+ /*01f4:*/ 0xc8, /* ##..#... */
+ /*01f5:*/ 0xd8, /* ##.##... */
+ /*01f6:*/ 0x70, /* .###.... */
+/* --- new character P (80) starting at offset 0x01f7 --- */
+ /*01f7:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01fc:*/ 0xf0, /* ####.... */
+ /*01fd:*/ 0xd8, /* ##.##... */
+ /*01fe:*/ 0xd8, /* ##.##... */
+ /*01ff:*/ 0xf0, /* ####.... */
+ /*0200:*/ 0xc0, /* ##...... */
+ /*0201:*/ 0xc0, /* ##...... */
+/* --- new character Q (81) starting at offset 0x0202 --- */
+ /*0202:*/ 6, 6, 7, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0207:*/ 0x70, /* .###.... */
+ /*0208:*/ 0xd8, /* ##.##... */
+ /*0209:*/ 0xc8, /* ##..#... */
+ /*020a:*/ 0xc8, /* ##..#... */
+ /*020b:*/ 0xd8, /* ##.##... */
+ /*020c:*/ 0x78, /* .####... */
+ /*020d:*/ 0x04, /* .....#.. */
+/* --- new character R (82) starting at offset 0x020e --- */
+ /*020e:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0213:*/ 0xf0, /* ####.... */
+ /*0214:*/ 0xd8, /* ##.##... */
+ /*0215:*/ 0xd8, /* ##.##... */
+ /*0216:*/ 0xf0, /* ####.... */
+ /*0217:*/ 0xd8, /* ##.##... */
+ /*0218:*/ 0xd8, /* ##.##... */
+/* --- new character S (83) starting at offset 0x0219 --- */
+ /*0219:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*021e:*/ 0x78, /* .####... */
+ /*021f:*/ 0xc0, /* ##...... */
+ /*0220:*/ 0xf0, /* ####.... */
+ /*0221:*/ 0x38, /* ..###... */
+ /*0222:*/ 0xd8, /* ##.##... */
+ /*0223:*/ 0x70, /* .###.... */
+/* --- new character T (84) starting at offset 0x0224 --- */
+ /*0224:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0229:*/ 0xf8, /* #####... */
+ /*022a:*/ 0x60, /* .##..... */
+ /*022b:*/ 0x60, /* .##..... */
+ /*022c:*/ 0x60, /* .##..... */
+ /*022d:*/ 0x60, /* .##..... */
+ /*022e:*/ 0x60, /* .##..... */
+/* --- new character U (85) starting at offset 0x022f --- */
+ /*022f:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0234:*/ 0xd8, /* ##.##... */
+ /*0235:*/ 0xd8, /* ##.##... */
+ /*0236:*/ 0xd8, /* ##.##... */
+ /*0237:*/ 0xd8, /* ##.##... */
+ /*0238:*/ 0xd8, /* ##.##... */
+ /*0239:*/ 0x70, /* .###.... */
+/* --- new character V (86) starting at offset 0x023a --- */
+ /*023a:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*023f:*/ 0xe8, /* ###.#... */
+ /*0240:*/ 0x68, /* .##.#... */
+ /*0241:*/ 0x68, /* .##.#... */
+ /*0242:*/ 0x68, /* .##.#... */
+ /*0243:*/ 0x70, /* .###.... */
+ /*0244:*/ 0x20, /* ..#..... */
+/* --- new character W (87) starting at offset 0x0245 --- */
+ /*0245:*/ 9, 8, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*024a:*/ 0xdb, /* ##.##.## */
+ /*024b:*/ 0xdb, /* ##.##.## */
+ /*024c:*/ 0xda, /* ##.##.#. */
+ /*024d:*/ 0xda, /* ##.##.#. */
+ /*024e:*/ 0x6c, /* .##.##.. */
+ /*024f:*/ 0x6c, /* .##.##.. */
+/* --- new character X (88) starting at offset 0x0250 --- */
+ /*0250:*/ 6, 5, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0255:*/ 0xd8, /* ##.##... */
+ /*0256:*/ 0xd8, /* ##.##... */
+ /*0257:*/ 0x70, /* .###.... */
+ /*0258:*/ 0x70, /* .###.... */
+ /*0259:*/ 0xd8, /* ##.##... */
+ /*025a:*/ 0xd8, /* ##.##... */
+/* --- new character Y (89) starting at offset 0x025b --- */
+ /*025b:*/ 7, 6, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0260:*/ 0xec, /* ###.##.. */
+ /*0261:*/ 0x68, /* .##.#... */
+ /*0262:*/ 0x68, /* .##.#... */
+ /*0263:*/ 0x78, /* .####... */
+ /*0264:*/ 0x30, /* ..##.... */
+ /*0265:*/ 0x30, /* ..##.... */
+/* --- new character Z (90) starting at offset 0x0266 --- */
+ /*0266:*/ 6, 6, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*026b:*/ 0xfc, /* ######.. */
+ /*026c:*/ 0x38, /* ..###... */
+ /*026d:*/ 0x30, /* ..##.... */
+ /*026e:*/ 0x60, /* .##..... */
+ /*026f:*/ 0xe0, /* ###..... */
+ /*0270:*/ 0xf8, /* #####... */
+/* --- new character bracketleft (91) starting at offset 0x0271 --- */
+ /*0271:*/ 3, 2, 8, 0, -2, /* width and bbox (w,h,x,y) */
+ /*0276:*/ 0xc0, /* ##...... */
+ /*0277:*/ 0x80, /* #....... */
+ /*0278:*/ 0x80, /* #....... */
+ /*0279:*/ 0x80, /* #....... */
+ /*027a:*/ 0x80, /* #....... */
+ /*027b:*/ 0x80, /* #....... */
+ /*027c:*/ 0x80, /* #....... */
+ /*027d:*/ 0xc0, /* ##...... */
+/* --- new character backslash (92) starting at offset 0x027e --- */
+ /*027e:*/ 3, 3, 6, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0283:*/ 0x80, /* #....... */
+ /*0284:*/ 0x80, /* #....... */
+ /*0285:*/ 0x40, /* .#...... */
+ /*0286:*/ 0x40, /* .#...... */
+ /*0287:*/ 0x20, /* ..#..... */
+ /*0288:*/ 0x20, /* ..#..... */
+/* --- new character bracketright (93) starting at offset 0x0289 --- */
+ /*0289:*/ 3, 2, 8, 0, -2, /* width and bbox (w,h,x,y) */
+ /*028e:*/ 0xc0, /* ##...... */
+ /*028f:*/ 0x40, /* .#...... */
+ /*0290:*/ 0x40, /* .#...... */
+ /*0291:*/ 0x40, /* .#...... */
+ /*0292:*/ 0x40, /* .#...... */
+ /*0293:*/ 0x40, /* .#...... */
+ /*0294:*/ 0x40, /* .#...... */
+ /*0295:*/ 0xc0, /* ##...... */
+/* --- new character asciicircum (94) starting at offset 0x0296 --- */
+ /*0296:*/ 4, 4, 3, 0, 3, /* width and bbox (w,h,x,y) */
+ /*029b:*/ 0x60, /* .##..... */
+ /*029c:*/ 0x60, /* .##..... */
+ /*029d:*/ 0x90, /* #..#.... */
+/* --- new character underscore (95) starting at offset 0x029e --- */
+ /*029e:*/ 5, 5, 1, 0, -1, /* width and bbox (w,h,x,y) */
+ /*02a3:*/ 0xf8, /* #####... */
+/* --- new character grave (96) starting at offset 0x02a4 --- */
+ /*02a4:*/ 3, 2, 2, 0, 6, /* width and bbox (w,h,x,y) */
+ /*02a9:*/ 0x80, /* #....... */
+ /*02aa:*/ 0x40, /* .#...... */
+/* --- new character a (97) starting at offset 0x02ab --- */
+ /*02ab:*/ 5, 5, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02b0:*/ 0xe0, /* ###..... */
+ /*02b1:*/ 0x30, /* ..##.... */
+ /*02b2:*/ 0xf0, /* ####.... */
+ /*02b3:*/ 0xb0, /* #.##.... */
+ /*02b4:*/ 0xd8, /* ##.##... */
+/* --- new character b (98) starting at offset 0x02b5 --- */
+ /*02b5:*/ 5, 4, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02ba:*/ 0xc0, /* ##...... */
+ /*02bb:*/ 0xc0, /* ##...... */
+ /*02bc:*/ 0xe0, /* ###..... */
+ /*02bd:*/ 0xd0, /* ##.#.... */
+ /*02be:*/ 0xd0, /* ##.#.... */
+ /*02bf:*/ 0xd0, /* ##.#.... */
+ /*02c0:*/ 0xe0, /* ###..... */
+/* --- new character c (99) starting at offset 0x02c1 --- */
+ /*02c1:*/ 4, 3, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02c6:*/ 0x60, /* .##..... */
+ /*02c7:*/ 0xc0, /* ##...... */
+ /*02c8:*/ 0xc0, /* ##...... */
+ /*02c9:*/ 0xc0, /* ##...... */
+ /*02ca:*/ 0x60, /* .##..... */
+/* --- new character d (100) starting at offset 0x02cb --- */
+ /*02cb:*/ 5, 4, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02d0:*/ 0x30, /* ..##.... */
+ /*02d1:*/ 0x30, /* ..##.... */
+ /*02d2:*/ 0x70, /* .###.... */
+ /*02d3:*/ 0xb0, /* #.##.... */
+ /*02d4:*/ 0xb0, /* #.##.... */
+ /*02d5:*/ 0xb0, /* #.##.... */
+ /*02d6:*/ 0x70, /* .###.... */
+/* --- new character e (101) starting at offset 0x02d7 --- */
+ /*02d7:*/ 5, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02dc:*/ 0x60, /* .##..... */
+ /*02dd:*/ 0xd0, /* ##.#.... */
+ /*02de:*/ 0xf0, /* ####.... */
+ /*02df:*/ 0xc0, /* ##...... */
+ /*02e0:*/ 0x60, /* .##..... */
+/* --- new character f (102) starting at offset 0x02e1 --- */
+ /*02e1:*/ 3, 4, 7, -1, 0, /* width and bbox (w,h,x,y) */
+ /*02e6:*/ 0x30, /* ..##.... */
+ /*02e7:*/ 0x60, /* .##..... */
+ /*02e8:*/ 0xf0, /* ####.... */
+ /*02e9:*/ 0x60, /* .##..... */
+ /*02ea:*/ 0x60, /* .##..... */
+ /*02eb:*/ 0x60, /* .##..... */
+ /*02ec:*/ 0x60, /* .##..... */
+/* --- new character g (103) starting at offset 0x02ed --- */
+ /*02ed:*/ 5, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*02f2:*/ 0xd0, /* ##.#.... */
+ /*02f3:*/ 0xb0, /* #.##.... */
+ /*02f4:*/ 0xb0, /* #.##.... */
+ /*02f5:*/ 0xf0, /* ####.... */
+ /*02f6:*/ 0x30, /* ..##.... */
+ /*02f7:*/ 0xe0, /* ###..... */
+/* --- new character h (104) starting at offset 0x02f8 --- */
+ /*02f8:*/ 5, 4, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02fd:*/ 0xc0, /* ##...... */
+ /*02fe:*/ 0xc0, /* ##...... */
+ /*02ff:*/ 0xe0, /* ###..... */
+ /*0300:*/ 0xd0, /* ##.#.... */
+ /*0301:*/ 0xd0, /* ##.#.... */
+ /*0302:*/ 0xd0, /* ##.#.... */
+ /*0303:*/ 0xd0, /* ##.#.... */
+/* --- new character i (105) starting at offset 0x0304 --- */
+ /*0304:*/ 2, 1, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0309:*/ 0x80, /* #....... */
+ /*030a:*/ 0x00, /* ........ */
+ /*030b:*/ 0x80, /* #....... */
+ /*030c:*/ 0x80, /* #....... */
+ /*030d:*/ 0x80, /* #....... */
+ /*030e:*/ 0x80, /* #....... */
+ /*030f:*/ 0x80, /* #....... */
+/* --- new character j (106) starting at offset 0x0310 --- */
+ /*0310:*/ 2, 2, 8, -1, -1, /* width and bbox (w,h,x,y) */
+ /*0315:*/ 0x40, /* .#...... */
+ /*0316:*/ 0x00, /* ........ */
+ /*0317:*/ 0x40, /* .#...... */
+ /*0318:*/ 0x40, /* .#...... */
+ /*0319:*/ 0x40, /* .#...... */
+ /*031a:*/ 0x40, /* .#...... */
+ /*031b:*/ 0x40, /* .#...... */
+ /*031c:*/ 0x80, /* #....... */
+/* --- new character k (107) starting at offset 0x031d --- */
+ /*031d:*/ 5, 4, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0322:*/ 0xc0, /* ##...... */
+ /*0323:*/ 0xc0, /* ##...... */
+ /*0324:*/ 0xd0, /* ##.#.... */
+ /*0325:*/ 0xd0, /* ##.#.... */
+ /*0326:*/ 0xe0, /* ###..... */
+ /*0327:*/ 0xd0, /* ##.#.... */
+ /*0328:*/ 0xd0, /* ##.#.... */
+/* --- new character l (108) starting at offset 0x0329 --- */
+ /*0329:*/ 2, 1, 7, 0, 0, /* width and bbox (w,h,x,y) */
+ /*032e:*/ 0x80, /* #....... */
+ /*032f:*/ 0x80, /* #....... */
+ /*0330:*/ 0x80, /* #....... */
+ /*0331:*/ 0x80, /* #....... */
+ /*0332:*/ 0x80, /* #....... */
+ /*0333:*/ 0x80, /* #....... */
+ /*0334:*/ 0x80, /* #....... */
+/* --- new character m (109) starting at offset 0x0335 --- */
+ /*0335:*/ 7, 6, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*033a:*/ 0xe8, /* ###.#... */
+ /*033b:*/ 0xd4, /* ##.#.#.. */
+ /*033c:*/ 0xd4, /* ##.#.#.. */
+ /*033d:*/ 0xd4, /* ##.#.#.. */
+ /*033e:*/ 0xd4, /* ##.#.#.. */
+/* --- new character n (110) starting at offset 0x033f --- */
+ /*033f:*/ 5, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0344:*/ 0xe0, /* ###..... */
+ /*0345:*/ 0xd0, /* ##.#.... */
+ /*0346:*/ 0xd0, /* ##.#.... */
+ /*0347:*/ 0xd0, /* ##.#.... */
+ /*0348:*/ 0xd0, /* ##.#.... */
+/* --- new character o (111) starting at offset 0x0349 --- */
+ /*0349:*/ 5, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*034e:*/ 0x60, /* .##..... */
+ /*034f:*/ 0xd0, /* ##.#.... */
+ /*0350:*/ 0xd0, /* ##.#.... */
+ /*0351:*/ 0xd0, /* ##.#.... */
+ /*0352:*/ 0x60, /* .##..... */
+/* --- new character p (112) starting at offset 0x0353 --- */
+ /*0353:*/ 5, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0358:*/ 0xe0, /* ###..... */
+ /*0359:*/ 0xd0, /* ##.#.... */
+ /*035a:*/ 0xd0, /* ##.#.... */
+ /*035b:*/ 0xd0, /* ##.#.... */
+ /*035c:*/ 0xe0, /* ###..... */
+ /*035d:*/ 0xc0, /* ##...... */
+/* --- new character q (113) starting at offset 0x035e --- */
+ /*035e:*/ 5, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0363:*/ 0x70, /* .###.... */
+ /*0364:*/ 0xb0, /* #.##.... */
+ /*0365:*/ 0xb0, /* #.##.... */
+ /*0366:*/ 0xb0, /* #.##.... */
+ /*0367:*/ 0x70, /* .###.... */
+ /*0368:*/ 0x30, /* ..##.... */
+/* --- new character r (114) starting at offset 0x0369 --- */
+ /*0369:*/ 3, 3, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*036e:*/ 0xa0, /* #.#..... */
+ /*036f:*/ 0xe0, /* ###..... */
+ /*0370:*/ 0xc0, /* ##...... */
+ /*0371:*/ 0xc0, /* ##...... */
+ /*0372:*/ 0xc0, /* ##...... */
+/* --- new character s (115) starting at offset 0x0373 --- */
+ /*0373:*/ 5, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0378:*/ 0x70, /* .###.... */
+ /*0379:*/ 0xc0, /* ##...... */
+ /*037a:*/ 0xf0, /* ####.... */
+ /*037b:*/ 0x30, /* ..##.... */
+ /*037c:*/ 0xe0, /* ###..... */
+/* --- new character t (116) starting at offset 0x037d --- */
+ /*037d:*/ 3, 4, 7, -1, 0, /* width and bbox (w,h,x,y) */
+ /*0382:*/ 0x20, /* ..#..... */
+ /*0383:*/ 0x60, /* .##..... */
+ /*0384:*/ 0xf0, /* ####.... */
+ /*0385:*/ 0x60, /* .##..... */
+ /*0386:*/ 0x60, /* .##..... */
+ /*0387:*/ 0x60, /* .##..... */
+ /*0388:*/ 0x30, /* ..##.... */
+/* --- new character u (117) starting at offset 0x0389 --- */
+ /*0389:*/ 5, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*038e:*/ 0xd0, /* ##.#.... */
+ /*038f:*/ 0xd0, /* ##.#.... */
+ /*0390:*/ 0xd0, /* ##.#.... */
+ /*0391:*/ 0xf0, /* ####.... */
+ /*0392:*/ 0x50, /* .#.#.... */
+/* --- new character v (118) starting at offset 0x0393 --- */
+ /*0393:*/ 5, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0398:*/ 0xd0, /* ##.#.... */
+ /*0399:*/ 0xd0, /* ##.#.... */
+ /*039a:*/ 0xd0, /* ##.#.... */
+ /*039b:*/ 0x60, /* .##..... */
+ /*039c:*/ 0x40, /* .#...... */
+/* --- new character w (119) starting at offset 0x039d --- */
+ /*039d:*/ 6, 5, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03a2:*/ 0xa8, /* #.#.#... */
+ /*03a3:*/ 0xa8, /* #.#.#... */
+ /*03a4:*/ 0xf8, /* #####... */
+ /*03a5:*/ 0xf8, /* #####... */
+ /*03a6:*/ 0x48, /* .#..#... */
+/* --- new character x (120) starting at offset 0x03a7 --- */
+ /*03a7:*/ 6, 5, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03ac:*/ 0xd8, /* ##.##... */
+ /*03ad:*/ 0xd8, /* ##.##... */
+ /*03ae:*/ 0x70, /* .###.... */
+ /*03af:*/ 0xd8, /* ##.##... */
+ /*03b0:*/ 0xd8, /* ##.##... */
+/* --- new character y (121) starting at offset 0x03b1 --- */
+ /*03b1:*/ 5, 4, 6, 0, -1, /* width and bbox (w,h,x,y) */
+ /*03b6:*/ 0xd0, /* ##.#.... */
+ /*03b7:*/ 0xd0, /* ##.#.... */
+ /*03b8:*/ 0xd0, /* ##.#.... */
+ /*03b9:*/ 0x70, /* .###.... */
+ /*03ba:*/ 0x60, /* .##..... */
+ /*03bb:*/ 0x60, /* .##..... */
+/* --- new character z (122) starting at offset 0x03bc --- */
+ /*03bc:*/ 5, 4, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03c1:*/ 0xf0, /* ####.... */
+ /*03c2:*/ 0x30, /* ..##.... */
+ /*03c3:*/ 0x60, /* .##..... */
+ /*03c4:*/ 0xc0, /* ##...... */
+ /*03c5:*/ 0xf0, /* ####.... */
+/* --- new character braceleft (123) starting at offset 0x03c6 --- */
+ /*03c6:*/ 4, 3, 7, 0, -1, /* width and bbox (w,h,x,y) */
+ /*03cb:*/ 0x20, /* ..#..... */
+ /*03cc:*/ 0x40, /* .#...... */
+ /*03cd:*/ 0x40, /* .#...... */
+ /*03ce:*/ 0x80, /* #....... */
+ /*03cf:*/ 0x40, /* .#...... */
+ /*03d0:*/ 0x40, /* .#...... */
+ /*03d1:*/ 0x20, /* ..#..... */
+/* --- new character bar (124) starting at offset 0x03d2 --- */
+ /*03d2:*/ 2, 1, 7, 1, -1, /* width and bbox (w,h,x,y) */
+ /*03d7:*/ 0x80, /* #....... */
+ /*03d8:*/ 0x80, /* #....... */
+ /*03d9:*/ 0x80, /* #....... */
+ /*03da:*/ 0x80, /* #....... */
+ /*03db:*/ 0x80, /* #....... */
+ /*03dc:*/ 0x80, /* #....... */
+ /*03dd:*/ 0x80, /* #....... */
+/* --- new character braceright (125) starting at offset 0x03de --- */
+ /*03de:*/ 4, 3, 7, 0, -1, /* width and bbox (w,h,x,y) */
+ /*03e3:*/ 0x80, /* #....... */
+ /*03e4:*/ 0x40, /* .#...... */
+ /*03e5:*/ 0x40, /* .#...... */
+ /*03e6:*/ 0x20, /* ..#..... */
+ /*03e7:*/ 0x40, /* .#...... */
+ /*03e8:*/ 0x40, /* .#...... */
+ /*03e9:*/ 0x80, /* #....... */
+/* --- new character asciitilde (126) starting at offset 0x03ea --- */
+ /*03ea:*/ 5, 5, 2, 0, 2, /* width and bbox (w,h,x,y) */
+ /*03ef:*/ 0x58, /* .#.##... */
+ /*03f0:*/ 0xb0, /* #.##.... */
+};
+static const uint16_t font_helvB08_offsets[] = {
+0x0000 /* space */,
+ 0x0006 /* exclam */,
+ 0x0012 /* quotedbl */,
+ 0x0019 /* numbersign */,
+ 0x0024 /* dollar */,
+ 0x0031 /* percent */,
+ 0x003c /* ampersand */,
+ 0x0047 /* quotesingle */,
+ 0x004f /* parenleft */,
+ 0x005c /* parenright */,
+ 0x0069 /* asterisk */,
+ 0x0071 /* plus */,
+ 0x007b /* comma */,
+ 0x0083 /* hyphen */,
+ 0x0089 /* period */,
+ 0x0090 /* slash */,
+ 0x009b /* zero */,
+ 0x00a6 /* one */,
+ 0x00b1 /* two */,
+ 0x00bc /* three */,
+ 0x00c7 /* four */,
+ 0x00d2 /* five */,
+ 0x00dd /* six */,
+ 0x00e8 /* seven */,
+ 0x00f3 /* eight */,
+ 0x00fe /* nine */,
+ 0x0109 /* colon */,
+ 0x0113 /* semicolon */,
+ 0x011e /* less */,
+ 0x0128 /* equal */,
+ 0x0130 /* greater */,
+ 0x013a /* question */,
+ 0x0146 /* at */,
+ 0x0152 /* A */,
+ 0x015d /* B */,
+ 0x0168 /* C */,
+ 0x0173 /* D */,
+ 0x017e /* E */,
+ 0x0189 /* F */,
+ 0x0194 /* G */,
+ 0x019f /* H */,
+ 0x01aa /* I */,
+ 0x01b5 /* J */,
+ 0x01c0 /* K */,
+ 0x01cb /* L */,
+ 0x01d6 /* M */,
+ 0x01e1 /* N */,
+ 0x01ec /* O */,
+ 0x01f7 /* P */,
+ 0x0202 /* Q */,
+ 0x020e /* R */,
+ 0x0219 /* S */,
+ 0x0224 /* T */,
+ 0x022f /* U */,
+ 0x023a /* V */,
+ 0x0245 /* W */,
+ 0x0250 /* X */,
+ 0x025b /* Y */,
+ 0x0266 /* Z */,
+ 0x0271 /* bracketleft */,
+ 0x027e /* backslash */,
+ 0x0289 /* bracketright */,
+ 0x0296 /* asciicircum */,
+ 0x029e /* underscore */,
+ 0x02a4 /* grave */,
+ 0x02ab /* a */,
+ 0x02b5 /* b */,
+ 0x02c1 /* c */,
+ 0x02cb /* d */,
+ 0x02d7 /* e */,
+ 0x02e1 /* f */,
+ 0x02ed /* g */,
+ 0x02f8 /* h */,
+ 0x0304 /* i */,
+ 0x0310 /* j */,
+ 0x031d /* k */,
+ 0x0329 /* l */,
+ 0x0335 /* m */,
+ 0x033f /* n */,
+ 0x0349 /* o */,
+ 0x0353 /* p */,
+ 0x035e /* q */,
+ 0x0369 /* r */,
+ 0x0373 /* s */,
+ 0x037d /* t */,
+ 0x0389 /* u */,
+ 0x0393 /* v */,
+ 0x039d /* w */,
+ 0x03a7 /* x */,
+ 0x03b1 /* y */,
+ 0x03bc /* z */,
+ 0x03c6 /* braceleft */,
+ 0x03d2 /* bar */,
+ 0x03de /* braceright */,
+ 0x03ea /* asciitilde */,
+ 0xffff /* (no glyph) */
+};
+const struct fb_font font_helvB08 = {
+ .height = 10,
+ .ascent = 8,
+ .firstchar = 32, /* space */
+ .lastchar = 127, /* ? */
+ .chardata = font_helvB08_data,
+ .charoffs = font_helvB08_offsets,
+};
diff --git a/Src/osmolib/src/target/firmware/fb/helvB14.c b/Src/osmolib/src/target/firmware/fb/helvB14.c
new file mode 100644
index 0000000..40c310e
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/helvB14.c
@@ -0,0 +1,1195 @@
+#include <fb/font.h>
+static const uint8_t font_helvB14_data[] = {
+/* --- new character space (32) starting at offset 0x0000 --- */
+ /*0000:*/ 4, 1, 1, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0005:*/ 0x00, /* ........ */
+/* --- new character exclam (33) starting at offset 0x0006 --- */
+ /*0006:*/ 4, 2, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*000b:*/ 0xc0, /* ##...... */
+ /*000c:*/ 0xc0, /* ##...... */
+ /*000d:*/ 0xc0, /* ##...... */
+ /*000e:*/ 0xc0, /* ##...... */
+ /*000f:*/ 0xc0, /* ##...... */
+ /*0010:*/ 0xc0, /* ##...... */
+ /*0011:*/ 0x80, /* #....... */
+ /*0012:*/ 0x80, /* #....... */
+ /*0013:*/ 0x00, /* ........ */
+ /*0014:*/ 0xc0, /* ##...... */
+ /*0015:*/ 0xc0, /* ##...... */
+/* --- new character quotedbl (34) starting at offset 0x0016 --- */
+ /*0016:*/ 7, 5, 3, 1, 8, /* width and bbox (w,h,x,y) */
+ /*001b:*/ 0xd8, /* ##.##... */
+ /*001c:*/ 0xd8, /* ##.##... */
+ /*001d:*/ 0x90, /* #..#.... */
+/* --- new character numbersign (35) starting at offset 0x001e --- */
+ /*001e:*/ 9, 9, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0023:*/ 0x1b,0x00, /* ...##.##........ */
+ /*0025:*/ 0x1b,0x00, /* ...##.##........ */
+ /*0027:*/ 0x1b,0x00, /* ...##.##........ */
+ /*0029:*/ 0x7f,0x80, /* .########....... */
+ /*002b:*/ 0x36,0x00, /* ..##.##......... */
+ /*002d:*/ 0x36,0x00, /* ..##.##......... */
+ /*002f:*/ 0xff,0x00, /* ########........ */
+ /*0031:*/ 0x6c,0x00, /* .##.##.......... */
+ /*0033:*/ 0x6c,0x00, /* .##.##.......... */
+ /*0035:*/ 0x6c,0x00, /* .##.##.......... */
+/* --- new character dollar (36) starting at offset 0x0037 --- */
+ /*0037:*/ 8, 7, 13, 0, -2, /* width and bbox (w,h,x,y) */
+ /*003c:*/ 0x10, /* ...#.... */
+ /*003d:*/ 0x7c, /* .#####.. */
+ /*003e:*/ 0xd6, /* ##.#.##. */
+ /*003f:*/ 0xd6, /* ##.#.##. */
+ /*0040:*/ 0xf0, /* ####.... */
+ /*0041:*/ 0x78, /* .####... */
+ /*0042:*/ 0x1c, /* ...###.. */
+ /*0043:*/ 0x16, /* ...#.##. */
+ /*0044:*/ 0xd6, /* ##.#.##. */
+ /*0045:*/ 0xd6, /* ##.#.##. */
+ /*0046:*/ 0x7c, /* .#####.. */
+ /*0047:*/ 0x10, /* ...#.... */
+ /*0048:*/ 0x10, /* ...#.... */
+/* --- new character percent (37) starting at offset 0x0049 --- */
+ /*0049:*/ 13, 12, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*004e:*/ 0x78,0x80, /* .####...#....... */
+ /*0050:*/ 0xcd,0x80, /* ##..##.##....... */
+ /*0052:*/ 0xcd,0x00, /* ##..##.#........ */
+ /*0054:*/ 0x7b,0x00, /* .####.##........ */
+ /*0056:*/ 0x06,0x00, /* .....##......... */
+ /*0058:*/ 0x04,0x00, /* .....#.......... */
+ /*005a:*/ 0x0d,0xe0, /* ....##.####..... */
+ /*005c:*/ 0x0b,0x30, /* ....#.##..##.... */
+ /*005e:*/ 0x1b,0x30, /* ...##.##..##.... */
+ /*0060:*/ 0x11,0xe0, /* ...#...####..... */
+/* --- new character ampersand (38) starting at offset 0x0062 --- */
+ /*0062:*/ 11, 9, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0067:*/ 0x38,0x00, /* ..###........... */
+ /*0069:*/ 0x6c,0x00, /* .##.##.......... */
+ /*006b:*/ 0x6c,0x00, /* .##.##.......... */
+ /*006d:*/ 0x38,0x00, /* ..###........... */
+ /*006f:*/ 0x73,0x00, /* .###..##........ */
+ /*0071:*/ 0xfb,0x00, /* #####.##........ */
+ /*0073:*/ 0xce,0x00, /* ##..###......... */
+ /*0075:*/ 0xc6,0x00, /* ##...##......... */
+ /*0077:*/ 0xcf,0x00, /* ##..####........ */
+ /*0079:*/ 0x7d,0x80, /* .#####.##....... */
+/* --- new character quotesingle (39) starting at offset 0x007b --- */
+ /*007b:*/ 4, 2, 3, 1, 8, /* width and bbox (w,h,x,y) */
+ /*0080:*/ 0xc0, /* ##...... */
+ /*0081:*/ 0xc0, /* ##...... */
+ /*0082:*/ 0x80, /* #....... */
+/* --- new character parenleft (40) starting at offset 0x0083 --- */
+ /*0083:*/ 5, 4, 14, 0, -3, /* width and bbox (w,h,x,y) */
+ /*0088:*/ 0x30, /* ..##.... */
+ /*0089:*/ 0x60, /* .##..... */
+ /*008a:*/ 0x60, /* .##..... */
+ /*008b:*/ 0xc0, /* ##...... */
+ /*008c:*/ 0xc0, /* ##...... */
+ /*008d:*/ 0xc0, /* ##...... */
+ /*008e:*/ 0xc0, /* ##...... */
+ /*008f:*/ 0xc0, /* ##...... */
+ /*0090:*/ 0xc0, /* ##...... */
+ /*0091:*/ 0xc0, /* ##...... */
+ /*0092:*/ 0xc0, /* ##...... */
+ /*0093:*/ 0x60, /* .##..... */
+ /*0094:*/ 0x60, /* .##..... */
+ /*0095:*/ 0x30, /* ..##.... */
+/* --- new character parenright (41) starting at offset 0x0096 --- */
+ /*0096:*/ 5, 4, 14, 1, -3, /* width and bbox (w,h,x,y) */
+ /*009b:*/ 0xc0, /* ##...... */
+ /*009c:*/ 0x60, /* .##..... */
+ /*009d:*/ 0x60, /* .##..... */
+ /*009e:*/ 0x30, /* ..##.... */
+ /*009f:*/ 0x30, /* ..##.... */
+ /*00a0:*/ 0x30, /* ..##.... */
+ /*00a1:*/ 0x30, /* ..##.... */
+ /*00a2:*/ 0x30, /* ..##.... */
+ /*00a3:*/ 0x30, /* ..##.... */
+ /*00a4:*/ 0x30, /* ..##.... */
+ /*00a5:*/ 0x30, /* ..##.... */
+ /*00a6:*/ 0x60, /* .##..... */
+ /*00a7:*/ 0x60, /* .##..... */
+ /*00a8:*/ 0xc0, /* ##...... */
+/* --- new character asterisk (42) starting at offset 0x00a9 --- */
+ /*00a9:*/ 6, 5, 4, 0, 7, /* width and bbox (w,h,x,y) */
+ /*00ae:*/ 0x20, /* ..#..... */
+ /*00af:*/ 0xf8, /* #####... */
+ /*00b0:*/ 0x70, /* .###.... */
+ /*00b1:*/ 0xd8, /* ##.##... */
+/* --- new character plus (43) starting at offset 0x00b2 --- */
+ /*00b2:*/ 9, 8, 7, 0, 1, /* width and bbox (w,h,x,y) */
+ /*00b7:*/ 0x18, /* ...##... */
+ /*00b8:*/ 0x18, /* ...##... */
+ /*00b9:*/ 0x18, /* ...##... */
+ /*00ba:*/ 0xff, /* ######## */
+ /*00bb:*/ 0x18, /* ...##... */
+ /*00bc:*/ 0x18, /* ...##... */
+ /*00bd:*/ 0x18, /* ...##... */
+/* --- new character comma (44) starting at offset 0x00be --- */
+ /*00be:*/ 4, 3, 3, 0, -1, /* width and bbox (w,h,x,y) */
+ /*00c3:*/ 0x60, /* .##..... */
+ /*00c4:*/ 0x60, /* .##..... */
+ /*00c5:*/ 0xc0, /* ##...... */
+/* --- new character hyphen (45) starting at offset 0x00c6 --- */
+ /*00c6:*/ 5, 5, 1, 0, 4, /* width and bbox (w,h,x,y) */
+ /*00cb:*/ 0xf8, /* #####... */
+/* --- new character period (46) starting at offset 0x00cc --- */
+ /*00cc:*/ 4, 2, 2, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00d1:*/ 0xc0, /* ##...... */
+ /*00d2:*/ 0xc0, /* ##...... */
+/* --- new character slash (47) starting at offset 0x00d3 --- */
+ /*00d3:*/ 4, 4, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00d8:*/ 0x30, /* ..##.... */
+ /*00d9:*/ 0x30, /* ..##.... */
+ /*00da:*/ 0x20, /* ..#..... */
+ /*00db:*/ 0x20, /* ..#..... */
+ /*00dc:*/ 0x60, /* .##..... */
+ /*00dd:*/ 0x60, /* .##..... */
+ /*00de:*/ 0x60, /* .##..... */
+ /*00df:*/ 0x40, /* .#...... */
+ /*00e0:*/ 0x40, /* .#...... */
+ /*00e1:*/ 0xc0, /* ##...... */
+ /*00e2:*/ 0xc0, /* ##...... */
+/* --- new character zero (48) starting at offset 0x00e3 --- */
+ /*00e3:*/ 8, 7, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00e8:*/ 0x38, /* ..###... */
+ /*00e9:*/ 0x6c, /* .##.##.. */
+ /*00ea:*/ 0xc6, /* ##...##. */
+ /*00eb:*/ 0xc6, /* ##...##. */
+ /*00ec:*/ 0xc6, /* ##...##. */
+ /*00ed:*/ 0xc6, /* ##...##. */
+ /*00ee:*/ 0xc6, /* ##...##. */
+ /*00ef:*/ 0xc6, /* ##...##. */
+ /*00f0:*/ 0x6c, /* .##.##.. */
+ /*00f1:*/ 0x38, /* ..###... */
+/* --- new character one (49) starting at offset 0x00f2 --- */
+ /*00f2:*/ 8, 4, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00f7:*/ 0x30, /* ..##.... */
+ /*00f8:*/ 0xf0, /* ####.... */
+ /*00f9:*/ 0x30, /* ..##.... */
+ /*00fa:*/ 0x30, /* ..##.... */
+ /*00fb:*/ 0x30, /* ..##.... */
+ /*00fc:*/ 0x30, /* ..##.... */
+ /*00fd:*/ 0x30, /* ..##.... */
+ /*00fe:*/ 0x30, /* ..##.... */
+ /*00ff:*/ 0x30, /* ..##.... */
+ /*0100:*/ 0x30, /* ..##.... */
+/* --- new character two (50) starting at offset 0x0101 --- */
+ /*0101:*/ 8, 7, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0106:*/ 0x7c, /* .#####.. */
+ /*0107:*/ 0xe6, /* ###..##. */
+ /*0108:*/ 0xc6, /* ##...##. */
+ /*0109:*/ 0x0e, /* ....###. */
+ /*010a:*/ 0x0c, /* ....##.. */
+ /*010b:*/ 0x38, /* ..###... */
+ /*010c:*/ 0x70, /* .###.... */
+ /*010d:*/ 0xe0, /* ###..... */
+ /*010e:*/ 0xc0, /* ##...... */
+ /*010f:*/ 0xfe, /* #######. */
+/* --- new character three (51) starting at offset 0x0110 --- */
+ /*0110:*/ 8, 7, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0115:*/ 0x7c, /* .#####.. */
+ /*0116:*/ 0xce, /* ##..###. */
+ /*0117:*/ 0xc6, /* ##...##. */
+ /*0118:*/ 0x06, /* .....##. */
+ /*0119:*/ 0x3c, /* ..####.. */
+ /*011a:*/ 0x06, /* .....##. */
+ /*011b:*/ 0x06, /* .....##. */
+ /*011c:*/ 0xc6, /* ##...##. */
+ /*011d:*/ 0xce, /* ##..###. */
+ /*011e:*/ 0x7c, /* .#####.. */
+/* --- new character four (52) starting at offset 0x011f --- */
+ /*011f:*/ 8, 8, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0124:*/ 0x0e, /* ....###. */
+ /*0125:*/ 0x1e, /* ...####. */
+ /*0126:*/ 0x36, /* ..##.##. */
+ /*0127:*/ 0x66, /* .##..##. */
+ /*0128:*/ 0xc6, /* ##...##. */
+ /*0129:*/ 0xc6, /* ##...##. */
+ /*012a:*/ 0xff, /* ######## */
+ /*012b:*/ 0x06, /* .....##. */
+ /*012c:*/ 0x06, /* .....##. */
+ /*012d:*/ 0x06, /* .....##. */
+/* --- new character five (53) starting at offset 0x012e --- */
+ /*012e:*/ 8, 7, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0133:*/ 0x7e, /* .######. */
+ /*0134:*/ 0x60, /* .##..... */
+ /*0135:*/ 0xc0, /* ##...... */
+ /*0136:*/ 0xf8, /* #####... */
+ /*0137:*/ 0x1c, /* ...###.. */
+ /*0138:*/ 0x06, /* .....##. */
+ /*0139:*/ 0x06, /* .....##. */
+ /*013a:*/ 0xc6, /* ##...##. */
+ /*013b:*/ 0xec, /* ###.##.. */
+ /*013c:*/ 0x78, /* .####... */
+/* --- new character six (54) starting at offset 0x013d --- */
+ /*013d:*/ 8, 7, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0142:*/ 0x3c, /* ..####.. */
+ /*0143:*/ 0x76, /* .###.##. */
+ /*0144:*/ 0x66, /* .##..##. */
+ /*0145:*/ 0xc0, /* ##...... */
+ /*0146:*/ 0xdc, /* ##.###.. */
+ /*0147:*/ 0xf6, /* ####.##. */
+ /*0148:*/ 0xc6, /* ##...##. */
+ /*0149:*/ 0xc6, /* ##...##. */
+ /*014a:*/ 0x6e, /* .##.###. */
+ /*014b:*/ 0x3c, /* ..####.. */
+/* --- new character seven (55) starting at offset 0x014c --- */
+ /*014c:*/ 8, 7, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0151:*/ 0xfe, /* #######. */
+ /*0152:*/ 0x06, /* .....##. */
+ /*0153:*/ 0x0c, /* ....##.. */
+ /*0154:*/ 0x0c, /* ....##.. */
+ /*0155:*/ 0x18, /* ...##... */
+ /*0156:*/ 0x18, /* ...##... */
+ /*0157:*/ 0x30, /* ..##.... */
+ /*0158:*/ 0x30, /* ..##.... */
+ /*0159:*/ 0x60, /* .##..... */
+ /*015a:*/ 0x60, /* .##..... */
+/* --- new character eight (56) starting at offset 0x015b --- */
+ /*015b:*/ 8, 7, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0160:*/ 0x7c, /* .#####.. */
+ /*0161:*/ 0xee, /* ###.###. */
+ /*0162:*/ 0xc6, /* ##...##. */
+ /*0163:*/ 0xc6, /* ##...##. */
+ /*0164:*/ 0x7c, /* .#####.. */
+ /*0165:*/ 0xee, /* ###.###. */
+ /*0166:*/ 0xc6, /* ##...##. */
+ /*0167:*/ 0xc6, /* ##...##. */
+ /*0168:*/ 0xc6, /* ##...##. */
+ /*0169:*/ 0x7c, /* .#####.. */
+/* --- new character nine (57) starting at offset 0x016a --- */
+ /*016a:*/ 8, 7, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*016f:*/ 0x7c, /* .#####.. */
+ /*0170:*/ 0xee, /* ###.###. */
+ /*0171:*/ 0xc6, /* ##...##. */
+ /*0172:*/ 0xc6, /* ##...##. */
+ /*0173:*/ 0xe6, /* ###..##. */
+ /*0174:*/ 0x7e, /* .######. */
+ /*0175:*/ 0x06, /* .....##. */
+ /*0176:*/ 0xc6, /* ##...##. */
+ /*0177:*/ 0xce, /* ##..###. */
+ /*0178:*/ 0x7c, /* .#####.. */
+/* --- new character colon (58) starting at offset 0x0179 --- */
+ /*0179:*/ 5, 2, 8, 2, 0, /* width and bbox (w,h,x,y) */
+ /*017e:*/ 0xc0, /* ##...... */
+ /*017f:*/ 0xc0, /* ##...... */
+ /*0180:*/ 0x00, /* ........ */
+ /*0181:*/ 0x00, /* ........ */
+ /*0182:*/ 0x00, /* ........ */
+ /*0183:*/ 0x00, /* ........ */
+ /*0184:*/ 0xc0, /* ##...... */
+ /*0185:*/ 0xc0, /* ##...... */
+/* --- new character semicolon (59) starting at offset 0x0186 --- */
+ /*0186:*/ 5, 3, 9, 1, -1, /* width and bbox (w,h,x,y) */
+ /*018b:*/ 0x60, /* .##..... */
+ /*018c:*/ 0x60, /* .##..... */
+ /*018d:*/ 0x00, /* ........ */
+ /*018e:*/ 0x00, /* ........ */
+ /*018f:*/ 0x00, /* ........ */
+ /*0190:*/ 0x00, /* ........ */
+ /*0191:*/ 0x60, /* .##..... */
+ /*0192:*/ 0x60, /* .##..... */
+ /*0193:*/ 0xc0, /* ##...... */
+/* --- new character less (60) starting at offset 0x0194 --- */
+ /*0194:*/ 8, 6, 5, 1, 2, /* width and bbox (w,h,x,y) */
+ /*0199:*/ 0x1c, /* ...###.. */
+ /*019a:*/ 0x70, /* .###.... */
+ /*019b:*/ 0xc0, /* ##...... */
+ /*019c:*/ 0x70, /* .###.... */
+ /*019d:*/ 0x1c, /* ...###.. */
+/* --- new character equal (61) starting at offset 0x019e --- */
+ /*019e:*/ 9, 7, 3, 1, 3, /* width and bbox (w,h,x,y) */
+ /*01a3:*/ 0xfe, /* #######. */
+ /*01a4:*/ 0x00, /* ........ */
+ /*01a5:*/ 0xfe, /* #######. */
+/* --- new character greater (62) starting at offset 0x01a6 --- */
+ /*01a6:*/ 8, 6, 5, 1, 2, /* width and bbox (w,h,x,y) */
+ /*01ab:*/ 0xe0, /* ###..... */
+ /*01ac:*/ 0x38, /* ..###... */
+ /*01ad:*/ 0x0c, /* ....##.. */
+ /*01ae:*/ 0x38, /* ..###... */
+ /*01af:*/ 0xe0, /* ###..... */
+/* --- new character question (63) starting at offset 0x01b0 --- */
+ /*01b0:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01b5:*/ 0x7c, /* .#####.. */
+ /*01b6:*/ 0xc6, /* ##...##. */
+ /*01b7:*/ 0xc6, /* ##...##. */
+ /*01b8:*/ 0x06, /* .....##. */
+ /*01b9:*/ 0x0c, /* ....##.. */
+ /*01ba:*/ 0x18, /* ...##... */
+ /*01bb:*/ 0x30, /* ..##.... */
+ /*01bc:*/ 0x30, /* ..##.... */
+ /*01bd:*/ 0x00, /* ........ */
+ /*01be:*/ 0x30, /* ..##.... */
+ /*01bf:*/ 0x30, /* ..##.... */
+/* --- new character at (64) starting at offset 0x01c0 --- */
+ /*01c0:*/ 14, 13, 12, 0, -1, /* width and bbox (w,h,x,y) */
+ /*01c5:*/ 0x0f,0x80, /* ....#####....... */
+ /*01c7:*/ 0x38,0xe0, /* ..###...###..... */
+ /*01c9:*/ 0x70,0x70, /* .###.....###.... */
+ /*01cb:*/ 0x66,0xb0, /* .##..##.#.##.... */
+ /*01cd:*/ 0xcd,0x98, /* ##..##.##..##... */
+ /*01cf:*/ 0xd9,0x98, /* ##.##..##..##... */
+ /*01d1:*/ 0xdb,0x18, /* ##.##.##...##... */
+ /*01d3:*/ 0xdb,0x30, /* ##.##.##..##.... */
+ /*01d5:*/ 0xce,0xe0, /* ##..###.###..... */
+ /*01d7:*/ 0x60,0x00, /* .##............. */
+ /*01d9:*/ 0x31,0x80, /* ..##...##....... */
+ /*01db:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character A (65) starting at offset 0x01dd --- */
+ /*01dd:*/ 10, 10, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01e2:*/ 0x0c,0x00, /* ....##.......... */
+ /*01e4:*/ 0x0c,0x00, /* ....##.......... */
+ /*01e6:*/ 0x1e,0x00, /* ...####......... */
+ /*01e8:*/ 0x12,0x00, /* ...#..#......... */
+ /*01ea:*/ 0x33,0x00, /* ..##..##........ */
+ /*01ec:*/ 0x33,0x00, /* ..##..##........ */
+ /*01ee:*/ 0x61,0x80, /* .##....##....... */
+ /*01f0:*/ 0x7f,0x80, /* .########....... */
+ /*01f2:*/ 0x61,0x80, /* .##....##....... */
+ /*01f4:*/ 0xc0,0xc0, /* ##......##...... */
+ /*01f6:*/ 0xc0,0xc0, /* ##......##...... */
+/* --- new character B (66) starting at offset 0x01f8 --- */
+ /*01f8:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01fd:*/ 0xfe, /* #######. */
+ /*01fe:*/ 0xc7, /* ##...### */
+ /*01ff:*/ 0xc3, /* ##....## */
+ /*0200:*/ 0xc3, /* ##....## */
+ /*0201:*/ 0xc6, /* ##...##. */
+ /*0202:*/ 0xfc, /* ######.. */
+ /*0203:*/ 0xc6, /* ##...##. */
+ /*0204:*/ 0xc3, /* ##....## */
+ /*0205:*/ 0xc3, /* ##....## */
+ /*0206:*/ 0xc7, /* ##...### */
+ /*0207:*/ 0xfe, /* #######. */
+/* --- new character C (67) starting at offset 0x0208 --- */
+ /*0208:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*020d:*/ 0x1f,0x00, /* ...#####........ */
+ /*020f:*/ 0x7b,0x80, /* .####.###....... */
+ /*0211:*/ 0x60,0x80, /* .##.....#....... */
+ /*0213:*/ 0xc0,0x00, /* ##.............. */
+ /*0215:*/ 0xc0,0x00, /* ##.............. */
+ /*0217:*/ 0xc0,0x00, /* ##.............. */
+ /*0219:*/ 0xc0,0x00, /* ##.............. */
+ /*021b:*/ 0xc0,0x00, /* ##.............. */
+ /*021d:*/ 0x60,0x80, /* .##.....#....... */
+ /*021f:*/ 0x7b,0x80, /* .####.###....... */
+ /*0221:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character D (68) starting at offset 0x0223 --- */
+ /*0223:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0228:*/ 0xfc,0x00, /* ######.......... */
+ /*022a:*/ 0xc7,0x00, /* ##...###........ */
+ /*022c:*/ 0xc3,0x00, /* ##....##........ */
+ /*022e:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0230:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0232:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0234:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0236:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0238:*/ 0xc3,0x00, /* ##....##........ */
+ /*023a:*/ 0xc7,0x00, /* ##...###........ */
+ /*023c:*/ 0xfc,0x00, /* ######.......... */
+/* --- new character E (69) starting at offset 0x023e --- */
+ /*023e:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0243:*/ 0xfe, /* #######. */
+ /*0244:*/ 0xc0, /* ##...... */
+ /*0245:*/ 0xc0, /* ##...... */
+ /*0246:*/ 0xc0, /* ##...... */
+ /*0247:*/ 0xc0, /* ##...... */
+ /*0248:*/ 0xfe, /* #######. */
+ /*0249:*/ 0xc0, /* ##...... */
+ /*024a:*/ 0xc0, /* ##...... */
+ /*024b:*/ 0xc0, /* ##...... */
+ /*024c:*/ 0xc0, /* ##...... */
+ /*024d:*/ 0xfe, /* #######. */
+/* --- new character F (70) starting at offset 0x024e --- */
+ /*024e:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0253:*/ 0xfe, /* #######. */
+ /*0254:*/ 0xc0, /* ##...... */
+ /*0255:*/ 0xc0, /* ##...... */
+ /*0256:*/ 0xc0, /* ##...... */
+ /*0257:*/ 0xc0, /* ##...... */
+ /*0258:*/ 0xfc, /* ######.. */
+ /*0259:*/ 0xc0, /* ##...... */
+ /*025a:*/ 0xc0, /* ##...... */
+ /*025b:*/ 0xc0, /* ##...... */
+ /*025c:*/ 0xc0, /* ##...... */
+ /*025d:*/ 0xc0, /* ##...... */
+/* --- new character G (71) starting at offset 0x025e --- */
+ /*025e:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0263:*/ 0x1f,0x00, /* ...#####........ */
+ /*0265:*/ 0x7b,0x80, /* .####.###....... */
+ /*0267:*/ 0x60,0x80, /* .##.....#....... */
+ /*0269:*/ 0xc0,0x00, /* ##.............. */
+ /*026b:*/ 0xc0,0x00, /* ##.............. */
+ /*026d:*/ 0xc7,0x80, /* ##...####....... */
+ /*026f:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0271:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0273:*/ 0x61,0x80, /* .##....##....... */
+ /*0275:*/ 0x7b,0x80, /* .####.###....... */
+ /*0277:*/ 0x1e,0x80, /* ...####.#....... */
+/* --- new character H (72) starting at offset 0x0279 --- */
+ /*0279:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*027e:*/ 0xc3, /* ##....## */
+ /*027f:*/ 0xc3, /* ##....## */
+ /*0280:*/ 0xc3, /* ##....## */
+ /*0281:*/ 0xc3, /* ##....## */
+ /*0282:*/ 0xc3, /* ##....## */
+ /*0283:*/ 0xff, /* ######## */
+ /*0284:*/ 0xc3, /* ##....## */
+ /*0285:*/ 0xc3, /* ##....## */
+ /*0286:*/ 0xc3, /* ##....## */
+ /*0287:*/ 0xc3, /* ##....## */
+ /*0288:*/ 0xc3, /* ##....## */
+/* --- new character I (73) starting at offset 0x0289 --- */
+ /*0289:*/ 4, 2, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*028e:*/ 0xc0, /* ##...... */
+ /*028f:*/ 0xc0, /* ##...... */
+ /*0290:*/ 0xc0, /* ##...... */
+ /*0291:*/ 0xc0, /* ##...... */
+ /*0292:*/ 0xc0, /* ##...... */
+ /*0293:*/ 0xc0, /* ##...... */
+ /*0294:*/ 0xc0, /* ##...... */
+ /*0295:*/ 0xc0, /* ##...... */
+ /*0296:*/ 0xc0, /* ##...... */
+ /*0297:*/ 0xc0, /* ##...... */
+ /*0298:*/ 0xc0, /* ##...... */
+/* --- new character J (74) starting at offset 0x0299 --- */
+ /*0299:*/ 8, 7, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*029e:*/ 0x06, /* .....##. */
+ /*029f:*/ 0x06, /* .....##. */
+ /*02a0:*/ 0x06, /* .....##. */
+ /*02a1:*/ 0x06, /* .....##. */
+ /*02a2:*/ 0x06, /* .....##. */
+ /*02a3:*/ 0x06, /* .....##. */
+ /*02a4:*/ 0x06, /* .....##. */
+ /*02a5:*/ 0xc6, /* ##...##. */
+ /*02a6:*/ 0xc6, /* ##...##. */
+ /*02a7:*/ 0xee, /* ###.###. */
+ /*02a8:*/ 0x7c, /* .#####.. */
+/* --- new character K (75) starting at offset 0x02a9 --- */
+ /*02a9:*/ 10, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02ae:*/ 0xc3,0x00, /* ##....##........ */
+ /*02b0:*/ 0xc6,0x00, /* ##...##......... */
+ /*02b2:*/ 0xcc,0x00, /* ##..##.......... */
+ /*02b4:*/ 0xd8,0x00, /* ##.##........... */
+ /*02b6:*/ 0xf0,0x00, /* ####............ */
+ /*02b8:*/ 0xf0,0x00, /* ####............ */
+ /*02ba:*/ 0xd8,0x00, /* ##.##........... */
+ /*02bc:*/ 0xcc,0x00, /* ##..##.......... */
+ /*02be:*/ 0xc6,0x00, /* ##...##......... */
+ /*02c0:*/ 0xc3,0x00, /* ##....##........ */
+ /*02c2:*/ 0xc1,0x80, /* ##.....##....... */
+/* --- new character L (76) starting at offset 0x02c4 --- */
+ /*02c4:*/ 8, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02c9:*/ 0xc0, /* ##...... */
+ /*02ca:*/ 0xc0, /* ##...... */
+ /*02cb:*/ 0xc0, /* ##...... */
+ /*02cc:*/ 0xc0, /* ##...... */
+ /*02cd:*/ 0xc0, /* ##...... */
+ /*02ce:*/ 0xc0, /* ##...... */
+ /*02cf:*/ 0xc0, /* ##...... */
+ /*02d0:*/ 0xc0, /* ##...... */
+ /*02d1:*/ 0xc0, /* ##...... */
+ /*02d2:*/ 0xc0, /* ##...... */
+ /*02d3:*/ 0xfe, /* #######. */
+/* --- new character M (77) starting at offset 0x02d4 --- */
+ /*02d4:*/ 13, 11, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02d9:*/ 0xc0,0x60, /* ##.......##..... */
+ /*02db:*/ 0xc0,0x60, /* ##.......##..... */
+ /*02dd:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*02df:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*02e1:*/ 0xf1,0xe0, /* ####...####..... */
+ /*02e3:*/ 0xd1,0x60, /* ##.#...#.##..... */
+ /*02e5:*/ 0xd1,0x60, /* ##.#...#.##..... */
+ /*02e7:*/ 0xdb,0x60, /* ##.##.##.##..... */
+ /*02e9:*/ 0xca,0x60, /* ##..#.#..##..... */
+ /*02eb:*/ 0xce,0x60, /* ##..###..##..... */
+ /*02ed:*/ 0xc4,0x60, /* ##...#...##..... */
+/* --- new character N (78) starting at offset 0x02ef --- */
+ /*02ef:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02f4:*/ 0xc1,0x80, /* ##.....##....... */
+ /*02f6:*/ 0xe1,0x80, /* ###....##....... */
+ /*02f8:*/ 0xe1,0x80, /* ###....##....... */
+ /*02fa:*/ 0xd1,0x80, /* ##.#...##....... */
+ /*02fc:*/ 0xd9,0x80, /* ##.##..##....... */
+ /*02fe:*/ 0xc9,0x80, /* ##..#..##....... */
+ /*0300:*/ 0xcd,0x80, /* ##..##.##....... */
+ /*0302:*/ 0xc5,0x80, /* ##...#.##....... */
+ /*0304:*/ 0xc3,0x80, /* ##....###....... */
+ /*0306:*/ 0xc3,0x80, /* ##....###....... */
+ /*0308:*/ 0xc1,0x80, /* ##.....##....... */
+/* --- new character O (79) starting at offset 0x030a --- */
+ /*030a:*/ 12, 10, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*030f:*/ 0x1e,0x00, /* ...####......... */
+ /*0311:*/ 0x73,0x80, /* .###..###....... */
+ /*0313:*/ 0x61,0x80, /* .##....##....... */
+ /*0315:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0317:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0319:*/ 0xc0,0xc0, /* ##......##...... */
+ /*031b:*/ 0xc0,0xc0, /* ##......##...... */
+ /*031d:*/ 0xc0,0xc0, /* ##......##...... */
+ /*031f:*/ 0x61,0x80, /* .##....##....... */
+ /*0321:*/ 0x73,0x80, /* .###..###....... */
+ /*0323:*/ 0x1e,0x00, /* ...####......... */
+/* --- new character P (80) starting at offset 0x0325 --- */
+ /*0325:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*032a:*/ 0xfe, /* #######. */
+ /*032b:*/ 0xc7, /* ##...### */
+ /*032c:*/ 0xc3, /* ##....## */
+ /*032d:*/ 0xc3, /* ##....## */
+ /*032e:*/ 0xc7, /* ##...### */
+ /*032f:*/ 0xfe, /* #######. */
+ /*0330:*/ 0xc0, /* ##...... */
+ /*0331:*/ 0xc0, /* ##...... */
+ /*0332:*/ 0xc0, /* ##...... */
+ /*0333:*/ 0xc0, /* ##...... */
+ /*0334:*/ 0xc0, /* ##...... */
+/* --- new character Q (81) starting at offset 0x0335 --- */
+ /*0335:*/ 12, 10, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*033a:*/ 0x1e,0x00, /* ...####......... */
+ /*033c:*/ 0x73,0x80, /* .###..###....... */
+ /*033e:*/ 0x61,0x80, /* .##....##....... */
+ /*0340:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0342:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0344:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0346:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0348:*/ 0xc6,0xc0, /* ##...##.##...... */
+ /*034a:*/ 0x63,0x80, /* .##...###....... */
+ /*034c:*/ 0x73,0x80, /* .###..###....... */
+ /*034e:*/ 0x1e,0xc0, /* ...####.##...... */
+/* --- new character R (82) starting at offset 0x0350 --- */
+ /*0350:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0355:*/ 0xfe,0x00, /* #######......... */
+ /*0357:*/ 0xc7,0x00, /* ##...###........ */
+ /*0359:*/ 0xc3,0x00, /* ##....##........ */
+ /*035b:*/ 0xc3,0x00, /* ##....##........ */
+ /*035d:*/ 0xc7,0x00, /* ##...###........ */
+ /*035f:*/ 0xfe,0x00, /* #######......... */
+ /*0361:*/ 0xc3,0x00, /* ##....##........ */
+ /*0363:*/ 0xc3,0x00, /* ##....##........ */
+ /*0365:*/ 0xc3,0x00, /* ##....##........ */
+ /*0367:*/ 0xc3,0x00, /* ##....##........ */
+ /*0369:*/ 0xc1,0x80, /* ##.....##....... */
+/* --- new character S (83) starting at offset 0x036b --- */
+ /*036b:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0370:*/ 0x7e, /* .######. */
+ /*0371:*/ 0xe7, /* ###..### */
+ /*0372:*/ 0xc3, /* ##....## */
+ /*0373:*/ 0xe0, /* ###..... */
+ /*0374:*/ 0x78, /* .####... */
+ /*0375:*/ 0x1e, /* ...####. */
+ /*0376:*/ 0x07, /* .....### */
+ /*0377:*/ 0x03, /* ......## */
+ /*0378:*/ 0xc3, /* ##....## */
+ /*0379:*/ 0xee, /* ###.###. */
+ /*037a:*/ 0x7c, /* .#####.. */
+/* --- new character T (84) starting at offset 0x037b --- */
+ /*037b:*/ 8, 8, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0380:*/ 0xff, /* ######## */
+ /*0381:*/ 0x18, /* ...##... */
+ /*0382:*/ 0x18, /* ...##... */
+ /*0383:*/ 0x18, /* ...##... */
+ /*0384:*/ 0x18, /* ...##... */
+ /*0385:*/ 0x18, /* ...##... */
+ /*0386:*/ 0x18, /* ...##... */
+ /*0387:*/ 0x18, /* ...##... */
+ /*0388:*/ 0x18, /* ...##... */
+ /*0389:*/ 0x18, /* ...##... */
+ /*038a:*/ 0x18, /* ...##... */
+/* --- new character U (85) starting at offset 0x038b --- */
+ /*038b:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0390:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0392:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0394:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0396:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0398:*/ 0xc1,0x80, /* ##.....##....... */
+ /*039a:*/ 0xc1,0x80, /* ##.....##....... */
+ /*039c:*/ 0xc1,0x80, /* ##.....##....... */
+ /*039e:*/ 0xc1,0x80, /* ##.....##....... */
+ /*03a0:*/ 0xc1,0x80, /* ##.....##....... */
+ /*03a2:*/ 0x63,0x00, /* .##...##........ */
+ /*03a4:*/ 0x3e,0x00, /* ..#####......... */
+/* --- new character V (86) starting at offset 0x03a6 --- */
+ /*03a6:*/ 10, 10, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03ab:*/ 0xc0,0xc0, /* ##......##...... */
+ /*03ad:*/ 0xc0,0xc0, /* ##......##...... */
+ /*03af:*/ 0x61,0x80, /* .##....##....... */
+ /*03b1:*/ 0x61,0x80, /* .##....##....... */
+ /*03b3:*/ 0x73,0x80, /* .###..###....... */
+ /*03b5:*/ 0x33,0x00, /* ..##..##........ */
+ /*03b7:*/ 0x33,0x00, /* ..##..##........ */
+ /*03b9:*/ 0x1e,0x00, /* ...####......... */
+ /*03bb:*/ 0x1e,0x00, /* ...####......... */
+ /*03bd:*/ 0x0c,0x00, /* ....##.......... */
+ /*03bf:*/ 0x0c,0x00, /* ....##.......... */
+/* --- new character W (87) starting at offset 0x03c1 --- */
+ /*03c1:*/ 14, 14, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03c6:*/ 0xc3,0x0c, /* ##....##....##.. */
+ /*03c8:*/ 0xc3,0x0c, /* ##....##....##.. */
+ /*03ca:*/ 0xc3,0x0c, /* ##....##....##.. */
+ /*03cc:*/ 0x67,0x98, /* .##..####..##... */
+ /*03ce:*/ 0x64,0x98, /* .##..#..#..##... */
+ /*03d0:*/ 0x64,0x98, /* .##..#..#..##... */
+ /*03d2:*/ 0x6c,0xd8, /* .##.##..##.##... */
+ /*03d4:*/ 0x2c,0xd0, /* ..#.##..##.#.... */
+ /*03d6:*/ 0x38,0x70, /* ..###....###.... */
+ /*03d8:*/ 0x18,0x60, /* ...##....##..... */
+ /*03da:*/ 0x18,0x60, /* ...##....##..... */
+/* --- new character X (88) starting at offset 0x03dc --- */
+ /*03dc:*/ 9, 9, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03e1:*/ 0xc1,0x80, /* ##.....##....... */
+ /*03e3:*/ 0xc1,0x80, /* ##.....##....... */
+ /*03e5:*/ 0x63,0x00, /* .##...##........ */
+ /*03e7:*/ 0x36,0x00, /* ..##.##......... */
+ /*03e9:*/ 0x1c,0x00, /* ...###.......... */
+ /*03eb:*/ 0x1c,0x00, /* ...###.......... */
+ /*03ed:*/ 0x36,0x00, /* ..##.##......... */
+ /*03ef:*/ 0x63,0x00, /* .##...##........ */
+ /*03f1:*/ 0x63,0x00, /* .##...##........ */
+ /*03f3:*/ 0xc1,0x80, /* ##.....##....... */
+ /*03f5:*/ 0xc1,0x80, /* ##.....##....... */
+/* --- new character Y (89) starting at offset 0x03f7 --- */
+ /*03f7:*/ 10, 10, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03fc:*/ 0xc0,0xc0, /* ##......##...... */
+ /*03fe:*/ 0x61,0x80, /* .##....##....... */
+ /*0400:*/ 0x61,0x80, /* .##....##....... */
+ /*0402:*/ 0x33,0x00, /* ..##..##........ */
+ /*0404:*/ 0x33,0x00, /* ..##..##........ */
+ /*0406:*/ 0x1e,0x00, /* ...####......... */
+ /*0408:*/ 0x1e,0x00, /* ...####......... */
+ /*040a:*/ 0x0c,0x00, /* ....##.......... */
+ /*040c:*/ 0x0c,0x00, /* ....##.......... */
+ /*040e:*/ 0x0c,0x00, /* ....##.......... */
+ /*0410:*/ 0x0c,0x00, /* ....##.......... */
+/* --- new character Z (90) starting at offset 0x0412 --- */
+ /*0412:*/ 9, 8, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0417:*/ 0xff, /* ######## */
+ /*0418:*/ 0x03, /* ......## */
+ /*0419:*/ 0x06, /* .....##. */
+ /*041a:*/ 0x0c, /* ....##.. */
+ /*041b:*/ 0x1c, /* ...###.. */
+ /*041c:*/ 0x18, /* ...##... */
+ /*041d:*/ 0x30, /* ..##.... */
+ /*041e:*/ 0x70, /* .###.... */
+ /*041f:*/ 0x60, /* .##..... */
+ /*0420:*/ 0xc0, /* ##...... */
+ /*0421:*/ 0xff, /* ######## */
+/* --- new character bracketleft (91) starting at offset 0x0422 --- */
+ /*0422:*/ 5, 4, 14, 1, -3, /* width and bbox (w,h,x,y) */
+ /*0427:*/ 0xf0, /* ####.... */
+ /*0428:*/ 0xc0, /* ##...... */
+ /*0429:*/ 0xc0, /* ##...... */
+ /*042a:*/ 0xc0, /* ##...... */
+ /*042b:*/ 0xc0, /* ##...... */
+ /*042c:*/ 0xc0, /* ##...... */
+ /*042d:*/ 0xc0, /* ##...... */
+ /*042e:*/ 0xc0, /* ##...... */
+ /*042f:*/ 0xc0, /* ##...... */
+ /*0430:*/ 0xc0, /* ##...... */
+ /*0431:*/ 0xc0, /* ##...... */
+ /*0432:*/ 0xc0, /* ##...... */
+ /*0433:*/ 0xc0, /* ##...... */
+ /*0434:*/ 0xf0, /* ####.... */
+/* --- new character backslash (92) starting at offset 0x0435 --- */
+ /*0435:*/ 4, 4, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*043a:*/ 0xc0, /* ##...... */
+ /*043b:*/ 0xc0, /* ##...... */
+ /*043c:*/ 0xc0, /* ##...... */
+ /*043d:*/ 0x40, /* .#...... */
+ /*043e:*/ 0x60, /* .##..... */
+ /*043f:*/ 0x60, /* .##..... */
+ /*0440:*/ 0x60, /* .##..... */
+ /*0441:*/ 0x20, /* ..#..... */
+ /*0442:*/ 0x30, /* ..##.... */
+ /*0443:*/ 0x30, /* ..##.... */
+ /*0444:*/ 0x30, /* ..##.... */
+/* --- new character bracketright (93) starting at offset 0x0445 --- */
+ /*0445:*/ 5, 4, 14, 0, -3, /* width and bbox (w,h,x,y) */
+ /*044a:*/ 0xf0, /* ####.... */
+ /*044b:*/ 0x30, /* ..##.... */
+ /*044c:*/ 0x30, /* ..##.... */
+ /*044d:*/ 0x30, /* ..##.... */
+ /*044e:*/ 0x30, /* ..##.... */
+ /*044f:*/ 0x30, /* ..##.... */
+ /*0450:*/ 0x30, /* ..##.... */
+ /*0451:*/ 0x30, /* ..##.... */
+ /*0452:*/ 0x30, /* ..##.... */
+ /*0453:*/ 0x30, /* ..##.... */
+ /*0454:*/ 0x30, /* ..##.... */
+ /*0455:*/ 0x30, /* ..##.... */
+ /*0456:*/ 0x30, /* ..##.... */
+ /*0457:*/ 0xf0, /* ####.... */
+/* --- new character asciicircum (94) starting at offset 0x0458 --- */
+ /*0458:*/ 8, 6, 4, 1, 7, /* width and bbox (w,h,x,y) */
+ /*045d:*/ 0x30, /* ..##.... */
+ /*045e:*/ 0x78, /* .####... */
+ /*045f:*/ 0xcc, /* ##..##.. */
+ /*0460:*/ 0x84, /* #....#.. */
+/* --- new character underscore (95) starting at offset 0x0461 --- */
+ /*0461:*/ 8, 8, 1, 0, -3, /* width and bbox (w,h,x,y) */
+ /*0466:*/ 0xff, /* ######## */
+/* --- new character grave (96) starting at offset 0x0467 --- */
+ /*0467:*/ 5, 3, 2, 1, 9, /* width and bbox (w,h,x,y) */
+ /*046c:*/ 0xc0, /* ##...... */
+ /*046d:*/ 0x60, /* .##..... */
+/* --- new character a (97) starting at offset 0x046e --- */
+ /*046e:*/ 8, 7, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0473:*/ 0x78, /* .####... */
+ /*0474:*/ 0xcc, /* ##..##.. */
+ /*0475:*/ 0x0c, /* ....##.. */
+ /*0476:*/ 0x7c, /* .#####.. */
+ /*0477:*/ 0xcc, /* ##..##.. */
+ /*0478:*/ 0xcc, /* ##..##.. */
+ /*0479:*/ 0xfc, /* ######.. */
+ /*047a:*/ 0x76, /* .###.##. */
+/* --- new character b (98) starting at offset 0x047b --- */
+ /*047b:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0480:*/ 0xc0, /* ##...... */
+ /*0481:*/ 0xc0, /* ##...... */
+ /*0482:*/ 0xc0, /* ##...... */
+ /*0483:*/ 0xf8, /* #####... */
+ /*0484:*/ 0xec, /* ###.##.. */
+ /*0485:*/ 0xc6, /* ##...##. */
+ /*0486:*/ 0xc6, /* ##...##. */
+ /*0487:*/ 0xc6, /* ##...##. */
+ /*0488:*/ 0xc6, /* ##...##. */
+ /*0489:*/ 0xec, /* ###.##.. */
+ /*048a:*/ 0xd8, /* ##.##... */
+/* --- new character c (99) starting at offset 0x048b --- */
+ /*048b:*/ 8, 6, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0490:*/ 0x38, /* ..###... */
+ /*0491:*/ 0x7c, /* .#####.. */
+ /*0492:*/ 0xc4, /* ##...#.. */
+ /*0493:*/ 0xc0, /* ##...... */
+ /*0494:*/ 0xc0, /* ##...... */
+ /*0495:*/ 0xc4, /* ##...#.. */
+ /*0496:*/ 0x7c, /* .#####.. */
+ /*0497:*/ 0x38, /* ..###... */
+/* --- new character d (100) starting at offset 0x0498 --- */
+ /*0498:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*049d:*/ 0x06, /* .....##. */
+ /*049e:*/ 0x06, /* .....##. */
+ /*049f:*/ 0x06, /* .....##. */
+ /*04a0:*/ 0x3e, /* ..#####. */
+ /*04a1:*/ 0x6e, /* .##.###. */
+ /*04a2:*/ 0xc6, /* ##...##. */
+ /*04a3:*/ 0xc6, /* ##...##. */
+ /*04a4:*/ 0xc6, /* ##...##. */
+ /*04a5:*/ 0xc6, /* ##...##. */
+ /*04a6:*/ 0x6e, /* .##.###. */
+ /*04a7:*/ 0x36, /* ..##.##. */
+/* --- new character e (101) starting at offset 0x04a8 --- */
+ /*04a8:*/ 8, 6, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*04ad:*/ 0x78, /* .####... */
+ /*04ae:*/ 0xcc, /* ##..##.. */
+ /*04af:*/ 0xcc, /* ##..##.. */
+ /*04b0:*/ 0xfc, /* ######.. */
+ /*04b1:*/ 0xc0, /* ##...... */
+ /*04b2:*/ 0xc0, /* ##...... */
+ /*04b3:*/ 0xec, /* ###.##.. */
+ /*04b4:*/ 0x78, /* .####... */
+/* --- new character f (102) starting at offset 0x04b5 --- */
+ /*04b5:*/ 4, 5, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*04ba:*/ 0x38, /* ..###... */
+ /*04bb:*/ 0x60, /* .##..... */
+ /*04bc:*/ 0x60, /* .##..... */
+ /*04bd:*/ 0xf0, /* ####.... */
+ /*04be:*/ 0x60, /* .##..... */
+ /*04bf:*/ 0x60, /* .##..... */
+ /*04c0:*/ 0x60, /* .##..... */
+ /*04c1:*/ 0x60, /* .##..... */
+ /*04c2:*/ 0x60, /* .##..... */
+ /*04c3:*/ 0x60, /* .##..... */
+ /*04c4:*/ 0x60, /* .##..... */
+/* --- new character g (103) starting at offset 0x04c5 --- */
+ /*04c5:*/ 9, 7, 11, 1, -3, /* width and bbox (w,h,x,y) */
+ /*04ca:*/ 0x3a, /* ..###.#. */
+ /*04cb:*/ 0x6e, /* .##.###. */
+ /*04cc:*/ 0xc6, /* ##...##. */
+ /*04cd:*/ 0xc6, /* ##...##. */
+ /*04ce:*/ 0xc6, /* ##...##. */
+ /*04cf:*/ 0xc6, /* ##...##. */
+ /*04d0:*/ 0x6e, /* .##.###. */
+ /*04d1:*/ 0x3e, /* ..#####. */
+ /*04d2:*/ 0x06, /* .....##. */
+ /*04d3:*/ 0xce, /* ##..###. */
+ /*04d4:*/ 0x7c, /* .#####.. */
+/* --- new character h (104) starting at offset 0x04d5 --- */
+ /*04d5:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*04da:*/ 0xc0, /* ##...... */
+ /*04db:*/ 0xc0, /* ##...... */
+ /*04dc:*/ 0xc0, /* ##...... */
+ /*04dd:*/ 0xdc, /* ##.###.. */
+ /*04de:*/ 0xee, /* ###.###. */
+ /*04df:*/ 0xc6, /* ##...##. */
+ /*04e0:*/ 0xc6, /* ##...##. */
+ /*04e1:*/ 0xc6, /* ##...##. */
+ /*04e2:*/ 0xc6, /* ##...##. */
+ /*04e3:*/ 0xc6, /* ##...##. */
+ /*04e4:*/ 0xc6, /* ##...##. */
+/* --- new character i (105) starting at offset 0x04e5 --- */
+ /*04e5:*/ 4, 2, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*04ea:*/ 0xc0, /* ##...... */
+ /*04eb:*/ 0xc0, /* ##...... */
+ /*04ec:*/ 0x00, /* ........ */
+ /*04ed:*/ 0xc0, /* ##...... */
+ /*04ee:*/ 0xc0, /* ##...... */
+ /*04ef:*/ 0xc0, /* ##...... */
+ /*04f0:*/ 0xc0, /* ##...... */
+ /*04f1:*/ 0xc0, /* ##...... */
+ /*04f2:*/ 0xc0, /* ##...... */
+ /*04f3:*/ 0xc0, /* ##...... */
+ /*04f4:*/ 0xc0, /* ##...... */
+/* --- new character j (106) starting at offset 0x04f5 --- */
+ /*04f5:*/ 4, 3, 14, 0, -3, /* width and bbox (w,h,x,y) */
+ /*04fa:*/ 0x60, /* .##..... */
+ /*04fb:*/ 0x60, /* .##..... */
+ /*04fc:*/ 0x00, /* ........ */
+ /*04fd:*/ 0x60, /* .##..... */
+ /*04fe:*/ 0x60, /* .##..... */
+ /*04ff:*/ 0x60, /* .##..... */
+ /*0500:*/ 0x60, /* .##..... */
+ /*0501:*/ 0x60, /* .##..... */
+ /*0502:*/ 0x60, /* .##..... */
+ /*0503:*/ 0x60, /* .##..... */
+ /*0504:*/ 0x60, /* .##..... */
+ /*0505:*/ 0x60, /* .##..... */
+ /*0506:*/ 0xe0, /* ###..... */
+ /*0507:*/ 0xc0, /* ##...... */
+/* --- new character k (107) starting at offset 0x0508 --- */
+ /*0508:*/ 8, 6, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*050d:*/ 0xc0, /* ##...... */
+ /*050e:*/ 0xc0, /* ##...... */
+ /*050f:*/ 0xc0, /* ##...... */
+ /*0510:*/ 0xcc, /* ##..##.. */
+ /*0511:*/ 0xd8, /* ##.##... */
+ /*0512:*/ 0xf0, /* ####.... */
+ /*0513:*/ 0xf0, /* ####.... */
+ /*0514:*/ 0xd8, /* ##.##... */
+ /*0515:*/ 0xd8, /* ##.##... */
+ /*0516:*/ 0xcc, /* ##..##.. */
+ /*0517:*/ 0xcc, /* ##..##.. */
+/* --- new character l (108) starting at offset 0x0518 --- */
+ /*0518:*/ 4, 2, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*051d:*/ 0xc0, /* ##...... */
+ /*051e:*/ 0xc0, /* ##...... */
+ /*051f:*/ 0xc0, /* ##...... */
+ /*0520:*/ 0xc0, /* ##...... */
+ /*0521:*/ 0xc0, /* ##...... */
+ /*0522:*/ 0xc0, /* ##...... */
+ /*0523:*/ 0xc0, /* ##...... */
+ /*0524:*/ 0xc0, /* ##...... */
+ /*0525:*/ 0xc0, /* ##...... */
+ /*0526:*/ 0xc0, /* ##...... */
+ /*0527:*/ 0xc0, /* ##...... */
+/* --- new character m (109) starting at offset 0x0528 --- */
+ /*0528:*/ 12, 10, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*052d:*/ 0xdb,0x80, /* ##.##.###....... */
+ /*052f:*/ 0xee,0xc0, /* ###.###.##...... */
+ /*0531:*/ 0xcc,0xc0, /* ##..##..##...... */
+ /*0533:*/ 0xcc,0xc0, /* ##..##..##...... */
+ /*0535:*/ 0xcc,0xc0, /* ##..##..##...... */
+ /*0537:*/ 0xcc,0xc0, /* ##..##..##...... */
+ /*0539:*/ 0xcc,0xc0, /* ##..##..##...... */
+ /*053b:*/ 0xcc,0xc0, /* ##..##..##...... */
+/* --- new character n (110) starting at offset 0x053d --- */
+ /*053d:*/ 9, 7, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0542:*/ 0xdc, /* ##.###.. */
+ /*0543:*/ 0xee, /* ###.###. */
+ /*0544:*/ 0xc6, /* ##...##. */
+ /*0545:*/ 0xc6, /* ##...##. */
+ /*0546:*/ 0xc6, /* ##...##. */
+ /*0547:*/ 0xc6, /* ##...##. */
+ /*0548:*/ 0xc6, /* ##...##. */
+ /*0549:*/ 0xc6, /* ##...##. */
+/* --- new character o (111) starting at offset 0x054a --- */
+ /*054a:*/ 9, 7, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*054f:*/ 0x38, /* ..###... */
+ /*0550:*/ 0x6c, /* .##.##.. */
+ /*0551:*/ 0xc6, /* ##...##. */
+ /*0552:*/ 0xc6, /* ##...##. */
+ /*0553:*/ 0xc6, /* ##...##. */
+ /*0554:*/ 0xc6, /* ##...##. */
+ /*0555:*/ 0x6c, /* .##.##.. */
+ /*0556:*/ 0x38, /* ..###... */
+/* --- new character p (112) starting at offset 0x0557 --- */
+ /*0557:*/ 9, 7, 11, 1, -3, /* width and bbox (w,h,x,y) */
+ /*055c:*/ 0xd8, /* ##.##... */
+ /*055d:*/ 0xec, /* ###.##.. */
+ /*055e:*/ 0xc6, /* ##...##. */
+ /*055f:*/ 0xc6, /* ##...##. */
+ /*0560:*/ 0xc6, /* ##...##. */
+ /*0561:*/ 0xc6, /* ##...##. */
+ /*0562:*/ 0xec, /* ###.##.. */
+ /*0563:*/ 0xf8, /* #####... */
+ /*0564:*/ 0xc0, /* ##...... */
+ /*0565:*/ 0xc0, /* ##...... */
+ /*0566:*/ 0xc0, /* ##...... */
+/* --- new character q (113) starting at offset 0x0567 --- */
+ /*0567:*/ 9, 7, 11, 1, -3, /* width and bbox (w,h,x,y) */
+ /*056c:*/ 0x36, /* ..##.##. */
+ /*056d:*/ 0x6e, /* .##.###. */
+ /*056e:*/ 0xc6, /* ##...##. */
+ /*056f:*/ 0xc6, /* ##...##. */
+ /*0570:*/ 0xc6, /* ##...##. */
+ /*0571:*/ 0xc6, /* ##...##. */
+ /*0572:*/ 0x6e, /* .##.###. */
+ /*0573:*/ 0x3e, /* ..#####. */
+ /*0574:*/ 0x06, /* .....##. */
+ /*0575:*/ 0x06, /* .....##. */
+ /*0576:*/ 0x06, /* .....##. */
+/* --- new character r (114) starting at offset 0x0577 --- */
+ /*0577:*/ 6, 5, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*057c:*/ 0xd8, /* ##.##... */
+ /*057d:*/ 0xf8, /* #####... */
+ /*057e:*/ 0xc0, /* ##...... */
+ /*057f:*/ 0xc0, /* ##...... */
+ /*0580:*/ 0xc0, /* ##...... */
+ /*0581:*/ 0xc0, /* ##...... */
+ /*0582:*/ 0xc0, /* ##...... */
+ /*0583:*/ 0xc0, /* ##...... */
+/* --- new character s (115) starting at offset 0x0584 --- */
+ /*0584:*/ 8, 6, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0589:*/ 0x78, /* .####... */
+ /*058a:*/ 0xec, /* ###.##.. */
+ /*058b:*/ 0xc0, /* ##...... */
+ /*058c:*/ 0x78, /* .####... */
+ /*058d:*/ 0x1c, /* ...###.. */
+ /*058e:*/ 0x0c, /* ....##.. */
+ /*058f:*/ 0xec, /* ###.##.. */
+ /*0590:*/ 0x78, /* .####... */
+/* --- new character t (116) starting at offset 0x0591 --- */
+ /*0591:*/ 5, 5, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0596:*/ 0x60, /* .##..... */
+ /*0597:*/ 0x60, /* .##..... */
+ /*0598:*/ 0xf8, /* #####... */
+ /*0599:*/ 0x60, /* .##..... */
+ /*059a:*/ 0x60, /* .##..... */
+ /*059b:*/ 0x60, /* .##..... */
+ /*059c:*/ 0x60, /* .##..... */
+ /*059d:*/ 0x60, /* .##..... */
+ /*059e:*/ 0x68, /* .##.#... */
+ /*059f:*/ 0x30, /* ..##.... */
+/* --- new character u (117) starting at offset 0x05a0 --- */
+ /*05a0:*/ 9, 7, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*05a5:*/ 0xc6, /* ##...##. */
+ /*05a6:*/ 0xc6, /* ##...##. */
+ /*05a7:*/ 0xc6, /* ##...##. */
+ /*05a8:*/ 0xc6, /* ##...##. */
+ /*05a9:*/ 0xc6, /* ##...##. */
+ /*05aa:*/ 0xc6, /* ##...##. */
+ /*05ab:*/ 0xee, /* ###.###. */
+ /*05ac:*/ 0x76, /* .###.##. */
+/* --- new character v (118) starting at offset 0x05ad --- */
+ /*05ad:*/ 8, 8, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*05b2:*/ 0xc3, /* ##....## */
+ /*05b3:*/ 0xc3, /* ##....## */
+ /*05b4:*/ 0x66, /* .##..##. */
+ /*05b5:*/ 0x66, /* .##..##. */
+ /*05b6:*/ 0x24, /* ..#..#.. */
+ /*05b7:*/ 0x3c, /* ..####.. */
+ /*05b8:*/ 0x18, /* ...##... */
+ /*05b9:*/ 0x18, /* ...##... */
+/* --- new character w (119) starting at offset 0x05ba --- */
+ /*05ba:*/ 10, 10, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*05bf:*/ 0xcc,0xc0, /* ##..##..##...... */
+ /*05c1:*/ 0xcc,0xc0, /* ##..##..##...... */
+ /*05c3:*/ 0xcc,0xc0, /* ##..##..##...... */
+ /*05c5:*/ 0x6d,0x80, /* .##.##.##....... */
+ /*05c7:*/ 0x6d,0x80, /* .##.##.##....... */
+ /*05c9:*/ 0x33,0x00, /* ..##..##........ */
+ /*05cb:*/ 0x33,0x00, /* ..##..##........ */
+ /*05cd:*/ 0x33,0x00, /* ..##..##........ */
+/* --- new character x (120) starting at offset 0x05cf --- */
+ /*05cf:*/ 7, 7, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*05d4:*/ 0xc6, /* ##...##. */
+ /*05d5:*/ 0xc6, /* ##...##. */
+ /*05d6:*/ 0x6c, /* .##.##.. */
+ /*05d7:*/ 0x38, /* ..###... */
+ /*05d8:*/ 0x38, /* ..###... */
+ /*05d9:*/ 0x6c, /* .##.##.. */
+ /*05da:*/ 0xc6, /* ##...##. */
+ /*05db:*/ 0xc6, /* ##...##. */
+/* --- new character y (121) starting at offset 0x05dc --- */
+ /*05dc:*/ 8, 8, 11, 0, -3, /* width and bbox (w,h,x,y) */
+ /*05e1:*/ 0xc3, /* ##....## */
+ /*05e2:*/ 0xc3, /* ##....## */
+ /*05e3:*/ 0x66, /* .##..##. */
+ /*05e4:*/ 0x66, /* .##..##. */
+ /*05e5:*/ 0x24, /* ..#..#.. */
+ /*05e6:*/ 0x3c, /* ..####.. */
+ /*05e7:*/ 0x18, /* ...##... */
+ /*05e8:*/ 0x18, /* ...##... */
+ /*05e9:*/ 0x18, /* ...##... */
+ /*05ea:*/ 0x30, /* ..##.... */
+ /*05eb:*/ 0x70, /* .###.... */
+/* --- new character z (122) starting at offset 0x05ec --- */
+ /*05ec:*/ 6, 6, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*05f1:*/ 0xfc, /* ######.. */
+ /*05f2:*/ 0x0c, /* ....##.. */
+ /*05f3:*/ 0x18, /* ...##... */
+ /*05f4:*/ 0x30, /* ..##.... */
+ /*05f5:*/ 0x30, /* ..##.... */
+ /*05f6:*/ 0x60, /* .##..... */
+ /*05f7:*/ 0xc0, /* ##...... */
+ /*05f8:*/ 0xfc, /* ######.. */
+/* --- new character braceleft (123) starting at offset 0x05f9 --- */
+ /*05f9:*/ 6, 5, 14, 0, -3, /* width and bbox (w,h,x,y) */
+ /*05fe:*/ 0x18, /* ...##... */
+ /*05ff:*/ 0x30, /* ..##.... */
+ /*0600:*/ 0x30, /* ..##.... */
+ /*0601:*/ 0x30, /* ..##.... */
+ /*0602:*/ 0x30, /* ..##.... */
+ /*0603:*/ 0x60, /* .##..... */
+ /*0604:*/ 0xc0, /* ##...... */
+ /*0605:*/ 0x60, /* .##..... */
+ /*0606:*/ 0x30, /* ..##.... */
+ /*0607:*/ 0x30, /* ..##.... */
+ /*0608:*/ 0x30, /* ..##.... */
+ /*0609:*/ 0x30, /* ..##.... */
+ /*060a:*/ 0x30, /* ..##.... */
+ /*060b:*/ 0x18, /* ...##... */
+/* --- new character bar (124) starting at offset 0x060c --- */
+ /*060c:*/ 4, 2, 14, 1, -3, /* width and bbox (w,h,x,y) */
+ /*0611:*/ 0xc0, /* ##...... */
+ /*0612:*/ 0xc0, /* ##...... */
+ /*0613:*/ 0xc0, /* ##...... */
+ /*0614:*/ 0xc0, /* ##...... */
+ /*0615:*/ 0xc0, /* ##...... */
+ /*0616:*/ 0xc0, /* ##...... */
+ /*0617:*/ 0xc0, /* ##...... */
+ /*0618:*/ 0xc0, /* ##...... */
+ /*0619:*/ 0xc0, /* ##...... */
+ /*061a:*/ 0xc0, /* ##...... */
+ /*061b:*/ 0xc0, /* ##...... */
+ /*061c:*/ 0xc0, /* ##...... */
+ /*061d:*/ 0xc0, /* ##...... */
+ /*061e:*/ 0xc0, /* ##...... */
+/* --- new character braceright (125) starting at offset 0x061f --- */
+ /*061f:*/ 6, 5, 14, 1, -3, /* width and bbox (w,h,x,y) */
+ /*0624:*/ 0xc0, /* ##...... */
+ /*0625:*/ 0x60, /* .##..... */
+ /*0626:*/ 0x60, /* .##..... */
+ /*0627:*/ 0x60, /* .##..... */
+ /*0628:*/ 0x60, /* .##..... */
+ /*0629:*/ 0x30, /* ..##.... */
+ /*062a:*/ 0x18, /* ...##... */
+ /*062b:*/ 0x30, /* ..##.... */
+ /*062c:*/ 0x60, /* .##..... */
+ /*062d:*/ 0x60, /* .##..... */
+ /*062e:*/ 0x60, /* .##..... */
+ /*062f:*/ 0x60, /* .##..... */
+ /*0630:*/ 0x60, /* .##..... */
+ /*0631:*/ 0xc0, /* ##...... */
+/* --- new character asciitilde (126) starting at offset 0x0632 --- */
+ /*0632:*/ 9, 7, 3, 1, 3, /* width and bbox (w,h,x,y) */
+ /*0637:*/ 0x72, /* .###..#. */
+ /*0638:*/ 0xde, /* ##.####. */
+ /*0639:*/ 0x8c, /* #...##.. */
+};
+static const uint16_t font_helvB14_offsets[] = {
+0x0000 /* space */,
+ 0x0006 /* exclam */,
+ 0x0016 /* quotedbl */,
+ 0x001e /* numbersign */,
+ 0x0037 /* dollar */,
+ 0x0049 /* percent */,
+ 0x0062 /* ampersand */,
+ 0x007b /* quotesingle */,
+ 0x0083 /* parenleft */,
+ 0x0096 /* parenright */,
+ 0x00a9 /* asterisk */,
+ 0x00b2 /* plus */,
+ 0x00be /* comma */,
+ 0x00c6 /* hyphen */,
+ 0x00cc /* period */,
+ 0x00d3 /* slash */,
+ 0x00e3 /* zero */,
+ 0x00f2 /* one */,
+ 0x0101 /* two */,
+ 0x0110 /* three */,
+ 0x011f /* four */,
+ 0x012e /* five */,
+ 0x013d /* six */,
+ 0x014c /* seven */,
+ 0x015b /* eight */,
+ 0x016a /* nine */,
+ 0x0179 /* colon */,
+ 0x0186 /* semicolon */,
+ 0x0194 /* less */,
+ 0x019e /* equal */,
+ 0x01a6 /* greater */,
+ 0x01b0 /* question */,
+ 0x01c0 /* at */,
+ 0x01dd /* A */,
+ 0x01f8 /* B */,
+ 0x0208 /* C */,
+ 0x0223 /* D */,
+ 0x023e /* E */,
+ 0x024e /* F */,
+ 0x025e /* G */,
+ 0x0279 /* H */,
+ 0x0289 /* I */,
+ 0x0299 /* J */,
+ 0x02a9 /* K */,
+ 0x02c4 /* L */,
+ 0x02d4 /* M */,
+ 0x02ef /* N */,
+ 0x030a /* O */,
+ 0x0325 /* P */,
+ 0x0335 /* Q */,
+ 0x0350 /* R */,
+ 0x036b /* S */,
+ 0x037b /* T */,
+ 0x038b /* U */,
+ 0x03a6 /* V */,
+ 0x03c1 /* W */,
+ 0x03dc /* X */,
+ 0x03f7 /* Y */,
+ 0x0412 /* Z */,
+ 0x0422 /* bracketleft */,
+ 0x0435 /* backslash */,
+ 0x0445 /* bracketright */,
+ 0x0458 /* asciicircum */,
+ 0x0461 /* underscore */,
+ 0x0467 /* grave */,
+ 0x046e /* a */,
+ 0x047b /* b */,
+ 0x048b /* c */,
+ 0x0498 /* d */,
+ 0x04a8 /* e */,
+ 0x04b5 /* f */,
+ 0x04c5 /* g */,
+ 0x04d5 /* h */,
+ 0x04e5 /* i */,
+ 0x04f5 /* j */,
+ 0x0508 /* k */,
+ 0x0518 /* l */,
+ 0x0528 /* m */,
+ 0x053d /* n */,
+ 0x054a /* o */,
+ 0x0557 /* p */,
+ 0x0567 /* q */,
+ 0x0577 /* r */,
+ 0x0584 /* s */,
+ 0x0591 /* t */,
+ 0x05a0 /* u */,
+ 0x05ad /* v */,
+ 0x05ba /* w */,
+ 0x05cf /* x */,
+ 0x05dc /* y */,
+ 0x05ec /* z */,
+ 0x05f9 /* braceleft */,
+ 0x060c /* bar */,
+ 0x061f /* braceright */,
+ 0x0632 /* asciitilde */,
+ 0xffff /* (no glyph) */
+};
+const struct fb_font font_helvB14 = {
+ .height = 16,
+ .ascent = 13,
+ .firstchar = 32, /* space */
+ .lastchar = 127, /* ? */
+ .chardata = font_helvB14_data,
+ .charoffs = font_helvB14_offsets,
+};
diff --git a/Src/osmolib/src/target/firmware/fb/helvB24.c b/Src/osmolib/src/target/firmware/fb/helvB24.c
new file mode 100644
index 0000000..509b9db
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/helvB24.c
@@ -0,0 +1,1871 @@
+#include <fb/font.h>
+static const uint8_t font_helvB24_data[] = {
+/* --- new character space (32) starting at offset 0x0000 --- */
+ /*0000:*/ 6, 1, 1, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0005:*/ 0x00, /* ........ */
+/* --- new character exclam (33) starting at offset 0x0006 --- */
+ /*0006:*/ 7, 3, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*000b:*/ 0xe0, /* ###..... */
+ /*000c:*/ 0xe0, /* ###..... */
+ /*000d:*/ 0xe0, /* ###..... */
+ /*000e:*/ 0xe0, /* ###..... */
+ /*000f:*/ 0xe0, /* ###..... */
+ /*0010:*/ 0xe0, /* ###..... */
+ /*0011:*/ 0xe0, /* ###..... */
+ /*0012:*/ 0xe0, /* ###..... */
+ /*0013:*/ 0xe0, /* ###..... */
+ /*0014:*/ 0xe0, /* ###..... */
+ /*0015:*/ 0xe0, /* ###..... */
+ /*0016:*/ 0xe0, /* ###..... */
+ /*0017:*/ 0xe0, /* ###..... */
+ /*0018:*/ 0xe0, /* ###..... */
+ /*0019:*/ 0x00, /* ........ */
+ /*001a:*/ 0x00, /* ........ */
+ /*001b:*/ 0xe0, /* ###..... */
+ /*001c:*/ 0xe0, /* ###..... */
+ /*001d:*/ 0xe0, /* ###..... */
+/* --- new character quotedbl (34) starting at offset 0x001e --- */
+ /*001e:*/ 9, 5, 6, 2, 13, /* width and bbox (w,h,x,y) */
+ /*0023:*/ 0xd8, /* ##.##... */
+ /*0024:*/ 0xd8, /* ##.##... */
+ /*0025:*/ 0xd8, /* ##.##... */
+ /*0026:*/ 0xd8, /* ##.##... */
+ /*0027:*/ 0xd8, /* ##.##... */
+ /*0028:*/ 0x90, /* #..#.... */
+/* --- new character numbersign (35) starting at offset 0x0029 --- */
+ /*0029:*/ 14, 12, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*002e:*/ 0x0c,0xc0, /* ....##..##...... */
+ /*0030:*/ 0x0c,0xc0, /* ....##..##...... */
+ /*0032:*/ 0x0c,0xc0, /* ....##..##...... */
+ /*0034:*/ 0x0c,0xc0, /* ....##..##...... */
+ /*0036:*/ 0x0c,0xc0, /* ....##..##...... */
+ /*0038:*/ 0x7f,0xf0, /* .###########.... */
+ /*003a:*/ 0x7f,0xf0, /* .###########.... */
+ /*003c:*/ 0x19,0x80, /* ...##..##....... */
+ /*003e:*/ 0x19,0x80, /* ...##..##....... */
+ /*0040:*/ 0x19,0x80, /* ...##..##....... */
+ /*0042:*/ 0x19,0x80, /* ...##..##....... */
+ /*0044:*/ 0xff,0xe0, /* ###########..... */
+ /*0046:*/ 0xff,0xe0, /* ###########..... */
+ /*0048:*/ 0x33,0x00, /* ..##..##........ */
+ /*004a:*/ 0x33,0x00, /* ..##..##........ */
+ /*004c:*/ 0x33,0x00, /* ..##..##........ */
+ /*004e:*/ 0x33,0x00, /* ..##..##........ */
+ /*0050:*/ 0x33,0x00, /* ..##..##........ */
+/* --- new character dollar (36) starting at offset 0x0052 --- */
+ /*0052:*/ 13, 12, 21, 0, -2, /* width and bbox (w,h,x,y) */
+ /*0057:*/ 0x06,0x00, /* .....##......... */
+ /*0059:*/ 0x3f,0x80, /* ..#######....... */
+ /*005b:*/ 0x7f,0xc0, /* .#########...... */
+ /*005d:*/ 0xf6,0xe0, /* ####.##.###..... */
+ /*005f:*/ 0xe6,0xe0, /* ###..##.###..... */
+ /*0061:*/ 0xe6,0xe0, /* ###..##.###..... */
+ /*0063:*/ 0xf6,0x00, /* ####.##......... */
+ /*0065:*/ 0x7e,0x00, /* .######......... */
+ /*0067:*/ 0x3e,0x00, /* ..#####......... */
+ /*0069:*/ 0x0f,0x00, /* ....####........ */
+ /*006b:*/ 0x07,0xc0, /* .....#####...... */
+ /*006d:*/ 0x07,0xe0, /* .....######..... */
+ /*006f:*/ 0x06,0xf0, /* .....##.####.... */
+ /*0071:*/ 0xe6,0x70, /* ###..##..###.... */
+ /*0073:*/ 0xe6,0x70, /* ###..##..###.... */
+ /*0075:*/ 0xe6,0x70, /* ###..##..###.... */
+ /*0077:*/ 0xf6,0xf0, /* ####.##.####.... */
+ /*0079:*/ 0x7f,0xe0, /* .##########..... */
+ /*007b:*/ 0x1f,0xc0, /* ...#######...... */
+ /*007d:*/ 0x06,0x00, /* .....##......... */
+ /*007f:*/ 0x06,0x00, /* .....##......... */
+/* --- new character percent (37) starting at offset 0x0081 --- */
+ /*0081:*/ 22, 21, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0086:*/ 0x00,0x07,0x00, /* .............###........ */
+ /*0089:*/ 0x3e,0x07,0x00, /* ..#####......###........ */
+ /*008c:*/ 0x7f,0x0e,0x00, /* .#######....###......... */
+ /*008f:*/ 0xe3,0x8e,0x00, /* ###...###...###......... */
+ /*0092:*/ 0xc1,0x9c,0x00, /* ##.....##..###.......... */
+ /*0095:*/ 0xc1,0x9c,0x00, /* ##.....##..###.......... */
+ /*0098:*/ 0xe3,0xb8,0x00, /* ###...###.###........... */
+ /*009b:*/ 0x7f,0x38,0x00, /* .#######..###........... */
+ /*009e:*/ 0x3e,0x70,0x00, /* ..#####..###............ */
+ /*00a1:*/ 0x00,0x70,0x00, /* .........###............ */
+ /*00a4:*/ 0x00,0xe3,0xe0, /* ........###...#####..... */
+ /*00a7:*/ 0x00,0xe7,0xf0, /* ........###..#######.... */
+ /*00aa:*/ 0x01,0xce,0x38, /* .......###..###...###... */
+ /*00ad:*/ 0x01,0xcc,0x18, /* .......###..##.....##... */
+ /*00b0:*/ 0x03,0x8c,0x18, /* ......###...##.....##... */
+ /*00b3:*/ 0x03,0x8e,0x38, /* ......###...###...###... */
+ /*00b6:*/ 0x07,0x07,0xf0, /* .....###.....#######.... */
+ /*00b9:*/ 0x07,0x03,0xe0, /* .....###......#####..... */
+/* --- new character ampersand (38) starting at offset 0x00bc --- */
+ /*00bc:*/ 18, 16, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00c1:*/ 0x0f,0x80, /* ....#####....... */
+ /*00c3:*/ 0x1f,0xc0, /* ...#######...... */
+ /*00c5:*/ 0x3d,0xe0, /* ..####.####..... */
+ /*00c7:*/ 0x38,0xe0, /* ..###...###..... */
+ /*00c9:*/ 0x38,0xe0, /* ..###...###..... */
+ /*00cb:*/ 0x38,0xe0, /* ..###...###..... */
+ /*00cd:*/ 0x1d,0xc0, /* ...###.###...... */
+ /*00cf:*/ 0x0f,0x80, /* ....#####....... */
+ /*00d1:*/ 0x1f,0x00, /* ...#####........ */
+ /*00d3:*/ 0x3f,0x9c, /* ..#######..###.. */
+ /*00d5:*/ 0x7b,0xdc, /* .####.####.###.. */
+ /*00d7:*/ 0x71,0xfc, /* .###...#######.. */
+ /*00d9:*/ 0xe0,0xf8, /* ###.....#####... */
+ /*00db:*/ 0xe0,0x70, /* ###......###.... */
+ /*00dd:*/ 0xe0,0xf8, /* ###.....#####... */
+ /*00df:*/ 0xf1,0xfc, /* ####...#######.. */
+ /*00e1:*/ 0x7f,0xce, /* .#########..###. */
+ /*00e3:*/ 0x1f,0x87, /* ...######....### */
+/* --- new character quotesingle (39) starting at offset 0x00e5 --- */
+ /*00e5:*/ 6, 2, 6, 2, 13, /* width and bbox (w,h,x,y) */
+ /*00ea:*/ 0xc0, /* ##...... */
+ /*00eb:*/ 0xc0, /* ##...... */
+ /*00ec:*/ 0xc0, /* ##...... */
+ /*00ed:*/ 0xc0, /* ##...... */
+ /*00ee:*/ 0xc0, /* ##...... */
+ /*00ef:*/ 0x80, /* #....... */
+/* --- new character parenleft (40) starting at offset 0x00f0 --- */
+ /*00f0:*/ 8, 6, 24, 1, -5, /* width and bbox (w,h,x,y) */
+ /*00f5:*/ 0x0c, /* ....##.. */
+ /*00f6:*/ 0x1c, /* ...###.. */
+ /*00f7:*/ 0x38, /* ..###... */
+ /*00f8:*/ 0x38, /* ..###... */
+ /*00f9:*/ 0x70, /* .###.... */
+ /*00fa:*/ 0x70, /* .###.... */
+ /*00fb:*/ 0x60, /* .##..... */
+ /*00fc:*/ 0xe0, /* ###..... */
+ /*00fd:*/ 0xe0, /* ###..... */
+ /*00fe:*/ 0xe0, /* ###..... */
+ /*00ff:*/ 0xe0, /* ###..... */
+ /*0100:*/ 0xe0, /* ###..... */
+ /*0101:*/ 0xe0, /* ###..... */
+ /*0102:*/ 0xe0, /* ###..... */
+ /*0103:*/ 0xe0, /* ###..... */
+ /*0104:*/ 0xe0, /* ###..... */
+ /*0105:*/ 0xe0, /* ###..... */
+ /*0106:*/ 0x60, /* .##..... */
+ /*0107:*/ 0x70, /* .###.... */
+ /*0108:*/ 0x70, /* .###.... */
+ /*0109:*/ 0x38, /* ..###... */
+ /*010a:*/ 0x38, /* ..###... */
+ /*010b:*/ 0x1c, /* ...###.. */
+ /*010c:*/ 0x0c, /* ....##.. */
+/* --- new character parenright (41) starting at offset 0x010d --- */
+ /*010d:*/ 8, 6, 24, 1, -5, /* width and bbox (w,h,x,y) */
+ /*0112:*/ 0xc0, /* ##...... */
+ /*0113:*/ 0xe0, /* ###..... */
+ /*0114:*/ 0x70, /* .###.... */
+ /*0115:*/ 0x70, /* .###.... */
+ /*0116:*/ 0x38, /* ..###... */
+ /*0117:*/ 0x38, /* ..###... */
+ /*0118:*/ 0x18, /* ...##... */
+ /*0119:*/ 0x1c, /* ...###.. */
+ /*011a:*/ 0x1c, /* ...###.. */
+ /*011b:*/ 0x1c, /* ...###.. */
+ /*011c:*/ 0x1c, /* ...###.. */
+ /*011d:*/ 0x1c, /* ...###.. */
+ /*011e:*/ 0x1c, /* ...###.. */
+ /*011f:*/ 0x1c, /* ...###.. */
+ /*0120:*/ 0x1c, /* ...###.. */
+ /*0121:*/ 0x1c, /* ...###.. */
+ /*0122:*/ 0x1c, /* ...###.. */
+ /*0123:*/ 0x18, /* ...##... */
+ /*0124:*/ 0x38, /* ..###... */
+ /*0125:*/ 0x38, /* ..###... */
+ /*0126:*/ 0x70, /* .###.... */
+ /*0127:*/ 0x70, /* .###.... */
+ /*0128:*/ 0xe0, /* ###..... */
+ /*0129:*/ 0xc0, /* ##...... */
+/* --- new character asterisk (42) starting at offset 0x012a --- */
+ /*012a:*/ 10, 8, 7, 1, 12, /* width and bbox (w,h,x,y) */
+ /*012f:*/ 0x18, /* ...##... */
+ /*0130:*/ 0x18, /* ...##... */
+ /*0131:*/ 0xdb, /* ##.##.## */
+ /*0132:*/ 0xff, /* ######## */
+ /*0133:*/ 0x3c, /* ..####.. */
+ /*0134:*/ 0x66, /* .##..##. */
+ /*0135:*/ 0x66, /* .##..##. */
+/* --- new character plus (43) starting at offset 0x0136 --- */
+ /*0136:*/ 15, 11, 12, 2, 1, /* width and bbox (w,h,x,y) */
+ /*013b:*/ 0x0e,0x00, /* ....###......... */
+ /*013d:*/ 0x0e,0x00, /* ....###......... */
+ /*013f:*/ 0x0e,0x00, /* ....###......... */
+ /*0141:*/ 0x0e,0x00, /* ....###......... */
+ /*0143:*/ 0x0e,0x00, /* ....###......... */
+ /*0145:*/ 0xff,0xe0, /* ###########..... */
+ /*0147:*/ 0xff,0xe0, /* ###########..... */
+ /*0149:*/ 0x0e,0x00, /* ....###......... */
+ /*014b:*/ 0x0e,0x00, /* ....###......... */
+ /*014d:*/ 0x0e,0x00, /* ....###......... */
+ /*014f:*/ 0x0e,0x00, /* ....###......... */
+ /*0151:*/ 0x0e,0x00, /* ....###......... */
+/* --- new character comma (44) starting at offset 0x0153 --- */
+ /*0153:*/ 7, 3, 6, 2, -3, /* width and bbox (w,h,x,y) */
+ /*0158:*/ 0xe0, /* ###..... */
+ /*0159:*/ 0xe0, /* ###..... */
+ /*015a:*/ 0xe0, /* ###..... */
+ /*015b:*/ 0x60, /* .##..... */
+ /*015c:*/ 0x60, /* .##..... */
+ /*015d:*/ 0xc0, /* ##...... */
+/* --- new character hyphen (45) starting at offset 0x015e --- */
+ /*015e:*/ 8, 7, 3, 0, 6, /* width and bbox (w,h,x,y) */
+ /*0163:*/ 0xfe, /* #######. */
+ /*0164:*/ 0xfe, /* #######. */
+ /*0165:*/ 0xfe, /* #######. */
+/* --- new character period (46) starting at offset 0x0166 --- */
+ /*0166:*/ 7, 3, 3, 2, 0, /* width and bbox (w,h,x,y) */
+ /*016b:*/ 0xe0, /* ###..... */
+ /*016c:*/ 0xe0, /* ###..... */
+ /*016d:*/ 0xe0, /* ###..... */
+/* --- new character slash (47) starting at offset 0x016e --- */
+ /*016e:*/ 8, 8, 19, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0173:*/ 0x07, /* .....### */
+ /*0174:*/ 0x07, /* .....### */
+ /*0175:*/ 0x06, /* .....##. */
+ /*0176:*/ 0x06, /* .....##. */
+ /*0177:*/ 0x0e, /* ....###. */
+ /*0178:*/ 0x0c, /* ....##.. */
+ /*0179:*/ 0x0c, /* ....##.. */
+ /*017a:*/ 0x1c, /* ...###.. */
+ /*017b:*/ 0x1c, /* ...###.. */
+ /*017c:*/ 0x18, /* ...##... */
+ /*017d:*/ 0x18, /* ...##... */
+ /*017e:*/ 0x38, /* ..###... */
+ /*017f:*/ 0x30, /* ..##.... */
+ /*0180:*/ 0x30, /* ..##.... */
+ /*0181:*/ 0x70, /* .###.... */
+ /*0182:*/ 0x60, /* .##..... */
+ /*0183:*/ 0x60, /* .##..... */
+ /*0184:*/ 0xe0, /* ###..... */
+ /*0185:*/ 0xe0, /* ###..... */
+/* --- new character zero (48) starting at offset 0x0186 --- */
+ /*0186:*/ 13, 12, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*018b:*/ 0x1f,0x80, /* ...######....... */
+ /*018d:*/ 0x3f,0xc0, /* ..########...... */
+ /*018f:*/ 0x79,0xe0, /* .####..####..... */
+ /*0191:*/ 0x70,0xe0, /* .###....###..... */
+ /*0193:*/ 0x70,0xe0, /* .###....###..... */
+ /*0195:*/ 0xe0,0x70, /* ###......###.... */
+ /*0197:*/ 0xe0,0x70, /* ###......###.... */
+ /*0199:*/ 0xe0,0x70, /* ###......###.... */
+ /*019b:*/ 0xe0,0x70, /* ###......###.... */
+ /*019d:*/ 0xe0,0x70, /* ###......###.... */
+ /*019f:*/ 0xe0,0x70, /* ###......###.... */
+ /*01a1:*/ 0xe0,0x70, /* ###......###.... */
+ /*01a3:*/ 0xe0,0x70, /* ###......###.... */
+ /*01a5:*/ 0x70,0xe0, /* .###....###..... */
+ /*01a7:*/ 0x70,0xe0, /* .###....###..... */
+ /*01a9:*/ 0x79,0xe0, /* .####..####..... */
+ /*01ab:*/ 0x3f,0xc0, /* ..########...... */
+ /*01ad:*/ 0x1f,0x80, /* ...######....... */
+/* --- new character one (49) starting at offset 0x01af --- */
+ /*01af:*/ 13, 7, 18, 2, 0, /* width and bbox (w,h,x,y) */
+ /*01b4:*/ 0x0e, /* ....###. */
+ /*01b5:*/ 0x0e, /* ....###. */
+ /*01b6:*/ 0x1e, /* ...####. */
+ /*01b7:*/ 0xfe, /* #######. */
+ /*01b8:*/ 0xfe, /* #######. */
+ /*01b9:*/ 0x0e, /* ....###. */
+ /*01ba:*/ 0x0e, /* ....###. */
+ /*01bb:*/ 0x0e, /* ....###. */
+ /*01bc:*/ 0x0e, /* ....###. */
+ /*01bd:*/ 0x0e, /* ....###. */
+ /*01be:*/ 0x0e, /* ....###. */
+ /*01bf:*/ 0x0e, /* ....###. */
+ /*01c0:*/ 0x0e, /* ....###. */
+ /*01c1:*/ 0x0e, /* ....###. */
+ /*01c2:*/ 0x0e, /* ....###. */
+ /*01c3:*/ 0x0e, /* ....###. */
+ /*01c4:*/ 0x0e, /* ....###. */
+ /*01c5:*/ 0x0e, /* ....###. */
+/* --- new character two (50) starting at offset 0x01c6 --- */
+ /*01c6:*/ 13, 12, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01cb:*/ 0x1f,0x00, /* ...#####........ */
+ /*01cd:*/ 0x7f,0xc0, /* .#########...... */
+ /*01cf:*/ 0x71,0xe0, /* .###...####..... */
+ /*01d1:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*01d3:*/ 0xe0,0x70, /* ###......###.... */
+ /*01d5:*/ 0xe0,0x70, /* ###......###.... */
+ /*01d7:*/ 0x00,0x70, /* .........###.... */
+ /*01d9:*/ 0x00,0xe0, /* ........###..... */
+ /*01db:*/ 0x01,0xe0, /* .......####..... */
+ /*01dd:*/ 0x03,0xc0, /* ......####...... */
+ /*01df:*/ 0x07,0x80, /* .....####....... */
+ /*01e1:*/ 0x1f,0x00, /* ...#####........ */
+ /*01e3:*/ 0x3c,0x00, /* ..####.......... */
+ /*01e5:*/ 0x78,0x00, /* .####........... */
+ /*01e7:*/ 0xf0,0x00, /* ####............ */
+ /*01e9:*/ 0xe0,0x00, /* ###............. */
+ /*01eb:*/ 0xff,0xf0, /* ############.... */
+ /*01ed:*/ 0xff,0xf0, /* ############.... */
+/* --- new character three (51) starting at offset 0x01ef --- */
+ /*01ef:*/ 13, 12, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*01f4:*/ 0x1f,0x00, /* ...#####........ */
+ /*01f6:*/ 0x7f,0xc0, /* .#########...... */
+ /*01f8:*/ 0x71,0xc0, /* .###...###...... */
+ /*01fa:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*01fc:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*01fe:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0200:*/ 0x00,0xe0, /* ........###..... */
+ /*0202:*/ 0x01,0xc0, /* .......###...... */
+ /*0204:*/ 0x0f,0x80, /* ....#####....... */
+ /*0206:*/ 0x0f,0xe0, /* ....#######..... */
+ /*0208:*/ 0x00,0xe0, /* ........###..... */
+ /*020a:*/ 0x00,0x70, /* .........###.... */
+ /*020c:*/ 0x00,0x70, /* .........###.... */
+ /*020e:*/ 0xe0,0x70, /* ###......###.... */
+ /*0210:*/ 0xe0,0xf0, /* ###.....####.... */
+ /*0212:*/ 0x71,0xe0, /* .###...####..... */
+ /*0214:*/ 0x7f,0xe0, /* .##########..... */
+ /*0216:*/ 0x1f,0x80, /* ...######....... */
+/* --- new character four (52) starting at offset 0x0218 --- */
+ /*0218:*/ 13, 12, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*021d:*/ 0x01,0xc0, /* .......###...... */
+ /*021f:*/ 0x03,0xc0, /* ......####...... */
+ /*0221:*/ 0x03,0xc0, /* ......####...... */
+ /*0223:*/ 0x07,0xc0, /* .....#####...... */
+ /*0225:*/ 0x07,0xc0, /* .....#####...... */
+ /*0227:*/ 0x0d,0xc0, /* ....##.###...... */
+ /*0229:*/ 0x1d,0xc0, /* ...###.###...... */
+ /*022b:*/ 0x19,0xc0, /* ...##..###...... */
+ /*022d:*/ 0x31,0xc0, /* ..##...###...... */
+ /*022f:*/ 0x71,0xc0, /* .###...###...... */
+ /*0231:*/ 0x61,0xc0, /* .##....###...... */
+ /*0233:*/ 0xe1,0xc0, /* ###....###...... */
+ /*0235:*/ 0xff,0xf0, /* ############.... */
+ /*0237:*/ 0xff,0xf0, /* ############.... */
+ /*0239:*/ 0x01,0xc0, /* .......###...... */
+ /*023b:*/ 0x01,0xc0, /* .......###...... */
+ /*023d:*/ 0x01,0xc0, /* .......###...... */
+ /*023f:*/ 0x01,0xc0, /* .......###...... */
+/* --- new character five (53) starting at offset 0x0241 --- */
+ /*0241:*/ 13, 12, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0246:*/ 0x7f,0xe0, /* .##########..... */
+ /*0248:*/ 0x7f,0xe0, /* .##########..... */
+ /*024a:*/ 0x70,0x00, /* .###............ */
+ /*024c:*/ 0x70,0x00, /* .###............ */
+ /*024e:*/ 0x70,0x00, /* .###............ */
+ /*0250:*/ 0x70,0x00, /* .###............ */
+ /*0252:*/ 0x7f,0x80, /* .########....... */
+ /*0254:*/ 0x7f,0xc0, /* .#########...... */
+ /*0256:*/ 0x71,0xe0, /* .###...####..... */
+ /*0258:*/ 0x00,0xe0, /* ........###..... */
+ /*025a:*/ 0x00,0x70, /* .........###.... */
+ /*025c:*/ 0x00,0x70, /* .........###.... */
+ /*025e:*/ 0x00,0x70, /* .........###.... */
+ /*0260:*/ 0xe0,0x70, /* ###......###.... */
+ /*0262:*/ 0xe0,0xf0, /* ###.....####.... */
+ /*0264:*/ 0xf1,0xe0, /* ####...####..... */
+ /*0266:*/ 0x7f,0xc0, /* .#########...... */
+ /*0268:*/ 0x1f,0x80, /* ...######....... */
+/* --- new character six (54) starting at offset 0x026a --- */
+ /*026a:*/ 13, 12, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*026f:*/ 0x0f,0x80, /* ....#####....... */
+ /*0271:*/ 0x3f,0xe0, /* ..#########..... */
+ /*0273:*/ 0x78,0xe0, /* .####...###..... */
+ /*0275:*/ 0x70,0x70, /* .###.....###.... */
+ /*0277:*/ 0xe0,0x70, /* ###......###.... */
+ /*0279:*/ 0xe0,0x00, /* ###............. */
+ /*027b:*/ 0xe0,0x00, /* ###............. */
+ /*027d:*/ 0xef,0x00, /* ###.####........ */
+ /*027f:*/ 0xff,0xc0, /* ##########...... */
+ /*0281:*/ 0xf9,0xe0, /* #####..####..... */
+ /*0283:*/ 0xf0,0xe0, /* ####....###..... */
+ /*0285:*/ 0xe0,0x70, /* ###......###.... */
+ /*0287:*/ 0xe0,0x70, /* ###......###.... */
+ /*0289:*/ 0xe0,0x70, /* ###......###.... */
+ /*028b:*/ 0x70,0xe0, /* .###....###..... */
+ /*028d:*/ 0x79,0xe0, /* .####..####..... */
+ /*028f:*/ 0x3f,0xc0, /* ..########...... */
+ /*0291:*/ 0x1f,0x80, /* ...######....... */
+/* --- new character seven (55) starting at offset 0x0293 --- */
+ /*0293:*/ 13, 12, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0298:*/ 0xff,0xf0, /* ############.... */
+ /*029a:*/ 0xff,0xf0, /* ############.... */
+ /*029c:*/ 0x00,0xf0, /* ........####.... */
+ /*029e:*/ 0x00,0xe0, /* ........###..... */
+ /*02a0:*/ 0x01,0xc0, /* .......###...... */
+ /*02a2:*/ 0x01,0xc0, /* .......###...... */
+ /*02a4:*/ 0x03,0x80, /* ......###....... */
+ /*02a6:*/ 0x03,0x80, /* ......###....... */
+ /*02a8:*/ 0x07,0x00, /* .....###........ */
+ /*02aa:*/ 0x07,0x00, /* .....###........ */
+ /*02ac:*/ 0x0e,0x00, /* ....###......... */
+ /*02ae:*/ 0x0e,0x00, /* ....###......... */
+ /*02b0:*/ 0x1e,0x00, /* ...####......... */
+ /*02b2:*/ 0x1c,0x00, /* ...###.......... */
+ /*02b4:*/ 0x1c,0x00, /* ...###.......... */
+ /*02b6:*/ 0x3c,0x00, /* ..####.......... */
+ /*02b8:*/ 0x38,0x00, /* ..###........... */
+ /*02ba:*/ 0x38,0x00, /* ..###........... */
+/* --- new character eight (56) starting at offset 0x02bc --- */
+ /*02bc:*/ 13, 12, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02c1:*/ 0x0f,0x00, /* ....####........ */
+ /*02c3:*/ 0x3f,0xc0, /* ..########...... */
+ /*02c5:*/ 0x39,0xc0, /* ..###..###...... */
+ /*02c7:*/ 0x70,0xe0, /* .###....###..... */
+ /*02c9:*/ 0x70,0xe0, /* .###....###..... */
+ /*02cb:*/ 0x70,0xe0, /* .###....###..... */
+ /*02cd:*/ 0x70,0xe0, /* .###....###..... */
+ /*02cf:*/ 0x39,0xc0, /* ..###..###...... */
+ /*02d1:*/ 0x1f,0x80, /* ...######....... */
+ /*02d3:*/ 0x3f,0xc0, /* ..########...... */
+ /*02d5:*/ 0x70,0xe0, /* .###....###..... */
+ /*02d7:*/ 0xe0,0x70, /* ###......###.... */
+ /*02d9:*/ 0xe0,0x70, /* ###......###.... */
+ /*02db:*/ 0xe0,0x70, /* ###......###.... */
+ /*02dd:*/ 0xe0,0x70, /* ###......###.... */
+ /*02df:*/ 0x70,0xe0, /* .###....###..... */
+ /*02e1:*/ 0x7f,0xe0, /* .##########..... */
+ /*02e3:*/ 0x1f,0x80, /* ...######....... */
+/* --- new character nine (57) starting at offset 0x02e5 --- */
+ /*02e5:*/ 13, 12, 18, 0, 0, /* width and bbox (w,h,x,y) */
+ /*02ea:*/ 0x1f,0x80, /* ...######....... */
+ /*02ec:*/ 0x7f,0xc0, /* .#########...... */
+ /*02ee:*/ 0x79,0xe0, /* .####..####..... */
+ /*02f0:*/ 0xf0,0xe0, /* ####....###..... */
+ /*02f2:*/ 0xe0,0x70, /* ###......###.... */
+ /*02f4:*/ 0xe0,0x70, /* ###......###.... */
+ /*02f6:*/ 0xe0,0x70, /* ###......###.... */
+ /*02f8:*/ 0xe0,0x70, /* ###......###.... */
+ /*02fa:*/ 0xf0,0xf0, /* ####....####.... */
+ /*02fc:*/ 0x79,0xf0, /* .####..#####.... */
+ /*02fe:*/ 0x7f,0xf0, /* .###########.... */
+ /*0300:*/ 0x1f,0x70, /* ...#####.###.... */
+ /*0302:*/ 0x00,0x70, /* .........###.... */
+ /*0304:*/ 0x00,0x70, /* .........###.... */
+ /*0306:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0308:*/ 0xf3,0xe0, /* ####..#####..... */
+ /*030a:*/ 0x7f,0xc0, /* .#########...... */
+ /*030c:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character colon (58) starting at offset 0x030e --- */
+ /*030e:*/ 7, 3, 14, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0313:*/ 0xe0, /* ###..... */
+ /*0314:*/ 0xe0, /* ###..... */
+ /*0315:*/ 0xe0, /* ###..... */
+ /*0316:*/ 0x00, /* ........ */
+ /*0317:*/ 0x00, /* ........ */
+ /*0318:*/ 0x00, /* ........ */
+ /*0319:*/ 0x00, /* ........ */
+ /*031a:*/ 0x00, /* ........ */
+ /*031b:*/ 0x00, /* ........ */
+ /*031c:*/ 0x00, /* ........ */
+ /*031d:*/ 0x00, /* ........ */
+ /*031e:*/ 0xe0, /* ###..... */
+ /*031f:*/ 0xe0, /* ###..... */
+ /*0320:*/ 0xe0, /* ###..... */
+/* --- new character semicolon (59) starting at offset 0x0321 --- */
+ /*0321:*/ 7, 3, 17, 2, -3, /* width and bbox (w,h,x,y) */
+ /*0326:*/ 0xe0, /* ###..... */
+ /*0327:*/ 0xe0, /* ###..... */
+ /*0328:*/ 0xe0, /* ###..... */
+ /*0329:*/ 0x00, /* ........ */
+ /*032a:*/ 0x00, /* ........ */
+ /*032b:*/ 0x00, /* ........ */
+ /*032c:*/ 0x00, /* ........ */
+ /*032d:*/ 0x00, /* ........ */
+ /*032e:*/ 0x00, /* ........ */
+ /*032f:*/ 0x00, /* ........ */
+ /*0330:*/ 0x00, /* ........ */
+ /*0331:*/ 0xe0, /* ###..... */
+ /*0332:*/ 0xe0, /* ###..... */
+ /*0333:*/ 0xe0, /* ###..... */
+ /*0334:*/ 0x60, /* .##..... */
+ /*0335:*/ 0x60, /* .##..... */
+ /*0336:*/ 0xc0, /* ##...... */
+/* --- new character less (60) starting at offset 0x0337 --- */
+ /*0337:*/ 15, 13, 12, 0, 1, /* width and bbox (w,h,x,y) */
+ /*033c:*/ 0x00,0x38, /* ..........###... */
+ /*033e:*/ 0x00,0xf8, /* ........#####... */
+ /*0340:*/ 0x03,0xe0, /* ......#####..... */
+ /*0342:*/ 0x0f,0x80, /* ....#####....... */
+ /*0344:*/ 0x3e,0x00, /* ..#####......... */
+ /*0346:*/ 0xf0,0x00, /* ####............ */
+ /*0348:*/ 0xf0,0x00, /* ####............ */
+ /*034a:*/ 0x3e,0x00, /* ..#####......... */
+ /*034c:*/ 0x0f,0x80, /* ....#####....... */
+ /*034e:*/ 0x03,0xe0, /* ......#####..... */
+ /*0350:*/ 0x00,0xf8, /* ........#####... */
+ /*0352:*/ 0x00,0x38, /* ..........###... */
+/* --- new character equal (61) starting at offset 0x0354 --- */
+ /*0354:*/ 14, 10, 6, 2, 4, /* width and bbox (w,h,x,y) */
+ /*0359:*/ 0xff,0xc0, /* ##########...... */
+ /*035b:*/ 0xff,0xc0, /* ##########...... */
+ /*035d:*/ 0x00,0x00, /* ................ */
+ /*035f:*/ 0x00,0x00, /* ................ */
+ /*0361:*/ 0xff,0xc0, /* ##########...... */
+ /*0363:*/ 0xff,0xc0, /* ##########...... */
+/* --- new character greater (62) starting at offset 0x0365 --- */
+ /*0365:*/ 14, 13, 12, 0, 1, /* width and bbox (w,h,x,y) */
+ /*036a:*/ 0xe0,0x00, /* ###............. */
+ /*036c:*/ 0xf8,0x00, /* #####........... */
+ /*036e:*/ 0x3e,0x00, /* ..#####......... */
+ /*0370:*/ 0x0f,0x80, /* ....#####....... */
+ /*0372:*/ 0x03,0xe0, /* ......#####..... */
+ /*0374:*/ 0x00,0x78, /* .........####... */
+ /*0376:*/ 0x00,0x78, /* .........####... */
+ /*0378:*/ 0x03,0xe0, /* ......#####..... */
+ /*037a:*/ 0x0f,0x80, /* ....#####....... */
+ /*037c:*/ 0x3e,0x00, /* ..#####......... */
+ /*037e:*/ 0xf8,0x00, /* #####........... */
+ /*0380:*/ 0xe0,0x00, /* ###............. */
+/* --- new character question (63) starting at offset 0x0382 --- */
+ /*0382:*/ 15, 11, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0387:*/ 0x1f,0x80, /* ...######....... */
+ /*0389:*/ 0x7f,0xc0, /* .#########...... */
+ /*038b:*/ 0x79,0xe0, /* .####..####..... */
+ /*038d:*/ 0xf0,0xe0, /* ####....###..... */
+ /*038f:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0391:*/ 0xe1,0xe0, /* ###....####..... */
+ /*0393:*/ 0x01,0xc0, /* .......###...... */
+ /*0395:*/ 0x03,0xc0, /* ......####...... */
+ /*0397:*/ 0x07,0x80, /* .....####....... */
+ /*0399:*/ 0x07,0x00, /* .....###........ */
+ /*039b:*/ 0x0e,0x00, /* ....###......... */
+ /*039d:*/ 0x0e,0x00, /* ....###......... */
+ /*039f:*/ 0x0e,0x00, /* ....###......... */
+ /*03a1:*/ 0x0e,0x00, /* ....###......... */
+ /*03a3:*/ 0x00,0x00, /* ................ */
+ /*03a5:*/ 0x00,0x00, /* ................ */
+ /*03a7:*/ 0x0e,0x00, /* ....###......... */
+ /*03a9:*/ 0x0e,0x00, /* ....###......... */
+ /*03ab:*/ 0x0e,0x00, /* ....###......... */
+/* --- new character at (64) starting at offset 0x03ad --- */
+ /*03ad:*/ 24, 22, 22, 1, -4, /* width and bbox (w,h,x,y) */
+ /*03b2:*/ 0x01,0xff,0x00, /* .......#########........ */
+ /*03b5:*/ 0x07,0xff,0xc0, /* .....#############...... */
+ /*03b8:*/ 0x0f,0x81,0xf0, /* ....#####......#####.... */
+ /*03bb:*/ 0x1e,0x00,0x78, /* ...####..........####... */
+ /*03be:*/ 0x3c,0x00,0x38, /* ..####............###... */
+ /*03c1:*/ 0x78,0x7d,0x9c, /* .####....#####.##..###.. */
+ /*03c4:*/ 0x70,0xff,0x9c, /* .###....#########..###.. */
+ /*03c7:*/ 0xf1,0xc7,0x1c, /* ####...###...###...###.. */
+ /*03ca:*/ 0xe3,0x87,0x1c, /* ###...###....###...###.. */
+ /*03cd:*/ 0xe3,0x0e,0x1c, /* ###...##....###....###.. */
+ /*03d0:*/ 0xe7,0x0e,0x38, /* ###..###....###...###... */
+ /*03d3:*/ 0xe7,0x0c,0x38, /* ###..###....##....###... */
+ /*03d6:*/ 0xe7,0x1c,0x70, /* ###..###...###...###.... */
+ /*03d9:*/ 0xe7,0x1c,0x70, /* ###..###...###...###.... */
+ /*03dc:*/ 0xe3,0x9d,0xe0, /* ###...###..###.####..... */
+ /*03df:*/ 0xf3,0xff,0xc0, /* ####..############...... */
+ /*03e2:*/ 0x71,0xf7,0x00, /* .###...#####.###........ */
+ /*03e5:*/ 0x78,0x00,0x00, /* .####................... */
+ /*03e8:*/ 0x3c,0x00,0x00, /* ..####.................. */
+ /*03eb:*/ 0x1f,0x07,0x00, /* ...#####.....###........ */
+ /*03ee:*/ 0x0f,0xff,0x00, /* ....############........ */
+ /*03f1:*/ 0x03,0xfc,0x00, /* ......########.......... */
+/* --- new character A (65) starting at offset 0x03f4 --- */
+ /*03f4:*/ 18, 16, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*03f9:*/ 0x03,0xc0, /* ......####...... */
+ /*03fb:*/ 0x03,0xc0, /* ......####...... */
+ /*03fd:*/ 0x07,0xe0, /* .....######..... */
+ /*03ff:*/ 0x07,0xe0, /* .....######..... */
+ /*0401:*/ 0x0e,0x60, /* ....###..##..... */
+ /*0403:*/ 0x0e,0x70, /* ....###..###.... */
+ /*0405:*/ 0x0e,0x70, /* ....###..###.... */
+ /*0407:*/ 0x1c,0x38, /* ...###....###... */
+ /*0409:*/ 0x1c,0x38, /* ...###....###... */
+ /*040b:*/ 0x1c,0x38, /* ...###....###... */
+ /*040d:*/ 0x38,0x1c, /* ..###......###.. */
+ /*040f:*/ 0x38,0x1c, /* ..###......###.. */
+ /*0411:*/ 0x3f,0xfc, /* ..############.. */
+ /*0413:*/ 0x7f,0xfe, /* .##############. */
+ /*0415:*/ 0x70,0x0e, /* .###........###. */
+ /*0417:*/ 0x70,0x0e, /* .###........###. */
+ /*0419:*/ 0xe0,0x07, /* ###..........### */
+ /*041b:*/ 0xe0,0x07, /* ###..........### */
+ /*041d:*/ 0xe0,0x07, /* ###..........### */
+/* --- new character B (66) starting at offset 0x041f --- */
+ /*041f:*/ 18, 15, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0424:*/ 0xff,0xe0, /* ###########..... */
+ /*0426:*/ 0xff,0xf8, /* #############... */
+ /*0428:*/ 0xe0,0x78, /* ###......####... */
+ /*042a:*/ 0xe0,0x1c, /* ###........###.. */
+ /*042c:*/ 0xe0,0x1c, /* ###........###.. */
+ /*042e:*/ 0xe0,0x1c, /* ###........###.. */
+ /*0430:*/ 0xe0,0x1c, /* ###........###.. */
+ /*0432:*/ 0xe0,0x38, /* ###.......###... */
+ /*0434:*/ 0xff,0xf0, /* ############.... */
+ /*0436:*/ 0xff,0xf8, /* #############... */
+ /*0438:*/ 0xe0,0x1c, /* ###........###.. */
+ /*043a:*/ 0xe0,0x0e, /* ###.........###. */
+ /*043c:*/ 0xe0,0x0e, /* ###.........###. */
+ /*043e:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0440:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0442:*/ 0xe0,0x1e, /* ###........####. */
+ /*0444:*/ 0xe0,0x7c, /* ###......#####.. */
+ /*0446:*/ 0xff,0xf8, /* #############... */
+ /*0448:*/ 0xff,0xe0, /* ###########..... */
+/* --- new character C (67) starting at offset 0x044a --- */
+ /*044a:*/ 18, 16, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*044f:*/ 0x07,0xf0, /* .....#######.... */
+ /*0451:*/ 0x1f,0xfc, /* ...###########.. */
+ /*0453:*/ 0x3e,0x3e, /* ..#####...#####. */
+ /*0455:*/ 0x78,0x0f, /* .####.......#### */
+ /*0457:*/ 0x70,0x07, /* .###.........### */
+ /*0459:*/ 0xf0,0x00, /* ####............ */
+ /*045b:*/ 0xe0,0x00, /* ###............. */
+ /*045d:*/ 0xe0,0x00, /* ###............. */
+ /*045f:*/ 0xe0,0x00, /* ###............. */
+ /*0461:*/ 0xe0,0x00, /* ###............. */
+ /*0463:*/ 0xe0,0x00, /* ###............. */
+ /*0465:*/ 0xe0,0x00, /* ###............. */
+ /*0467:*/ 0xe0,0x00, /* ###............. */
+ /*0469:*/ 0xf0,0x07, /* ####.........### */
+ /*046b:*/ 0x70,0x07, /* .###.........### */
+ /*046d:*/ 0x78,0x0f, /* .####.......#### */
+ /*046f:*/ 0x3e,0x3e, /* ..#####...#####. */
+ /*0471:*/ 0x1f,0xfc, /* ...###########.. */
+ /*0473:*/ 0x07,0xf0, /* .....#######.... */
+/* --- new character D (68) starting at offset 0x0475 --- */
+ /*0475:*/ 19, 16, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*047a:*/ 0xff,0xe0, /* ###########..... */
+ /*047c:*/ 0xff,0xf8, /* #############... */
+ /*047e:*/ 0xe0,0x7c, /* ###......#####.. */
+ /*0480:*/ 0xe0,0x1e, /* ###........####. */
+ /*0482:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0484:*/ 0xe0,0x0f, /* ###.........#### */
+ /*0486:*/ 0xe0,0x07, /* ###..........### */
+ /*0488:*/ 0xe0,0x07, /* ###..........### */
+ /*048a:*/ 0xe0,0x07, /* ###..........### */
+ /*048c:*/ 0xe0,0x07, /* ###..........### */
+ /*048e:*/ 0xe0,0x07, /* ###..........### */
+ /*0490:*/ 0xe0,0x07, /* ###..........### */
+ /*0492:*/ 0xe0,0x07, /* ###..........### */
+ /*0494:*/ 0xe0,0x0f, /* ###.........#### */
+ /*0496:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0498:*/ 0xe0,0x1e, /* ###........####. */
+ /*049a:*/ 0xe0,0x7c, /* ###......#####.. */
+ /*049c:*/ 0xff,0xf8, /* #############... */
+ /*049e:*/ 0xff,0xe0, /* ###########..... */
+/* --- new character E (69) starting at offset 0x04a0 --- */
+ /*04a0:*/ 16, 13, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*04a5:*/ 0xff,0xf0, /* ############.... */
+ /*04a7:*/ 0xff,0xf0, /* ############.... */
+ /*04a9:*/ 0xe0,0x00, /* ###............. */
+ /*04ab:*/ 0xe0,0x00, /* ###............. */
+ /*04ad:*/ 0xe0,0x00, /* ###............. */
+ /*04af:*/ 0xe0,0x00, /* ###............. */
+ /*04b1:*/ 0xe0,0x00, /* ###............. */
+ /*04b3:*/ 0xe0,0x00, /* ###............. */
+ /*04b5:*/ 0xff,0xe0, /* ###########..... */
+ /*04b7:*/ 0xff,0xe0, /* ###########..... */
+ /*04b9:*/ 0xe0,0x00, /* ###............. */
+ /*04bb:*/ 0xe0,0x00, /* ###............. */
+ /*04bd:*/ 0xe0,0x00, /* ###............. */
+ /*04bf:*/ 0xe0,0x00, /* ###............. */
+ /*04c1:*/ 0xe0,0x00, /* ###............. */
+ /*04c3:*/ 0xe0,0x00, /* ###............. */
+ /*04c5:*/ 0xe0,0x00, /* ###............. */
+ /*04c7:*/ 0xff,0xf8, /* #############... */
+ /*04c9:*/ 0xff,0xf8, /* #############... */
+/* --- new character F (70) starting at offset 0x04cb --- */
+ /*04cb:*/ 15, 12, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*04d0:*/ 0xff,0xf0, /* ############.... */
+ /*04d2:*/ 0xff,0xf0, /* ############.... */
+ /*04d4:*/ 0xe0,0x00, /* ###............. */
+ /*04d6:*/ 0xe0,0x00, /* ###............. */
+ /*04d8:*/ 0xe0,0x00, /* ###............. */
+ /*04da:*/ 0xe0,0x00, /* ###............. */
+ /*04dc:*/ 0xe0,0x00, /* ###............. */
+ /*04de:*/ 0xe0,0x00, /* ###............. */
+ /*04e0:*/ 0xff,0xe0, /* ###########..... */
+ /*04e2:*/ 0xff,0xe0, /* ###########..... */
+ /*04e4:*/ 0xe0,0x00, /* ###............. */
+ /*04e6:*/ 0xe0,0x00, /* ###............. */
+ /*04e8:*/ 0xe0,0x00, /* ###............. */
+ /*04ea:*/ 0xe0,0x00, /* ###............. */
+ /*04ec:*/ 0xe0,0x00, /* ###............. */
+ /*04ee:*/ 0xe0,0x00, /* ###............. */
+ /*04f0:*/ 0xe0,0x00, /* ###............. */
+ /*04f2:*/ 0xe0,0x00, /* ###............. */
+ /*04f4:*/ 0xe0,0x00, /* ###............. */
+/* --- new character G (71) starting at offset 0x04f6 --- */
+ /*04f6:*/ 19, 17, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*04fb:*/ 0x07,0xf0,0x00, /* .....#######............ */
+ /*04fe:*/ 0x1f,0xfc,0x00, /* ...###########.......... */
+ /*0501:*/ 0x3e,0x3e,0x00, /* ..#####...#####......... */
+ /*0504:*/ 0x78,0x0f,0x00, /* .####.......####........ */
+ /*0507:*/ 0x70,0x07,0x00, /* .###.........###........ */
+ /*050a:*/ 0xf0,0x00,0x00, /* ####.................... */
+ /*050d:*/ 0xe0,0x00,0x00, /* ###..................... */
+ /*0510:*/ 0xe0,0x00,0x00, /* ###..................... */
+ /*0513:*/ 0xe0,0x00,0x00, /* ###..................... */
+ /*0516:*/ 0xe0,0x7f,0x80, /* ###......########....... */
+ /*0519:*/ 0xe0,0x7f,0x80, /* ###......########....... */
+ /*051c:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*051f:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*0522:*/ 0xf0,0x03,0x80, /* ####..........###....... */
+ /*0525:*/ 0x70,0x07,0x80, /* .###.........####....... */
+ /*0528:*/ 0x78,0x0f,0x80, /* .####.......#####....... */
+ /*052b:*/ 0x3e,0x3f,0x80, /* ..#####...#######....... */
+ /*052e:*/ 0x1f,0xfb,0x80, /* ...##########.###....... */
+ /*0531:*/ 0x07,0xf1,0x80, /* .....#######...##....... */
+/* --- new character H (72) starting at offset 0x0534 --- */
+ /*0534:*/ 19, 15, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0539:*/ 0xe0,0x0e, /* ###.........###. */
+ /*053b:*/ 0xe0,0x0e, /* ###.........###. */
+ /*053d:*/ 0xe0,0x0e, /* ###.........###. */
+ /*053f:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0541:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0543:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0545:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0547:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0549:*/ 0xff,0xfe, /* ###############. */
+ /*054b:*/ 0xff,0xfe, /* ###############. */
+ /*054d:*/ 0xe0,0x0e, /* ###.........###. */
+ /*054f:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0551:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0553:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0555:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0557:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0559:*/ 0xe0,0x0e, /* ###.........###. */
+ /*055b:*/ 0xe0,0x0e, /* ###.........###. */
+ /*055d:*/ 0xe0,0x0e, /* ###.........###. */
+/* --- new character I (73) starting at offset 0x055f --- */
+ /*055f:*/ 7, 3, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0564:*/ 0xe0, /* ###..... */
+ /*0565:*/ 0xe0, /* ###..... */
+ /*0566:*/ 0xe0, /* ###..... */
+ /*0567:*/ 0xe0, /* ###..... */
+ /*0568:*/ 0xe0, /* ###..... */
+ /*0569:*/ 0xe0, /* ###..... */
+ /*056a:*/ 0xe0, /* ###..... */
+ /*056b:*/ 0xe0, /* ###..... */
+ /*056c:*/ 0xe0, /* ###..... */
+ /*056d:*/ 0xe0, /* ###..... */
+ /*056e:*/ 0xe0, /* ###..... */
+ /*056f:*/ 0xe0, /* ###..... */
+ /*0570:*/ 0xe0, /* ###..... */
+ /*0571:*/ 0xe0, /* ###..... */
+ /*0572:*/ 0xe0, /* ###..... */
+ /*0573:*/ 0xe0, /* ###..... */
+ /*0574:*/ 0xe0, /* ###..... */
+ /*0575:*/ 0xe0, /* ###..... */
+ /*0576:*/ 0xe0, /* ###..... */
+/* --- new character J (74) starting at offset 0x0577 --- */
+ /*0577:*/ 14, 11, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*057c:*/ 0x00,0xe0, /* ........###..... */
+ /*057e:*/ 0x00,0xe0, /* ........###..... */
+ /*0580:*/ 0x00,0xe0, /* ........###..... */
+ /*0582:*/ 0x00,0xe0, /* ........###..... */
+ /*0584:*/ 0x00,0xe0, /* ........###..... */
+ /*0586:*/ 0x00,0xe0, /* ........###..... */
+ /*0588:*/ 0x00,0xe0, /* ........###..... */
+ /*058a:*/ 0x00,0xe0, /* ........###..... */
+ /*058c:*/ 0x00,0xe0, /* ........###..... */
+ /*058e:*/ 0x00,0xe0, /* ........###..... */
+ /*0590:*/ 0x00,0xe0, /* ........###..... */
+ /*0592:*/ 0x00,0xe0, /* ........###..... */
+ /*0594:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0596:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0598:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*059a:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*059c:*/ 0x71,0xe0, /* .###...####..... */
+ /*059e:*/ 0x7f,0xc0, /* .#########...... */
+ /*05a0:*/ 0x3f,0x80, /* ..#######....... */
+/* --- new character K (75) starting at offset 0x05a2 --- */
+ /*05a2:*/ 18, 16, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*05a7:*/ 0xe0,0x3c, /* ###.......####.. */
+ /*05a9:*/ 0xe0,0x78, /* ###......####... */
+ /*05ab:*/ 0xe0,0xf0, /* ###.....####.... */
+ /*05ad:*/ 0xe1,0xe0, /* ###....####..... */
+ /*05af:*/ 0xe3,0xc0, /* ###...####...... */
+ /*05b1:*/ 0xe7,0x80, /* ###..####....... */
+ /*05b3:*/ 0xef,0x00, /* ###.####........ */
+ /*05b5:*/ 0xfe,0x00, /* #######......... */
+ /*05b7:*/ 0xfe,0x00, /* #######......... */
+ /*05b9:*/ 0xff,0x00, /* ########........ */
+ /*05bb:*/ 0xf7,0x80, /* ####.####....... */
+ /*05bd:*/ 0xe3,0xc0, /* ###...####...... */
+ /*05bf:*/ 0xe1,0xe0, /* ###....####..... */
+ /*05c1:*/ 0xe0,0xf0, /* ###.....####.... */
+ /*05c3:*/ 0xe0,0x78, /* ###......####... */
+ /*05c5:*/ 0xe0,0x3c, /* ###.......####.. */
+ /*05c7:*/ 0xe0,0x1e, /* ###........####. */
+ /*05c9:*/ 0xe0,0x0f, /* ###.........#### */
+ /*05cb:*/ 0xe0,0x07, /* ###..........### */
+/* --- new character L (76) starting at offset 0x05cd --- */
+ /*05cd:*/ 15, 12, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*05d2:*/ 0xe0,0x00, /* ###............. */
+ /*05d4:*/ 0xe0,0x00, /* ###............. */
+ /*05d6:*/ 0xe0,0x00, /* ###............. */
+ /*05d8:*/ 0xe0,0x00, /* ###............. */
+ /*05da:*/ 0xe0,0x00, /* ###............. */
+ /*05dc:*/ 0xe0,0x00, /* ###............. */
+ /*05de:*/ 0xe0,0x00, /* ###............. */
+ /*05e0:*/ 0xe0,0x00, /* ###............. */
+ /*05e2:*/ 0xe0,0x00, /* ###............. */
+ /*05e4:*/ 0xe0,0x00, /* ###............. */
+ /*05e6:*/ 0xe0,0x00, /* ###............. */
+ /*05e8:*/ 0xe0,0x00, /* ###............. */
+ /*05ea:*/ 0xe0,0x00, /* ###............. */
+ /*05ec:*/ 0xe0,0x00, /* ###............. */
+ /*05ee:*/ 0xe0,0x00, /* ###............. */
+ /*05f0:*/ 0xe0,0x00, /* ###............. */
+ /*05f2:*/ 0xe0,0x00, /* ###............. */
+ /*05f4:*/ 0xff,0xf0, /* ############.... */
+ /*05f6:*/ 0xff,0xf0, /* ############.... */
+/* --- new character M (77) starting at offset 0x05f8 --- */
+ /*05f8:*/ 23, 19, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*05fd:*/ 0xe0,0x00,0xe0, /* ###.............###..... */
+ /*0600:*/ 0xf0,0x01,0xe0, /* ####...........####..... */
+ /*0603:*/ 0xf0,0x01,0xe0, /* ####...........####..... */
+ /*0606:*/ 0xf8,0x03,0xe0, /* #####.........#####..... */
+ /*0609:*/ 0xf8,0x03,0xe0, /* #####.........#####..... */
+ /*060c:*/ 0xfc,0x07,0xe0, /* ######.......######..... */
+ /*060f:*/ 0xec,0x06,0xe0, /* ###.##.......##.###..... */
+ /*0612:*/ 0xee,0x0e,0xe0, /* ###.###.....###.###..... */
+ /*0615:*/ 0xe6,0x0c,0xe0, /* ###..##.....##..###..... */
+ /*0618:*/ 0xe7,0x1c,0xe0, /* ###..###...###..###..... */
+ /*061b:*/ 0xe7,0x1c,0xe0, /* ###..###...###..###..... */
+ /*061e:*/ 0xe3,0x18,0xe0, /* ###...##...##...###..... */
+ /*0621:*/ 0xe3,0xb8,0xe0, /* ###...###.###...###..... */
+ /*0624:*/ 0xe3,0xb8,0xe0, /* ###...###.###...###..... */
+ /*0627:*/ 0xe1,0xf0,0xe0, /* ###....#####....###..... */
+ /*062a:*/ 0xe1,0xf0,0xe0, /* ###....#####....###..... */
+ /*062d:*/ 0xe0,0xe0,0xe0, /* ###.....###.....###..... */
+ /*0630:*/ 0xe0,0xe0,0xe0, /* ###.....###.....###..... */
+ /*0633:*/ 0xe0,0xe0,0xe0, /* ###.....###.....###..... */
+/* --- new character N (78) starting at offset 0x0636 --- */
+ /*0636:*/ 19, 15, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*063b:*/ 0xe0,0x0e, /* ###.........###. */
+ /*063d:*/ 0xf0,0x0e, /* ####........###. */
+ /*063f:*/ 0xf0,0x0e, /* ####........###. */
+ /*0641:*/ 0xf8,0x0e, /* #####.......###. */
+ /*0643:*/ 0xf8,0x0e, /* #####.......###. */
+ /*0645:*/ 0xfc,0x0e, /* ######......###. */
+ /*0647:*/ 0xee,0x0e, /* ###.###.....###. */
+ /*0649:*/ 0xee,0x0e, /* ###.###.....###. */
+ /*064b:*/ 0xe7,0x0e, /* ###..###....###. */
+ /*064d:*/ 0xe3,0x8e, /* ###...###...###. */
+ /*064f:*/ 0xe3,0x8e, /* ###...###...###. */
+ /*0651:*/ 0xe1,0xce, /* ###....###..###. */
+ /*0653:*/ 0xe0,0xce, /* ###.....##..###. */
+ /*0655:*/ 0xe0,0xee, /* ###.....###.###. */
+ /*0657:*/ 0xe0,0x7e, /* ###......######. */
+ /*0659:*/ 0xe0,0x3e, /* ###.......#####. */
+ /*065b:*/ 0xe0,0x3e, /* ###.......#####. */
+ /*065d:*/ 0xe0,0x1e, /* ###........####. */
+ /*065f:*/ 0xe0,0x0e, /* ###.........###. */
+/* --- new character O (79) starting at offset 0x0661 --- */
+ /*0661:*/ 19, 17, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0666:*/ 0x07,0xf0,0x00, /* .....#######............ */
+ /*0669:*/ 0x1f,0xfc,0x00, /* ...###########.......... */
+ /*066c:*/ 0x3e,0x3e,0x00, /* ..#####...#####......... */
+ /*066f:*/ 0x78,0x0f,0x00, /* .####.......####........ */
+ /*0672:*/ 0x70,0x07,0x00, /* .###.........###........ */
+ /*0675:*/ 0xf0,0x07,0x80, /* ####.........####....... */
+ /*0678:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*067b:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*067e:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*0681:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*0684:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*0687:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*068a:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*068d:*/ 0xf0,0x07,0x80, /* ####.........####....... */
+ /*0690:*/ 0x70,0x07,0x00, /* .###.........###........ */
+ /*0693:*/ 0x78,0x0f,0x00, /* .####.......####........ */
+ /*0696:*/ 0x3e,0x3e,0x00, /* ..#####...#####......... */
+ /*0699:*/ 0x1f,0xfc,0x00, /* ...###########.......... */
+ /*069c:*/ 0x07,0xf0,0x00, /* .....#######............ */
+/* --- new character P (80) starting at offset 0x069f --- */
+ /*069f:*/ 17, 14, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*06a4:*/ 0xff,0xe0, /* ###########..... */
+ /*06a6:*/ 0xff,0xf8, /* #############... */
+ /*06a8:*/ 0xe0,0x38, /* ###.......###... */
+ /*06aa:*/ 0xe0,0x1c, /* ###........###.. */
+ /*06ac:*/ 0xe0,0x1c, /* ###........###.. */
+ /*06ae:*/ 0xe0,0x1c, /* ###........###.. */
+ /*06b0:*/ 0xe0,0x1c, /* ###........###.. */
+ /*06b2:*/ 0xe0,0x38, /* ###.......###... */
+ /*06b4:*/ 0xff,0xf8, /* #############... */
+ /*06b6:*/ 0xff,0xf0, /* ############.... */
+ /*06b8:*/ 0xe0,0x00, /* ###............. */
+ /*06ba:*/ 0xe0,0x00, /* ###............. */
+ /*06bc:*/ 0xe0,0x00, /* ###............. */
+ /*06be:*/ 0xe0,0x00, /* ###............. */
+ /*06c0:*/ 0xe0,0x00, /* ###............. */
+ /*06c2:*/ 0xe0,0x00, /* ###............. */
+ /*06c4:*/ 0xe0,0x00, /* ###............. */
+ /*06c6:*/ 0xe0,0x00, /* ###............. */
+ /*06c8:*/ 0xe0,0x00, /* ###............. */
+/* --- new character Q (81) starting at offset 0x06ca --- */
+ /*06ca:*/ 19, 17, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*06cf:*/ 0x07,0xf0,0x00, /* .....#######............ */
+ /*06d2:*/ 0x1f,0xfc,0x00, /* ...###########.......... */
+ /*06d5:*/ 0x3e,0x3e,0x00, /* ..#####...#####......... */
+ /*06d8:*/ 0x78,0x0f,0x00, /* .####.......####........ */
+ /*06db:*/ 0x70,0x07,0x00, /* .###.........###........ */
+ /*06de:*/ 0xf0,0x07,0x80, /* ####.........####....... */
+ /*06e1:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*06e4:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*06e7:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*06ea:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*06ed:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*06f0:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*06f3:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*06f6:*/ 0xf0,0x07,0x80, /* ####.........####....... */
+ /*06f9:*/ 0x70,0xf7,0x00, /* .###....####.###........ */
+ /*06fc:*/ 0x78,0x7f,0x00, /* .####....#######........ */
+ /*06ff:*/ 0x3e,0x1e,0x00, /* ..#####....####......... */
+ /*0702:*/ 0x1f,0xff,0x00, /* ...#############........ */
+ /*0705:*/ 0x07,0xf7,0x80, /* .....#######.####....... */
+/* --- new character R (82) starting at offset 0x0708 --- */
+ /*0708:*/ 17, 14, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*070d:*/ 0xff,0xe0, /* ###########..... */
+ /*070f:*/ 0xff,0xf8, /* #############... */
+ /*0711:*/ 0xe0,0x38, /* ###.......###... */
+ /*0713:*/ 0xe0,0x1c, /* ###........###.. */
+ /*0715:*/ 0xe0,0x1c, /* ###........###.. */
+ /*0717:*/ 0xe0,0x1c, /* ###........###.. */
+ /*0719:*/ 0xe0,0x1c, /* ###........###.. */
+ /*071b:*/ 0xe0,0x38, /* ###.......###... */
+ /*071d:*/ 0xff,0xf8, /* #############... */
+ /*071f:*/ 0xff,0xf0, /* ############.... */
+ /*0721:*/ 0xe0,0x78, /* ###......####... */
+ /*0723:*/ 0xe0,0x38, /* ###.......###... */
+ /*0725:*/ 0xe0,0x1c, /* ###........###.. */
+ /*0727:*/ 0xe0,0x1c, /* ###........###.. */
+ /*0729:*/ 0xe0,0x1c, /* ###........###.. */
+ /*072b:*/ 0xe0,0x1c, /* ###........###.. */
+ /*072d:*/ 0xe0,0x1c, /* ###........###.. */
+ /*072f:*/ 0xe0,0x1c, /* ###........###.. */
+ /*0731:*/ 0xe0,0x1c, /* ###........###.. */
+/* --- new character S (83) starting at offset 0x0733 --- */
+ /*0733:*/ 17, 15, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0738:*/ 0x07,0xe0, /* .....######..... */
+ /*073a:*/ 0x1f,0xf8, /* ...##########... */
+ /*073c:*/ 0x3c,0x7c, /* ..####...#####.. */
+ /*073e:*/ 0x78,0x1c, /* .####......###.. */
+ /*0740:*/ 0x70,0x1c, /* .###.......###.. */
+ /*0742:*/ 0x70,0x00, /* .###............ */
+ /*0744:*/ 0x78,0x00, /* .####........... */
+ /*0746:*/ 0x3e,0x00, /* ..#####......... */
+ /*0748:*/ 0x1f,0xe0, /* ...########..... */
+ /*074a:*/ 0x03,0xf8, /* ......#######... */
+ /*074c:*/ 0x00,0x7c, /* .........#####.. */
+ /*074e:*/ 0x00,0x1e, /* ...........####. */
+ /*0750:*/ 0x00,0x0e, /* ............###. */
+ /*0752:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0754:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0756:*/ 0xf0,0x1e, /* ####.......####. */
+ /*0758:*/ 0x7c,0x7c, /* .#####...#####.. */
+ /*075a:*/ 0x3f,0xf8, /* ..###########... */
+ /*075c:*/ 0x0f,0xe0, /* ....#######..... */
+/* --- new character T (84) starting at offset 0x075e --- */
+ /*075e:*/ 15, 15, 19, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0763:*/ 0xff,0xfe, /* ###############. */
+ /*0765:*/ 0xff,0xfe, /* ###############. */
+ /*0767:*/ 0x03,0x80, /* ......###....... */
+ /*0769:*/ 0x03,0x80, /* ......###....... */
+ /*076b:*/ 0x03,0x80, /* ......###....... */
+ /*076d:*/ 0x03,0x80, /* ......###....... */
+ /*076f:*/ 0x03,0x80, /* ......###....... */
+ /*0771:*/ 0x03,0x80, /* ......###....... */
+ /*0773:*/ 0x03,0x80, /* ......###....... */
+ /*0775:*/ 0x03,0x80, /* ......###....... */
+ /*0777:*/ 0x03,0x80, /* ......###....... */
+ /*0779:*/ 0x03,0x80, /* ......###....... */
+ /*077b:*/ 0x03,0x80, /* ......###....... */
+ /*077d:*/ 0x03,0x80, /* ......###....... */
+ /*077f:*/ 0x03,0x80, /* ......###....... */
+ /*0781:*/ 0x03,0x80, /* ......###....... */
+ /*0783:*/ 0x03,0x80, /* ......###....... */
+ /*0785:*/ 0x03,0x80, /* ......###....... */
+ /*0787:*/ 0x03,0x80, /* ......###....... */
+/* --- new character U (85) starting at offset 0x0789 --- */
+ /*0789:*/ 19, 15, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*078e:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0790:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0792:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0794:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0796:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0798:*/ 0xe0,0x0e, /* ###.........###. */
+ /*079a:*/ 0xe0,0x0e, /* ###.........###. */
+ /*079c:*/ 0xe0,0x0e, /* ###.........###. */
+ /*079e:*/ 0xe0,0x0e, /* ###.........###. */
+ /*07a0:*/ 0xe0,0x0e, /* ###.........###. */
+ /*07a2:*/ 0xe0,0x0e, /* ###.........###. */
+ /*07a4:*/ 0xe0,0x0e, /* ###.........###. */
+ /*07a6:*/ 0xe0,0x0e, /* ###.........###. */
+ /*07a8:*/ 0xe0,0x0e, /* ###.........###. */
+ /*07aa:*/ 0xf0,0x1e, /* ####.......####. */
+ /*07ac:*/ 0x70,0x1c, /* .###.......###.. */
+ /*07ae:*/ 0x7c,0x7c, /* .#####...#####.. */
+ /*07b0:*/ 0x3f,0xf8, /* ..###########... */
+ /*07b2:*/ 0x0f,0xe0, /* ....#######..... */
+/* --- new character V (86) starting at offset 0x07b4 --- */
+ /*07b4:*/ 18, 16, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*07b9:*/ 0xe0,0x07, /* ###..........### */
+ /*07bb:*/ 0xe0,0x07, /* ###..........### */
+ /*07bd:*/ 0xf0,0x0f, /* ####........#### */
+ /*07bf:*/ 0x70,0x0e, /* .###........###. */
+ /*07c1:*/ 0x78,0x1e, /* .####......####. */
+ /*07c3:*/ 0x38,0x1c, /* ..###......###.. */
+ /*07c5:*/ 0x38,0x1c, /* ..###......###.. */
+ /*07c7:*/ 0x3c,0x3c, /* ..####....####.. */
+ /*07c9:*/ 0x1c,0x38, /* ...###....###... */
+ /*07cb:*/ 0x1c,0x38, /* ...###....###... */
+ /*07cd:*/ 0x1e,0x78, /* ...####..####... */
+ /*07cf:*/ 0x0e,0x70, /* ....###..###.... */
+ /*07d1:*/ 0x0e,0x70, /* ....###..###.... */
+ /*07d3:*/ 0x0e,0x70, /* ....###..###.... */
+ /*07d5:*/ 0x07,0xe0, /* .....######..... */
+ /*07d7:*/ 0x07,0xe0, /* .....######..... */
+ /*07d9:*/ 0x03,0xc0, /* ......####...... */
+ /*07db:*/ 0x03,0xc0, /* ......####...... */
+ /*07dd:*/ 0x03,0xc0, /* ......####...... */
+/* --- new character W (87) starting at offset 0x07df --- */
+ /*07df:*/ 23, 21, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*07e4:*/ 0xe0,0x70,0x38, /* ###......###......###... */
+ /*07e7:*/ 0xe0,0x70,0x38, /* ###......###......###... */
+ /*07ea:*/ 0xe0,0x70,0x38, /* ###......###......###... */
+ /*07ed:*/ 0xe0,0x70,0x38, /* ###......###......###... */
+ /*07f0:*/ 0x70,0xf8,0x70, /* .###....#####....###.... */
+ /*07f3:*/ 0x70,0xf8,0x70, /* .###....#####....###.... */
+ /*07f6:*/ 0x70,0xd8,0x70, /* .###....##.##....###.... */
+ /*07f9:*/ 0x71,0xdc,0x70, /* .###...###.###...###.... */
+ /*07fc:*/ 0x31,0xdc,0x60, /* ..##...###.###...##..... */
+ /*07ff:*/ 0x39,0xdc,0xe0, /* ..###..###.###..###..... */
+ /*0802:*/ 0x39,0x8c,0xe0, /* ..###..##...##..###..... */
+ /*0805:*/ 0x3b,0x8e,0xe0, /* ..###.###...###.###..... */
+ /*0808:*/ 0x1b,0x8e,0xc0, /* ...##.###...###.##...... */
+ /*080b:*/ 0x1b,0x8e,0xc0, /* ...##.###...###.##...... */
+ /*080e:*/ 0x1f,0x07,0xc0, /* ...#####.....#####...... */
+ /*0811:*/ 0x1f,0x07,0xc0, /* ...#####.....#####...... */
+ /*0814:*/ 0x0e,0x03,0x80, /* ....###.......###....... */
+ /*0817:*/ 0x0e,0x03,0x80, /* ....###.......###....... */
+ /*081a:*/ 0x0e,0x03,0x80, /* ....###.......###....... */
+/* --- new character X (88) starting at offset 0x081d --- */
+ /*081d:*/ 18, 16, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0822:*/ 0xe0,0x07, /* ###..........### */
+ /*0824:*/ 0xf0,0x0f, /* ####........#### */
+ /*0826:*/ 0x78,0x1e, /* .####......####. */
+ /*0828:*/ 0x38,0x1c, /* ..###......###.. */
+ /*082a:*/ 0x1c,0x38, /* ...###....###... */
+ /*082c:*/ 0x0e,0x70, /* ....###..###.... */
+ /*082e:*/ 0x0f,0xf0, /* ....########.... */
+ /*0830:*/ 0x07,0xe0, /* .....######..... */
+ /*0832:*/ 0x03,0xc0, /* ......####...... */
+ /*0834:*/ 0x03,0xc0, /* ......####...... */
+ /*0836:*/ 0x07,0xe0, /* .....######..... */
+ /*0838:*/ 0x0f,0xf0, /* ....########.... */
+ /*083a:*/ 0x0e,0x70, /* ....###..###.... */
+ /*083c:*/ 0x1c,0x38, /* ...###....###... */
+ /*083e:*/ 0x3c,0x3c, /* ..####....####.. */
+ /*0840:*/ 0x38,0x1c, /* ..###......###.. */
+ /*0842:*/ 0x70,0x0e, /* .###........###. */
+ /*0844:*/ 0xf0,0x0f, /* ####........#### */
+ /*0846:*/ 0xe0,0x07, /* ###..........### */
+/* --- new character Y (89) starting at offset 0x0848 --- */
+ /*0848:*/ 17, 15, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*084d:*/ 0xe0,0x0e, /* ###.........###. */
+ /*084f:*/ 0xf0,0x1e, /* ####.......####. */
+ /*0851:*/ 0x70,0x1c, /* .###.......###.. */
+ /*0853:*/ 0x78,0x3c, /* .####.....####.. */
+ /*0855:*/ 0x38,0x38, /* ..###.....###... */
+ /*0857:*/ 0x3c,0x78, /* ..####...####... */
+ /*0859:*/ 0x1c,0x70, /* ...###...###.... */
+ /*085b:*/ 0x1e,0xf0, /* ...####.####.... */
+ /*085d:*/ 0x0e,0xe0, /* ....###.###..... */
+ /*085f:*/ 0x0f,0xe0, /* ....#######..... */
+ /*0861:*/ 0x07,0xc0, /* .....#####...... */
+ /*0863:*/ 0x07,0xc0, /* .....#####...... */
+ /*0865:*/ 0x03,0x80, /* ......###....... */
+ /*0867:*/ 0x03,0x80, /* ......###....... */
+ /*0869:*/ 0x03,0x80, /* ......###....... */
+ /*086b:*/ 0x03,0x80, /* ......###....... */
+ /*086d:*/ 0x03,0x80, /* ......###....... */
+ /*086f:*/ 0x03,0x80, /* ......###....... */
+ /*0871:*/ 0x03,0x80, /* ......###....... */
+/* --- new character Z (90) starting at offset 0x0873 --- */
+ /*0873:*/ 16, 14, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0878:*/ 0xff,0xfc, /* ##############.. */
+ /*087a:*/ 0xff,0xfc, /* ##############.. */
+ /*087c:*/ 0x00,0x3c, /* ..........####.. */
+ /*087e:*/ 0x00,0x78, /* .........####... */
+ /*0880:*/ 0x00,0xf0, /* ........####.... */
+ /*0882:*/ 0x01,0xe0, /* .......####..... */
+ /*0884:*/ 0x01,0xe0, /* .......####..... */
+ /*0886:*/ 0x03,0xc0, /* ......####...... */
+ /*0888:*/ 0x07,0x80, /* .....####....... */
+ /*088a:*/ 0x07,0x80, /* .....####....... */
+ /*088c:*/ 0x0f,0x00, /* ....####........ */
+ /*088e:*/ 0x1e,0x00, /* ...####......... */
+ /*0890:*/ 0x1e,0x00, /* ...####......... */
+ /*0892:*/ 0x3c,0x00, /* ..####.......... */
+ /*0894:*/ 0x38,0x00, /* ..###........... */
+ /*0896:*/ 0x78,0x00, /* .####........... */
+ /*0898:*/ 0xf0,0x00, /* ####............ */
+ /*089a:*/ 0xff,0xfc, /* ##############.. */
+ /*089c:*/ 0xff,0xfc, /* ##############.. */
+/* --- new character bracketleft (91) starting at offset 0x089e --- */
+ /*089e:*/ 8, 5, 24, 1, -5, /* width and bbox (w,h,x,y) */
+ /*08a3:*/ 0xf8, /* #####... */
+ /*08a4:*/ 0xf8, /* #####... */
+ /*08a5:*/ 0xe0, /* ###..... */
+ /*08a6:*/ 0xe0, /* ###..... */
+ /*08a7:*/ 0xe0, /* ###..... */
+ /*08a8:*/ 0xe0, /* ###..... */
+ /*08a9:*/ 0xe0, /* ###..... */
+ /*08aa:*/ 0xe0, /* ###..... */
+ /*08ab:*/ 0xe0, /* ###..... */
+ /*08ac:*/ 0xe0, /* ###..... */
+ /*08ad:*/ 0xe0, /* ###..... */
+ /*08ae:*/ 0xe0, /* ###..... */
+ /*08af:*/ 0xe0, /* ###..... */
+ /*08b0:*/ 0xe0, /* ###..... */
+ /*08b1:*/ 0xe0, /* ###..... */
+ /*08b2:*/ 0xe0, /* ###..... */
+ /*08b3:*/ 0xe0, /* ###..... */
+ /*08b4:*/ 0xe0, /* ###..... */
+ /*08b5:*/ 0xe0, /* ###..... */
+ /*08b6:*/ 0xe0, /* ###..... */
+ /*08b7:*/ 0xe0, /* ###..... */
+ /*08b8:*/ 0xe0, /* ###..... */
+ /*08b9:*/ 0xf8, /* #####... */
+ /*08ba:*/ 0xf8, /* #####... */
+/* --- new character backslash (92) starting at offset 0x08bb --- */
+ /*08bb:*/ 8, 8, 19, 0, 0, /* width and bbox (w,h,x,y) */
+ /*08c0:*/ 0xe0, /* ###..... */
+ /*08c1:*/ 0xe0, /* ###..... */
+ /*08c2:*/ 0x60, /* .##..... */
+ /*08c3:*/ 0x60, /* .##..... */
+ /*08c4:*/ 0x70, /* .###.... */
+ /*08c5:*/ 0x30, /* ..##.... */
+ /*08c6:*/ 0x30, /* ..##.... */
+ /*08c7:*/ 0x38, /* ..###... */
+ /*08c8:*/ 0x38, /* ..###... */
+ /*08c9:*/ 0x18, /* ...##... */
+ /*08ca:*/ 0x18, /* ...##... */
+ /*08cb:*/ 0x1c, /* ...###.. */
+ /*08cc:*/ 0x0c, /* ....##.. */
+ /*08cd:*/ 0x0c, /* ....##.. */
+ /*08ce:*/ 0x0e, /* ....###. */
+ /*08cf:*/ 0x06, /* .....##. */
+ /*08d0:*/ 0x06, /* .....##. */
+ /*08d1:*/ 0x07, /* .....### */
+ /*08d2:*/ 0x07, /* .....### */
+/* --- new character bracketright (93) starting at offset 0x08d3 --- */
+ /*08d3:*/ 8, 5, 24, 2, -5, /* width and bbox (w,h,x,y) */
+ /*08d8:*/ 0xf8, /* #####... */
+ /*08d9:*/ 0xf8, /* #####... */
+ /*08da:*/ 0x38, /* ..###... */
+ /*08db:*/ 0x38, /* ..###... */
+ /*08dc:*/ 0x38, /* ..###... */
+ /*08dd:*/ 0x38, /* ..###... */
+ /*08de:*/ 0x38, /* ..###... */
+ /*08df:*/ 0x38, /* ..###... */
+ /*08e0:*/ 0x38, /* ..###... */
+ /*08e1:*/ 0x38, /* ..###... */
+ /*08e2:*/ 0x38, /* ..###... */
+ /*08e3:*/ 0x38, /* ..###... */
+ /*08e4:*/ 0x38, /* ..###... */
+ /*08e5:*/ 0x38, /* ..###... */
+ /*08e6:*/ 0x38, /* ..###... */
+ /*08e7:*/ 0x38, /* ..###... */
+ /*08e8:*/ 0x38, /* ..###... */
+ /*08e9:*/ 0x38, /* ..###... */
+ /*08ea:*/ 0x38, /* ..###... */
+ /*08eb:*/ 0x38, /* ..###... */
+ /*08ec:*/ 0x38, /* ..###... */
+ /*08ed:*/ 0x38, /* ..###... */
+ /*08ee:*/ 0xf8, /* #####... */
+ /*08ef:*/ 0xf8, /* #####... */
+/* --- new character asciicircum (94) starting at offset 0x08f0 --- */
+ /*08f0:*/ 14, 11, 9, 1, 10, /* width and bbox (w,h,x,y) */
+ /*08f5:*/ 0x0e,0x00, /* ....###......... */
+ /*08f7:*/ 0x0e,0x00, /* ....###......... */
+ /*08f9:*/ 0x1f,0x00, /* ...#####........ */
+ /*08fb:*/ 0x1b,0x00, /* ...##.##........ */
+ /*08fd:*/ 0x3b,0x80, /* ..###.###....... */
+ /*08ff:*/ 0x71,0xc0, /* .###...###...... */
+ /*0901:*/ 0x71,0xc0, /* .###...###...... */
+ /*0903:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0905:*/ 0xe0,0xe0, /* ###.....###..... */
+/* --- new character underscore (95) starting at offset 0x0907 --- */
+ /*0907:*/ 14, 14, 2, 0, -5, /* width and bbox (w,h,x,y) */
+ /*090c:*/ 0xff,0xfc, /* ##############.. */
+ /*090e:*/ 0xff,0xfc, /* ##############.. */
+/* --- new character grave (96) starting at offset 0x0910 --- */
+ /*0910:*/ 8, 6, 4, 1, 15, /* width and bbox (w,h,x,y) */
+ /*0915:*/ 0xe0, /* ###..... */
+ /*0916:*/ 0x70, /* .###.... */
+ /*0917:*/ 0x38, /* ..###... */
+ /*0918:*/ 0x1c, /* ...###.. */
+/* --- new character a (97) starting at offset 0x0919 --- */
+ /*0919:*/ 14, 12, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*091e:*/ 0x1f,0x80, /* ...######....... */
+ /*0920:*/ 0x3f,0xc0, /* ..########...... */
+ /*0922:*/ 0x71,0xe0, /* .###...####..... */
+ /*0924:*/ 0x70,0xe0, /* .###....###..... */
+ /*0926:*/ 0x00,0xe0, /* ........###..... */
+ /*0928:*/ 0x07,0xe0, /* .....######..... */
+ /*092a:*/ 0x3f,0xe0, /* ..#########..... */
+ /*092c:*/ 0x7c,0xe0, /* .#####..###..... */
+ /*092e:*/ 0xf0,0xe0, /* ####....###..... */
+ /*0930:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0932:*/ 0xe1,0xe0, /* ###....####..... */
+ /*0934:*/ 0xf3,0xe0, /* ####..#####..... */
+ /*0936:*/ 0x7f,0xf0, /* .###########.... */
+ /*0938:*/ 0x3e,0x70, /* ..#####..###.... */
+/* --- new character b (98) starting at offset 0x093a --- */
+ /*093a:*/ 15, 12, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*093f:*/ 0xe0,0x00, /* ###............. */
+ /*0941:*/ 0xe0,0x00, /* ###............. */
+ /*0943:*/ 0xe0,0x00, /* ###............. */
+ /*0945:*/ 0xe0,0x00, /* ###............. */
+ /*0947:*/ 0xe0,0x00, /* ###............. */
+ /*0949:*/ 0xef,0x80, /* ###.#####....... */
+ /*094b:*/ 0xff,0xc0, /* ##########...... */
+ /*094d:*/ 0xf9,0xe0, /* #####..####..... */
+ /*094f:*/ 0xf0,0xe0, /* ####....###..... */
+ /*0951:*/ 0xe0,0x70, /* ###......###.... */
+ /*0953:*/ 0xe0,0x70, /* ###......###.... */
+ /*0955:*/ 0xe0,0x70, /* ###......###.... */
+ /*0957:*/ 0xe0,0x70, /* ###......###.... */
+ /*0959:*/ 0xe0,0x70, /* ###......###.... */
+ /*095b:*/ 0xe0,0x70, /* ###......###.... */
+ /*095d:*/ 0xf0,0xe0, /* ####....###..... */
+ /*095f:*/ 0xf9,0xe0, /* #####..####..... */
+ /*0961:*/ 0xff,0xc0, /* ##########...... */
+ /*0963:*/ 0xef,0x80, /* ###.#####....... */
+/* --- new character c (99) starting at offset 0x0965 --- */
+ /*0965:*/ 13, 11, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*096a:*/ 0x1f,0x80, /* ...######....... */
+ /*096c:*/ 0x3f,0xc0, /* ..########...... */
+ /*096e:*/ 0x79,0xe0, /* .####..####..... */
+ /*0970:*/ 0x70,0xe0, /* .###....###..... */
+ /*0972:*/ 0xe0,0x00, /* ###............. */
+ /*0974:*/ 0xe0,0x00, /* ###............. */
+ /*0976:*/ 0xe0,0x00, /* ###............. */
+ /*0978:*/ 0xe0,0x00, /* ###............. */
+ /*097a:*/ 0xe0,0x00, /* ###............. */
+ /*097c:*/ 0xe0,0x00, /* ###............. */
+ /*097e:*/ 0x70,0xe0, /* .###....###..... */
+ /*0980:*/ 0x79,0xe0, /* .####..####..... */
+ /*0982:*/ 0x3f,0xc0, /* ..########...... */
+ /*0984:*/ 0x1f,0x80, /* ...######....... */
+/* --- new character d (100) starting at offset 0x0986 --- */
+ /*0986:*/ 15, 12, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*098b:*/ 0x00,0x70, /* .........###.... */
+ /*098d:*/ 0x00,0x70, /* .........###.... */
+ /*098f:*/ 0x00,0x70, /* .........###.... */
+ /*0991:*/ 0x00,0x70, /* .........###.... */
+ /*0993:*/ 0x00,0x70, /* .........###.... */
+ /*0995:*/ 0x1f,0x70, /* ...#####.###.... */
+ /*0997:*/ 0x3f,0xf0, /* ..##########.... */
+ /*0999:*/ 0x79,0xf0, /* .####..#####.... */
+ /*099b:*/ 0x70,0xf0, /* .###....####.... */
+ /*099d:*/ 0xe0,0x70, /* ###......###.... */
+ /*099f:*/ 0xe0,0x70, /* ###......###.... */
+ /*09a1:*/ 0xe0,0x70, /* ###......###.... */
+ /*09a3:*/ 0xe0,0x70, /* ###......###.... */
+ /*09a5:*/ 0xe0,0x70, /* ###......###.... */
+ /*09a7:*/ 0xe0,0x70, /* ###......###.... */
+ /*09a9:*/ 0x70,0xf0, /* .###....####.... */
+ /*09ab:*/ 0x79,0xf0, /* .####..#####.... */
+ /*09ad:*/ 0x3f,0xf0, /* ..##########.... */
+ /*09af:*/ 0x1f,0x70, /* ...#####.###.... */
+/* --- new character e (101) starting at offset 0x09b1 --- */
+ /*09b1:*/ 14, 12, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*09b6:*/ 0x0f,0x00, /* ....####........ */
+ /*09b8:*/ 0x3f,0xc0, /* ..########...... */
+ /*09ba:*/ 0x79,0xe0, /* .####..####..... */
+ /*09bc:*/ 0x70,0xe0, /* .###....###..... */
+ /*09be:*/ 0xe0,0x70, /* ###......###.... */
+ /*09c0:*/ 0xe0,0x70, /* ###......###.... */
+ /*09c2:*/ 0xff,0xf0, /* ############.... */
+ /*09c4:*/ 0xff,0xf0, /* ############.... */
+ /*09c6:*/ 0xe0,0x00, /* ###............. */
+ /*09c8:*/ 0xe0,0x00, /* ###............. */
+ /*09ca:*/ 0x70,0x70, /* .###.....###.... */
+ /*09cc:*/ 0x78,0xf0, /* .####...####.... */
+ /*09ce:*/ 0x3f,0xe0, /* ..#########..... */
+ /*09d0:*/ 0x0f,0x80, /* ....#####....... */
+/* --- new character f (102) starting at offset 0x09d2 --- */
+ /*09d2:*/ 9, 7, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*09d7:*/ 0x1e, /* ...####. */
+ /*09d8:*/ 0x3e, /* ..#####. */
+ /*09d9:*/ 0x38, /* ..###... */
+ /*09da:*/ 0x38, /* ..###... */
+ /*09db:*/ 0x38, /* ..###... */
+ /*09dc:*/ 0xfe, /* #######. */
+ /*09dd:*/ 0xfe, /* #######. */
+ /*09de:*/ 0x38, /* ..###... */
+ /*09df:*/ 0x38, /* ..###... */
+ /*09e0:*/ 0x38, /* ..###... */
+ /*09e1:*/ 0x38, /* ..###... */
+ /*09e2:*/ 0x38, /* ..###... */
+ /*09e3:*/ 0x38, /* ..###... */
+ /*09e4:*/ 0x38, /* ..###... */
+ /*09e5:*/ 0x38, /* ..###... */
+ /*09e6:*/ 0x38, /* ..###... */
+ /*09e7:*/ 0x38, /* ..###... */
+ /*09e8:*/ 0x38, /* ..###... */
+ /*09e9:*/ 0x38, /* ..###... */
+/* --- new character g (103) starting at offset 0x09ea --- */
+ /*09ea:*/ 15, 12, 19, 1, -5, /* width and bbox (w,h,x,y) */
+ /*09ef:*/ 0x1f,0x70, /* ...#####.###.... */
+ /*09f1:*/ 0x3f,0xf0, /* ..##########.... */
+ /*09f3:*/ 0x79,0xf0, /* .####..#####.... */
+ /*09f5:*/ 0x70,0xf0, /* .###....####.... */
+ /*09f7:*/ 0xe0,0x70, /* ###......###.... */
+ /*09f9:*/ 0xe0,0x70, /* ###......###.... */
+ /*09fb:*/ 0xe0,0x70, /* ###......###.... */
+ /*09fd:*/ 0xe0,0x70, /* ###......###.... */
+ /*09ff:*/ 0xe0,0x70, /* ###......###.... */
+ /*0a01:*/ 0xe0,0x70, /* ###......###.... */
+ /*0a03:*/ 0x70,0xf0, /* .###....####.... */
+ /*0a05:*/ 0x79,0xf0, /* .####..#####.... */
+ /*0a07:*/ 0x3f,0xf0, /* ..##########.... */
+ /*0a09:*/ 0x1f,0x70, /* ...#####.###.... */
+ /*0a0b:*/ 0x00,0x70, /* .........###.... */
+ /*0a0d:*/ 0xe0,0x70, /* ###......###.... */
+ /*0a0f:*/ 0xf0,0xe0, /* ####....###..... */
+ /*0a11:*/ 0x7f,0xe0, /* .##########..... */
+ /*0a13:*/ 0x1f,0x80, /* ...######....... */
+/* --- new character h (104) starting at offset 0x0a15 --- */
+ /*0a15:*/ 15, 11, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0a1a:*/ 0xe0,0x00, /* ###............. */
+ /*0a1c:*/ 0xe0,0x00, /* ###............. */
+ /*0a1e:*/ 0xe0,0x00, /* ###............. */
+ /*0a20:*/ 0xe0,0x00, /* ###............. */
+ /*0a22:*/ 0xe0,0x00, /* ###............. */
+ /*0a24:*/ 0xef,0x00, /* ###.####........ */
+ /*0a26:*/ 0xff,0xc0, /* ##########...... */
+ /*0a28:*/ 0xf1,0xc0, /* ####...###...... */
+ /*0a2a:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0a2c:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0a2e:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0a30:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0a32:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0a34:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0a36:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0a38:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0a3a:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0a3c:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0a3e:*/ 0xe0,0xe0, /* ###.....###..... */
+/* --- new character i (105) starting at offset 0x0a40 --- */
+ /*0a40:*/ 7, 3, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0a45:*/ 0xe0, /* ###..... */
+ /*0a46:*/ 0xe0, /* ###..... */
+ /*0a47:*/ 0xe0, /* ###..... */
+ /*0a48:*/ 0x00, /* ........ */
+ /*0a49:*/ 0x00, /* ........ */
+ /*0a4a:*/ 0xe0, /* ###..... */
+ /*0a4b:*/ 0xe0, /* ###..... */
+ /*0a4c:*/ 0xe0, /* ###..... */
+ /*0a4d:*/ 0xe0, /* ###..... */
+ /*0a4e:*/ 0xe0, /* ###..... */
+ /*0a4f:*/ 0xe0, /* ###..... */
+ /*0a50:*/ 0xe0, /* ###..... */
+ /*0a51:*/ 0xe0, /* ###..... */
+ /*0a52:*/ 0xe0, /* ###..... */
+ /*0a53:*/ 0xe0, /* ###..... */
+ /*0a54:*/ 0xe0, /* ###..... */
+ /*0a55:*/ 0xe0, /* ###..... */
+ /*0a56:*/ 0xe0, /* ###..... */
+ /*0a57:*/ 0xe0, /* ###..... */
+/* --- new character j (106) starting at offset 0x0a58 --- */
+ /*0a58:*/ 7, 5, 24, 0, -5, /* width and bbox (w,h,x,y) */
+ /*0a5d:*/ 0x38, /* ..###... */
+ /*0a5e:*/ 0x38, /* ..###... */
+ /*0a5f:*/ 0x38, /* ..###... */
+ /*0a60:*/ 0x00, /* ........ */
+ /*0a61:*/ 0x00, /* ........ */
+ /*0a62:*/ 0x38, /* ..###... */
+ /*0a63:*/ 0x38, /* ..###... */
+ /*0a64:*/ 0x38, /* ..###... */
+ /*0a65:*/ 0x38, /* ..###... */
+ /*0a66:*/ 0x38, /* ..###... */
+ /*0a67:*/ 0x38, /* ..###... */
+ /*0a68:*/ 0x38, /* ..###... */
+ /*0a69:*/ 0x38, /* ..###... */
+ /*0a6a:*/ 0x38, /* ..###... */
+ /*0a6b:*/ 0x38, /* ..###... */
+ /*0a6c:*/ 0x38, /* ..###... */
+ /*0a6d:*/ 0x38, /* ..###... */
+ /*0a6e:*/ 0x38, /* ..###... */
+ /*0a6f:*/ 0x38, /* ..###... */
+ /*0a70:*/ 0x38, /* ..###... */
+ /*0a71:*/ 0x38, /* ..###... */
+ /*0a72:*/ 0x38, /* ..###... */
+ /*0a73:*/ 0xf8, /* #####... */
+ /*0a74:*/ 0xf0, /* ####.... */
+/* --- new character k (107) starting at offset 0x0a75 --- */
+ /*0a75:*/ 14, 12, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0a7a:*/ 0xe0,0x00, /* ###............. */
+ /*0a7c:*/ 0xe0,0x00, /* ###............. */
+ /*0a7e:*/ 0xe0,0x00, /* ###............. */
+ /*0a80:*/ 0xe0,0x00, /* ###............. */
+ /*0a82:*/ 0xe0,0x00, /* ###............. */
+ /*0a84:*/ 0xe1,0xe0, /* ###....####..... */
+ /*0a86:*/ 0xe3,0xc0, /* ###...####...... */
+ /*0a88:*/ 0xe7,0x80, /* ###..####....... */
+ /*0a8a:*/ 0xef,0x00, /* ###.####........ */
+ /*0a8c:*/ 0xfe,0x00, /* #######......... */
+ /*0a8e:*/ 0xfc,0x00, /* ######.......... */
+ /*0a90:*/ 0xfe,0x00, /* #######......... */
+ /*0a92:*/ 0xef,0x00, /* ###.####........ */
+ /*0a94:*/ 0xe7,0x00, /* ###..###........ */
+ /*0a96:*/ 0xe7,0x80, /* ###..####....... */
+ /*0a98:*/ 0xe3,0xc0, /* ###...####...... */
+ /*0a9a:*/ 0xe1,0xc0, /* ###....###...... */
+ /*0a9c:*/ 0xe1,0xe0, /* ###....####..... */
+ /*0a9e:*/ 0xe0,0xf0, /* ###.....####.... */
+/* --- new character l (108) starting at offset 0x0aa0 --- */
+ /*0aa0:*/ 7, 3, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0aa5:*/ 0xe0, /* ###..... */
+ /*0aa6:*/ 0xe0, /* ###..... */
+ /*0aa7:*/ 0xe0, /* ###..... */
+ /*0aa8:*/ 0xe0, /* ###..... */
+ /*0aa9:*/ 0xe0, /* ###..... */
+ /*0aaa:*/ 0xe0, /* ###..... */
+ /*0aab:*/ 0xe0, /* ###..... */
+ /*0aac:*/ 0xe0, /* ###..... */
+ /*0aad:*/ 0xe0, /* ###..... */
+ /*0aae:*/ 0xe0, /* ###..... */
+ /*0aaf:*/ 0xe0, /* ###..... */
+ /*0ab0:*/ 0xe0, /* ###..... */
+ /*0ab1:*/ 0xe0, /* ###..... */
+ /*0ab2:*/ 0xe0, /* ###..... */
+ /*0ab3:*/ 0xe0, /* ###..... */
+ /*0ab4:*/ 0xe0, /* ###..... */
+ /*0ab5:*/ 0xe0, /* ###..... */
+ /*0ab6:*/ 0xe0, /* ###..... */
+ /*0ab7:*/ 0xe0, /* ###..... */
+/* --- new character m (109) starting at offset 0x0ab8 --- */
+ /*0ab8:*/ 21, 17, 14, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0abd:*/ 0xef,0x3e,0x00, /* ###.####..#####......... */
+ /*0ac0:*/ 0xff,0xff,0x00, /* ################........ */
+ /*0ac3:*/ 0xf3,0xe7,0x80, /* ####..#####..####....... */
+ /*0ac6:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+ /*0ac9:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+ /*0acc:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+ /*0acf:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+ /*0ad2:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+ /*0ad5:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+ /*0ad8:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+ /*0adb:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+ /*0ade:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+ /*0ae1:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+ /*0ae4:*/ 0xe1,0xc3,0x80, /* ###....###....###....... */
+/* --- new character n (110) starting at offset 0x0ae7 --- */
+ /*0ae7:*/ 15, 11, 14, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0aec:*/ 0xef,0x80, /* ###.#####....... */
+ /*0aee:*/ 0xff,0xc0, /* ##########...... */
+ /*0af0:*/ 0xf1,0xc0, /* ####...###...... */
+ /*0af2:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0af4:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0af6:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0af8:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0afa:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0afc:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0afe:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0b00:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0b02:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0b04:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0b06:*/ 0xe0,0xe0, /* ###.....###..... */
+/* --- new character o (111) starting at offset 0x0b08 --- */
+ /*0b08:*/ 14, 12, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0b0d:*/ 0x0f,0x00, /* ....####........ */
+ /*0b0f:*/ 0x3f,0xc0, /* ..########...... */
+ /*0b11:*/ 0x79,0xe0, /* .####..####..... */
+ /*0b13:*/ 0x70,0xe0, /* .###....###..... */
+ /*0b15:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b17:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b19:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b1b:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b1d:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b1f:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b21:*/ 0x70,0xe0, /* .###....###..... */
+ /*0b23:*/ 0x79,0xe0, /* .####..####..... */
+ /*0b25:*/ 0x3f,0xc0, /* ..########...... */
+ /*0b27:*/ 0x0f,0x00, /* ....####........ */
+/* --- new character p (112) starting at offset 0x0b29 --- */
+ /*0b29:*/ 15, 12, 19, 2, -5, /* width and bbox (w,h,x,y) */
+ /*0b2e:*/ 0xef,0x80, /* ###.#####....... */
+ /*0b30:*/ 0xff,0xc0, /* ##########...... */
+ /*0b32:*/ 0xf9,0xe0, /* #####..####..... */
+ /*0b34:*/ 0xf0,0xe0, /* ####....###..... */
+ /*0b36:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b38:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b3a:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b3c:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b3e:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b40:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b42:*/ 0xf0,0xe0, /* ####....###..... */
+ /*0b44:*/ 0xf9,0xe0, /* #####..####..... */
+ /*0b46:*/ 0xff,0xc0, /* ##########...... */
+ /*0b48:*/ 0xef,0x80, /* ###.#####....... */
+ /*0b4a:*/ 0xe0,0x00, /* ###............. */
+ /*0b4c:*/ 0xe0,0x00, /* ###............. */
+ /*0b4e:*/ 0xe0,0x00, /* ###............. */
+ /*0b50:*/ 0xe0,0x00, /* ###............. */
+ /*0b52:*/ 0xe0,0x00, /* ###............. */
+/* --- new character q (113) starting at offset 0x0b54 --- */
+ /*0b54:*/ 15, 12, 19, 1, -5, /* width and bbox (w,h,x,y) */
+ /*0b59:*/ 0x1f,0x70, /* ...#####.###.... */
+ /*0b5b:*/ 0x3f,0xf0, /* ..##########.... */
+ /*0b5d:*/ 0x79,0xf0, /* .####..#####.... */
+ /*0b5f:*/ 0x70,0xf0, /* .###....####.... */
+ /*0b61:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b63:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b65:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b67:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b69:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b6b:*/ 0xe0,0x70, /* ###......###.... */
+ /*0b6d:*/ 0x70,0xf0, /* .###....####.... */
+ /*0b6f:*/ 0x79,0xf0, /* .####..#####.... */
+ /*0b71:*/ 0x3f,0xf0, /* ..##########.... */
+ /*0b73:*/ 0x1f,0x70, /* ...#####.###.... */
+ /*0b75:*/ 0x00,0x70, /* .........###.... */
+ /*0b77:*/ 0x00,0x70, /* .........###.... */
+ /*0b79:*/ 0x00,0x70, /* .........###.... */
+ /*0b7b:*/ 0x00,0x70, /* .........###.... */
+ /*0b7d:*/ 0x00,0x70, /* .........###.... */
+/* --- new character r (114) starting at offset 0x0b7f --- */
+ /*0b7f:*/ 10, 7, 14, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0b84:*/ 0xe6, /* ###..##. */
+ /*0b85:*/ 0xee, /* ###.###. */
+ /*0b86:*/ 0xfe, /* #######. */
+ /*0b87:*/ 0xf0, /* ####.... */
+ /*0b88:*/ 0xe0, /* ###..... */
+ /*0b89:*/ 0xe0, /* ###..... */
+ /*0b8a:*/ 0xe0, /* ###..... */
+ /*0b8b:*/ 0xe0, /* ###..... */
+ /*0b8c:*/ 0xe0, /* ###..... */
+ /*0b8d:*/ 0xe0, /* ###..... */
+ /*0b8e:*/ 0xe0, /* ###..... */
+ /*0b8f:*/ 0xe0, /* ###..... */
+ /*0b90:*/ 0xe0, /* ###..... */
+ /*0b91:*/ 0xe0, /* ###..... */
+/* --- new character s (115) starting at offset 0x0b92 --- */
+ /*0b92:*/ 13, 11, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0b97:*/ 0x3f,0x00, /* ..######........ */
+ /*0b99:*/ 0x7f,0x80, /* .########....... */
+ /*0b9b:*/ 0xf3,0xc0, /* ####..####...... */
+ /*0b9d:*/ 0xe1,0xc0, /* ###....###...... */
+ /*0b9f:*/ 0xe0,0x00, /* ###............. */
+ /*0ba1:*/ 0xfc,0x00, /* ######.......... */
+ /*0ba3:*/ 0x7f,0x80, /* .########....... */
+ /*0ba5:*/ 0x0f,0xc0, /* ....######...... */
+ /*0ba7:*/ 0x01,0xe0, /* .......####..... */
+ /*0ba9:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0bab:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0bad:*/ 0xf1,0xe0, /* ####...####..... */
+ /*0baf:*/ 0x7f,0xc0, /* .#########...... */
+ /*0bb1:*/ 0x3f,0x80, /* ..#######....... */
+/* --- new character t (116) starting at offset 0x0bb3 --- */
+ /*0bb3:*/ 9, 7, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0bb8:*/ 0x38, /* ..###... */
+ /*0bb9:*/ 0x38, /* ..###... */
+ /*0bba:*/ 0x38, /* ..###... */
+ /*0bbb:*/ 0x38, /* ..###... */
+ /*0bbc:*/ 0xfe, /* #######. */
+ /*0bbd:*/ 0xfe, /* #######. */
+ /*0bbe:*/ 0x38, /* ..###... */
+ /*0bbf:*/ 0x38, /* ..###... */
+ /*0bc0:*/ 0x38, /* ..###... */
+ /*0bc1:*/ 0x38, /* ..###... */
+ /*0bc2:*/ 0x38, /* ..###... */
+ /*0bc3:*/ 0x38, /* ..###... */
+ /*0bc4:*/ 0x38, /* ..###... */
+ /*0bc5:*/ 0x38, /* ..###... */
+ /*0bc6:*/ 0x38, /* ..###... */
+ /*0bc7:*/ 0x38, /* ..###... */
+ /*0bc8:*/ 0x3e, /* ..#####. */
+ /*0bc9:*/ 0x1e, /* ...####. */
+/* --- new character u (117) starting at offset 0x0bca --- */
+ /*0bca:*/ 15, 11, 14, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0bcf:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0bd1:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0bd3:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0bd5:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0bd7:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0bd9:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0bdb:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0bdd:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0bdf:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0be1:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0be3:*/ 0xe1,0xe0, /* ###....####..... */
+ /*0be5:*/ 0x73,0xe0, /* .###..#####..... */
+ /*0be7:*/ 0x7e,0xe0, /* .######.###..... */
+ /*0be9:*/ 0x1c,0xe0, /* ...###..###..... */
+/* --- new character v (118) starting at offset 0x0beb --- */
+ /*0beb:*/ 14, 12, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0bf0:*/ 0xe0,0x70, /* ###......###.... */
+ /*0bf2:*/ 0xe0,0x70, /* ###......###.... */
+ /*0bf4:*/ 0xe0,0x70, /* ###......###.... */
+ /*0bf6:*/ 0x70,0xe0, /* .###....###..... */
+ /*0bf8:*/ 0x70,0xe0, /* .###....###..... */
+ /*0bfa:*/ 0x70,0xe0, /* .###....###..... */
+ /*0bfc:*/ 0x39,0xc0, /* ..###..###...... */
+ /*0bfe:*/ 0x39,0xc0, /* ..###..###...... */
+ /*0c00:*/ 0x39,0xc0, /* ..###..###...... */
+ /*0c02:*/ 0x1f,0x80, /* ...######....... */
+ /*0c04:*/ 0x1f,0x80, /* ...######....... */
+ /*0c06:*/ 0x0f,0x00, /* ....####........ */
+ /*0c08:*/ 0x0f,0x00, /* ....####........ */
+ /*0c0a:*/ 0x0f,0x00, /* ....####........ */
+/* --- new character w (119) starting at offset 0x0c0c --- */
+ /*0c0c:*/ 19, 19, 14, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0c11:*/ 0xe0,0xe0,0xe0, /* ###.....###.....###..... */
+ /*0c14:*/ 0xe0,0xe0,0xe0, /* ###.....###.....###..... */
+ /*0c17:*/ 0x60,0xe0,0xc0, /* .##.....###.....##...... */
+ /*0c1a:*/ 0x71,0xf1,0xc0, /* .###...#####...###...... */
+ /*0c1d:*/ 0x71,0xf1,0xc0, /* .###...#####...###...... */
+ /*0c20:*/ 0x31,0xb1,0x80, /* ..##...##.##...##....... */
+ /*0c23:*/ 0x33,0xb9,0x80, /* ..##..###.###..##....... */
+ /*0c26:*/ 0x3b,0xbb,0x80, /* ..###.###.###.###....... */
+ /*0c29:*/ 0x1b,0x1b,0x00, /* ...##.##...##.##........ */
+ /*0c2c:*/ 0x1f,0x1f,0x00, /* ...#####...#####........ */
+ /*0c2f:*/ 0x1f,0x1f,0x00, /* ...#####...#####........ */
+ /*0c32:*/ 0x0e,0x0e,0x00, /* ....###.....###......... */
+ /*0c35:*/ 0x0e,0x0e,0x00, /* ....###.....###......... */
+ /*0c38:*/ 0x0e,0x0e,0x00, /* ....###.....###......... */
+/* --- new character x (120) starting at offset 0x0c3b --- */
+ /*0c3b:*/ 13, 11, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0c40:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*0c42:*/ 0xf1,0xe0, /* ####...####..... */
+ /*0c44:*/ 0x71,0xc0, /* .###...###...... */
+ /*0c46:*/ 0x3b,0x80, /* ..###.###....... */
+ /*0c48:*/ 0x3f,0x80, /* ..#######....... */
+ /*0c4a:*/ 0x1f,0x00, /* ...#####........ */
+ /*0c4c:*/ 0x0e,0x00, /* ....###......... */
+ /*0c4e:*/ 0x1f,0x00, /* ...#####........ */
+ /*0c50:*/ 0x1f,0x00, /* ...#####........ */
+ /*0c52:*/ 0x3b,0x80, /* ..###.###....... */
+ /*0c54:*/ 0x7b,0xc0, /* .####.####...... */
+ /*0c56:*/ 0x71,0xc0, /* .###...###...... */
+ /*0c58:*/ 0xf1,0xe0, /* ####...####..... */
+ /*0c5a:*/ 0xe0,0xe0, /* ###.....###..... */
+/* --- new character y (121) starting at offset 0x0c5c --- */
+ /*0c5c:*/ 15, 13, 19, 1, -5, /* width and bbox (w,h,x,y) */
+ /*0c61:*/ 0xe0,0x38, /* ###.......###... */
+ /*0c63:*/ 0xe0,0x38, /* ###.......###... */
+ /*0c65:*/ 0x70,0x38, /* .###......###... */
+ /*0c67:*/ 0x78,0x70, /* .####....###.... */
+ /*0c69:*/ 0x38,0x70, /* ..###....###.... */
+ /*0c6b:*/ 0x3c,0xf0, /* ..####..####.... */
+ /*0c6d:*/ 0x1c,0xe0, /* ...###..###..... */
+ /*0c6f:*/ 0x1c,0xe0, /* ...###..###..... */
+ /*0c71:*/ 0x0f,0xc0, /* ....######...... */
+ /*0c73:*/ 0x0f,0xc0, /* ....######...... */
+ /*0c75:*/ 0x07,0xc0, /* .....#####...... */
+ /*0c77:*/ 0x07,0x80, /* .....####....... */
+ /*0c79:*/ 0x03,0x80, /* ......###....... */
+ /*0c7b:*/ 0x03,0x80, /* ......###....... */
+ /*0c7d:*/ 0x07,0x00, /* .....###........ */
+ /*0c7f:*/ 0x07,0x00, /* .....###........ */
+ /*0c81:*/ 0x0e,0x00, /* ....###......... */
+ /*0c83:*/ 0x3e,0x00, /* ..#####......... */
+ /*0c85:*/ 0x3c,0x00, /* ..####.......... */
+/* --- new character z (122) starting at offset 0x0c87 --- */
+ /*0c87:*/ 13, 11, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0c8c:*/ 0xff,0xe0, /* ###########..... */
+ /*0c8e:*/ 0xff,0xe0, /* ###########..... */
+ /*0c90:*/ 0x01,0xc0, /* .......###...... */
+ /*0c92:*/ 0x03,0x80, /* ......###....... */
+ /*0c94:*/ 0x07,0x80, /* .....####....... */
+ /*0c96:*/ 0x0f,0x00, /* ....####........ */
+ /*0c98:*/ 0x0e,0x00, /* ....###......... */
+ /*0c9a:*/ 0x1e,0x00, /* ...####......... */
+ /*0c9c:*/ 0x3c,0x00, /* ..####.......... */
+ /*0c9e:*/ 0x38,0x00, /* ..###........... */
+ /*0ca0:*/ 0x70,0x00, /* .###............ */
+ /*0ca2:*/ 0xf0,0x00, /* ####............ */
+ /*0ca4:*/ 0xff,0xe0, /* ###########..... */
+ /*0ca6:*/ 0xff,0xe0, /* ###########..... */
+/* --- new character braceleft (123) starting at offset 0x0ca8 --- */
+ /*0ca8:*/ 10, 7, 24, 1, -5, /* width and bbox (w,h,x,y) */
+ /*0cad:*/ 0x0e, /* ....###. */
+ /*0cae:*/ 0x1c, /* ...###.. */
+ /*0caf:*/ 0x38, /* ..###... */
+ /*0cb0:*/ 0x38, /* ..###... */
+ /*0cb1:*/ 0x38, /* ..###... */
+ /*0cb2:*/ 0x38, /* ..###... */
+ /*0cb3:*/ 0x38, /* ..###... */
+ /*0cb4:*/ 0x38, /* ..###... */
+ /*0cb5:*/ 0x38, /* ..###... */
+ /*0cb6:*/ 0x38, /* ..###... */
+ /*0cb7:*/ 0x70, /* .###.... */
+ /*0cb8:*/ 0xe0, /* ###..... */
+ /*0cb9:*/ 0xe0, /* ###..... */
+ /*0cba:*/ 0x70, /* .###.... */
+ /*0cbb:*/ 0x38, /* ..###... */
+ /*0cbc:*/ 0x38, /* ..###... */
+ /*0cbd:*/ 0x38, /* ..###... */
+ /*0cbe:*/ 0x38, /* ..###... */
+ /*0cbf:*/ 0x38, /* ..###... */
+ /*0cc0:*/ 0x38, /* ..###... */
+ /*0cc1:*/ 0x38, /* ..###... */
+ /*0cc2:*/ 0x38, /* ..###... */
+ /*0cc3:*/ 0x1c, /* ...###.. */
+ /*0cc4:*/ 0x0e, /* ....###. */
+/* --- new character bar (124) starting at offset 0x0cc5 --- */
+ /*0cc5:*/ 7, 3, 24, 2, -5, /* width and bbox (w,h,x,y) */
+ /*0cca:*/ 0xe0, /* ###..... */
+ /*0ccb:*/ 0xe0, /* ###..... */
+ /*0ccc:*/ 0xe0, /* ###..... */
+ /*0ccd:*/ 0xe0, /* ###..... */
+ /*0cce:*/ 0xe0, /* ###..... */
+ /*0ccf:*/ 0xe0, /* ###..... */
+ /*0cd0:*/ 0xe0, /* ###..... */
+ /*0cd1:*/ 0xe0, /* ###..... */
+ /*0cd2:*/ 0xe0, /* ###..... */
+ /*0cd3:*/ 0xe0, /* ###..... */
+ /*0cd4:*/ 0xe0, /* ###..... */
+ /*0cd5:*/ 0xe0, /* ###..... */
+ /*0cd6:*/ 0xe0, /* ###..... */
+ /*0cd7:*/ 0xe0, /* ###..... */
+ /*0cd8:*/ 0xe0, /* ###..... */
+ /*0cd9:*/ 0xe0, /* ###..... */
+ /*0cda:*/ 0xe0, /* ###..... */
+ /*0cdb:*/ 0xe0, /* ###..... */
+ /*0cdc:*/ 0xe0, /* ###..... */
+ /*0cdd:*/ 0xe0, /* ###..... */
+ /*0cde:*/ 0xe0, /* ###..... */
+ /*0cdf:*/ 0xe0, /* ###..... */
+ /*0ce0:*/ 0xe0, /* ###..... */
+ /*0ce1:*/ 0xe0, /* ###..... */
+/* --- new character braceright (125) starting at offset 0x0ce2 --- */
+ /*0ce2:*/ 10, 7, 24, 2, -5, /* width and bbox (w,h,x,y) */
+ /*0ce7:*/ 0xe0, /* ###..... */
+ /*0ce8:*/ 0x70, /* .###.... */
+ /*0ce9:*/ 0x38, /* ..###... */
+ /*0cea:*/ 0x38, /* ..###... */
+ /*0ceb:*/ 0x38, /* ..###... */
+ /*0cec:*/ 0x38, /* ..###... */
+ /*0ced:*/ 0x38, /* ..###... */
+ /*0cee:*/ 0x38, /* ..###... */
+ /*0cef:*/ 0x38, /* ..###... */
+ /*0cf0:*/ 0x38, /* ..###... */
+ /*0cf1:*/ 0x1c, /* ...###.. */
+ /*0cf2:*/ 0x0e, /* ....###. */
+ /*0cf3:*/ 0x0e, /* ....###. */
+ /*0cf4:*/ 0x1c, /* ...###.. */
+ /*0cf5:*/ 0x38, /* ..###... */
+ /*0cf6:*/ 0x38, /* ..###... */
+ /*0cf7:*/ 0x38, /* ..###... */
+ /*0cf8:*/ 0x38, /* ..###... */
+ /*0cf9:*/ 0x38, /* ..###... */
+ /*0cfa:*/ 0x38, /* ..###... */
+ /*0cfb:*/ 0x38, /* ..###... */
+ /*0cfc:*/ 0x38, /* ..###... */
+ /*0cfd:*/ 0x70, /* .###.... */
+ /*0cfe:*/ 0xe0, /* ###..... */
+/* --- new character asciitilde (126) starting at offset 0x0cff --- */
+ /*0cff:*/ 14, 11, 4, 1, 5, /* width and bbox (w,h,x,y) */
+ /*0d04:*/ 0x78,0xe0, /* .####...###..... */
+ /*0d06:*/ 0xfe,0xe0, /* #######.###..... */
+ /*0d08:*/ 0xef,0xe0, /* ###.#######..... */
+ /*0d0a:*/ 0xe3,0xc0, /* ###...####...... */
+};
+static const uint16_t font_helvB24_offsets[] = {
+0x0000 /* space */,
+ 0x0006 /* exclam */,
+ 0x001e /* quotedbl */,
+ 0x0029 /* numbersign */,
+ 0x0052 /* dollar */,
+ 0x0081 /* percent */,
+ 0x00bc /* ampersand */,
+ 0x00e5 /* quotesingle */,
+ 0x00f0 /* parenleft */,
+ 0x010d /* parenright */,
+ 0x012a /* asterisk */,
+ 0x0136 /* plus */,
+ 0x0153 /* comma */,
+ 0x015e /* hyphen */,
+ 0x0166 /* period */,
+ 0x016e /* slash */,
+ 0x0186 /* zero */,
+ 0x01af /* one */,
+ 0x01c6 /* two */,
+ 0x01ef /* three */,
+ 0x0218 /* four */,
+ 0x0241 /* five */,
+ 0x026a /* six */,
+ 0x0293 /* seven */,
+ 0x02bc /* eight */,
+ 0x02e5 /* nine */,
+ 0x030e /* colon */,
+ 0x0321 /* semicolon */,
+ 0x0337 /* less */,
+ 0x0354 /* equal */,
+ 0x0365 /* greater */,
+ 0x0382 /* question */,
+ 0x03ad /* at */,
+ 0x03f4 /* A */,
+ 0x041f /* B */,
+ 0x044a /* C */,
+ 0x0475 /* D */,
+ 0x04a0 /* E */,
+ 0x04cb /* F */,
+ 0x04f6 /* G */,
+ 0x0534 /* H */,
+ 0x055f /* I */,
+ 0x0577 /* J */,
+ 0x05a2 /* K */,
+ 0x05cd /* L */,
+ 0x05f8 /* M */,
+ 0x0636 /* N */,
+ 0x0661 /* O */,
+ 0x069f /* P */,
+ 0x06ca /* Q */,
+ 0x0708 /* R */,
+ 0x0733 /* S */,
+ 0x075e /* T */,
+ 0x0789 /* U */,
+ 0x07b4 /* V */,
+ 0x07df /* W */,
+ 0x081d /* X */,
+ 0x0848 /* Y */,
+ 0x0873 /* Z */,
+ 0x089e /* bracketleft */,
+ 0x08bb /* backslash */,
+ 0x08d3 /* bracketright */,
+ 0x08f0 /* asciicircum */,
+ 0x0907 /* underscore */,
+ 0x0910 /* grave */,
+ 0x0919 /* a */,
+ 0x093a /* b */,
+ 0x0965 /* c */,
+ 0x0986 /* d */,
+ 0x09b1 /* e */,
+ 0x09d2 /* f */,
+ 0x09ea /* g */,
+ 0x0a15 /* h */,
+ 0x0a40 /* i */,
+ 0x0a58 /* j */,
+ 0x0a75 /* k */,
+ 0x0aa0 /* l */,
+ 0x0ab8 /* m */,
+ 0x0ae7 /* n */,
+ 0x0b08 /* o */,
+ 0x0b29 /* p */,
+ 0x0b54 /* q */,
+ 0x0b7f /* r */,
+ 0x0b92 /* s */,
+ 0x0bb3 /* t */,
+ 0x0bca /* u */,
+ 0x0beb /* v */,
+ 0x0c0c /* w */,
+ 0x0c3b /* x */,
+ 0x0c5c /* y */,
+ 0x0c87 /* z */,
+ 0x0ca8 /* braceleft */,
+ 0x0cc5 /* bar */,
+ 0x0ce2 /* braceright */,
+ 0x0cff /* asciitilde */,
+ 0xffff /* (no glyph) */
+};
+const struct fb_font font_helvB24 = {
+ .height = 27,
+ .ascent = 22,
+ .firstchar = 32, /* space */
+ .lastchar = 127, /* ? */
+ .chardata = font_helvB24_data,
+ .charoffs = font_helvB24_offsets,
+};
diff --git a/Src/osmolib/src/target/firmware/fb/helvR08.c b/Src/osmolib/src/target/firmware/fb/helvR08.c
new file mode 100644
index 0000000..7ebf82e
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/helvR08.c
@@ -0,0 +1,826 @@
+#include <fb/font.h>
+static const uint8_t font_helvR08_data[] = {
+/* --- new character space (32) starting at offset 0x0000 --- */
+ /*0000:*/ 2, 1, 1, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0005:*/ 0x00, /* ........ */
+/* --- new character exclam (33) starting at offset 0x0006 --- */
+ /*0006:*/ 2, 1, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*000b:*/ 0x80, /* #....... */
+ /*000c:*/ 0x80, /* #....... */
+ /*000d:*/ 0x80, /* #....... */
+ /*000e:*/ 0x80, /* #....... */
+ /*000f:*/ 0x00, /* ........ */
+ /*0010:*/ 0x80, /* #....... */
+/* --- new character quotedbl (34) starting at offset 0x0011 --- */
+ /*0011:*/ 3, 3, 3, 1, 3, /* width and bbox (w,h,x,y) */
+ /*0016:*/ 0xa0, /* #.#..... */
+ /*0017:*/ 0xa0, /* #.#..... */
+ /*0018:*/ 0xa0, /* #.#..... */
+/* --- new character numbersign (35) starting at offset 0x0019 --- */
+ /*0019:*/ 5, 5, 5, 0, 0, /* width and bbox (w,h,x,y) */
+ /*001e:*/ 0x50, /* .#.#.... */
+ /*001f:*/ 0xf8, /* #####... */
+ /*0020:*/ 0x50, /* .#.#.... */
+ /*0021:*/ 0xf8, /* #####... */
+ /*0022:*/ 0x50, /* .#.#.... */
+/* --- new character dollar (36) starting at offset 0x0023 --- */
+ /*0023:*/ 5, 4, 7, 1, -1, /* width and bbox (w,h,x,y) */
+ /*0028:*/ 0x20, /* ..#..... */
+ /*0029:*/ 0x70, /* .###.... */
+ /*002a:*/ 0x80, /* #....... */
+ /*002b:*/ 0x60, /* .##..... */
+ /*002c:*/ 0x10, /* ...#.... */
+ /*002d:*/ 0xe0, /* ###..... */
+ /*002e:*/ 0x40, /* .#...... */
+/* --- new character percent (37) starting at offset 0x002f --- */
+ /*002f:*/ 7, 6, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0034:*/ 0xe8, /* ###.#... */
+ /*0035:*/ 0xa8, /* #.#.#... */
+ /*0036:*/ 0xd0, /* ##.#.... */
+ /*0037:*/ 0x2c, /* ..#.##.. */
+ /*0038:*/ 0x54, /* .#.#.#.. */
+ /*0039:*/ 0x5c, /* .#.###.. */
+/* --- new character ampersand (38) starting at offset 0x003a --- */
+ /*003a:*/ 6, 5, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*003f:*/ 0x40, /* .#...... */
+ /*0040:*/ 0xa0, /* #.#..... */
+ /*0041:*/ 0x48, /* .#..#... */
+ /*0042:*/ 0xa8, /* #.#.#... */
+ /*0043:*/ 0xb0, /* #.##.... */
+ /*0044:*/ 0x58, /* .#.##... */
+/* --- new character quotesingle (39) starting at offset 0x0045 --- */
+ /*0045:*/ 2, 1, 2, 0, 6, /* width and bbox (w,h,x,y) */
+ /*004a:*/ 0x80, /* #....... */
+ /*004b:*/ 0x80, /* #....... */
+/* --- new character parenleft (40) starting at offset 0x004c --- */
+ /*004c:*/ 3, 2, 7, 1, -1, /* width and bbox (w,h,x,y) */
+ /*0051:*/ 0x40, /* .#...... */
+ /*0052:*/ 0x80, /* #....... */
+ /*0053:*/ 0x80, /* #....... */
+ /*0054:*/ 0x80, /* #....... */
+ /*0055:*/ 0x80, /* #....... */
+ /*0056:*/ 0x80, /* #....... */
+ /*0057:*/ 0x40, /* .#...... */
+/* --- new character parenright (41) starting at offset 0x0058 --- */
+ /*0058:*/ 3, 2, 7, 1, -1, /* width and bbox (w,h,x,y) */
+ /*005d:*/ 0x80, /* #....... */
+ /*005e:*/ 0x40, /* .#...... */
+ /*005f:*/ 0x40, /* .#...... */
+ /*0060:*/ 0x40, /* .#...... */
+ /*0061:*/ 0x40, /* .#...... */
+ /*0062:*/ 0x40, /* .#...... */
+ /*0063:*/ 0x80, /* #....... */
+/* --- new character asterisk (42) starting at offset 0x0064 --- */
+ /*0064:*/ 3, 3, 3, 1, 2, /* width and bbox (w,h,x,y) */
+ /*0069:*/ 0x40, /* .#...... */
+ /*006a:*/ 0xe0, /* ###..... */
+ /*006b:*/ 0x40, /* .#...... */
+/* --- new character plus (43) starting at offset 0x006c --- */
+ /*006c:*/ 5, 5, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0071:*/ 0x20, /* ..#..... */
+ /*0072:*/ 0x20, /* ..#..... */
+ /*0073:*/ 0xf8, /* #####... */
+ /*0074:*/ 0x20, /* ..#..... */
+ /*0075:*/ 0x20, /* ..#..... */
+/* --- new character comma (44) starting at offset 0x0076 --- */
+ /*0076:*/ 2, 2, 3, 0, -2, /* width and bbox (w,h,x,y) */
+ /*007b:*/ 0x40, /* .#...... */
+ /*007c:*/ 0x40, /* .#...... */
+ /*007d:*/ 0x80, /* #....... */
+/* --- new character hyphen (45) starting at offset 0x007e --- */
+ /*007e:*/ 3, 2, 1, 0, 2, /* width and bbox (w,h,x,y) */
+ /*0083:*/ 0xc0, /* ##...... */
+/* --- new character period (46) starting at offset 0x0084 --- */
+ /*0084:*/ 2, 1, 1, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0089:*/ 0x80, /* #....... */
+/* --- new character slash (47) starting at offset 0x008a --- */
+ /*008a:*/ 2, 2, 7, 1, -1, /* width and bbox (w,h,x,y) */
+ /*008f:*/ 0x40, /* .#...... */
+ /*0090:*/ 0x40, /* .#...... */
+ /*0091:*/ 0x40, /* .#...... */
+ /*0092:*/ 0x80, /* #....... */
+ /*0093:*/ 0x80, /* #....... */
+ /*0094:*/ 0x80, /* #....... */
+ /*0095:*/ 0x80, /* #....... */
+/* --- new character zero (48) starting at offset 0x0096 --- */
+ /*0096:*/ 5, 4, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*009b:*/ 0x60, /* .##..... */
+ /*009c:*/ 0x90, /* #..#.... */
+ /*009d:*/ 0x90, /* #..#.... */
+ /*009e:*/ 0x90, /* #..#.... */
+ /*009f:*/ 0x90, /* #..#.... */
+ /*00a0:*/ 0x60, /* .##..... */
+/* --- new character one (49) starting at offset 0x00a1 --- */
+ /*00a1:*/ 5, 2, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*00a6:*/ 0x40, /* .#...... */
+ /*00a7:*/ 0xc0, /* ##...... */
+ /*00a8:*/ 0x40, /* .#...... */
+ /*00a9:*/ 0x40, /* .#...... */
+ /*00aa:*/ 0x40, /* .#...... */
+ /*00ab:*/ 0x40, /* .#...... */
+/* --- new character two (50) starting at offset 0x00ac --- */
+ /*00ac:*/ 5, 4, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00b1:*/ 0x60, /* .##..... */
+ /*00b2:*/ 0x90, /* #..#.... */
+ /*00b3:*/ 0x10, /* ...#.... */
+ /*00b4:*/ 0x20, /* ..#..... */
+ /*00b5:*/ 0x40, /* .#...... */
+ /*00b6:*/ 0xf0, /* ####.... */
+/* --- new character three (51) starting at offset 0x00b7 --- */
+ /*00b7:*/ 5, 3, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*00bc:*/ 0xc0, /* ##...... */
+ /*00bd:*/ 0x20, /* ..#..... */
+ /*00be:*/ 0xc0, /* ##...... */
+ /*00bf:*/ 0x20, /* ..#..... */
+ /*00c0:*/ 0x20, /* ..#..... */
+ /*00c1:*/ 0xc0, /* ##...... */
+/* --- new character four (52) starting at offset 0x00c2 --- */
+ /*00c2:*/ 5, 4, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00c7:*/ 0x20, /* ..#..... */
+ /*00c8:*/ 0x20, /* ..#..... */
+ /*00c9:*/ 0x60, /* .##..... */
+ /*00ca:*/ 0xf0, /* ####.... */
+ /*00cb:*/ 0x20, /* ..#..... */
+ /*00cc:*/ 0x20, /* ..#..... */
+/* --- new character five (53) starting at offset 0x00cd --- */
+ /*00cd:*/ 5, 3, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*00d2:*/ 0xe0, /* ###..... */
+ /*00d3:*/ 0x80, /* #....... */
+ /*00d4:*/ 0xc0, /* ##...... */
+ /*00d5:*/ 0x20, /* ..#..... */
+ /*00d6:*/ 0x20, /* ..#..... */
+ /*00d7:*/ 0xc0, /* ##...... */
+/* --- new character six (54) starting at offset 0x00d8 --- */
+ /*00d8:*/ 5, 4, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00dd:*/ 0x70, /* .###.... */
+ /*00de:*/ 0x80, /* #....... */
+ /*00df:*/ 0xe0, /* ###..... */
+ /*00e0:*/ 0x90, /* #..#.... */
+ /*00e1:*/ 0x90, /* #..#.... */
+ /*00e2:*/ 0x60, /* .##..... */
+/* --- new character seven (55) starting at offset 0x00e3 --- */
+ /*00e3:*/ 5, 4, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00e8:*/ 0xf0, /* ####.... */
+ /*00e9:*/ 0x10, /* ...#.... */
+ /*00ea:*/ 0x20, /* ..#..... */
+ /*00eb:*/ 0x40, /* .#...... */
+ /*00ec:*/ 0x40, /* .#...... */
+ /*00ed:*/ 0x40, /* .#...... */
+/* --- new character eight (56) starting at offset 0x00ee --- */
+ /*00ee:*/ 5, 4, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00f3:*/ 0x60, /* .##..... */
+ /*00f4:*/ 0x90, /* #..#.... */
+ /*00f5:*/ 0x60, /* .##..... */
+ /*00f6:*/ 0x90, /* #..#.... */
+ /*00f7:*/ 0x90, /* #..#.... */
+ /*00f8:*/ 0x60, /* .##..... */
+/* --- new character nine (57) starting at offset 0x00f9 --- */
+ /*00f9:*/ 5, 4, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00fe:*/ 0x60, /* .##..... */
+ /*00ff:*/ 0x90, /* #..#.... */
+ /*0100:*/ 0x90, /* #..#.... */
+ /*0101:*/ 0x70, /* .###.... */
+ /*0102:*/ 0x10, /* ...#.... */
+ /*0103:*/ 0x60, /* .##..... */
+/* --- new character colon (58) starting at offset 0x0104 --- */
+ /*0104:*/ 2, 1, 4, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0109:*/ 0x80, /* #....... */
+ /*010a:*/ 0x00, /* ........ */
+ /*010b:*/ 0x00, /* ........ */
+ /*010c:*/ 0x80, /* #....... */
+/* --- new character semicolon (59) starting at offset 0x010d --- */
+ /*010d:*/ 2, 2, 6, 0, -2, /* width and bbox (w,h,x,y) */
+ /*0112:*/ 0x40, /* .#...... */
+ /*0113:*/ 0x00, /* ........ */
+ /*0114:*/ 0x00, /* ........ */
+ /*0115:*/ 0x40, /* .#...... */
+ /*0116:*/ 0x40, /* .#...... */
+ /*0117:*/ 0x80, /* #....... */
+/* --- new character less (60) starting at offset 0x0118 --- */
+ /*0118:*/ 5, 3, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*011d:*/ 0x20, /* ..#..... */
+ /*011e:*/ 0x40, /* .#...... */
+ /*011f:*/ 0x80, /* #....... */
+ /*0120:*/ 0x40, /* .#...... */
+ /*0121:*/ 0x20, /* ..#..... */
+/* --- new character equal (61) starting at offset 0x0122 --- */
+ /*0122:*/ 4, 3, 3, 1, 1, /* width and bbox (w,h,x,y) */
+ /*0127:*/ 0xe0, /* ###..... */
+ /*0128:*/ 0x00, /* ........ */
+ /*0129:*/ 0xe0, /* ###..... */
+/* --- new character greater (62) starting at offset 0x012a --- */
+ /*012a:*/ 5, 3, 5, 2, 0, /* width and bbox (w,h,x,y) */
+ /*012f:*/ 0x80, /* #....... */
+ /*0130:*/ 0x40, /* .#...... */
+ /*0131:*/ 0x20, /* ..#..... */
+ /*0132:*/ 0x40, /* .#...... */
+ /*0133:*/ 0x80, /* #....... */
+/* --- new character question (63) starting at offset 0x0134 --- */
+ /*0134:*/ 5, 3, 5, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0139:*/ 0xc0, /* ##...... */
+ /*013a:*/ 0x20, /* ..#..... */
+ /*013b:*/ 0x40, /* .#...... */
+ /*013c:*/ 0x00, /* ........ */
+ /*013d:*/ 0x40, /* .#...... */
+/* --- new character at (64) starting at offset 0x013e --- */
+ /*013e:*/ 9, 8, 7, 1, -1, /* width and bbox (w,h,x,y) */
+ /*0143:*/ 0x3e, /* ..#####. */
+ /*0144:*/ 0x41, /* .#.....# */
+ /*0145:*/ 0x99, /* #..##..# */
+ /*0146:*/ 0xa5, /* #.#..#.# */
+ /*0147:*/ 0x9e, /* #..####. */
+ /*0148:*/ 0x80, /* #....... */
+ /*0149:*/ 0x78, /* .####... */
+/* --- new character A (65) starting at offset 0x014a --- */
+ /*014a:*/ 6, 5, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*014f:*/ 0x20, /* ..#..... */
+ /*0150:*/ 0x20, /* ..#..... */
+ /*0151:*/ 0x50, /* .#.#.... */
+ /*0152:*/ 0x70, /* .###.... */
+ /*0153:*/ 0x88, /* #...#... */
+ /*0154:*/ 0x88, /* #...#... */
+/* --- new character B (66) starting at offset 0x0155 --- */
+ /*0155:*/ 6, 4, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*015a:*/ 0xe0, /* ###..... */
+ /*015b:*/ 0x90, /* #..#.... */
+ /*015c:*/ 0xe0, /* ###..... */
+ /*015d:*/ 0x90, /* #..#.... */
+ /*015e:*/ 0x90, /* #..#.... */
+ /*015f:*/ 0xe0, /* ###..... */
+/* --- new character C (67) starting at offset 0x0160 --- */
+ /*0160:*/ 6, 5, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0165:*/ 0x70, /* .###.... */
+ /*0166:*/ 0x88, /* #...#... */
+ /*0167:*/ 0x80, /* #....... */
+ /*0168:*/ 0x80, /* #....... */
+ /*0169:*/ 0x88, /* #...#... */
+ /*016a:*/ 0x70, /* .###.... */
+/* --- new character D (68) starting at offset 0x016b --- */
+ /*016b:*/ 6, 5, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0170:*/ 0xf0, /* ####.... */
+ /*0171:*/ 0x88, /* #...#... */
+ /*0172:*/ 0x88, /* #...#... */
+ /*0173:*/ 0x88, /* #...#... */
+ /*0174:*/ 0x88, /* #...#... */
+ /*0175:*/ 0xf0, /* ####.... */
+/* --- new character E (69) starting at offset 0x0176 --- */
+ /*0176:*/ 6, 4, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*017b:*/ 0xf0, /* ####.... */
+ /*017c:*/ 0x80, /* #....... */
+ /*017d:*/ 0xe0, /* ###..... */
+ /*017e:*/ 0x80, /* #....... */
+ /*017f:*/ 0x80, /* #....... */
+ /*0180:*/ 0xf0, /* ####.... */
+/* --- new character F (70) starting at offset 0x0181 --- */
+ /*0181:*/ 5, 4, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0186:*/ 0xf0, /* ####.... */
+ /*0187:*/ 0x80, /* #....... */
+ /*0188:*/ 0xe0, /* ###..... */
+ /*0189:*/ 0x80, /* #....... */
+ /*018a:*/ 0x80, /* #....... */
+ /*018b:*/ 0x80, /* #....... */
+/* --- new character G (71) starting at offset 0x018c --- */
+ /*018c:*/ 6, 5, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0191:*/ 0x70, /* .###.... */
+ /*0192:*/ 0x80, /* #....... */
+ /*0193:*/ 0x98, /* #..##... */
+ /*0194:*/ 0x88, /* #...#... */
+ /*0195:*/ 0x88, /* #...#... */
+ /*0196:*/ 0x70, /* .###.... */
+/* --- new character H (72) starting at offset 0x0197 --- */
+ /*0197:*/ 6, 5, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*019c:*/ 0x88, /* #...#... */
+ /*019d:*/ 0x88, /* #...#... */
+ /*019e:*/ 0xf8, /* #####... */
+ /*019f:*/ 0x88, /* #...#... */
+ /*01a0:*/ 0x88, /* #...#... */
+ /*01a1:*/ 0x88, /* #...#... */
+/* --- new character I (73) starting at offset 0x01a2 --- */
+ /*01a2:*/ 2, 1, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01a7:*/ 0x80, /* #....... */
+ /*01a8:*/ 0x80, /* #....... */
+ /*01a9:*/ 0x80, /* #....... */
+ /*01aa:*/ 0x80, /* #....... */
+ /*01ab:*/ 0x80, /* #....... */
+ /*01ac:*/ 0x80, /* #....... */
+/* --- new character J (74) starting at offset 0x01ad --- */
+ /*01ad:*/ 4, 3, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01b2:*/ 0x20, /* ..#..... */
+ /*01b3:*/ 0x20, /* ..#..... */
+ /*01b4:*/ 0x20, /* ..#..... */
+ /*01b5:*/ 0x20, /* ..#..... */
+ /*01b6:*/ 0xa0, /* #.#..... */
+ /*01b7:*/ 0x40, /* .#...... */
+/* --- new character K (75) starting at offset 0x01b8 --- */
+ /*01b8:*/ 6, 4, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*01bd:*/ 0x90, /* #..#.... */
+ /*01be:*/ 0xa0, /* #.#..... */
+ /*01bf:*/ 0xc0, /* ##...... */
+ /*01c0:*/ 0xe0, /* ###..... */
+ /*01c1:*/ 0x90, /* #..#.... */
+ /*01c2:*/ 0x90, /* #..#.... */
+/* --- new character L (76) starting at offset 0x01c3 --- */
+ /*01c3:*/ 5, 3, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*01c8:*/ 0x80, /* #....... */
+ /*01c9:*/ 0x80, /* #....... */
+ /*01ca:*/ 0x80, /* #....... */
+ /*01cb:*/ 0x80, /* #....... */
+ /*01cc:*/ 0x80, /* #....... */
+ /*01cd:*/ 0xe0, /* ###..... */
+/* --- new character M (77) starting at offset 0x01ce --- */
+ /*01ce:*/ 7, 5, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*01d3:*/ 0x88, /* #...#... */
+ /*01d4:*/ 0xd8, /* ##.##... */
+ /*01d5:*/ 0xa8, /* #.#.#... */
+ /*01d6:*/ 0xa8, /* #.#.#... */
+ /*01d7:*/ 0xa8, /* #.#.#... */
+ /*01d8:*/ 0xa8, /* #.#.#... */
+/* --- new character N (78) starting at offset 0x01d9 --- */
+ /*01d9:*/ 6, 5, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01de:*/ 0x88, /* #...#... */
+ /*01df:*/ 0xc8, /* ##..#... */
+ /*01e0:*/ 0xa8, /* #.#.#... */
+ /*01e1:*/ 0xa8, /* #.#.#... */
+ /*01e2:*/ 0x98, /* #..##... */
+ /*01e3:*/ 0x88, /* #...#... */
+/* --- new character O (79) starting at offset 0x01e4 --- */
+ /*01e4:*/ 6, 5, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01e9:*/ 0x70, /* .###.... */
+ /*01ea:*/ 0x88, /* #...#... */
+ /*01eb:*/ 0x88, /* #...#... */
+ /*01ec:*/ 0x88, /* #...#... */
+ /*01ed:*/ 0x88, /* #...#... */
+ /*01ee:*/ 0x70, /* .###.... */
+/* --- new character P (80) starting at offset 0x01ef --- */
+ /*01ef:*/ 6, 4, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*01f4:*/ 0xe0, /* ###..... */
+ /*01f5:*/ 0x90, /* #..#.... */
+ /*01f6:*/ 0x90, /* #..#.... */
+ /*01f7:*/ 0xe0, /* ###..... */
+ /*01f8:*/ 0x80, /* #....... */
+ /*01f9:*/ 0x80, /* #....... */
+/* --- new character Q (81) starting at offset 0x01fa --- */
+ /*01fa:*/ 6, 5, 8, 1, -2, /* width and bbox (w,h,x,y) */
+ /*01ff:*/ 0x70, /* .###.... */
+ /*0200:*/ 0x88, /* #...#... */
+ /*0201:*/ 0x88, /* #...#... */
+ /*0202:*/ 0x88, /* #...#... */
+ /*0203:*/ 0x88, /* #...#... */
+ /*0204:*/ 0x70, /* .###.... */
+ /*0205:*/ 0x20, /* ..#..... */
+ /*0206:*/ 0x10, /* ...#.... */
+/* --- new character R (82) starting at offset 0x0207 --- */
+ /*0207:*/ 6, 4, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*020c:*/ 0xe0, /* ###..... */
+ /*020d:*/ 0x90, /* #..#.... */
+ /*020e:*/ 0x90, /* #..#.... */
+ /*020f:*/ 0xe0, /* ###..... */
+ /*0210:*/ 0x90, /* #..#.... */
+ /*0211:*/ 0x90, /* #..#.... */
+/* --- new character S (83) starting at offset 0x0212 --- */
+ /*0212:*/ 6, 4, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0217:*/ 0x70, /* .###.... */
+ /*0218:*/ 0x80, /* #....... */
+ /*0219:*/ 0xe0, /* ###..... */
+ /*021a:*/ 0x10, /* ...#.... */
+ /*021b:*/ 0x10, /* ...#.... */
+ /*021c:*/ 0xe0, /* ###..... */
+/* --- new character T (84) starting at offset 0x021d --- */
+ /*021d:*/ 4, 3, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0222:*/ 0xe0, /* ###..... */
+ /*0223:*/ 0x40, /* .#...... */
+ /*0224:*/ 0x40, /* .#...... */
+ /*0225:*/ 0x40, /* .#...... */
+ /*0226:*/ 0x40, /* .#...... */
+ /*0227:*/ 0x40, /* .#...... */
+/* --- new character U (85) starting at offset 0x0228 --- */
+ /*0228:*/ 6, 5, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*022d:*/ 0x88, /* #...#... */
+ /*022e:*/ 0x88, /* #...#... */
+ /*022f:*/ 0x88, /* #...#... */
+ /*0230:*/ 0x88, /* #...#... */
+ /*0231:*/ 0x88, /* #...#... */
+ /*0232:*/ 0x70, /* .###.... */
+/* --- new character V (86) starting at offset 0x0233 --- */
+ /*0233:*/ 6, 4, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0238:*/ 0x90, /* #..#.... */
+ /*0239:*/ 0x90, /* #..#.... */
+ /*023a:*/ 0x90, /* #..#.... */
+ /*023b:*/ 0x90, /* #..#.... */
+ /*023c:*/ 0xa0, /* #.#..... */
+ /*023d:*/ 0x40, /* .#...... */
+/* --- new character W (87) starting at offset 0x023e --- */
+ /*023e:*/ 7, 7, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0243:*/ 0x92, /* #..#..#. */
+ /*0244:*/ 0x92, /* #..#..#. */
+ /*0245:*/ 0x92, /* #..#..#. */
+ /*0246:*/ 0x6c, /* .##.##.. */
+ /*0247:*/ 0x48, /* .#..#... */
+ /*0248:*/ 0x48, /* .#..#... */
+/* --- new character X (88) starting at offset 0x0249 --- */
+ /*0249:*/ 6, 4, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*024e:*/ 0x90, /* #..#.... */
+ /*024f:*/ 0x90, /* #..#.... */
+ /*0250:*/ 0x60, /* .##..... */
+ /*0251:*/ 0x60, /* .##..... */
+ /*0252:*/ 0x90, /* #..#.... */
+ /*0253:*/ 0x90, /* #..#.... */
+/* --- new character Y (89) starting at offset 0x0254 --- */
+ /*0254:*/ 6, 5, 6, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0259:*/ 0xc8, /* ##..#... */
+ /*025a:*/ 0x48, /* .#..#... */
+ /*025b:*/ 0x48, /* .#..#... */
+ /*025c:*/ 0x30, /* ..##.... */
+ /*025d:*/ 0x20, /* ..#..... */
+ /*025e:*/ 0x20, /* ..#..... */
+/* --- new character Z (90) starting at offset 0x025f --- */
+ /*025f:*/ 6, 4, 6, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0264:*/ 0xf0, /* ####.... */
+ /*0265:*/ 0x10, /* ...#.... */
+ /*0266:*/ 0x20, /* ..#..... */
+ /*0267:*/ 0x40, /* .#...... */
+ /*0268:*/ 0x80, /* #....... */
+ /*0269:*/ 0xf0, /* ####.... */
+/* --- new character bracketleft (91) starting at offset 0x026a --- */
+ /*026a:*/ 2, 2, 7, 1, -1, /* width and bbox (w,h,x,y) */
+ /*026f:*/ 0xc0, /* ##...... */
+ /*0270:*/ 0x80, /* #....... */
+ /*0271:*/ 0x80, /* #....... */
+ /*0272:*/ 0x80, /* #....... */
+ /*0273:*/ 0x80, /* #....... */
+ /*0274:*/ 0x80, /* #....... */
+ /*0275:*/ 0xc0, /* ##...... */
+/* --- new character backslash (92) starting at offset 0x0276 --- */
+ /*0276:*/ 2, 2, 7, 0, -1, /* width and bbox (w,h,x,y) */
+ /*027b:*/ 0x80, /* #....... */
+ /*027c:*/ 0x80, /* #....... */
+ /*027d:*/ 0x80, /* #....... */
+ /*027e:*/ 0x40, /* .#...... */
+ /*027f:*/ 0x40, /* .#...... */
+ /*0280:*/ 0x40, /* .#...... */
+ /*0281:*/ 0x40, /* .#...... */
+/* --- new character bracketright (93) starting at offset 0x0282 --- */
+ /*0282:*/ 2, 2, 7, 0, -1, /* width and bbox (w,h,x,y) */
+ /*0287:*/ 0xc0, /* ##...... */
+ /*0288:*/ 0x40, /* .#...... */
+ /*0289:*/ 0x40, /* .#...... */
+ /*028a:*/ 0x40, /* .#...... */
+ /*028b:*/ 0x40, /* .#...... */
+ /*028c:*/ 0x40, /* .#...... */
+ /*028d:*/ 0xc0, /* ##...... */
+/* --- new character asciicircum (94) starting at offset 0x028e --- */
+ /*028e:*/ 5, 5, 3, 0, 2, /* width and bbox (w,h,x,y) */
+ /*0293:*/ 0x20, /* ..#..... */
+ /*0294:*/ 0x50, /* .#.#.... */
+ /*0295:*/ 0x88, /* #...#... */
+/* --- new character underscore (95) starting at offset 0x0296 --- */
+ /*0296:*/ 5, 5, 1, 0, -1, /* width and bbox (w,h,x,y) */
+ /*029b:*/ 0xf8, /* #####... */
+/* --- new character grave (96) starting at offset 0x029c --- */
+ /*029c:*/ 3, 2, 2, 0, 6, /* width and bbox (w,h,x,y) */
+ /*02a1:*/ 0x80, /* #....... */
+ /*02a2:*/ 0x40, /* .#...... */
+/* --- new character a (97) starting at offset 0x02a3 --- */
+ /*02a3:*/ 4, 4, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02a8:*/ 0xc0, /* ##...... */
+ /*02a9:*/ 0x20, /* ..#..... */
+ /*02aa:*/ 0xe0, /* ###..... */
+ /*02ab:*/ 0xa0, /* #.#..... */
+ /*02ac:*/ 0xd0, /* ##.#.... */
+/* --- new character b (98) starting at offset 0x02ad --- */
+ /*02ad:*/ 5, 4, 7, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02b2:*/ 0x80, /* #....... */
+ /*02b3:*/ 0x80, /* #....... */
+ /*02b4:*/ 0xe0, /* ###..... */
+ /*02b5:*/ 0x90, /* #..#.... */
+ /*02b6:*/ 0x90, /* #..#.... */
+ /*02b7:*/ 0x90, /* #..#.... */
+ /*02b8:*/ 0xe0, /* ###..... */
+/* --- new character c (99) starting at offset 0x02b9 --- */
+ /*02b9:*/ 4, 3, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02be:*/ 0x60, /* .##..... */
+ /*02bf:*/ 0x80, /* #....... */
+ /*02c0:*/ 0x80, /* #....... */
+ /*02c1:*/ 0x80, /* #....... */
+ /*02c2:*/ 0x60, /* .##..... */
+/* --- new character d (100) starting at offset 0x02c3 --- */
+ /*02c3:*/ 5, 4, 7, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02c8:*/ 0x10, /* ...#.... */
+ /*02c9:*/ 0x10, /* ...#.... */
+ /*02ca:*/ 0x70, /* .###.... */
+ /*02cb:*/ 0x90, /* #..#.... */
+ /*02cc:*/ 0x90, /* #..#.... */
+ /*02cd:*/ 0x90, /* #..#.... */
+ /*02ce:*/ 0x70, /* .###.... */
+/* --- new character e (101) starting at offset 0x02cf --- */
+ /*02cf:*/ 4, 3, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02d4:*/ 0x40, /* .#...... */
+ /*02d5:*/ 0xa0, /* #.#..... */
+ /*02d6:*/ 0xe0, /* ###..... */
+ /*02d7:*/ 0x80, /* #....... */
+ /*02d8:*/ 0x60, /* .##..... */
+/* --- new character f (102) starting at offset 0x02d9 --- */
+ /*02d9:*/ 4, 3, 7, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02de:*/ 0x20, /* ..#..... */
+ /*02df:*/ 0x40, /* .#...... */
+ /*02e0:*/ 0xe0, /* ###..... */
+ /*02e1:*/ 0x40, /* .#...... */
+ /*02e2:*/ 0x40, /* .#...... */
+ /*02e3:*/ 0x40, /* .#...... */
+ /*02e4:*/ 0x40, /* .#...... */
+/* --- new character g (103) starting at offset 0x02e5 --- */
+ /*02e5:*/ 5, 4, 6, 1, -1, /* width and bbox (w,h,x,y) */
+ /*02ea:*/ 0x70, /* .###.... */
+ /*02eb:*/ 0x90, /* #..#.... */
+ /*02ec:*/ 0x90, /* #..#.... */
+ /*02ed:*/ 0x70, /* .###.... */
+ /*02ee:*/ 0x10, /* ...#.... */
+ /*02ef:*/ 0x60, /* .##..... */
+/* --- new character h (104) starting at offset 0x02f0 --- */
+ /*02f0:*/ 5, 4, 7, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02f5:*/ 0x80, /* #....... */
+ /*02f6:*/ 0x80, /* #....... */
+ /*02f7:*/ 0xe0, /* ###..... */
+ /*02f8:*/ 0x90, /* #..#.... */
+ /*02f9:*/ 0x90, /* #..#.... */
+ /*02fa:*/ 0x90, /* #..#.... */
+ /*02fb:*/ 0x90, /* #..#.... */
+/* --- new character i (105) starting at offset 0x02fc --- */
+ /*02fc:*/ 2, 1, 7, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0301:*/ 0x80, /* #....... */
+ /*0302:*/ 0x00, /* ........ */
+ /*0303:*/ 0x80, /* #....... */
+ /*0304:*/ 0x80, /* #....... */
+ /*0305:*/ 0x80, /* #....... */
+ /*0306:*/ 0x80, /* #....... */
+ /*0307:*/ 0x80, /* #....... */
+/* --- new character j (106) starting at offset 0x0308 --- */
+ /*0308:*/ 2, 2, 9, 0, -2, /* width and bbox (w,h,x,y) */
+ /*030d:*/ 0x40, /* .#...... */
+ /*030e:*/ 0x00, /* ........ */
+ /*030f:*/ 0x40, /* .#...... */
+ /*0310:*/ 0x40, /* .#...... */
+ /*0311:*/ 0x40, /* .#...... */
+ /*0312:*/ 0x40, /* .#...... */
+ /*0313:*/ 0x40, /* .#...... */
+ /*0314:*/ 0x40, /* .#...... */
+ /*0315:*/ 0x80, /* #....... */
+/* --- new character k (107) starting at offset 0x0316 --- */
+ /*0316:*/ 4, 3, 7, 1, 0, /* width and bbox (w,h,x,y) */
+ /*031b:*/ 0x80, /* #....... */
+ /*031c:*/ 0x80, /* #....... */
+ /*031d:*/ 0xa0, /* #.#..... */
+ /*031e:*/ 0xc0, /* ##...... */
+ /*031f:*/ 0xc0, /* ##...... */
+ /*0320:*/ 0xa0, /* #.#..... */
+ /*0321:*/ 0xa0, /* #.#..... */
+/* --- new character l (108) starting at offset 0x0322 --- */
+ /*0322:*/ 2, 1, 7, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0327:*/ 0x80, /* #....... */
+ /*0328:*/ 0x80, /* #....... */
+ /*0329:*/ 0x80, /* #....... */
+ /*032a:*/ 0x80, /* #....... */
+ /*032b:*/ 0x80, /* #....... */
+ /*032c:*/ 0x80, /* #....... */
+ /*032d:*/ 0x80, /* #....... */
+/* --- new character m (109) starting at offset 0x032e --- */
+ /*032e:*/ 6, 5, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0333:*/ 0xf0, /* ####.... */
+ /*0334:*/ 0xa8, /* #.#.#... */
+ /*0335:*/ 0xa8, /* #.#.#... */
+ /*0336:*/ 0xa8, /* #.#.#... */
+ /*0337:*/ 0xa8, /* #.#.#... */
+/* --- new character n (110) starting at offset 0x0338 --- */
+ /*0338:*/ 5, 4, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*033d:*/ 0xe0, /* ###..... */
+ /*033e:*/ 0x90, /* #..#.... */
+ /*033f:*/ 0x90, /* #..#.... */
+ /*0340:*/ 0x90, /* #..#.... */
+ /*0341:*/ 0x90, /* #..#.... */
+/* --- new character o (111) starting at offset 0x0342 --- */
+ /*0342:*/ 5, 4, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0347:*/ 0x60, /* .##..... */
+ /*0348:*/ 0x90, /* #..#.... */
+ /*0349:*/ 0x90, /* #..#.... */
+ /*034a:*/ 0x90, /* #..#.... */
+ /*034b:*/ 0x60, /* .##..... */
+/* --- new character p (112) starting at offset 0x034c --- */
+ /*034c:*/ 5, 4, 6, 1, -1, /* width and bbox (w,h,x,y) */
+ /*0351:*/ 0xe0, /* ###..... */
+ /*0352:*/ 0x90, /* #..#.... */
+ /*0353:*/ 0x90, /* #..#.... */
+ /*0354:*/ 0x90, /* #..#.... */
+ /*0355:*/ 0xe0, /* ###..... */
+ /*0356:*/ 0x80, /* #....... */
+/* --- new character q (113) starting at offset 0x0357 --- */
+ /*0357:*/ 5, 4, 6, 1, -1, /* width and bbox (w,h,x,y) */
+ /*035c:*/ 0x70, /* .###.... */
+ /*035d:*/ 0x90, /* #..#.... */
+ /*035e:*/ 0x90, /* #..#.... */
+ /*035f:*/ 0x90, /* #..#.... */
+ /*0360:*/ 0x70, /* .###.... */
+ /*0361:*/ 0x10, /* ...#.... */
+/* --- new character r (114) starting at offset 0x0362 --- */
+ /*0362:*/ 3, 3, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0367:*/ 0xa0, /* #.#..... */
+ /*0368:*/ 0xc0, /* ##...... */
+ /*0369:*/ 0x80, /* #....... */
+ /*036a:*/ 0x80, /* #....... */
+ /*036b:*/ 0x80, /* #....... */
+/* --- new character s (115) starting at offset 0x036c --- */
+ /*036c:*/ 4, 3, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0371:*/ 0x60, /* .##..... */
+ /*0372:*/ 0x80, /* #....... */
+ /*0373:*/ 0x60, /* .##..... */
+ /*0374:*/ 0x20, /* ..#..... */
+ /*0375:*/ 0xc0, /* ##...... */
+/* --- new character t (116) starting at offset 0x0376 --- */
+ /*0376:*/ 3, 3, 7, 1, 0, /* width and bbox (w,h,x,y) */
+ /*037b:*/ 0x40, /* .#...... */
+ /*037c:*/ 0x40, /* .#...... */
+ /*037d:*/ 0xe0, /* ###..... */
+ /*037e:*/ 0x40, /* .#...... */
+ /*037f:*/ 0x40, /* .#...... */
+ /*0380:*/ 0x40, /* .#...... */
+ /*0381:*/ 0x40, /* .#...... */
+/* --- new character u (117) starting at offset 0x0382 --- */
+ /*0382:*/ 4, 3, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0387:*/ 0xa0, /* #.#..... */
+ /*0388:*/ 0xa0, /* #.#..... */
+ /*0389:*/ 0xa0, /* #.#..... */
+ /*038a:*/ 0xa0, /* #.#..... */
+ /*038b:*/ 0x60, /* .##..... */
+/* --- new character v (118) starting at offset 0x038c --- */
+ /*038c:*/ 5, 4, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0391:*/ 0x90, /* #..#.... */
+ /*0392:*/ 0x90, /* #..#.... */
+ /*0393:*/ 0x90, /* #..#.... */
+ /*0394:*/ 0xa0, /* #.#..... */
+ /*0395:*/ 0x40, /* .#...... */
+/* --- new character w (119) starting at offset 0x0396 --- */
+ /*0396:*/ 6, 5, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*039b:*/ 0xa8, /* #.#.#... */
+ /*039c:*/ 0xa8, /* #.#.#... */
+ /*039d:*/ 0xa8, /* #.#.#... */
+ /*039e:*/ 0x50, /* .#.#.... */
+ /*039f:*/ 0x50, /* .#.#.... */
+/* --- new character x (120) starting at offset 0x03a0 --- */
+ /*03a0:*/ 5, 4, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*03a5:*/ 0x90, /* #..#.... */
+ /*03a6:*/ 0x90, /* #..#.... */
+ /*03a7:*/ 0x60, /* .##..... */
+ /*03a8:*/ 0x90, /* #..#.... */
+ /*03a9:*/ 0x90, /* #..#.... */
+/* --- new character y (121) starting at offset 0x03aa --- */
+ /*03aa:*/ 4, 4, 6, 1, -1, /* width and bbox (w,h,x,y) */
+ /*03af:*/ 0x90, /* #..#.... */
+ /*03b0:*/ 0x90, /* #..#.... */
+ /*03b1:*/ 0x90, /* #..#.... */
+ /*03b2:*/ 0x60, /* .##..... */
+ /*03b3:*/ 0x40, /* .#...... */
+ /*03b4:*/ 0x80, /* #....... */
+/* --- new character z (122) starting at offset 0x03b5 --- */
+ /*03b5:*/ 4, 3, 5, 1, 0, /* width and bbox (w,h,x,y) */
+ /*03ba:*/ 0xe0, /* ###..... */
+ /*03bb:*/ 0x20, /* ..#..... */
+ /*03bc:*/ 0x40, /* .#...... */
+ /*03bd:*/ 0x80, /* #....... */
+ /*03be:*/ 0xe0, /* ###..... */
+/* --- new character braceleft (123) starting at offset 0x03bf --- */
+ /*03bf:*/ 2, 3, 7, 0, -1, /* width and bbox (w,h,x,y) */
+ /*03c4:*/ 0x20, /* ..#..... */
+ /*03c5:*/ 0x40, /* .#...... */
+ /*03c6:*/ 0x40, /* .#...... */
+ /*03c7:*/ 0xc0, /* ##...... */
+ /*03c8:*/ 0x40, /* .#...... */
+ /*03c9:*/ 0x40, /* .#...... */
+ /*03ca:*/ 0x20, /* ..#..... */
+/* --- new character bar (124) starting at offset 0x03cb --- */
+ /*03cb:*/ 2, 1, 7, 1, -1, /* width and bbox (w,h,x,y) */
+ /*03d0:*/ 0x80, /* #....... */
+ /*03d1:*/ 0x80, /* #....... */
+ /*03d2:*/ 0x80, /* #....... */
+ /*03d3:*/ 0x80, /* #....... */
+ /*03d4:*/ 0x80, /* #....... */
+ /*03d5:*/ 0x80, /* #....... */
+ /*03d6:*/ 0x80, /* #....... */
+/* --- new character braceright (125) starting at offset 0x03d7 --- */
+ /*03d7:*/ 2, 3, 7, 0, -1, /* width and bbox (w,h,x,y) */
+ /*03dc:*/ 0x80, /* #....... */
+ /*03dd:*/ 0x40, /* .#...... */
+ /*03de:*/ 0x40, /* .#...... */
+ /*03df:*/ 0x60, /* .##..... */
+ /*03e0:*/ 0x40, /* .#...... */
+ /*03e1:*/ 0x40, /* .#...... */
+ /*03e2:*/ 0x80, /* #....... */
+/* --- new character asciitilde (126) starting at offset 0x03e3 --- */
+ /*03e3:*/ 6, 5, 2, 1, 2, /* width and bbox (w,h,x,y) */
+ /*03e8:*/ 0x48, /* .#..#... */
+ /*03e9:*/ 0xb0, /* #.##.... */
+};
+static const uint16_t font_helvR08_offsets[] = {
+0x0000 /* space */,
+ 0x0006 /* exclam */,
+ 0x0011 /* quotedbl */,
+ 0x0019 /* numbersign */,
+ 0x0023 /* dollar */,
+ 0x002f /* percent */,
+ 0x003a /* ampersand */,
+ 0x0045 /* quotesingle */,
+ 0x004c /* parenleft */,
+ 0x0058 /* parenright */,
+ 0x0064 /* asterisk */,
+ 0x006c /* plus */,
+ 0x0076 /* comma */,
+ 0x007e /* hyphen */,
+ 0x0084 /* period */,
+ 0x008a /* slash */,
+ 0x0096 /* zero */,
+ 0x00a1 /* one */,
+ 0x00ac /* two */,
+ 0x00b7 /* three */,
+ 0x00c2 /* four */,
+ 0x00cd /* five */,
+ 0x00d8 /* six */,
+ 0x00e3 /* seven */,
+ 0x00ee /* eight */,
+ 0x00f9 /* nine */,
+ 0x0104 /* colon */,
+ 0x010d /* semicolon */,
+ 0x0118 /* less */,
+ 0x0122 /* equal */,
+ 0x012a /* greater */,
+ 0x0134 /* question */,
+ 0x013e /* at */,
+ 0x014a /* A */,
+ 0x0155 /* B */,
+ 0x0160 /* C */,
+ 0x016b /* D */,
+ 0x0176 /* E */,
+ 0x0181 /* F */,
+ 0x018c /* G */,
+ 0x0197 /* H */,
+ 0x01a2 /* I */,
+ 0x01ad /* J */,
+ 0x01b8 /* K */,
+ 0x01c3 /* L */,
+ 0x01ce /* M */,
+ 0x01d9 /* N */,
+ 0x01e4 /* O */,
+ 0x01ef /* P */,
+ 0x01fa /* Q */,
+ 0x0207 /* R */,
+ 0x0212 /* S */,
+ 0x021d /* T */,
+ 0x0228 /* U */,
+ 0x0233 /* V */,
+ 0x023e /* W */,
+ 0x0249 /* X */,
+ 0x0254 /* Y */,
+ 0x025f /* Z */,
+ 0x026a /* bracketleft */,
+ 0x0276 /* backslash */,
+ 0x0282 /* bracketright */,
+ 0x028e /* asciicircum */,
+ 0x0296 /* underscore */,
+ 0x029c /* grave */,
+ 0x02a3 /* a */,
+ 0x02ad /* b */,
+ 0x02b9 /* c */,
+ 0x02c3 /* d */,
+ 0x02cf /* e */,
+ 0x02d9 /* f */,
+ 0x02e5 /* g */,
+ 0x02f0 /* h */,
+ 0x02fc /* i */,
+ 0x0308 /* j */,
+ 0x0316 /* k */,
+ 0x0322 /* l */,
+ 0x032e /* m */,
+ 0x0338 /* n */,
+ 0x0342 /* o */,
+ 0x034c /* p */,
+ 0x0357 /* q */,
+ 0x0362 /* r */,
+ 0x036c /* s */,
+ 0x0376 /* t */,
+ 0x0382 /* u */,
+ 0x038c /* v */,
+ 0x0396 /* w */,
+ 0x03a0 /* x */,
+ 0x03aa /* y */,
+ 0x03b5 /* z */,
+ 0x03bf /* braceleft */,
+ 0x03cb /* bar */,
+ 0x03d7 /* braceright */,
+ 0x03e3 /* asciitilde */,
+ 0xffff /* (no glyph) */
+};
+const struct fb_font font_helvR08 = {
+ .height = 10,
+ .ascent = 8,
+ .firstchar = 32, /* space */
+ .lastchar = 127, /* ? */
+ .chardata = font_helvR08_data,
+ .charoffs = font_helvR08_offsets,
+};
diff --git a/Src/osmolib/src/target/firmware/fb/helvR14.c b/Src/osmolib/src/target/firmware/fb/helvR14.c
new file mode 100644
index 0000000..b028125
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/helvR14.c
@@ -0,0 +1,1198 @@
+#include <fb/font.h>
+static const uint8_t font_helvR14_data[] = {
+/* --- new character space (32) starting at offset 0x0000 --- */
+ /*0000:*/ 4, 1, 1, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0005:*/ 0x00, /* ........ */
+/* --- new character exclam (33) starting at offset 0x0006 --- */
+ /*0006:*/ 4, 1, 11, 2, 0, /* width and bbox (w,h,x,y) */
+ /*000b:*/ 0x80, /* #....... */
+ /*000c:*/ 0x80, /* #....... */
+ /*000d:*/ 0x80, /* #....... */
+ /*000e:*/ 0x80, /* #....... */
+ /*000f:*/ 0x80, /* #....... */
+ /*0010:*/ 0x80, /* #....... */
+ /*0011:*/ 0x80, /* #....... */
+ /*0012:*/ 0x80, /* #....... */
+ /*0013:*/ 0x00, /* ........ */
+ /*0014:*/ 0x80, /* #....... */
+ /*0015:*/ 0x80, /* #....... */
+/* --- new character quotedbl (34) starting at offset 0x0016 --- */
+ /*0016:*/ 5, 3, 3, 1, 8, /* width and bbox (w,h,x,y) */
+ /*001b:*/ 0xa0, /* #.#..... */
+ /*001c:*/ 0xa0, /* #.#..... */
+ /*001d:*/ 0xa0, /* #.#..... */
+/* --- new character numbersign (35) starting at offset 0x001e --- */
+ /*001e:*/ 8, 7, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0023:*/ 0x14, /* ...#.#.. */
+ /*0024:*/ 0x14, /* ...#.#.. */
+ /*0025:*/ 0x14, /* ...#.#.. */
+ /*0026:*/ 0x7e, /* .######. */
+ /*0027:*/ 0x28, /* ..#.#... */
+ /*0028:*/ 0x28, /* ..#.#... */
+ /*0029:*/ 0xfc, /* ######.. */
+ /*002a:*/ 0x50, /* .#.#.... */
+ /*002b:*/ 0x50, /* .#.#.... */
+ /*002c:*/ 0x50, /* .#.#.... */
+/* --- new character dollar (36) starting at offset 0x002d --- */
+ /*002d:*/ 8, 7, 14, 0, -2, /* width and bbox (w,h,x,y) */
+ /*0032:*/ 0x10, /* ...#.... */
+ /*0033:*/ 0x10, /* ...#.... */
+ /*0034:*/ 0x7c, /* .#####.. */
+ /*0035:*/ 0x92, /* #..#..#. */
+ /*0036:*/ 0x92, /* #..#..#. */
+ /*0037:*/ 0x50, /* .#.#.... */
+ /*0038:*/ 0x38, /* ..###... */
+ /*0039:*/ 0x14, /* ...#.#.. */
+ /*003a:*/ 0x12, /* ...#..#. */
+ /*003b:*/ 0x92, /* #..#..#. */
+ /*003c:*/ 0x92, /* #..#..#. */
+ /*003d:*/ 0x7c, /* .#####.. */
+ /*003e:*/ 0x10, /* ...#.... */
+ /*003f:*/ 0x10, /* ...#.... */
+/* --- new character percent (37) starting at offset 0x0040 --- */
+ /*0040:*/ 12, 11, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0045:*/ 0x70,0x80, /* .###....#....... */
+ /*0047:*/ 0x89,0x00, /* #...#..#........ */
+ /*0049:*/ 0x89,0x00, /* #...#..#........ */
+ /*004b:*/ 0x72,0x00, /* .###..#......... */
+ /*004d:*/ 0x02,0x00, /* ......#......... */
+ /*004f:*/ 0x04,0x00, /* .....#.......... */
+ /*0051:*/ 0x09,0xc0, /* ....#..###...... */
+ /*0053:*/ 0x12,0x20, /* ...#..#...#..... */
+ /*0055:*/ 0x12,0x20, /* ...#..#...#..... */
+ /*0057:*/ 0x21,0xc0, /* ..#....###...... */
+/* --- new character ampersand (38) starting at offset 0x0059 --- */
+ /*0059:*/ 10, 8, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*005e:*/ 0x30, /* ..##.... */
+ /*005f:*/ 0x48, /* .#..#... */
+ /*0060:*/ 0x48, /* .#..#... */
+ /*0061:*/ 0x30, /* ..##.... */
+ /*0062:*/ 0x20, /* ..#..... */
+ /*0063:*/ 0x52, /* .#.#..#. */
+ /*0064:*/ 0x8a, /* #...#.#. */
+ /*0065:*/ 0x84, /* #....#.. */
+ /*0066:*/ 0x8a, /* #...#.#. */
+ /*0067:*/ 0x71, /* .###...# */
+/* --- new character quotesingle (39) starting at offset 0x0068 --- */
+ /*0068:*/ 3, 1, 3, 1, 8, /* width and bbox (w,h,x,y) */
+ /*006d:*/ 0x80, /* #....... */
+ /*006e:*/ 0x80, /* #....... */
+ /*006f:*/ 0x80, /* #....... */
+/* --- new character parenleft (40) starting at offset 0x0070 --- */
+ /*0070:*/ 5, 3, 14, 1, -3, /* width and bbox (w,h,x,y) */
+ /*0075:*/ 0x20, /* ..#..... */
+ /*0076:*/ 0x40, /* .#...... */
+ /*0077:*/ 0x40, /* .#...... */
+ /*0078:*/ 0x80, /* #....... */
+ /*0079:*/ 0x80, /* #....... */
+ /*007a:*/ 0x80, /* #....... */
+ /*007b:*/ 0x80, /* #....... */
+ /*007c:*/ 0x80, /* #....... */
+ /*007d:*/ 0x80, /* #....... */
+ /*007e:*/ 0x80, /* #....... */
+ /*007f:*/ 0x80, /* #....... */
+ /*0080:*/ 0x40, /* .#...... */
+ /*0081:*/ 0x40, /* .#...... */
+ /*0082:*/ 0x20, /* ..#..... */
+/* --- new character parenright (41) starting at offset 0x0083 --- */
+ /*0083:*/ 5, 3, 14, 1, -3, /* width and bbox (w,h,x,y) */
+ /*0088:*/ 0x80, /* #....... */
+ /*0089:*/ 0x40, /* .#...... */
+ /*008a:*/ 0x40, /* .#...... */
+ /*008b:*/ 0x20, /* ..#..... */
+ /*008c:*/ 0x20, /* ..#..... */
+ /*008d:*/ 0x20, /* ..#..... */
+ /*008e:*/ 0x20, /* ..#..... */
+ /*008f:*/ 0x20, /* ..#..... */
+ /*0090:*/ 0x20, /* ..#..... */
+ /*0091:*/ 0x20, /* ..#..... */
+ /*0092:*/ 0x20, /* ..#..... */
+ /*0093:*/ 0x40, /* .#...... */
+ /*0094:*/ 0x40, /* .#...... */
+ /*0095:*/ 0x80, /* #....... */
+/* --- new character asterisk (42) starting at offset 0x0096 --- */
+ /*0096:*/ 7, 5, 4, 1, 6, /* width and bbox (w,h,x,y) */
+ /*009b:*/ 0x20, /* ..#..... */
+ /*009c:*/ 0xf8, /* #####... */
+ /*009d:*/ 0x20, /* ..#..... */
+ /*009e:*/ 0x50, /* .#.#.... */
+/* --- new character plus (43) starting at offset 0x009f --- */
+ /*009f:*/ 9, 7, 7, 1, 1, /* width and bbox (w,h,x,y) */
+ /*00a4:*/ 0x10, /* ...#.... */
+ /*00a5:*/ 0x10, /* ...#.... */
+ /*00a6:*/ 0x10, /* ...#.... */
+ /*00a7:*/ 0xfe, /* #######. */
+ /*00a8:*/ 0x10, /* ...#.... */
+ /*00a9:*/ 0x10, /* ...#.... */
+ /*00aa:*/ 0x10, /* ...#.... */
+/* --- new character comma (44) starting at offset 0x00ab --- */
+ /*00ab:*/ 3, 2, 4, 0, -2, /* width and bbox (w,h,x,y) */
+ /*00b0:*/ 0x40, /* .#...... */
+ /*00b1:*/ 0x40, /* .#...... */
+ /*00b2:*/ 0x40, /* .#...... */
+ /*00b3:*/ 0x80, /* #....... */
+/* --- new character hyphen (45) starting at offset 0x00b4 --- */
+ /*00b4:*/ 5, 4, 1, 0, 4, /* width and bbox (w,h,x,y) */
+ /*00b9:*/ 0xf0, /* ####.... */
+/* --- new character period (46) starting at offset 0x00ba --- */
+ /*00ba:*/ 3, 1, 2, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00bf:*/ 0x80, /* #....... */
+ /*00c0:*/ 0x80, /* #....... */
+/* --- new character slash (47) starting at offset 0x00c1 --- */
+ /*00c1:*/ 4, 4, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*00c6:*/ 0x10, /* ...#.... */
+ /*00c7:*/ 0x10, /* ...#.... */
+ /*00c8:*/ 0x20, /* ..#..... */
+ /*00c9:*/ 0x20, /* ..#..... */
+ /*00ca:*/ 0x20, /* ..#..... */
+ /*00cb:*/ 0x40, /* .#...... */
+ /*00cc:*/ 0x40, /* .#...... */
+ /*00cd:*/ 0x40, /* .#...... */
+ /*00ce:*/ 0x80, /* #....... */
+ /*00cf:*/ 0x80, /* #....... */
+ /*00d0:*/ 0x80, /* #....... */
+/* --- new character zero (48) starting at offset 0x00d1 --- */
+ /*00d1:*/ 8, 6, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00d6:*/ 0x78, /* .####... */
+ /*00d7:*/ 0x84, /* #....#.. */
+ /*00d8:*/ 0x84, /* #....#.. */
+ /*00d9:*/ 0x84, /* #....#.. */
+ /*00da:*/ 0x84, /* #....#.. */
+ /*00db:*/ 0x84, /* #....#.. */
+ /*00dc:*/ 0x84, /* #....#.. */
+ /*00dd:*/ 0x84, /* #....#.. */
+ /*00de:*/ 0x84, /* #....#.. */
+ /*00df:*/ 0x78, /* .####... */
+/* --- new character one (49) starting at offset 0x00e0 --- */
+ /*00e0:*/ 8, 3, 10, 2, 0, /* width and bbox (w,h,x,y) */
+ /*00e5:*/ 0x20, /* ..#..... */
+ /*00e6:*/ 0xe0, /* ###..... */
+ /*00e7:*/ 0x20, /* ..#..... */
+ /*00e8:*/ 0x20, /* ..#..... */
+ /*00e9:*/ 0x20, /* ..#..... */
+ /*00ea:*/ 0x20, /* ..#..... */
+ /*00eb:*/ 0x20, /* ..#..... */
+ /*00ec:*/ 0x20, /* ..#..... */
+ /*00ed:*/ 0x20, /* ..#..... */
+ /*00ee:*/ 0x20, /* ..#..... */
+/* --- new character two (50) starting at offset 0x00ef --- */
+ /*00ef:*/ 8, 6, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00f4:*/ 0x78, /* .####... */
+ /*00f5:*/ 0x84, /* #....#.. */
+ /*00f6:*/ 0x84, /* #....#.. */
+ /*00f7:*/ 0x08, /* ....#... */
+ /*00f8:*/ 0x10, /* ...#.... */
+ /*00f9:*/ 0x20, /* ..#..... */
+ /*00fa:*/ 0x40, /* .#...... */
+ /*00fb:*/ 0x80, /* #....... */
+ /*00fc:*/ 0x80, /* #....... */
+ /*00fd:*/ 0xfc, /* ######.. */
+/* --- new character three (51) starting at offset 0x00fe --- */
+ /*00fe:*/ 8, 6, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0103:*/ 0x78, /* .####... */
+ /*0104:*/ 0x84, /* #....#.. */
+ /*0105:*/ 0x84, /* #....#.. */
+ /*0106:*/ 0x04, /* .....#.. */
+ /*0107:*/ 0x38, /* ..###... */
+ /*0108:*/ 0x04, /* .....#.. */
+ /*0109:*/ 0x04, /* .....#.. */
+ /*010a:*/ 0x84, /* #....#.. */
+ /*010b:*/ 0x84, /* #....#.. */
+ /*010c:*/ 0x78, /* .####... */
+/* --- new character four (52) starting at offset 0x010d --- */
+ /*010d:*/ 8, 7, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0112:*/ 0x0c, /* ....##.. */
+ /*0113:*/ 0x14, /* ...#.#.. */
+ /*0114:*/ 0x24, /* ..#..#.. */
+ /*0115:*/ 0x24, /* ..#..#.. */
+ /*0116:*/ 0x44, /* .#...#.. */
+ /*0117:*/ 0x84, /* #....#.. */
+ /*0118:*/ 0xfe, /* #######. */
+ /*0119:*/ 0x04, /* .....#.. */
+ /*011a:*/ 0x04, /* .....#.. */
+ /*011b:*/ 0x04, /* .....#.. */
+/* --- new character five (53) starting at offset 0x011c --- */
+ /*011c:*/ 8, 6, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0121:*/ 0xfc, /* ######.. */
+ /*0122:*/ 0x80, /* #....... */
+ /*0123:*/ 0x80, /* #....... */
+ /*0124:*/ 0x80, /* #....... */
+ /*0125:*/ 0xf8, /* #####... */
+ /*0126:*/ 0x04, /* .....#.. */
+ /*0127:*/ 0x04, /* .....#.. */
+ /*0128:*/ 0x84, /* #....#.. */
+ /*0129:*/ 0x84, /* #....#.. */
+ /*012a:*/ 0x78, /* .####... */
+/* --- new character six (54) starting at offset 0x012b --- */
+ /*012b:*/ 8, 6, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0130:*/ 0x78, /* .####... */
+ /*0131:*/ 0x84, /* #....#.. */
+ /*0132:*/ 0x80, /* #....... */
+ /*0133:*/ 0x80, /* #....... */
+ /*0134:*/ 0xb8, /* #.###... */
+ /*0135:*/ 0xc4, /* ##...#.. */
+ /*0136:*/ 0x84, /* #....#.. */
+ /*0137:*/ 0x84, /* #....#.. */
+ /*0138:*/ 0x84, /* #....#.. */
+ /*0139:*/ 0x78, /* .####... */
+/* --- new character seven (55) starting at offset 0x013a --- */
+ /*013a:*/ 8, 6, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*013f:*/ 0xfc, /* ######.. */
+ /*0140:*/ 0x04, /* .....#.. */
+ /*0141:*/ 0x08, /* ....#... */
+ /*0142:*/ 0x08, /* ....#... */
+ /*0143:*/ 0x10, /* ...#.... */
+ /*0144:*/ 0x10, /* ...#.... */
+ /*0145:*/ 0x20, /* ..#..... */
+ /*0146:*/ 0x20, /* ..#..... */
+ /*0147:*/ 0x40, /* .#...... */
+ /*0148:*/ 0x40, /* .#...... */
+/* --- new character eight (56) starting at offset 0x0149 --- */
+ /*0149:*/ 8, 6, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*014e:*/ 0x78, /* .####... */
+ /*014f:*/ 0x84, /* #....#.. */
+ /*0150:*/ 0x84, /* #....#.. */
+ /*0151:*/ 0x84, /* #....#.. */
+ /*0152:*/ 0x78, /* .####... */
+ /*0153:*/ 0x84, /* #....#.. */
+ /*0154:*/ 0x84, /* #....#.. */
+ /*0155:*/ 0x84, /* #....#.. */
+ /*0156:*/ 0x84, /* #....#.. */
+ /*0157:*/ 0x78, /* .####... */
+/* --- new character nine (57) starting at offset 0x0158 --- */
+ /*0158:*/ 8, 6, 10, 1, 0, /* width and bbox (w,h,x,y) */
+ /*015d:*/ 0x78, /* .####... */
+ /*015e:*/ 0x84, /* #....#.. */
+ /*015f:*/ 0x84, /* #....#.. */
+ /*0160:*/ 0x84, /* #....#.. */
+ /*0161:*/ 0x84, /* #....#.. */
+ /*0162:*/ 0x7c, /* .#####.. */
+ /*0163:*/ 0x04, /* .....#.. */
+ /*0164:*/ 0x84, /* #....#.. */
+ /*0165:*/ 0x84, /* #....#.. */
+ /*0166:*/ 0x78, /* .####... */
+/* --- new character colon (58) starting at offset 0x0167 --- */
+ /*0167:*/ 3, 1, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*016c:*/ 0x80, /* #....... */
+ /*016d:*/ 0x80, /* #....... */
+ /*016e:*/ 0x00, /* ........ */
+ /*016f:*/ 0x00, /* ........ */
+ /*0170:*/ 0x00, /* ........ */
+ /*0171:*/ 0x00, /* ........ */
+ /*0172:*/ 0x80, /* #....... */
+ /*0173:*/ 0x80, /* #....... */
+/* --- new character semicolon (59) starting at offset 0x0174 --- */
+ /*0174:*/ 4, 2, 10, 0, -2, /* width and bbox (w,h,x,y) */
+ /*0179:*/ 0x40, /* .#...... */
+ /*017a:*/ 0x40, /* .#...... */
+ /*017b:*/ 0x00, /* ........ */
+ /*017c:*/ 0x00, /* ........ */
+ /*017d:*/ 0x00, /* ........ */
+ /*017e:*/ 0x00, /* ........ */
+ /*017f:*/ 0x40, /* .#...... */
+ /*0180:*/ 0x40, /* .#...... */
+ /*0181:*/ 0x40, /* .#...... */
+ /*0182:*/ 0x80, /* #....... */
+/* --- new character less (60) starting at offset 0x0183 --- */
+ /*0183:*/ 8, 6, 5, 1, 2, /* width and bbox (w,h,x,y) */
+ /*0188:*/ 0x0c, /* ....##.. */
+ /*0189:*/ 0x30, /* ..##.... */
+ /*018a:*/ 0xc0, /* ##...... */
+ /*018b:*/ 0x30, /* ..##.... */
+ /*018c:*/ 0x0c, /* ....##.. */
+/* --- new character equal (61) starting at offset 0x018d --- */
+ /*018d:*/ 9, 6, 3, 1, 3, /* width and bbox (w,h,x,y) */
+ /*0192:*/ 0xfc, /* ######.. */
+ /*0193:*/ 0x00, /* ........ */
+ /*0194:*/ 0xfc, /* ######.. */
+/* --- new character greater (62) starting at offset 0x0195 --- */
+ /*0195:*/ 8, 6, 5, 1, 2, /* width and bbox (w,h,x,y) */
+ /*019a:*/ 0xc0, /* ##...... */
+ /*019b:*/ 0x30, /* ..##.... */
+ /*019c:*/ 0x0c, /* ....##.. */
+ /*019d:*/ 0x30, /* ..##.... */
+ /*019e:*/ 0xc0, /* ##...... */
+/* --- new character question (63) starting at offset 0x019f --- */
+ /*019f:*/ 8, 6, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01a4:*/ 0x30, /* ..##.... */
+ /*01a5:*/ 0xcc, /* ##..##.. */
+ /*01a6:*/ 0x84, /* #....#.. */
+ /*01a7:*/ 0x84, /* #....#.. */
+ /*01a8:*/ 0x04, /* .....#.. */
+ /*01a9:*/ 0x08, /* ....#... */
+ /*01aa:*/ 0x10, /* ...#.... */
+ /*01ab:*/ 0x20, /* ..#..... */
+ /*01ac:*/ 0x00, /* ........ */
+ /*01ad:*/ 0x20, /* ..#..... */
+ /*01ae:*/ 0x20, /* ..#..... */
+/* --- new character at (64) starting at offset 0x01af --- */
+ /*01af:*/ 13, 11, 12, 1, -1, /* width and bbox (w,h,x,y) */
+ /*01b4:*/ 0x0f,0x00, /* ....####........ */
+ /*01b6:*/ 0x30,0xc0, /* ..##....##...... */
+ /*01b8:*/ 0x40,0x20, /* .#........#..... */
+ /*01ba:*/ 0x46,0xa0, /* .#...##.#.#..... */
+ /*01bc:*/ 0x89,0x20, /* #...#..#..#..... */
+ /*01be:*/ 0x91,0x20, /* #..#...#..#..... */
+ /*01c0:*/ 0x91,0x20, /* #..#...#..#..... */
+ /*01c2:*/ 0x93,0x40, /* #..#..##.#...... */
+ /*01c4:*/ 0x8d,0x80, /* #...##.##....... */
+ /*01c6:*/ 0x40,0x00, /* .#.............. */
+ /*01c8:*/ 0x60,0x80, /* .##.....#....... */
+ /*01ca:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character A (65) starting at offset 0x01cc --- */
+ /*01cc:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01d1:*/ 0x08,0x00, /* ....#........... */
+ /*01d3:*/ 0x08,0x00, /* ....#........... */
+ /*01d5:*/ 0x14,0x00, /* ...#.#.......... */
+ /*01d7:*/ 0x14,0x00, /* ...#.#.......... */
+ /*01d9:*/ 0x22,0x00, /* ..#...#......... */
+ /*01db:*/ 0x22,0x00, /* ..#...#......... */
+ /*01dd:*/ 0x41,0x00, /* .#.....#........ */
+ /*01df:*/ 0x7f,0x00, /* .#######........ */
+ /*01e1:*/ 0x41,0x00, /* .#.....#........ */
+ /*01e3:*/ 0x80,0x80, /* #.......#....... */
+ /*01e5:*/ 0x80,0x80, /* #.......#....... */
+/* --- new character B (66) starting at offset 0x01e7 --- */
+ /*01e7:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01ec:*/ 0xfc, /* ######.. */
+ /*01ed:*/ 0x86, /* #....##. */
+ /*01ee:*/ 0x82, /* #.....#. */
+ /*01ef:*/ 0x82, /* #.....#. */
+ /*01f0:*/ 0x82, /* #.....#. */
+ /*01f1:*/ 0xfc, /* ######.. */
+ /*01f2:*/ 0x82, /* #.....#. */
+ /*01f3:*/ 0x82, /* #.....#. */
+ /*01f4:*/ 0x82, /* #.....#. */
+ /*01f5:*/ 0x82, /* #.....#. */
+ /*01f6:*/ 0xfc, /* ######.. */
+/* --- new character C (67) starting at offset 0x01f7 --- */
+ /*01f7:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01fc:*/ 0x1c, /* ...###.. */
+ /*01fd:*/ 0x63, /* .##...## */
+ /*01fe:*/ 0x41, /* .#.....# */
+ /*01ff:*/ 0x80, /* #....... */
+ /*0200:*/ 0x80, /* #....... */
+ /*0201:*/ 0x80, /* #....... */
+ /*0202:*/ 0x80, /* #....... */
+ /*0203:*/ 0x80, /* #....... */
+ /*0204:*/ 0x41, /* .#.....# */
+ /*0205:*/ 0x63, /* .##...## */
+ /*0206:*/ 0x1c, /* ...###.. */
+/* --- new character D (68) starting at offset 0x0207 --- */
+ /*0207:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*020c:*/ 0xf8, /* #####... */
+ /*020d:*/ 0x86, /* #....##. */
+ /*020e:*/ 0x82, /* #.....#. */
+ /*020f:*/ 0x81, /* #......# */
+ /*0210:*/ 0x81, /* #......# */
+ /*0211:*/ 0x81, /* #......# */
+ /*0212:*/ 0x81, /* #......# */
+ /*0213:*/ 0x81, /* #......# */
+ /*0214:*/ 0x82, /* #.....#. */
+ /*0215:*/ 0x86, /* #....##. */
+ /*0216:*/ 0xf8, /* #####... */
+/* --- new character E (69) starting at offset 0x0217 --- */
+ /*0217:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*021c:*/ 0xfe, /* #######. */
+ /*021d:*/ 0x80, /* #....... */
+ /*021e:*/ 0x80, /* #....... */
+ /*021f:*/ 0x80, /* #....... */
+ /*0220:*/ 0x80, /* #....... */
+ /*0221:*/ 0xfc, /* ######.. */
+ /*0222:*/ 0x80, /* #....... */
+ /*0223:*/ 0x80, /* #....... */
+ /*0224:*/ 0x80, /* #....... */
+ /*0225:*/ 0x80, /* #....... */
+ /*0226:*/ 0xfe, /* #######. */
+/* --- new character F (70) starting at offset 0x0227 --- */
+ /*0227:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*022c:*/ 0xfe, /* #######. */
+ /*022d:*/ 0x80, /* #....... */
+ /*022e:*/ 0x80, /* #....... */
+ /*022f:*/ 0x80, /* #....... */
+ /*0230:*/ 0x80, /* #....... */
+ /*0231:*/ 0xfc, /* ######.. */
+ /*0232:*/ 0x80, /* #....... */
+ /*0233:*/ 0x80, /* #....... */
+ /*0234:*/ 0x80, /* #....... */
+ /*0235:*/ 0x80, /* #....... */
+ /*0236:*/ 0x80, /* #....... */
+/* --- new character G (71) starting at offset 0x0237 --- */
+ /*0237:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*023c:*/ 0x1e,0x00, /* ...####......... */
+ /*023e:*/ 0x61,0x80, /* .##....##....... */
+ /*0240:*/ 0x40,0x80, /* .#......#....... */
+ /*0242:*/ 0x80,0x00, /* #............... */
+ /*0244:*/ 0x80,0x00, /* #............... */
+ /*0246:*/ 0x87,0x80, /* #....####....... */
+ /*0248:*/ 0x80,0x80, /* #.......#....... */
+ /*024a:*/ 0x80,0x80, /* #.......#....... */
+ /*024c:*/ 0x40,0x80, /* .#......#....... */
+ /*024e:*/ 0x63,0x80, /* .##...###....... */
+ /*0250:*/ 0x1c,0x80, /* ...###..#....... */
+/* --- new character H (72) starting at offset 0x0252 --- */
+ /*0252:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0257:*/ 0x81, /* #......# */
+ /*0258:*/ 0x81, /* #......# */
+ /*0259:*/ 0x81, /* #......# */
+ /*025a:*/ 0x81, /* #......# */
+ /*025b:*/ 0x81, /* #......# */
+ /*025c:*/ 0xff, /* ######## */
+ /*025d:*/ 0x81, /* #......# */
+ /*025e:*/ 0x81, /* #......# */
+ /*025f:*/ 0x81, /* #......# */
+ /*0260:*/ 0x81, /* #......# */
+ /*0261:*/ 0x81, /* #......# */
+/* --- new character I (73) starting at offset 0x0262 --- */
+ /*0262:*/ 5, 1, 11, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0267:*/ 0x80, /* #....... */
+ /*0268:*/ 0x80, /* #....... */
+ /*0269:*/ 0x80, /* #....... */
+ /*026a:*/ 0x80, /* #....... */
+ /*026b:*/ 0x80, /* #....... */
+ /*026c:*/ 0x80, /* #....... */
+ /*026d:*/ 0x80, /* #....... */
+ /*026e:*/ 0x80, /* #....... */
+ /*026f:*/ 0x80, /* #....... */
+ /*0270:*/ 0x80, /* #....... */
+ /*0271:*/ 0x80, /* #....... */
+/* --- new character J (74) starting at offset 0x0272 --- */
+ /*0272:*/ 8, 6, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0277:*/ 0x04, /* .....#.. */
+ /*0278:*/ 0x04, /* .....#.. */
+ /*0279:*/ 0x04, /* .....#.. */
+ /*027a:*/ 0x04, /* .....#.. */
+ /*027b:*/ 0x04, /* .....#.. */
+ /*027c:*/ 0x04, /* .....#.. */
+ /*027d:*/ 0x04, /* .....#.. */
+ /*027e:*/ 0x04, /* .....#.. */
+ /*027f:*/ 0x84, /* #....#.. */
+ /*0280:*/ 0x84, /* #....#.. */
+ /*0281:*/ 0x78, /* .####... */
+/* --- new character K (75) starting at offset 0x0282 --- */
+ /*0282:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0287:*/ 0x82, /* #.....#. */
+ /*0288:*/ 0x84, /* #....#.. */
+ /*0289:*/ 0x88, /* #...#... */
+ /*028a:*/ 0x90, /* #..#.... */
+ /*028b:*/ 0xa0, /* #.#..... */
+ /*028c:*/ 0xe0, /* ###..... */
+ /*028d:*/ 0x90, /* #..#.... */
+ /*028e:*/ 0x88, /* #...#... */
+ /*028f:*/ 0x84, /* #....#.. */
+ /*0290:*/ 0x82, /* #.....#. */
+ /*0291:*/ 0x81, /* #......# */
+/* --- new character L (76) starting at offset 0x0292 --- */
+ /*0292:*/ 8, 6, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0297:*/ 0x80, /* #....... */
+ /*0298:*/ 0x80, /* #....... */
+ /*0299:*/ 0x80, /* #....... */
+ /*029a:*/ 0x80, /* #....... */
+ /*029b:*/ 0x80, /* #....... */
+ /*029c:*/ 0x80, /* #....... */
+ /*029d:*/ 0x80, /* #....... */
+ /*029e:*/ 0x80, /* #....... */
+ /*029f:*/ 0x80, /* #....... */
+ /*02a0:*/ 0x80, /* #....... */
+ /*02a1:*/ 0xfc, /* ######.. */
+/* --- new character M (77) starting at offset 0x02a2 --- */
+ /*02a2:*/ 13, 11, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02a7:*/ 0x80,0x20, /* #.........#..... */
+ /*02a9:*/ 0x80,0x20, /* #.........#..... */
+ /*02ab:*/ 0xc0,0x60, /* ##.......##..... */
+ /*02ad:*/ 0xa0,0xa0, /* #.#.....#.#..... */
+ /*02af:*/ 0xa0,0xa0, /* #.#.....#.#..... */
+ /*02b1:*/ 0x91,0x20, /* #..#...#..#..... */
+ /*02b3:*/ 0x91,0x20, /* #..#...#..#..... */
+ /*02b5:*/ 0x8a,0x20, /* #...#.#...#..... */
+ /*02b7:*/ 0x8a,0x20, /* #...#.#...#..... */
+ /*02b9:*/ 0x84,0x20, /* #....#....#..... */
+ /*02bb:*/ 0x84,0x20, /* #....#....#..... */
+/* --- new character N (78) starting at offset 0x02bd --- */
+ /*02bd:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02c2:*/ 0xc1, /* ##.....# */
+ /*02c3:*/ 0xc1, /* ##.....# */
+ /*02c4:*/ 0xa1, /* #.#....# */
+ /*02c5:*/ 0x91, /* #..#...# */
+ /*02c6:*/ 0x91, /* #..#...# */
+ /*02c7:*/ 0x89, /* #...#..# */
+ /*02c8:*/ 0x89, /* #...#..# */
+ /*02c9:*/ 0x85, /* #....#.# */
+ /*02ca:*/ 0x85, /* #....#.# */
+ /*02cb:*/ 0x83, /* #.....## */
+ /*02cc:*/ 0x83, /* #.....## */
+/* --- new character O (79) starting at offset 0x02cd --- */
+ /*02cd:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02d2:*/ 0x1c,0x00, /* ...###.......... */
+ /*02d4:*/ 0x63,0x00, /* .##...##........ */
+ /*02d6:*/ 0x41,0x00, /* .#.....#........ */
+ /*02d8:*/ 0x80,0x80, /* #.......#....... */
+ /*02da:*/ 0x80,0x80, /* #.......#....... */
+ /*02dc:*/ 0x80,0x80, /* #.......#....... */
+ /*02de:*/ 0x80,0x80, /* #.......#....... */
+ /*02e0:*/ 0x80,0x80, /* #.......#....... */
+ /*02e2:*/ 0x41,0x00, /* .#.....#........ */
+ /*02e4:*/ 0x63,0x00, /* .##...##........ */
+ /*02e6:*/ 0x1c,0x00, /* ...###.......... */
+/* --- new character P (80) starting at offset 0x02e8 --- */
+ /*02e8:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02ed:*/ 0xfc, /* ######.. */
+ /*02ee:*/ 0x86, /* #....##. */
+ /*02ef:*/ 0x82, /* #.....#. */
+ /*02f0:*/ 0x82, /* #.....#. */
+ /*02f1:*/ 0x86, /* #....##. */
+ /*02f2:*/ 0xfc, /* ######.. */
+ /*02f3:*/ 0x80, /* #....... */
+ /*02f4:*/ 0x80, /* #....... */
+ /*02f5:*/ 0x80, /* #....... */
+ /*02f6:*/ 0x80, /* #....... */
+ /*02f7:*/ 0x80, /* #....... */
+/* --- new character Q (81) starting at offset 0x02f8 --- */
+ /*02f8:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02fd:*/ 0x1c,0x00, /* ...###.......... */
+ /*02ff:*/ 0x63,0x00, /* .##...##........ */
+ /*0301:*/ 0x41,0x00, /* .#.....#........ */
+ /*0303:*/ 0x80,0x80, /* #.......#....... */
+ /*0305:*/ 0x80,0x80, /* #.......#....... */
+ /*0307:*/ 0x80,0x80, /* #.......#....... */
+ /*0309:*/ 0x88,0x80, /* #...#...#....... */
+ /*030b:*/ 0x84,0x80, /* #....#..#....... */
+ /*030d:*/ 0x43,0x00, /* .#....##........ */
+ /*030f:*/ 0x63,0x00, /* .##...##........ */
+ /*0311:*/ 0x1c,0x80, /* ...###..#....... */
+/* --- new character R (82) starting at offset 0x0313 --- */
+ /*0313:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0318:*/ 0xfc, /* ######.. */
+ /*0319:*/ 0x86, /* #....##. */
+ /*031a:*/ 0x82, /* #.....#. */
+ /*031b:*/ 0x82, /* #.....#. */
+ /*031c:*/ 0x84, /* #....#.. */
+ /*031d:*/ 0xf8, /* #####... */
+ /*031e:*/ 0x84, /* #....#.. */
+ /*031f:*/ 0x82, /* #.....#. */
+ /*0320:*/ 0x82, /* #.....#. */
+ /*0321:*/ 0x82, /* #.....#. */
+ /*0322:*/ 0x82, /* #.....#. */
+/* --- new character S (83) starting at offset 0x0323 --- */
+ /*0323:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0328:*/ 0x38, /* ..###... */
+ /*0329:*/ 0xc6, /* ##...##. */
+ /*032a:*/ 0x82, /* #.....#. */
+ /*032b:*/ 0x80, /* #....... */
+ /*032c:*/ 0x60, /* .##..... */
+ /*032d:*/ 0x18, /* ...##... */
+ /*032e:*/ 0x06, /* .....##. */
+ /*032f:*/ 0x02, /* ......#. */
+ /*0330:*/ 0x82, /* #.....#. */
+ /*0331:*/ 0xc6, /* ##...##. */
+ /*0332:*/ 0x38, /* ..###... */
+/* --- new character T (84) starting at offset 0x0333 --- */
+ /*0333:*/ 9, 9, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0338:*/ 0xff,0x80, /* #########....... */
+ /*033a:*/ 0x08,0x00, /* ....#........... */
+ /*033c:*/ 0x08,0x00, /* ....#........... */
+ /*033e:*/ 0x08,0x00, /* ....#........... */
+ /*0340:*/ 0x08,0x00, /* ....#........... */
+ /*0342:*/ 0x08,0x00, /* ....#........... */
+ /*0344:*/ 0x08,0x00, /* ....#........... */
+ /*0346:*/ 0x08,0x00, /* ....#........... */
+ /*0348:*/ 0x08,0x00, /* ....#........... */
+ /*034a:*/ 0x08,0x00, /* ....#........... */
+ /*034c:*/ 0x08,0x00, /* ....#........... */
+/* --- new character U (85) starting at offset 0x034e --- */
+ /*034e:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0353:*/ 0x81, /* #......# */
+ /*0354:*/ 0x81, /* #......# */
+ /*0355:*/ 0x81, /* #......# */
+ /*0356:*/ 0x81, /* #......# */
+ /*0357:*/ 0x81, /* #......# */
+ /*0358:*/ 0x81, /* #......# */
+ /*0359:*/ 0x81, /* #......# */
+ /*035a:*/ 0x81, /* #......# */
+ /*035b:*/ 0x81, /* #......# */
+ /*035c:*/ 0x42, /* .#....#. */
+ /*035d:*/ 0x3c, /* ..####.. */
+/* --- new character V (86) starting at offset 0x035e --- */
+ /*035e:*/ 11, 9, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0363:*/ 0x80,0x80, /* #.......#....... */
+ /*0365:*/ 0x80,0x80, /* #.......#....... */
+ /*0367:*/ 0x41,0x00, /* .#.....#........ */
+ /*0369:*/ 0x41,0x00, /* .#.....#........ */
+ /*036b:*/ 0x22,0x00, /* ..#...#......... */
+ /*036d:*/ 0x22,0x00, /* ..#...#......... */
+ /*036f:*/ 0x22,0x00, /* ..#...#......... */
+ /*0371:*/ 0x14,0x00, /* ...#.#.......... */
+ /*0373:*/ 0x14,0x00, /* ...#.#.......... */
+ /*0375:*/ 0x08,0x00, /* ....#........... */
+ /*0377:*/ 0x08,0x00, /* ....#........... */
+/* --- new character W (87) starting at offset 0x0379 --- */
+ /*0379:*/ 15, 13, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*037e:*/ 0x82,0x08, /* #.....#.....#... */
+ /*0380:*/ 0x82,0x08, /* #.....#.....#... */
+ /*0382:*/ 0x85,0x08, /* #....#.#....#... */
+ /*0384:*/ 0x45,0x10, /* .#...#.#...#.... */
+ /*0386:*/ 0x45,0x10, /* .#...#.#...#.... */
+ /*0388:*/ 0x45,0x10, /* .#...#.#...#.... */
+ /*038a:*/ 0x28,0xa0, /* ..#.#...#.#..... */
+ /*038c:*/ 0x28,0xa0, /* ..#.#...#.#..... */
+ /*038e:*/ 0x28,0xa0, /* ..#.#...#.#..... */
+ /*0390:*/ 0x10,0x40, /* ...#.....#...... */
+ /*0392:*/ 0x10,0x40, /* ...#.....#...... */
+/* --- new character X (88) starting at offset 0x0394 --- */
+ /*0394:*/ 10, 8, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0399:*/ 0x81, /* #......# */
+ /*039a:*/ 0x81, /* #......# */
+ /*039b:*/ 0x42, /* .#....#. */
+ /*039c:*/ 0x24, /* ..#..#.. */
+ /*039d:*/ 0x18, /* ...##... */
+ /*039e:*/ 0x18, /* ...##... */
+ /*039f:*/ 0x24, /* ..#..#.. */
+ /*03a0:*/ 0x42, /* .#....#. */
+ /*03a1:*/ 0x42, /* .#....#. */
+ /*03a2:*/ 0x81, /* #......# */
+ /*03a3:*/ 0x81, /* #......# */
+/* --- new character Y (89) starting at offset 0x03a4 --- */
+ /*03a4:*/ 9, 9, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03a9:*/ 0x80,0x80, /* #.......#....... */
+ /*03ab:*/ 0x41,0x00, /* .#.....#........ */
+ /*03ad:*/ 0x41,0x00, /* .#.....#........ */
+ /*03af:*/ 0x22,0x00, /* ..#...#......... */
+ /*03b1:*/ 0x22,0x00, /* ..#...#......... */
+ /*03b3:*/ 0x14,0x00, /* ...#.#.......... */
+ /*03b5:*/ 0x08,0x00, /* ....#........... */
+ /*03b7:*/ 0x08,0x00, /* ....#........... */
+ /*03b9:*/ 0x08,0x00, /* ....#........... */
+ /*03bb:*/ 0x08,0x00, /* ....#........... */
+ /*03bd:*/ 0x08,0x00, /* ....#........... */
+/* --- new character Z (90) starting at offset 0x03bf --- */
+ /*03bf:*/ 9, 7, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*03c4:*/ 0xfe, /* #######. */
+ /*03c5:*/ 0x02, /* ......#. */
+ /*03c6:*/ 0x04, /* .....#.. */
+ /*03c7:*/ 0x08, /* ....#... */
+ /*03c8:*/ 0x18, /* ...##... */
+ /*03c9:*/ 0x10, /* ...#.... */
+ /*03ca:*/ 0x20, /* ..#..... */
+ /*03cb:*/ 0x60, /* .##..... */
+ /*03cc:*/ 0x40, /* .#...... */
+ /*03cd:*/ 0x80, /* #....... */
+ /*03ce:*/ 0xfe, /* #######. */
+/* --- new character bracketleft (91) starting at offset 0x03cf --- */
+ /*03cf:*/ 4, 3, 14, 1, -3, /* width and bbox (w,h,x,y) */
+ /*03d4:*/ 0xe0, /* ###..... */
+ /*03d5:*/ 0x80, /* #....... */
+ /*03d6:*/ 0x80, /* #....... */
+ /*03d7:*/ 0x80, /* #....... */
+ /*03d8:*/ 0x80, /* #....... */
+ /*03d9:*/ 0x80, /* #....... */
+ /*03da:*/ 0x80, /* #....... */
+ /*03db:*/ 0x80, /* #....... */
+ /*03dc:*/ 0x80, /* #....... */
+ /*03dd:*/ 0x80, /* #....... */
+ /*03de:*/ 0x80, /* #....... */
+ /*03df:*/ 0x80, /* #....... */
+ /*03e0:*/ 0x80, /* #....... */
+ /*03e1:*/ 0xe0, /* ###..... */
+/* --- new character backslash (92) starting at offset 0x03e2 --- */
+ /*03e2:*/ 4, 4, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*03e7:*/ 0x80, /* #....... */
+ /*03e8:*/ 0x80, /* #....... */
+ /*03e9:*/ 0x40, /* .#...... */
+ /*03ea:*/ 0x40, /* .#...... */
+ /*03eb:*/ 0x40, /* .#...... */
+ /*03ec:*/ 0x20, /* ..#..... */
+ /*03ed:*/ 0x20, /* ..#..... */
+ /*03ee:*/ 0x20, /* ..#..... */
+ /*03ef:*/ 0x10, /* ...#.... */
+ /*03f0:*/ 0x10, /* ...#.... */
+ /*03f1:*/ 0x10, /* ...#.... */
+/* --- new character bracketright (93) starting at offset 0x03f2 --- */
+ /*03f2:*/ 4, 3, 14, 0, -3, /* width and bbox (w,h,x,y) */
+ /*03f7:*/ 0xe0, /* ###..... */
+ /*03f8:*/ 0x20, /* ..#..... */
+ /*03f9:*/ 0x20, /* ..#..... */
+ /*03fa:*/ 0x20, /* ..#..... */
+ /*03fb:*/ 0x20, /* ..#..... */
+ /*03fc:*/ 0x20, /* ..#..... */
+ /*03fd:*/ 0x20, /* ..#..... */
+ /*03fe:*/ 0x20, /* ..#..... */
+ /*03ff:*/ 0x20, /* ..#..... */
+ /*0400:*/ 0x20, /* ..#..... */
+ /*0401:*/ 0x20, /* ..#..... */
+ /*0402:*/ 0x20, /* ..#..... */
+ /*0403:*/ 0x20, /* ..#..... */
+ /*0404:*/ 0xe0, /* ###..... */
+/* --- new character asciicircum (94) starting at offset 0x0405 --- */
+ /*0405:*/ 7, 7, 4, 0, 6, /* width and bbox (w,h,x,y) */
+ /*040a:*/ 0x10, /* ...#.... */
+ /*040b:*/ 0x28, /* ..#.#... */
+ /*040c:*/ 0x44, /* .#...#.. */
+ /*040d:*/ 0x82, /* #.....#. */
+/* --- new character underscore (95) starting at offset 0x040e --- */
+ /*040e:*/ 8, 8, 1, 0, -3, /* width and bbox (w,h,x,y) */
+ /*0413:*/ 0xff, /* ######## */
+/* --- new character grave (96) starting at offset 0x0414 --- */
+ /*0414:*/ 5, 2, 2, 1, 9, /* width and bbox (w,h,x,y) */
+ /*0419:*/ 0x80, /* #....... */
+ /*041a:*/ 0x40, /* .#...... */
+/* --- new character a (97) starting at offset 0x041b --- */
+ /*041b:*/ 8, 7, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0420:*/ 0x78, /* .####... */
+ /*0421:*/ 0xcc, /* ##..##.. */
+ /*0422:*/ 0x04, /* .....#.. */
+ /*0423:*/ 0x7c, /* .#####.. */
+ /*0424:*/ 0xc4, /* ##...#.. */
+ /*0425:*/ 0x84, /* #....#.. */
+ /*0426:*/ 0xcc, /* ##..##.. */
+ /*0427:*/ 0x76, /* .###.##. */
+/* --- new character b (98) starting at offset 0x0428 --- */
+ /*0428:*/ 8, 6, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*042d:*/ 0x80, /* #....... */
+ /*042e:*/ 0x80, /* #....... */
+ /*042f:*/ 0x80, /* #....... */
+ /*0430:*/ 0xb8, /* #.###... */
+ /*0431:*/ 0xcc, /* ##..##.. */
+ /*0432:*/ 0x84, /* #....#.. */
+ /*0433:*/ 0x84, /* #....#.. */
+ /*0434:*/ 0x84, /* #....#.. */
+ /*0435:*/ 0x84, /* #....#.. */
+ /*0436:*/ 0xcc, /* ##..##.. */
+ /*0437:*/ 0xb8, /* #.###... */
+/* --- new character c (99) starting at offset 0x0438 --- */
+ /*0438:*/ 8, 6, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*043d:*/ 0x78, /* .####... */
+ /*043e:*/ 0xcc, /* ##..##.. */
+ /*043f:*/ 0x80, /* #....... */
+ /*0440:*/ 0x80, /* #....... */
+ /*0441:*/ 0x80, /* #....... */
+ /*0442:*/ 0x84, /* #....#.. */
+ /*0443:*/ 0xcc, /* ##..##.. */
+ /*0444:*/ 0x78, /* .####... */
+/* --- new character d (100) starting at offset 0x0445 --- */
+ /*0445:*/ 8, 6, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*044a:*/ 0x04, /* .....#.. */
+ /*044b:*/ 0x04, /* .....#.. */
+ /*044c:*/ 0x04, /* .....#.. */
+ /*044d:*/ 0x74, /* .###.#.. */
+ /*044e:*/ 0xcc, /* ##..##.. */
+ /*044f:*/ 0x84, /* #....#.. */
+ /*0450:*/ 0x84, /* #....#.. */
+ /*0451:*/ 0x84, /* #....#.. */
+ /*0452:*/ 0x84, /* #....#.. */
+ /*0453:*/ 0xcc, /* ##..##.. */
+ /*0454:*/ 0x74, /* .###.#.. */
+/* --- new character e (101) starting at offset 0x0455 --- */
+ /*0455:*/ 8, 6, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*045a:*/ 0x78, /* .####... */
+ /*045b:*/ 0xcc, /* ##..##.. */
+ /*045c:*/ 0x84, /* #....#.. */
+ /*045d:*/ 0xfc, /* ######.. */
+ /*045e:*/ 0x80, /* #....... */
+ /*045f:*/ 0x80, /* #....... */
+ /*0460:*/ 0xcc, /* ##..##.. */
+ /*0461:*/ 0x78, /* .####... */
+/* --- new character f (102) starting at offset 0x0462 --- */
+ /*0462:*/ 3, 4, 11, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0467:*/ 0x30, /* ..##.... */
+ /*0468:*/ 0x40, /* .#...... */
+ /*0469:*/ 0x40, /* .#...... */
+ /*046a:*/ 0xe0, /* ###..... */
+ /*046b:*/ 0x40, /* .#...... */
+ /*046c:*/ 0x40, /* .#...... */
+ /*046d:*/ 0x40, /* .#...... */
+ /*046e:*/ 0x40, /* .#...... */
+ /*046f:*/ 0x40, /* .#...... */
+ /*0470:*/ 0x40, /* .#...... */
+ /*0471:*/ 0x40, /* .#...... */
+/* --- new character g (103) starting at offset 0x0472 --- */
+ /*0472:*/ 8, 6, 11, 1, -3, /* width and bbox (w,h,x,y) */
+ /*0477:*/ 0x74, /* .###.#.. */
+ /*0478:*/ 0xcc, /* ##..##.. */
+ /*0479:*/ 0x84, /* #....#.. */
+ /*047a:*/ 0x84, /* #....#.. */
+ /*047b:*/ 0x84, /* #....#.. */
+ /*047c:*/ 0x84, /* #....#.. */
+ /*047d:*/ 0xcc, /* ##..##.. */
+ /*047e:*/ 0x74, /* .###.#.. */
+ /*047f:*/ 0x04, /* .....#.. */
+ /*0480:*/ 0xcc, /* ##..##.. */
+ /*0481:*/ 0x78, /* .####... */
+/* --- new character h (104) starting at offset 0x0482 --- */
+ /*0482:*/ 8, 6, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0487:*/ 0x80, /* #....... */
+ /*0488:*/ 0x80, /* #....... */
+ /*0489:*/ 0x80, /* #....... */
+ /*048a:*/ 0xb8, /* #.###... */
+ /*048b:*/ 0xcc, /* ##..##.. */
+ /*048c:*/ 0x84, /* #....#.. */
+ /*048d:*/ 0x84, /* #....#.. */
+ /*048e:*/ 0x84, /* #....#.. */
+ /*048f:*/ 0x84, /* #....#.. */
+ /*0490:*/ 0x84, /* #....#.. */
+ /*0491:*/ 0x84, /* #....#.. */
+/* --- new character i (105) starting at offset 0x0492 --- */
+ /*0492:*/ 3, 1, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0497:*/ 0x80, /* #....... */
+ /*0498:*/ 0x80, /* #....... */
+ /*0499:*/ 0x00, /* ........ */
+ /*049a:*/ 0x80, /* #....... */
+ /*049b:*/ 0x80, /* #....... */
+ /*049c:*/ 0x80, /* #....... */
+ /*049d:*/ 0x80, /* #....... */
+ /*049e:*/ 0x80, /* #....... */
+ /*049f:*/ 0x80, /* #....... */
+ /*04a0:*/ 0x80, /* #....... */
+ /*04a1:*/ 0x80, /* #....... */
+/* --- new character j (106) starting at offset 0x04a2 --- */
+ /*04a2:*/ 3, 3, 14, -1, -3, /* width and bbox (w,h,x,y) */
+ /*04a7:*/ 0x20, /* ..#..... */
+ /*04a8:*/ 0x20, /* ..#..... */
+ /*04a9:*/ 0x00, /* ........ */
+ /*04aa:*/ 0x20, /* ..#..... */
+ /*04ab:*/ 0x20, /* ..#..... */
+ /*04ac:*/ 0x20, /* ..#..... */
+ /*04ad:*/ 0x20, /* ..#..... */
+ /*04ae:*/ 0x20, /* ..#..... */
+ /*04af:*/ 0x20, /* ..#..... */
+ /*04b0:*/ 0x20, /* ..#..... */
+ /*04b1:*/ 0x20, /* ..#..... */
+ /*04b2:*/ 0x20, /* ..#..... */
+ /*04b3:*/ 0x20, /* ..#..... */
+ /*04b4:*/ 0xc0, /* ##...... */
+/* --- new character k (107) starting at offset 0x04b5 --- */
+ /*04b5:*/ 7, 6, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*04ba:*/ 0x80, /* #....... */
+ /*04bb:*/ 0x80, /* #....... */
+ /*04bc:*/ 0x80, /* #....... */
+ /*04bd:*/ 0x88, /* #...#... */
+ /*04be:*/ 0x90, /* #..#.... */
+ /*04bf:*/ 0xa0, /* #.#..... */
+ /*04c0:*/ 0xc0, /* ##...... */
+ /*04c1:*/ 0xa0, /* #.#..... */
+ /*04c2:*/ 0x90, /* #..#.... */
+ /*04c3:*/ 0x88, /* #...#... */
+ /*04c4:*/ 0x84, /* #....#.. */
+/* --- new character l (108) starting at offset 0x04c5 --- */
+ /*04c5:*/ 3, 1, 11, 1, 0, /* width and bbox (w,h,x,y) */
+ /*04ca:*/ 0x80, /* #....... */
+ /*04cb:*/ 0x80, /* #....... */
+ /*04cc:*/ 0x80, /* #....... */
+ /*04cd:*/ 0x80, /* #....... */
+ /*04ce:*/ 0x80, /* #....... */
+ /*04cf:*/ 0x80, /* #....... */
+ /*04d0:*/ 0x80, /* #....... */
+ /*04d1:*/ 0x80, /* #....... */
+ /*04d2:*/ 0x80, /* #....... */
+ /*04d3:*/ 0x80, /* #....... */
+ /*04d4:*/ 0x80, /* #....... */
+/* --- new character m (109) starting at offset 0x04d5 --- */
+ /*04d5:*/ 11, 9, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*04da:*/ 0xb3,0x00, /* #.##..##........ */
+ /*04dc:*/ 0xcc,0x80, /* ##..##..#....... */
+ /*04de:*/ 0x88,0x80, /* #...#...#....... */
+ /*04e0:*/ 0x88,0x80, /* #...#...#....... */
+ /*04e2:*/ 0x88,0x80, /* #...#...#....... */
+ /*04e4:*/ 0x88,0x80, /* #...#...#....... */
+ /*04e6:*/ 0x88,0x80, /* #...#...#....... */
+ /*04e8:*/ 0x88,0x80, /* #...#...#....... */
+/* --- new character n (110) starting at offset 0x04ea --- */
+ /*04ea:*/ 8, 6, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*04ef:*/ 0xb8, /* #.###... */
+ /*04f0:*/ 0xcc, /* ##..##.. */
+ /*04f1:*/ 0x84, /* #....#.. */
+ /*04f2:*/ 0x84, /* #....#.. */
+ /*04f3:*/ 0x84, /* #....#.. */
+ /*04f4:*/ 0x84, /* #....#.. */
+ /*04f5:*/ 0x84, /* #....#.. */
+ /*04f6:*/ 0x84, /* #....#.. */
+/* --- new character o (111) starting at offset 0x04f7 --- */
+ /*04f7:*/ 8, 6, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*04fc:*/ 0x78, /* .####... */
+ /*04fd:*/ 0xcc, /* ##..##.. */
+ /*04fe:*/ 0x84, /* #....#.. */
+ /*04ff:*/ 0x84, /* #....#.. */
+ /*0500:*/ 0x84, /* #....#.. */
+ /*0501:*/ 0x84, /* #....#.. */
+ /*0502:*/ 0xcc, /* ##..##.. */
+ /*0503:*/ 0x78, /* .####... */
+/* --- new character p (112) starting at offset 0x0504 --- */
+ /*0504:*/ 8, 6, 11, 1, -3, /* width and bbox (w,h,x,y) */
+ /*0509:*/ 0xb8, /* #.###... */
+ /*050a:*/ 0xcc, /* ##..##.. */
+ /*050b:*/ 0x84, /* #....#.. */
+ /*050c:*/ 0x84, /* #....#.. */
+ /*050d:*/ 0x84, /* #....#.. */
+ /*050e:*/ 0x84, /* #....#.. */
+ /*050f:*/ 0xcc, /* ##..##.. */
+ /*0510:*/ 0xb8, /* #.###... */
+ /*0511:*/ 0x80, /* #....... */
+ /*0512:*/ 0x80, /* #....... */
+ /*0513:*/ 0x80, /* #....... */
+/* --- new character q (113) starting at offset 0x0514 --- */
+ /*0514:*/ 8, 6, 11, 1, -3, /* width and bbox (w,h,x,y) */
+ /*0519:*/ 0x74, /* .###.#.. */
+ /*051a:*/ 0xcc, /* ##..##.. */
+ /*051b:*/ 0x84, /* #....#.. */
+ /*051c:*/ 0x84, /* #....#.. */
+ /*051d:*/ 0x84, /* #....#.. */
+ /*051e:*/ 0x84, /* #....#.. */
+ /*051f:*/ 0xcc, /* ##..##.. */
+ /*0520:*/ 0x74, /* .###.#.. */
+ /*0521:*/ 0x04, /* .....#.. */
+ /*0522:*/ 0x04, /* .....#.. */
+ /*0523:*/ 0x04, /* .....#.. */
+/* --- new character r (114) starting at offset 0x0524 --- */
+ /*0524:*/ 5, 4, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0529:*/ 0xb0, /* #.##.... */
+ /*052a:*/ 0xc0, /* ##...... */
+ /*052b:*/ 0x80, /* #....... */
+ /*052c:*/ 0x80, /* #....... */
+ /*052d:*/ 0x80, /* #....... */
+ /*052e:*/ 0x80, /* #....... */
+ /*052f:*/ 0x80, /* #....... */
+ /*0530:*/ 0x80, /* #....... */
+/* --- new character s (115) starting at offset 0x0531 --- */
+ /*0531:*/ 8, 6, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0536:*/ 0x78, /* .####... */
+ /*0537:*/ 0x84, /* #....#.. */
+ /*0538:*/ 0x80, /* #....... */
+ /*0539:*/ 0x78, /* .####... */
+ /*053a:*/ 0x0c, /* ....##.. */
+ /*053b:*/ 0x04, /* .....#.. */
+ /*053c:*/ 0x84, /* #....#.. */
+ /*053d:*/ 0x78, /* .####... */
+/* --- new character t (116) starting at offset 0x053e --- */
+ /*053e:*/ 4, 4, 10, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0543:*/ 0x40, /* .#...... */
+ /*0544:*/ 0x40, /* .#...... */
+ /*0545:*/ 0xf0, /* ####.... */
+ /*0546:*/ 0x40, /* .#...... */
+ /*0547:*/ 0x40, /* .#...... */
+ /*0548:*/ 0x40, /* .#...... */
+ /*0549:*/ 0x40, /* .#...... */
+ /*054a:*/ 0x40, /* .#...... */
+ /*054b:*/ 0x40, /* .#...... */
+ /*054c:*/ 0x30, /* ..##.... */
+/* --- new character u (117) starting at offset 0x054d --- */
+ /*054d:*/ 8, 6, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0552:*/ 0x84, /* #....#.. */
+ /*0553:*/ 0x84, /* #....#.. */
+ /*0554:*/ 0x84, /* #....#.. */
+ /*0555:*/ 0x84, /* #....#.. */
+ /*0556:*/ 0x84, /* #....#.. */
+ /*0557:*/ 0x84, /* #....#.. */
+ /*0558:*/ 0xcc, /* ##..##.. */
+ /*0559:*/ 0x74, /* .###.#.. */
+/* --- new character v (118) starting at offset 0x055a --- */
+ /*055a:*/ 8, 6, 8, 1, 0, /* width and bbox (w,h,x,y) */
+ /*055f:*/ 0x84, /* #....#.. */
+ /*0560:*/ 0x84, /* #....#.. */
+ /*0561:*/ 0x84, /* #....#.. */
+ /*0562:*/ 0x48, /* .#..#... */
+ /*0563:*/ 0x48, /* .#..#... */
+ /*0564:*/ 0x48, /* .#..#... */
+ /*0565:*/ 0x30, /* ..##.... */
+ /*0566:*/ 0x30, /* ..##.... */
+/* --- new character w (119) starting at offset 0x0567 --- */
+ /*0567:*/ 10, 9, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*056c:*/ 0x88,0x80, /* #...#...#....... */
+ /*056e:*/ 0x88,0x80, /* #...#...#....... */
+ /*0570:*/ 0x88,0x80, /* #...#...#....... */
+ /*0572:*/ 0x49,0x00, /* .#..#..#........ */
+ /*0574:*/ 0x49,0x00, /* .#..#..#........ */
+ /*0576:*/ 0x55,0x00, /* .#.#.#.#........ */
+ /*0578:*/ 0x22,0x00, /* ..#...#......... */
+ /*057a:*/ 0x22,0x00, /* ..#...#......... */
+/* --- new character x (120) starting at offset 0x057c --- */
+ /*057c:*/ 7, 7, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0581:*/ 0xc6, /* ##...##. */
+ /*0582:*/ 0x44, /* .#...#.. */
+ /*0583:*/ 0x28, /* ..#.#... */
+ /*0584:*/ 0x10, /* ...#.... */
+ /*0585:*/ 0x10, /* ...#.... */
+ /*0586:*/ 0x28, /* ..#.#... */
+ /*0587:*/ 0x44, /* .#...#.. */
+ /*0588:*/ 0xc6, /* ##...##. */
+/* --- new character y (121) starting at offset 0x0589 --- */
+ /*0589:*/ 7, 7, 11, 0, -3, /* width and bbox (w,h,x,y) */
+ /*058e:*/ 0x82, /* #.....#. */
+ /*058f:*/ 0x82, /* #.....#. */
+ /*0590:*/ 0x44, /* .#...#.. */
+ /*0591:*/ 0x44, /* .#...#.. */
+ /*0592:*/ 0x24, /* ..#..#.. */
+ /*0593:*/ 0x28, /* ..#.#... */
+ /*0594:*/ 0x18, /* ...##... */
+ /*0595:*/ 0x10, /* ...#.... */
+ /*0596:*/ 0x10, /* ...#.... */
+ /*0597:*/ 0x30, /* ..##.... */
+ /*0598:*/ 0x60, /* .##..... */
+/* --- new character z (122) starting at offset 0x0599 --- */
+ /*0599:*/ 7, 6, 8, 0, 0, /* width and bbox (w,h,x,y) */
+ /*059e:*/ 0xfc, /* ######.. */
+ /*059f:*/ 0x04, /* .....#.. */
+ /*05a0:*/ 0x08, /* ....#... */
+ /*05a1:*/ 0x10, /* ...#.... */
+ /*05a2:*/ 0x20, /* ..#..... */
+ /*05a3:*/ 0x40, /* .#...... */
+ /*05a4:*/ 0x80, /* #....... */
+ /*05a5:*/ 0xfc, /* ######.. */
+/* --- new character braceleft (123) starting at offset 0x05a6 --- */
+ /*05a6:*/ 5, 5, 14, 0, -3, /* width and bbox (w,h,x,y) */
+ /*05ab:*/ 0x18, /* ...##... */
+ /*05ac:*/ 0x20, /* ..#..... */
+ /*05ad:*/ 0x20, /* ..#..... */
+ /*05ae:*/ 0x20, /* ..#..... */
+ /*05af:*/ 0x20, /* ..#..... */
+ /*05b0:*/ 0x40, /* .#...... */
+ /*05b1:*/ 0x80, /* #....... */
+ /*05b2:*/ 0x40, /* .#...... */
+ /*05b3:*/ 0x20, /* ..#..... */
+ /*05b4:*/ 0x20, /* ..#..... */
+ /*05b5:*/ 0x20, /* ..#..... */
+ /*05b6:*/ 0x20, /* ..#..... */
+ /*05b7:*/ 0x20, /* ..#..... */
+ /*05b8:*/ 0x18, /* ...##... */
+/* --- new character bar (124) starting at offset 0x05b9 --- */
+ /*05b9:*/ 3, 1, 14, 1, -3, /* width and bbox (w,h,x,y) */
+ /*05be:*/ 0x80, /* #....... */
+ /*05bf:*/ 0x80, /* #....... */
+ /*05c0:*/ 0x80, /* #....... */
+ /*05c1:*/ 0x80, /* #....... */
+ /*05c2:*/ 0x80, /* #....... */
+ /*05c3:*/ 0x80, /* #....... */
+ /*05c4:*/ 0x80, /* #....... */
+ /*05c5:*/ 0x80, /* #....... */
+ /*05c6:*/ 0x80, /* #....... */
+ /*05c7:*/ 0x80, /* #....... */
+ /*05c8:*/ 0x80, /* #....... */
+ /*05c9:*/ 0x80, /* #....... */
+ /*05ca:*/ 0x80, /* #....... */
+ /*05cb:*/ 0x80, /* #....... */
+/* --- new character braceright (125) starting at offset 0x05cc --- */
+ /*05cc:*/ 5, 5, 14, 0, -3, /* width and bbox (w,h,x,y) */
+ /*05d1:*/ 0xc0, /* ##...... */
+ /*05d2:*/ 0x20, /* ..#..... */
+ /*05d3:*/ 0x20, /* ..#..... */
+ /*05d4:*/ 0x20, /* ..#..... */
+ /*05d5:*/ 0x20, /* ..#..... */
+ /*05d6:*/ 0x10, /* ...#.... */
+ /*05d7:*/ 0x08, /* ....#... */
+ /*05d8:*/ 0x10, /* ...#.... */
+ /*05d9:*/ 0x20, /* ..#..... */
+ /*05da:*/ 0x20, /* ..#..... */
+ /*05db:*/ 0x20, /* ..#..... */
+ /*05dc:*/ 0x20, /* ..#..... */
+ /*05dd:*/ 0x20, /* ..#..... */
+ /*05de:*/ 0xc0, /* ##...... */
+/* --- new character asciitilde (126) starting at offset 0x05df --- */
+ /*05df:*/ 8, 6, 3, 1, 3, /* width and bbox (w,h,x,y) */
+ /*05e4:*/ 0x64, /* .##..#.. */
+ /*05e5:*/ 0xb4, /* #.##.#.. */
+ /*05e6:*/ 0x98, /* #..##... */
+};
+static const uint16_t font_helvR14_offsets[] = {
+0x0000 /* space */,
+ 0x0006 /* exclam */,
+ 0x0016 /* quotedbl */,
+ 0x001e /* numbersign */,
+ 0x002d /* dollar */,
+ 0x0040 /* percent */,
+ 0x0059 /* ampersand */,
+ 0x0068 /* quotesingle */,
+ 0x0070 /* parenleft */,
+ 0x0083 /* parenright */,
+ 0x0096 /* asterisk */,
+ 0x009f /* plus */,
+ 0x00ab /* comma */,
+ 0x00b4 /* hyphen */,
+ 0x00ba /* period */,
+ 0x00c1 /* slash */,
+ 0x00d1 /* zero */,
+ 0x00e0 /* one */,
+ 0x00ef /* two */,
+ 0x00fe /* three */,
+ 0x010d /* four */,
+ 0x011c /* five */,
+ 0x012b /* six */,
+ 0x013a /* seven */,
+ 0x0149 /* eight */,
+ 0x0158 /* nine */,
+ 0x0167 /* colon */,
+ 0x0174 /* semicolon */,
+ 0x0183 /* less */,
+ 0x018d /* equal */,
+ 0x0195 /* greater */,
+ 0x019f /* question */,
+ 0x01af /* at */,
+ 0x01cc /* A */,
+ 0x01e7 /* B */,
+ 0x01f7 /* C */,
+ 0x0207 /* D */,
+ 0x0217 /* E */,
+ 0x0227 /* F */,
+ 0x0237 /* G */,
+ 0x0252 /* H */,
+ 0x0262 /* I */,
+ 0x0272 /* J */,
+ 0x0282 /* K */,
+ 0x0292 /* L */,
+ 0x02a2 /* M */,
+ 0x02bd /* N */,
+ 0x02cd /* O */,
+ 0x02e8 /* P */,
+ 0x02f8 /* Q */,
+ 0x0313 /* R */,
+ 0x0323 /* S */,
+ 0x0333 /* T */,
+ 0x034e /* U */,
+ 0x035e /* V */,
+ 0x0379 /* W */,
+ 0x0394 /* X */,
+ 0x03a4 /* Y */,
+ 0x03bf /* Z */,
+ 0x03cf /* bracketleft */,
+ 0x03e2 /* backslash */,
+ 0x03f2 /* bracketright */,
+ 0x0405 /* asciicircum */,
+ 0x040e /* underscore */,
+ 0x0414 /* grave */,
+ 0x041b /* a */,
+ 0x0428 /* b */,
+ 0x0438 /* c */,
+ 0x0445 /* d */,
+ 0x0455 /* e */,
+ 0x0462 /* f */,
+ 0x0472 /* g */,
+ 0x0482 /* h */,
+ 0x0492 /* i */,
+ 0x04a2 /* j */,
+ 0x04b5 /* k */,
+ 0x04c5 /* l */,
+ 0x04d5 /* m */,
+ 0x04ea /* n */,
+ 0x04f7 /* o */,
+ 0x0504 /* p */,
+ 0x0514 /* q */,
+ 0x0524 /* r */,
+ 0x0531 /* s */,
+ 0x053e /* t */,
+ 0x054d /* u */,
+ 0x055a /* v */,
+ 0x0567 /* w */,
+ 0x057c /* x */,
+ 0x0589 /* y */,
+ 0x0599 /* z */,
+ 0x05a6 /* braceleft */,
+ 0x05b9 /* bar */,
+ 0x05cc /* braceright */,
+ 0x05df /* asciitilde */,
+ 0xffff /* (no glyph) */
+};
+const struct fb_font font_helvR14 = {
+ .height = 16,
+ .ascent = 13,
+ .firstchar = 32, /* space */
+ .lastchar = 127, /* ? */
+ .chardata = font_helvR14_data,
+ .charoffs = font_helvR14_offsets,
+};
diff --git a/Src/osmolib/src/target/firmware/fb/helvR24.c b/Src/osmolib/src/target/firmware/fb/helvR24.c
new file mode 100644
index 0000000..18ff0c4
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/fb/helvR24.c
@@ -0,0 +1,1870 @@
+#include <fb/font.h>
+static const uint8_t font_helvR24_data[] = {
+/* --- new character space (32) starting at offset 0x0000 --- */
+ /*0000:*/ 6, 1, 1, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0005:*/ 0x00, /* ........ */
+/* --- new character exclam (33) starting at offset 0x0006 --- */
+ /*0006:*/ 6, 2, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*000b:*/ 0xc0, /* ##...... */
+ /*000c:*/ 0xc0, /* ##...... */
+ /*000d:*/ 0xc0, /* ##...... */
+ /*000e:*/ 0xc0, /* ##...... */
+ /*000f:*/ 0xc0, /* ##...... */
+ /*0010:*/ 0xc0, /* ##...... */
+ /*0011:*/ 0xc0, /* ##...... */
+ /*0012:*/ 0xc0, /* ##...... */
+ /*0013:*/ 0xc0, /* ##...... */
+ /*0014:*/ 0xc0, /* ##...... */
+ /*0015:*/ 0xc0, /* ##...... */
+ /*0016:*/ 0xc0, /* ##...... */
+ /*0017:*/ 0x80, /* #....... */
+ /*0018:*/ 0x80, /* #....... */
+ /*0019:*/ 0x00, /* ........ */
+ /*001a:*/ 0x00, /* ........ */
+ /*001b:*/ 0xc0, /* ##...... */
+ /*001c:*/ 0xc0, /* ##...... */
+ /*001d:*/ 0xc0, /* ##...... */
+/* --- new character quotedbl (34) starting at offset 0x001e --- */
+ /*001e:*/ 8, 6, 6, 1, 13, /* width and bbox (w,h,x,y) */
+ /*0023:*/ 0xcc, /* ##..##.. */
+ /*0024:*/ 0xcc, /* ##..##.. */
+ /*0025:*/ 0xcc, /* ##..##.. */
+ /*0026:*/ 0xcc, /* ##..##.. */
+ /*0027:*/ 0xcc, /* ##..##.. */
+ /*0028:*/ 0x44, /* .#...#.. */
+/* --- new character numbersign (35) starting at offset 0x0029 --- */
+ /*0029:*/ 14, 11, 17, 2, 0, /* width and bbox (w,h,x,y) */
+ /*002e:*/ 0x0c,0xc0, /* ....##..##...... */
+ /*0030:*/ 0x0c,0xc0, /* ....##..##...... */
+ /*0032:*/ 0x0c,0xc0, /* ....##..##...... */
+ /*0034:*/ 0x19,0x80, /* ...##..##....... */
+ /*0036:*/ 0xff,0xe0, /* ###########..... */
+ /*0038:*/ 0xff,0xe0, /* ###########..... */
+ /*003a:*/ 0x19,0x80, /* ...##..##....... */
+ /*003c:*/ 0x19,0x80, /* ...##..##....... */
+ /*003e:*/ 0x33,0x00, /* ..##..##........ */
+ /*0040:*/ 0x33,0x00, /* ..##..##........ */
+ /*0042:*/ 0xff,0xe0, /* ###########..... */
+ /*0044:*/ 0xff,0xe0, /* ###########..... */
+ /*0046:*/ 0x33,0x00, /* ..##..##........ */
+ /*0048:*/ 0x33,0x00, /* ..##..##........ */
+ /*004a:*/ 0x66,0x00, /* .##..##......... */
+ /*004c:*/ 0x66,0x00, /* .##..##......... */
+ /*004e:*/ 0x66,0x00, /* .##..##......... */
+/* --- new character dollar (36) starting at offset 0x0050 --- */
+ /*0050:*/ 13, 11, 21, 1, -2, /* width and bbox (w,h,x,y) */
+ /*0055:*/ 0x06,0x00, /* .....##......... */
+ /*0057:*/ 0x06,0x00, /* .....##......... */
+ /*0059:*/ 0x3f,0x80, /* ..#######....... */
+ /*005b:*/ 0x7f,0xc0, /* .#########...... */
+ /*005d:*/ 0xe6,0xe0, /* ###..##.###..... */
+ /*005f:*/ 0xc6,0x60, /* ##...##..##..... */
+ /*0061:*/ 0xc6,0x00, /* ##...##......... */
+ /*0063:*/ 0xe6,0x00, /* ###..##......... */
+ /*0065:*/ 0x76,0x00, /* .###.##......... */
+ /*0067:*/ 0x3e,0x00, /* ..#####......... */
+ /*0069:*/ 0x0f,0x80, /* ....#####....... */
+ /*006b:*/ 0x07,0xc0, /* .....#####...... */
+ /*006d:*/ 0x06,0xe0, /* .....##.###..... */
+ /*006f:*/ 0x06,0x60, /* .....##..##..... */
+ /*0071:*/ 0xc6,0x60, /* ##...##..##..... */
+ /*0073:*/ 0xc6,0x60, /* ##...##..##..... */
+ /*0075:*/ 0xe6,0xe0, /* ###..##.###..... */
+ /*0077:*/ 0x7f,0xc0, /* .#########...... */
+ /*0079:*/ 0x3f,0x80, /* ..#######....... */
+ /*007b:*/ 0x06,0x00, /* .....##......... */
+ /*007d:*/ 0x06,0x00, /* .....##......... */
+/* --- new character percent (37) starting at offset 0x007f --- */
+ /*007f:*/ 22, 19, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0084:*/ 0x00,0x06,0x00, /* .............##......... */
+ /*0087:*/ 0x3c,0x0c,0x00, /* ..####......##.......... */
+ /*008a:*/ 0x7e,0x0c,0x00, /* .######.....##.......... */
+ /*008d:*/ 0xc3,0x18,0x00, /* ##....##...##........... */
+ /*0090:*/ 0xc3,0x18,0x00, /* ##....##...##........... */
+ /*0093:*/ 0xc3,0x30,0x00, /* ##....##..##............ */
+ /*0096:*/ 0xc3,0x30,0x00, /* ##....##..##............ */
+ /*0099:*/ 0x7e,0x60,0x00, /* .######..##............. */
+ /*009c:*/ 0x3c,0x60,0x00, /* ..####...##............. */
+ /*009f:*/ 0x00,0xc0,0x00, /* ........##.............. */
+ /*00a2:*/ 0x00,0xc7,0x80, /* ........##...####....... */
+ /*00a5:*/ 0x01,0x8f,0xc0, /* .......##...######...... */
+ /*00a8:*/ 0x01,0x98,0x60, /* .......##..##....##..... */
+ /*00ab:*/ 0x03,0x18,0x60, /* ......##...##....##..... */
+ /*00ae:*/ 0x03,0x18,0x60, /* ......##...##....##..... */
+ /*00b1:*/ 0x06,0x18,0x60, /* .....##....##....##..... */
+ /*00b4:*/ 0x06,0x0f,0xc0, /* .....##.....######...... */
+ /*00b7:*/ 0x04,0x07,0x80, /* .....#.......####....... */
+/* --- new character ampersand (38) starting at offset 0x00ba --- */
+ /*00ba:*/ 17, 14, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*00bf:*/ 0x0f,0x00, /* ....####........ */
+ /*00c1:*/ 0x1f,0x80, /* ...######....... */
+ /*00c3:*/ 0x39,0xc0, /* ..###..###...... */
+ /*00c5:*/ 0x30,0xc0, /* ..##....##...... */
+ /*00c7:*/ 0x30,0xc0, /* ..##....##...... */
+ /*00c9:*/ 0x30,0xc0, /* ..##....##...... */
+ /*00cb:*/ 0x19,0x80, /* ...##..##....... */
+ /*00cd:*/ 0x0f,0x00, /* ....####........ */
+ /*00cf:*/ 0x1e,0x00, /* ...####......... */
+ /*00d1:*/ 0x3f,0x18, /* ..######...##... */
+ /*00d3:*/ 0x73,0x98, /* .###..###..##... */
+ /*00d5:*/ 0x61,0xd8, /* .##....###.##... */
+ /*00d7:*/ 0xc0,0xf0, /* ##......####.... */
+ /*00d9:*/ 0xc0,0x60, /* ##.......##..... */
+ /*00db:*/ 0xc0,0xf0, /* ##......####.... */
+ /*00dd:*/ 0xe1,0xd8, /* ###....###.##... */
+ /*00df:*/ 0x7f,0x9c, /* .########..###.. */
+ /*00e1:*/ 0x1e,0x00, /* ...####......... */
+/* --- new character quotesingle (39) starting at offset 0x00e3 --- */
+ /*00e3:*/ 6, 2, 6, 2, 13, /* width and bbox (w,h,x,y) */
+ /*00e8:*/ 0xc0, /* ##...... */
+ /*00e9:*/ 0xc0, /* ##...... */
+ /*00ea:*/ 0xc0, /* ##...... */
+ /*00eb:*/ 0xc0, /* ##...... */
+ /*00ec:*/ 0xc0, /* ##...... */
+ /*00ed:*/ 0x40, /* .#...... */
+/* --- new character parenleft (40) starting at offset 0x00ee --- */
+ /*00ee:*/ 8, 5, 24, 2, -5, /* width and bbox (w,h,x,y) */
+ /*00f3:*/ 0x18, /* ...##... */
+ /*00f4:*/ 0x18, /* ...##... */
+ /*00f5:*/ 0x30, /* ..##.... */
+ /*00f6:*/ 0x30, /* ..##.... */
+ /*00f7:*/ 0x60, /* .##..... */
+ /*00f8:*/ 0x60, /* .##..... */
+ /*00f9:*/ 0x60, /* .##..... */
+ /*00fa:*/ 0xc0, /* ##...... */
+ /*00fb:*/ 0xc0, /* ##...... */
+ /*00fc:*/ 0xc0, /* ##...... */
+ /*00fd:*/ 0xc0, /* ##...... */
+ /*00fe:*/ 0xc0, /* ##...... */
+ /*00ff:*/ 0xc0, /* ##...... */
+ /*0100:*/ 0xc0, /* ##...... */
+ /*0101:*/ 0xc0, /* ##...... */
+ /*0102:*/ 0xc0, /* ##...... */
+ /*0103:*/ 0xc0, /* ##...... */
+ /*0104:*/ 0x60, /* .##..... */
+ /*0105:*/ 0x60, /* .##..... */
+ /*0106:*/ 0x60, /* .##..... */
+ /*0107:*/ 0x30, /* ..##.... */
+ /*0108:*/ 0x30, /* ..##.... */
+ /*0109:*/ 0x18, /* ...##... */
+ /*010a:*/ 0x18, /* ...##... */
+/* --- new character parenright (41) starting at offset 0x010b --- */
+ /*010b:*/ 8, 5, 24, 1, -5, /* width and bbox (w,h,x,y) */
+ /*0110:*/ 0xc0, /* ##...... */
+ /*0111:*/ 0xc0, /* ##...... */
+ /*0112:*/ 0x60, /* .##..... */
+ /*0113:*/ 0x60, /* .##..... */
+ /*0114:*/ 0x30, /* ..##.... */
+ /*0115:*/ 0x30, /* ..##.... */
+ /*0116:*/ 0x30, /* ..##.... */
+ /*0117:*/ 0x18, /* ...##... */
+ /*0118:*/ 0x18, /* ...##... */
+ /*0119:*/ 0x18, /* ...##... */
+ /*011a:*/ 0x18, /* ...##... */
+ /*011b:*/ 0x18, /* ...##... */
+ /*011c:*/ 0x18, /* ...##... */
+ /*011d:*/ 0x18, /* ...##... */
+ /*011e:*/ 0x18, /* ...##... */
+ /*011f:*/ 0x18, /* ...##... */
+ /*0120:*/ 0x18, /* ...##... */
+ /*0121:*/ 0x30, /* ..##.... */
+ /*0122:*/ 0x30, /* ..##.... */
+ /*0123:*/ 0x30, /* ..##.... */
+ /*0124:*/ 0x60, /* .##..... */
+ /*0125:*/ 0x60, /* .##..... */
+ /*0126:*/ 0xc0, /* ##...... */
+ /*0127:*/ 0xc0, /* ##...... */
+/* --- new character asterisk (42) starting at offset 0x0128 --- */
+ /*0128:*/ 10, 7, 7, 1, 12, /* width and bbox (w,h,x,y) */
+ /*012d:*/ 0x10, /* ...#.... */
+ /*012e:*/ 0x10, /* ...#.... */
+ /*012f:*/ 0xd6, /* ##.#.##. */
+ /*0130:*/ 0x7c, /* .#####.. */
+ /*0131:*/ 0x38, /* ..###... */
+ /*0132:*/ 0x6c, /* .##.##.. */
+ /*0133:*/ 0x44, /* .#...#.. */
+/* --- new character plus (43) starting at offset 0x0134 --- */
+ /*0134:*/ 14, 12, 12, 1, 1, /* width and bbox (w,h,x,y) */
+ /*0139:*/ 0x06,0x00, /* .....##......... */
+ /*013b:*/ 0x06,0x00, /* .....##......... */
+ /*013d:*/ 0x06,0x00, /* .....##......... */
+ /*013f:*/ 0x06,0x00, /* .....##......... */
+ /*0141:*/ 0x06,0x00, /* .....##......... */
+ /*0143:*/ 0xff,0xf0, /* ############.... */
+ /*0145:*/ 0xff,0xf0, /* ############.... */
+ /*0147:*/ 0x06,0x00, /* .....##......... */
+ /*0149:*/ 0x06,0x00, /* .....##......... */
+ /*014b:*/ 0x06,0x00, /* .....##......... */
+ /*014d:*/ 0x06,0x00, /* .....##......... */
+ /*014f:*/ 0x06,0x00, /* .....##......... */
+/* --- new character comma (44) starting at offset 0x0151 --- */
+ /*0151:*/ 6, 2, 6, 2, -3, /* width and bbox (w,h,x,y) */
+ /*0156:*/ 0xc0, /* ##...... */
+ /*0157:*/ 0xc0, /* ##...... */
+ /*0158:*/ 0xc0, /* ##...... */
+ /*0159:*/ 0x40, /* .#...... */
+ /*015a:*/ 0x40, /* .#...... */
+ /*015b:*/ 0x80, /* #....... */
+/* --- new character hyphen (45) starting at offset 0x015c --- */
+ /*015c:*/ 8, 6, 2, 1, 6, /* width and bbox (w,h,x,y) */
+ /*0161:*/ 0xfc, /* ######.. */
+ /*0162:*/ 0xfc, /* ######.. */
+/* --- new character period (46) starting at offset 0x0163 --- */
+ /*0163:*/ 6, 2, 3, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0168:*/ 0xc0, /* ##...... */
+ /*0169:*/ 0xc0, /* ##...... */
+ /*016a:*/ 0xc0, /* ##...... */
+/* --- new character slash (47) starting at offset 0x016b --- */
+ /*016b:*/ 7, 7, 19, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0170:*/ 0x06, /* .....##. */
+ /*0171:*/ 0x06, /* .....##. */
+ /*0172:*/ 0x06, /* .....##. */
+ /*0173:*/ 0x0c, /* ....##.. */
+ /*0174:*/ 0x0c, /* ....##.. */
+ /*0175:*/ 0x0c, /* ....##.. */
+ /*0176:*/ 0x18, /* ...##... */
+ /*0177:*/ 0x18, /* ...##... */
+ /*0178:*/ 0x18, /* ...##... */
+ /*0179:*/ 0x18, /* ...##... */
+ /*017a:*/ 0x30, /* ..##.... */
+ /*017b:*/ 0x30, /* ..##.... */
+ /*017c:*/ 0x30, /* ..##.... */
+ /*017d:*/ 0x60, /* .##..... */
+ /*017e:*/ 0x60, /* .##..... */
+ /*017f:*/ 0x60, /* .##..... */
+ /*0180:*/ 0xc0, /* ##...... */
+ /*0181:*/ 0xc0, /* ##...... */
+ /*0182:*/ 0xc0, /* ##...... */
+/* --- new character zero (48) starting at offset 0x0183 --- */
+ /*0183:*/ 13, 11, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0188:*/ 0x1f,0x00, /* ...#####........ */
+ /*018a:*/ 0x3f,0x80, /* ..#######....... */
+ /*018c:*/ 0x71,0xc0, /* .###...###...... */
+ /*018e:*/ 0x60,0xc0, /* .##.....##...... */
+ /*0190:*/ 0x60,0xc0, /* .##.....##...... */
+ /*0192:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0194:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0196:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0198:*/ 0xc0,0x60, /* ##.......##..... */
+ /*019a:*/ 0xc0,0x60, /* ##.......##..... */
+ /*019c:*/ 0xc0,0x60, /* ##.......##..... */
+ /*019e:*/ 0xc0,0x60, /* ##.......##..... */
+ /*01a0:*/ 0xc0,0x60, /* ##.......##..... */
+ /*01a2:*/ 0x60,0xc0, /* .##.....##...... */
+ /*01a4:*/ 0x60,0xc0, /* .##.....##...... */
+ /*01a6:*/ 0x71,0xc0, /* .###...###...... */
+ /*01a8:*/ 0x3f,0x80, /* ..#######....... */
+ /*01aa:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character one (49) starting at offset 0x01ac --- */
+ /*01ac:*/ 13, 6, 18, 2, 0, /* width and bbox (w,h,x,y) */
+ /*01b1:*/ 0x0c, /* ....##.. */
+ /*01b2:*/ 0x0c, /* ....##.. */
+ /*01b3:*/ 0x1c, /* ...###.. */
+ /*01b4:*/ 0xfc, /* ######.. */
+ /*01b5:*/ 0xfc, /* ######.. */
+ /*01b6:*/ 0x0c, /* ....##.. */
+ /*01b7:*/ 0x0c, /* ....##.. */
+ /*01b8:*/ 0x0c, /* ....##.. */
+ /*01b9:*/ 0x0c, /* ....##.. */
+ /*01ba:*/ 0x0c, /* ....##.. */
+ /*01bb:*/ 0x0c, /* ....##.. */
+ /*01bc:*/ 0x0c, /* ....##.. */
+ /*01bd:*/ 0x0c, /* ....##.. */
+ /*01be:*/ 0x0c, /* ....##.. */
+ /*01bf:*/ 0x0c, /* ....##.. */
+ /*01c0:*/ 0x0c, /* ....##.. */
+ /*01c1:*/ 0x0c, /* ....##.. */
+ /*01c2:*/ 0x0c, /* ....##.. */
+/* --- new character two (50) starting at offset 0x01c3 --- */
+ /*01c3:*/ 13, 11, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01c8:*/ 0x1e,0x00, /* ...####......... */
+ /*01ca:*/ 0x7f,0x80, /* .########....... */
+ /*01cc:*/ 0x61,0xc0, /* .##....###...... */
+ /*01ce:*/ 0xc0,0xc0, /* ##......##...... */
+ /*01d0:*/ 0xc0,0x60, /* ##.......##..... */
+ /*01d2:*/ 0xc0,0x60, /* ##.......##..... */
+ /*01d4:*/ 0x00,0x60, /* .........##..... */
+ /*01d6:*/ 0x00,0xc0, /* ........##...... */
+ /*01d8:*/ 0x01,0xc0, /* .......###...... */
+ /*01da:*/ 0x03,0x80, /* ......###....... */
+ /*01dc:*/ 0x0f,0x00, /* ....####........ */
+ /*01de:*/ 0x1c,0x00, /* ...###.......... */
+ /*01e0:*/ 0x38,0x00, /* ..###........... */
+ /*01e2:*/ 0x70,0x00, /* .###............ */
+ /*01e4:*/ 0xe0,0x00, /* ###............. */
+ /*01e6:*/ 0xc0,0x00, /* ##.............. */
+ /*01e8:*/ 0xff,0xe0, /* ###########..... */
+ /*01ea:*/ 0xff,0xe0, /* ###########..... */
+/* --- new character three (51) starting at offset 0x01ec --- */
+ /*01ec:*/ 13, 11, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*01f1:*/ 0x1f,0x00, /* ...#####........ */
+ /*01f3:*/ 0x7f,0x80, /* .########....... */
+ /*01f5:*/ 0x61,0x80, /* .##....##....... */
+ /*01f7:*/ 0xc0,0xc0, /* ##......##...... */
+ /*01f9:*/ 0xc0,0xc0, /* ##......##...... */
+ /*01fb:*/ 0xc0,0xc0, /* ##......##...... */
+ /*01fd:*/ 0x00,0xc0, /* ........##...... */
+ /*01ff:*/ 0x01,0x80, /* .......##....... */
+ /*0201:*/ 0x0f,0x00, /* ....####........ */
+ /*0203:*/ 0x0f,0xc0, /* ....######...... */
+ /*0205:*/ 0x00,0xc0, /* ........##...... */
+ /*0207:*/ 0x00,0x60, /* .........##..... */
+ /*0209:*/ 0x00,0x60, /* .........##..... */
+ /*020b:*/ 0xc0,0x60, /* ##.......##..... */
+ /*020d:*/ 0xc0,0xc0, /* ##......##...... */
+ /*020f:*/ 0x61,0xc0, /* .##....###...... */
+ /*0211:*/ 0x7f,0x80, /* .########....... */
+ /*0213:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character four (52) starting at offset 0x0215 --- */
+ /*0215:*/ 13, 11, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*021a:*/ 0x01,0x80, /* .......##....... */
+ /*021c:*/ 0x03,0x80, /* ......###....... */
+ /*021e:*/ 0x03,0x80, /* ......###....... */
+ /*0220:*/ 0x07,0x80, /* .....####....... */
+ /*0222:*/ 0x0f,0x80, /* ....#####....... */
+ /*0224:*/ 0x0d,0x80, /* ....##.##....... */
+ /*0226:*/ 0x19,0x80, /* ...##..##....... */
+ /*0228:*/ 0x39,0x80, /* ..###..##....... */
+ /*022a:*/ 0x31,0x80, /* ..##...##....... */
+ /*022c:*/ 0x61,0x80, /* .##....##....... */
+ /*022e:*/ 0xe1,0x80, /* ###....##....... */
+ /*0230:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0232:*/ 0xff,0xe0, /* ###########..... */
+ /*0234:*/ 0xff,0xe0, /* ###########..... */
+ /*0236:*/ 0x01,0x80, /* .......##....... */
+ /*0238:*/ 0x01,0x80, /* .......##....... */
+ /*023a:*/ 0x01,0x80, /* .......##....... */
+ /*023c:*/ 0x01,0x80, /* .......##....... */
+/* --- new character five (53) starting at offset 0x023e --- */
+ /*023e:*/ 13, 11, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0243:*/ 0x7f,0xc0, /* .#########...... */
+ /*0245:*/ 0x7f,0xc0, /* .#########...... */
+ /*0247:*/ 0x60,0x00, /* .##............. */
+ /*0249:*/ 0x60,0x00, /* .##............. */
+ /*024b:*/ 0x60,0x00, /* .##............. */
+ /*024d:*/ 0x60,0x00, /* .##............. */
+ /*024f:*/ 0x6e,0x00, /* .##.###......... */
+ /*0251:*/ 0x7f,0x80, /* .########....... */
+ /*0253:*/ 0x71,0xc0, /* .###...###...... */
+ /*0255:*/ 0x00,0xc0, /* ........##...... */
+ /*0257:*/ 0x00,0x60, /* .........##..... */
+ /*0259:*/ 0x00,0x60, /* .........##..... */
+ /*025b:*/ 0x00,0x60, /* .........##..... */
+ /*025d:*/ 0xc0,0x60, /* ##.......##..... */
+ /*025f:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0261:*/ 0xe1,0xc0, /* ###....###...... */
+ /*0263:*/ 0x7f,0x80, /* .########....... */
+ /*0265:*/ 0x1e,0x00, /* ...####......... */
+/* --- new character six (54) starting at offset 0x0267 --- */
+ /*0267:*/ 13, 11, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*026c:*/ 0x0f,0x00, /* ....####........ */
+ /*026e:*/ 0x3f,0xc0, /* ..########...... */
+ /*0270:*/ 0x70,0xc0, /* .###....##...... */
+ /*0272:*/ 0x60,0x60, /* .##......##..... */
+ /*0274:*/ 0xe0,0x60, /* ###......##..... */
+ /*0276:*/ 0xc0,0x00, /* ##.............. */
+ /*0278:*/ 0xc0,0x00, /* ##.............. */
+ /*027a:*/ 0xcf,0x00, /* ##..####........ */
+ /*027c:*/ 0xdf,0x80, /* ##.######....... */
+ /*027e:*/ 0xf1,0xc0, /* ####...###...... */
+ /*0280:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*0282:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0284:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0286:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0288:*/ 0xe0,0x60, /* ###......##..... */
+ /*028a:*/ 0x60,0xc0, /* .##.....##...... */
+ /*028c:*/ 0x7f,0xc0, /* .#########...... */
+ /*028e:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character seven (55) starting at offset 0x0290 --- */
+ /*0290:*/ 13, 11, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0295:*/ 0xff,0xe0, /* ###########..... */
+ /*0297:*/ 0xff,0xe0, /* ###########..... */
+ /*0299:*/ 0x00,0xe0, /* ........###..... */
+ /*029b:*/ 0x00,0xc0, /* ........##...... */
+ /*029d:*/ 0x01,0x80, /* .......##....... */
+ /*029f:*/ 0x01,0x80, /* .......##....... */
+ /*02a1:*/ 0x03,0x00, /* ......##........ */
+ /*02a3:*/ 0x03,0x00, /* ......##........ */
+ /*02a5:*/ 0x06,0x00, /* .....##......... */
+ /*02a7:*/ 0x06,0x00, /* .....##......... */
+ /*02a9:*/ 0x0c,0x00, /* ....##.......... */
+ /*02ab:*/ 0x0c,0x00, /* ....##.......... */
+ /*02ad:*/ 0x1c,0x00, /* ...###.......... */
+ /*02af:*/ 0x18,0x00, /* ...##........... */
+ /*02b1:*/ 0x18,0x00, /* ...##........... */
+ /*02b3:*/ 0x38,0x00, /* ..###........... */
+ /*02b5:*/ 0x30,0x00, /* ..##............ */
+ /*02b7:*/ 0x30,0x00, /* ..##............ */
+/* --- new character eight (56) starting at offset 0x02b9 --- */
+ /*02b9:*/ 13, 11, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02be:*/ 0x0e,0x00, /* ....###......... */
+ /*02c0:*/ 0x3f,0x80, /* ..#######....... */
+ /*02c2:*/ 0x31,0x80, /* ..##...##....... */
+ /*02c4:*/ 0x60,0xc0, /* .##.....##...... */
+ /*02c6:*/ 0x60,0xc0, /* .##.....##...... */
+ /*02c8:*/ 0x60,0xc0, /* .##.....##...... */
+ /*02ca:*/ 0x60,0xc0, /* .##.....##...... */
+ /*02cc:*/ 0x31,0x80, /* ..##...##....... */
+ /*02ce:*/ 0x1f,0x00, /* ...#####........ */
+ /*02d0:*/ 0x3f,0x80, /* ..#######....... */
+ /*02d2:*/ 0x60,0xc0, /* .##.....##...... */
+ /*02d4:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*02d6:*/ 0xc0,0x60, /* ##.......##..... */
+ /*02d8:*/ 0xc0,0x60, /* ##.......##..... */
+ /*02da:*/ 0xc0,0x60, /* ##.......##..... */
+ /*02dc:*/ 0x71,0xc0, /* .###...###...... */
+ /*02de:*/ 0x7f,0xc0, /* .#########...... */
+ /*02e0:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character nine (57) starting at offset 0x02e2 --- */
+ /*02e2:*/ 13, 11, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*02e7:*/ 0x1f,0x00, /* ...#####........ */
+ /*02e9:*/ 0x7f,0xc0, /* .#########...... */
+ /*02eb:*/ 0x71,0xc0, /* .###...###...... */
+ /*02ed:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*02ef:*/ 0xc0,0x60, /* ##.......##..... */
+ /*02f1:*/ 0xc0,0x60, /* ##.......##..... */
+ /*02f3:*/ 0xc0,0x60, /* ##.......##..... */
+ /*02f5:*/ 0xc0,0x60, /* ##.......##..... */
+ /*02f7:*/ 0xe0,0xe0, /* ###.....###..... */
+ /*02f9:*/ 0x71,0xe0, /* .###...####..... */
+ /*02fb:*/ 0x7f,0x60, /* .#######.##..... */
+ /*02fd:*/ 0x1e,0x60, /* ...####..##..... */
+ /*02ff:*/ 0x00,0x60, /* .........##..... */
+ /*0301:*/ 0x00,0xe0, /* ........###..... */
+ /*0303:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0305:*/ 0xe1,0xc0, /* ###....###...... */
+ /*0307:*/ 0x7f,0x80, /* .########....... */
+ /*0309:*/ 0x1e,0x00, /* ...####......... */
+/* --- new character colon (58) starting at offset 0x030b --- */
+ /*030b:*/ 6, 2, 14, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0310:*/ 0xc0, /* ##...... */
+ /*0311:*/ 0xc0, /* ##...... */
+ /*0312:*/ 0xc0, /* ##...... */
+ /*0313:*/ 0x00, /* ........ */
+ /*0314:*/ 0x00, /* ........ */
+ /*0315:*/ 0x00, /* ........ */
+ /*0316:*/ 0x00, /* ........ */
+ /*0317:*/ 0x00, /* ........ */
+ /*0318:*/ 0x00, /* ........ */
+ /*0319:*/ 0x00, /* ........ */
+ /*031a:*/ 0x00, /* ........ */
+ /*031b:*/ 0xc0, /* ##...... */
+ /*031c:*/ 0xc0, /* ##...... */
+ /*031d:*/ 0xc0, /* ##...... */
+/* --- new character semicolon (59) starting at offset 0x031e --- */
+ /*031e:*/ 6, 2, 17, 2, -3, /* width and bbox (w,h,x,y) */
+ /*0323:*/ 0xc0, /* ##...... */
+ /*0324:*/ 0xc0, /* ##...... */
+ /*0325:*/ 0xc0, /* ##...... */
+ /*0326:*/ 0x00, /* ........ */
+ /*0327:*/ 0x00, /* ........ */
+ /*0328:*/ 0x00, /* ........ */
+ /*0329:*/ 0x00, /* ........ */
+ /*032a:*/ 0x00, /* ........ */
+ /*032b:*/ 0x00, /* ........ */
+ /*032c:*/ 0x00, /* ........ */
+ /*032d:*/ 0x00, /* ........ */
+ /*032e:*/ 0xc0, /* ##...... */
+ /*032f:*/ 0xc0, /* ##...... */
+ /*0330:*/ 0xc0, /* ##...... */
+ /*0331:*/ 0x40, /* .#...... */
+ /*0332:*/ 0x40, /* .#...... */
+ /*0333:*/ 0x80, /* #....... */
+/* --- new character less (60) starting at offset 0x0334 --- */
+ /*0334:*/ 15, 12, 12, 1, 1, /* width and bbox (w,h,x,y) */
+ /*0339:*/ 0x00,0x30, /* ..........##.... */
+ /*033b:*/ 0x00,0xf0, /* ........####.... */
+ /*033d:*/ 0x03,0xc0, /* ......####...... */
+ /*033f:*/ 0x0f,0x00, /* ....####........ */
+ /*0341:*/ 0x3c,0x00, /* ..####.......... */
+ /*0343:*/ 0xe0,0x00, /* ###............. */
+ /*0345:*/ 0xe0,0x00, /* ###............. */
+ /*0347:*/ 0x3c,0x00, /* ..####.......... */
+ /*0349:*/ 0x0f,0x00, /* ....####........ */
+ /*034b:*/ 0x03,0xc0, /* ......####...... */
+ /*034d:*/ 0x00,0xf0, /* ........####.... */
+ /*034f:*/ 0x00,0x30, /* ..........##.... */
+/* --- new character equal (61) starting at offset 0x0351 --- */
+ /*0351:*/ 15, 10, 6, 2, 5, /* width and bbox (w,h,x,y) */
+ /*0356:*/ 0xff,0xc0, /* ##########...... */
+ /*0358:*/ 0xff,0xc0, /* ##########...... */
+ /*035a:*/ 0x00,0x00, /* ................ */
+ /*035c:*/ 0x00,0x00, /* ................ */
+ /*035e:*/ 0xff,0xc0, /* ##########...... */
+ /*0360:*/ 0xff,0xc0, /* ##########...... */
+/* --- new character greater (62) starting at offset 0x0362 --- */
+ /*0362:*/ 15, 12, 12, 1, 1, /* width and bbox (w,h,x,y) */
+ /*0367:*/ 0xc0,0x00, /* ##.............. */
+ /*0369:*/ 0xf0,0x00, /* ####............ */
+ /*036b:*/ 0x3c,0x00, /* ..####.......... */
+ /*036d:*/ 0x0f,0x00, /* ....####........ */
+ /*036f:*/ 0x03,0xc0, /* ......####...... */
+ /*0371:*/ 0x00,0x70, /* .........###.... */
+ /*0373:*/ 0x00,0x70, /* .........###.... */
+ /*0375:*/ 0x03,0xc0, /* ......####...... */
+ /*0377:*/ 0x0f,0x00, /* ....####........ */
+ /*0379:*/ 0x3c,0x00, /* ..####.......... */
+ /*037b:*/ 0xf0,0x00, /* ####............ */
+ /*037d:*/ 0xc0,0x00, /* ##.............. */
+/* --- new character question (63) starting at offset 0x037f --- */
+ /*037f:*/ 12, 10, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0384:*/ 0x1f,0x00, /* ...#####........ */
+ /*0386:*/ 0x7f,0x80, /* .########....... */
+ /*0388:*/ 0x71,0xc0, /* .###...###...... */
+ /*038a:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*038c:*/ 0xc0,0xc0, /* ##......##...... */
+ /*038e:*/ 0xc1,0xc0, /* ##.....###...... */
+ /*0390:*/ 0x01,0x80, /* .......##....... */
+ /*0392:*/ 0x03,0x80, /* ......###....... */
+ /*0394:*/ 0x07,0x00, /* .....###........ */
+ /*0396:*/ 0x06,0x00, /* .....##......... */
+ /*0398:*/ 0x0c,0x00, /* ....##.......... */
+ /*039a:*/ 0x0c,0x00, /* ....##.......... */
+ /*039c:*/ 0x0c,0x00, /* ....##.......... */
+ /*039e:*/ 0x0c,0x00, /* ....##.......... */
+ /*03a0:*/ 0x00,0x00, /* ................ */
+ /*03a2:*/ 0x00,0x00, /* ................ */
+ /*03a4:*/ 0x0c,0x00, /* ....##.......... */
+ /*03a6:*/ 0x0c,0x00, /* ....##.......... */
+ /*03a8:*/ 0x0c,0x00, /* ....##.......... */
+/* --- new character at (64) starting at offset 0x03aa --- */
+ /*03aa:*/ 25, 22, 23, 2, -4, /* width and bbox (w,h,x,y) */
+ /*03af:*/ 0x00,0xff,0x00, /* ........########........ */
+ /*03b2:*/ 0x03,0xff,0xc0, /* ......############...... */
+ /*03b5:*/ 0x0f,0x01,0xe0, /* ....####.......####..... */
+ /*03b8:*/ 0x1c,0x00,0x70, /* ...###...........###.... */
+ /*03bb:*/ 0x38,0x00,0x18, /* ..###..............##... */
+ /*03be:*/ 0x30,0x00,0x18, /* ..##...............##... */
+ /*03c1:*/ 0x60,0x73,0x0c, /* .##......###..##....##.. */
+ /*03c4:*/ 0x60,0xfb,0x0c, /* .##.....#####.##....##.. */
+ /*03c7:*/ 0xc1,0xc7,0x0c, /* ##.....###...###....##.. */
+ /*03ca:*/ 0xc3,0x86,0x0c, /* ##....###....##.....##.. */
+ /*03cd:*/ 0xc3,0x06,0x0c, /* ##....##.....##.....##.. */
+ /*03d0:*/ 0xc6,0x06,0x0c, /* ##...##......##.....##.. */
+ /*03d3:*/ 0xc6,0x0c,0x1c, /* ##...##.....##.....###.. */
+ /*03d6:*/ 0xc6,0x0c,0x18, /* ##...##.....##.....##... */
+ /*03d9:*/ 0xc6,0x0c,0x38, /* ##...##.....##....###... */
+ /*03dc:*/ 0xe7,0x1c,0x70, /* ###..###...###...###.... */
+ /*03df:*/ 0x63,0xf7,0xe0, /* .##...######.######..... */
+ /*03e2:*/ 0x71,0xe3,0x80, /* .###...####...###....... */
+ /*03e5:*/ 0x38,0x00,0x00, /* ..###................... */
+ /*03e8:*/ 0x1c,0x00,0x00, /* ...###.................. */
+ /*03eb:*/ 0x0f,0x03,0x00, /* ....####......##........ */
+ /*03ee:*/ 0x07,0xff,0x00, /* .....###########........ */
+ /*03f1:*/ 0x00,0xfc,0x00, /* ........######.......... */
+/* --- new character A (65) starting at offset 0x03f4 --- */
+ /*03f4:*/ 17, 15, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*03f9:*/ 0x03,0x80, /* ......###....... */
+ /*03fb:*/ 0x03,0x80, /* ......###....... */
+ /*03fd:*/ 0x06,0xc0, /* .....##.##...... */
+ /*03ff:*/ 0x06,0xc0, /* .....##.##...... */
+ /*0401:*/ 0x0c,0x40, /* ....##...#...... */
+ /*0403:*/ 0x0c,0x60, /* ....##...##..... */
+ /*0405:*/ 0x0c,0x60, /* ....##...##..... */
+ /*0407:*/ 0x18,0x30, /* ...##.....##.... */
+ /*0409:*/ 0x18,0x30, /* ...##.....##.... */
+ /*040b:*/ 0x18,0x30, /* ...##.....##.... */
+ /*040d:*/ 0x30,0x18, /* ..##.......##... */
+ /*040f:*/ 0x3f,0xf8, /* ..###########... */
+ /*0411:*/ 0x3f,0xf8, /* ..###########... */
+ /*0413:*/ 0x60,0x0c, /* .##.........##.. */
+ /*0415:*/ 0x60,0x0c, /* .##.........##.. */
+ /*0417:*/ 0x60,0x0c, /* .##.........##.. */
+ /*0419:*/ 0xc0,0x06, /* ##...........##. */
+ /*041b:*/ 0xc0,0x06, /* ##...........##. */
+ /*041d:*/ 0xc0,0x06, /* ##...........##. */
+/* --- new character B (66) starting at offset 0x041f --- */
+ /*041f:*/ 17, 14, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0424:*/ 0xff,0xc0, /* ##########...... */
+ /*0426:*/ 0xff,0xf0, /* ############.... */
+ /*0428:*/ 0xc0,0x70, /* ##.......###.... */
+ /*042a:*/ 0xc0,0x18, /* ##.........##... */
+ /*042c:*/ 0xc0,0x18, /* ##.........##... */
+ /*042e:*/ 0xc0,0x18, /* ##.........##... */
+ /*0430:*/ 0xc0,0x18, /* ##.........##... */
+ /*0432:*/ 0xc0,0x30, /* ##........##.... */
+ /*0434:*/ 0xff,0xe0, /* ###########..... */
+ /*0436:*/ 0xff,0xf0, /* ############.... */
+ /*0438:*/ 0xc0,0x18, /* ##.........##... */
+ /*043a:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*043c:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*043e:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0440:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0442:*/ 0xc0,0x1c, /* ##.........###.. */
+ /*0444:*/ 0xc0,0x38, /* ##........###... */
+ /*0446:*/ 0xff,0xf0, /* ############.... */
+ /*0448:*/ 0xff,0xc0, /* ##########...... */
+/* --- new character C (67) starting at offset 0x044a --- */
+ /*044a:*/ 18, 16, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*044f:*/ 0x07,0xe0, /* .....######..... */
+ /*0451:*/ 0x1f,0xf8, /* ...##########... */
+ /*0453:*/ 0x3c,0x3c, /* ..####....####.. */
+ /*0455:*/ 0x70,0x0e, /* .###........###. */
+ /*0457:*/ 0x60,0x06, /* .##..........##. */
+ /*0459:*/ 0xe0,0x06, /* ###..........##. */
+ /*045b:*/ 0xc0,0x00, /* ##.............. */
+ /*045d:*/ 0xc0,0x00, /* ##.............. */
+ /*045f:*/ 0xc0,0x00, /* ##.............. */
+ /*0461:*/ 0xc0,0x00, /* ##.............. */
+ /*0463:*/ 0xc0,0x00, /* ##.............. */
+ /*0465:*/ 0xc0,0x00, /* ##.............. */
+ /*0467:*/ 0xc0,0x03, /* ##............## */
+ /*0469:*/ 0xe0,0x03, /* ###...........## */
+ /*046b:*/ 0x60,0x06, /* .##..........##. */
+ /*046d:*/ 0x70,0x0e, /* .###........###. */
+ /*046f:*/ 0x3c,0x3c, /* ..####....####.. */
+ /*0471:*/ 0x1f,0xf8, /* ...##########... */
+ /*0473:*/ 0x07,0xe0, /* .....######..... */
+/* --- new character D (68) starting at offset 0x0475 --- */
+ /*0475:*/ 18, 15, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*047a:*/ 0xff,0xc0, /* ##########...... */
+ /*047c:*/ 0xff,0xf0, /* ############.... */
+ /*047e:*/ 0xc0,0x78, /* ##.......####... */
+ /*0480:*/ 0xc0,0x1c, /* ##.........###.. */
+ /*0482:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0484:*/ 0xc0,0x0e, /* ##..........###. */
+ /*0486:*/ 0xc0,0x06, /* ##...........##. */
+ /*0488:*/ 0xc0,0x06, /* ##...........##. */
+ /*048a:*/ 0xc0,0x06, /* ##...........##. */
+ /*048c:*/ 0xc0,0x06, /* ##...........##. */
+ /*048e:*/ 0xc0,0x06, /* ##...........##. */
+ /*0490:*/ 0xc0,0x06, /* ##...........##. */
+ /*0492:*/ 0xc0,0x06, /* ##...........##. */
+ /*0494:*/ 0xc0,0x0e, /* ##..........###. */
+ /*0496:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0498:*/ 0xc0,0x1c, /* ##.........###.. */
+ /*049a:*/ 0xc0,0x78, /* ##.......####... */
+ /*049c:*/ 0xff,0xf0, /* ############.... */
+ /*049e:*/ 0xff,0xc0, /* ##########...... */
+/* --- new character E (69) starting at offset 0x04a0 --- */
+ /*04a0:*/ 16, 12, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*04a5:*/ 0xff,0xf0, /* ############.... */
+ /*04a7:*/ 0xff,0xf0, /* ############.... */
+ /*04a9:*/ 0xc0,0x00, /* ##.............. */
+ /*04ab:*/ 0xc0,0x00, /* ##.............. */
+ /*04ad:*/ 0xc0,0x00, /* ##.............. */
+ /*04af:*/ 0xc0,0x00, /* ##.............. */
+ /*04b1:*/ 0xc0,0x00, /* ##.............. */
+ /*04b3:*/ 0xc0,0x00, /* ##.............. */
+ /*04b5:*/ 0xff,0xe0, /* ###########..... */
+ /*04b7:*/ 0xff,0xe0, /* ###########..... */
+ /*04b9:*/ 0xc0,0x00, /* ##.............. */
+ /*04bb:*/ 0xc0,0x00, /* ##.............. */
+ /*04bd:*/ 0xc0,0x00, /* ##.............. */
+ /*04bf:*/ 0xc0,0x00, /* ##.............. */
+ /*04c1:*/ 0xc0,0x00, /* ##.............. */
+ /*04c3:*/ 0xc0,0x00, /* ##.............. */
+ /*04c5:*/ 0xc0,0x00, /* ##.............. */
+ /*04c7:*/ 0xff,0xf0, /* ############.... */
+ /*04c9:*/ 0xff,0xf0, /* ############.... */
+/* --- new character F (70) starting at offset 0x04cb --- */
+ /*04cb:*/ 14, 11, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*04d0:*/ 0xff,0xe0, /* ###########..... */
+ /*04d2:*/ 0xff,0xe0, /* ###########..... */
+ /*04d4:*/ 0xc0,0x00, /* ##.............. */
+ /*04d6:*/ 0xc0,0x00, /* ##.............. */
+ /*04d8:*/ 0xc0,0x00, /* ##.............. */
+ /*04da:*/ 0xc0,0x00, /* ##.............. */
+ /*04dc:*/ 0xc0,0x00, /* ##.............. */
+ /*04de:*/ 0xc0,0x00, /* ##.............. */
+ /*04e0:*/ 0xc0,0x00, /* ##.............. */
+ /*04e2:*/ 0xff,0xc0, /* ##########...... */
+ /*04e4:*/ 0xff,0xc0, /* ##########...... */
+ /*04e6:*/ 0xc0,0x00, /* ##.............. */
+ /*04e8:*/ 0xc0,0x00, /* ##.............. */
+ /*04ea:*/ 0xc0,0x00, /* ##.............. */
+ /*04ec:*/ 0xc0,0x00, /* ##.............. */
+ /*04ee:*/ 0xc0,0x00, /* ##.............. */
+ /*04f0:*/ 0xc0,0x00, /* ##.............. */
+ /*04f2:*/ 0xc0,0x00, /* ##.............. */
+ /*04f4:*/ 0xc0,0x00, /* ##.............. */
+/* --- new character G (71) starting at offset 0x04f6 --- */
+ /*04f6:*/ 19, 16, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*04fb:*/ 0x07,0xe0, /* .....######..... */
+ /*04fd:*/ 0x1f,0xf8, /* ...##########... */
+ /*04ff:*/ 0x3c,0x3c, /* ..####....####.. */
+ /*0501:*/ 0x70,0x0e, /* .###........###. */
+ /*0503:*/ 0x60,0x06, /* .##..........##. */
+ /*0505:*/ 0xe0,0x06, /* ###..........##. */
+ /*0507:*/ 0xc0,0x00, /* ##.............. */
+ /*0509:*/ 0xc0,0x00, /* ##.............. */
+ /*050b:*/ 0xc0,0x00, /* ##.............. */
+ /*050d:*/ 0xc0,0x7f, /* ##.......####### */
+ /*050f:*/ 0xc0,0x7f, /* ##.......####### */
+ /*0511:*/ 0xc0,0x03, /* ##............## */
+ /*0513:*/ 0xc0,0x03, /* ##............## */
+ /*0515:*/ 0xe0,0x03, /* ###...........## */
+ /*0517:*/ 0x60,0x07, /* .##..........### */
+ /*0519:*/ 0x70,0x0f, /* .###........#### */
+ /*051b:*/ 0x3c,0x3f, /* ..####....###### */
+ /*051d:*/ 0x1f,0xfb, /* ...##########.## */
+ /*051f:*/ 0x07,0xe3, /* .....######...## */
+/* --- new character H (72) starting at offset 0x0521 --- */
+ /*0521:*/ 18, 14, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0526:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0528:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*052a:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*052c:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*052e:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0530:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0532:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0534:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0536:*/ 0xff,0xfc, /* ##############.. */
+ /*0538:*/ 0xff,0xfc, /* ##############.. */
+ /*053a:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*053c:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*053e:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0540:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0542:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0544:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0546:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0548:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*054a:*/ 0xc0,0x0c, /* ##..........##.. */
+/* --- new character I (73) starting at offset 0x054c --- */
+ /*054c:*/ 8, 2, 19, 3, 0, /* width and bbox (w,h,x,y) */
+ /*0551:*/ 0xc0, /* ##...... */
+ /*0552:*/ 0xc0, /* ##...... */
+ /*0553:*/ 0xc0, /* ##...... */
+ /*0554:*/ 0xc0, /* ##...... */
+ /*0555:*/ 0xc0, /* ##...... */
+ /*0556:*/ 0xc0, /* ##...... */
+ /*0557:*/ 0xc0, /* ##...... */
+ /*0558:*/ 0xc0, /* ##...... */
+ /*0559:*/ 0xc0, /* ##...... */
+ /*055a:*/ 0xc0, /* ##...... */
+ /*055b:*/ 0xc0, /* ##...... */
+ /*055c:*/ 0xc0, /* ##...... */
+ /*055d:*/ 0xc0, /* ##...... */
+ /*055e:*/ 0xc0, /* ##...... */
+ /*055f:*/ 0xc0, /* ##...... */
+ /*0560:*/ 0xc0, /* ##...... */
+ /*0561:*/ 0xc0, /* ##...... */
+ /*0562:*/ 0xc0, /* ##...... */
+ /*0563:*/ 0xc0, /* ##...... */
+/* --- new character J (74) starting at offset 0x0564 --- */
+ /*0564:*/ 13, 10, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0569:*/ 0x00,0xc0, /* ........##...... */
+ /*056b:*/ 0x00,0xc0, /* ........##...... */
+ /*056d:*/ 0x00,0xc0, /* ........##...... */
+ /*056f:*/ 0x00,0xc0, /* ........##...... */
+ /*0571:*/ 0x00,0xc0, /* ........##...... */
+ /*0573:*/ 0x00,0xc0, /* ........##...... */
+ /*0575:*/ 0x00,0xc0, /* ........##...... */
+ /*0577:*/ 0x00,0xc0, /* ........##...... */
+ /*0579:*/ 0x00,0xc0, /* ........##...... */
+ /*057b:*/ 0x00,0xc0, /* ........##...... */
+ /*057d:*/ 0x00,0xc0, /* ........##...... */
+ /*057f:*/ 0x00,0xc0, /* ........##...... */
+ /*0581:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0583:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0585:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0587:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0589:*/ 0x61,0x80, /* .##....##....... */
+ /*058b:*/ 0x7f,0x80, /* .########....... */
+ /*058d:*/ 0x3f,0x00, /* ..######........ */
+/* --- new character K (75) starting at offset 0x058f --- */
+ /*058f:*/ 18, 15, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0594:*/ 0xc0,0x38, /* ##........###... */
+ /*0596:*/ 0xc0,0x70, /* ##.......###.... */
+ /*0598:*/ 0xc0,0xe0, /* ##......###..... */
+ /*059a:*/ 0xc1,0xc0, /* ##.....###...... */
+ /*059c:*/ 0xc3,0x80, /* ##....###....... */
+ /*059e:*/ 0xc7,0x00, /* ##...###........ */
+ /*05a0:*/ 0xce,0x00, /* ##..###......... */
+ /*05a2:*/ 0xdc,0x00, /* ##.###.......... */
+ /*05a4:*/ 0xfc,0x00, /* ######.......... */
+ /*05a6:*/ 0xfe,0x00, /* #######......... */
+ /*05a8:*/ 0xe7,0x00, /* ###..###........ */
+ /*05aa:*/ 0xc3,0x80, /* ##....###....... */
+ /*05ac:*/ 0xc1,0xc0, /* ##.....###...... */
+ /*05ae:*/ 0xc0,0xe0, /* ##......###..... */
+ /*05b0:*/ 0xc0,0x70, /* ##.......###.... */
+ /*05b2:*/ 0xc0,0x38, /* ##........###... */
+ /*05b4:*/ 0xc0,0x1c, /* ##.........###.. */
+ /*05b6:*/ 0xc0,0x0e, /* ##..........###. */
+ /*05b8:*/ 0xc0,0x06, /* ##...........##. */
+/* --- new character L (76) starting at offset 0x05ba --- */
+ /*05ba:*/ 14, 11, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*05bf:*/ 0xc0,0x00, /* ##.............. */
+ /*05c1:*/ 0xc0,0x00, /* ##.............. */
+ /*05c3:*/ 0xc0,0x00, /* ##.............. */
+ /*05c5:*/ 0xc0,0x00, /* ##.............. */
+ /*05c7:*/ 0xc0,0x00, /* ##.............. */
+ /*05c9:*/ 0xc0,0x00, /* ##.............. */
+ /*05cb:*/ 0xc0,0x00, /* ##.............. */
+ /*05cd:*/ 0xc0,0x00, /* ##.............. */
+ /*05cf:*/ 0xc0,0x00, /* ##.............. */
+ /*05d1:*/ 0xc0,0x00, /* ##.............. */
+ /*05d3:*/ 0xc0,0x00, /* ##.............. */
+ /*05d5:*/ 0xc0,0x00, /* ##.............. */
+ /*05d7:*/ 0xc0,0x00, /* ##.............. */
+ /*05d9:*/ 0xc0,0x00, /* ##.............. */
+ /*05db:*/ 0xc0,0x00, /* ##.............. */
+ /*05dd:*/ 0xc0,0x00, /* ##.............. */
+ /*05df:*/ 0xc0,0x00, /* ##.............. */
+ /*05e1:*/ 0xff,0xe0, /* ###########..... */
+ /*05e3:*/ 0xff,0xe0, /* ###########..... */
+/* --- new character M (77) starting at offset 0x05e5 --- */
+ /*05e5:*/ 21, 17, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*05ea:*/ 0xc0,0x01,0x80, /* ##.............##....... */
+ /*05ed:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*05f0:*/ 0xe0,0x03,0x80, /* ###...........###....... */
+ /*05f3:*/ 0xf0,0x07,0x80, /* ####.........####....... */
+ /*05f6:*/ 0xf0,0x07,0x80, /* ####.........####....... */
+ /*05f9:*/ 0xd8,0x0d,0x80, /* ##.##.......##.##....... */
+ /*05fc:*/ 0xd8,0x0d,0x80, /* ##.##.......##.##....... */
+ /*05ff:*/ 0xd8,0x0d,0x80, /* ##.##.......##.##....... */
+ /*0602:*/ 0xcc,0x19,0x80, /* ##..##.....##..##....... */
+ /*0605:*/ 0xcc,0x19,0x80, /* ##..##.....##..##....... */
+ /*0608:*/ 0xcc,0x19,0x80, /* ##..##.....##..##....... */
+ /*060b:*/ 0xc6,0x31,0x80, /* ##...##...##...##....... */
+ /*060e:*/ 0xc6,0x31,0x80, /* ##...##...##...##....... */
+ /*0611:*/ 0xc6,0x31,0x80, /* ##...##...##...##....... */
+ /*0614:*/ 0xc3,0x61,0x80, /* ##....##.##....##....... */
+ /*0617:*/ 0xc3,0x61,0x80, /* ##....##.##....##....... */
+ /*061a:*/ 0xc3,0x61,0x80, /* ##....##.##....##....... */
+ /*061d:*/ 0xc1,0xc1,0x80, /* ##.....###.....##....... */
+ /*0620:*/ 0xc1,0xc1,0x80, /* ##.....###.....##....... */
+/* --- new character N (78) starting at offset 0x0623 --- */
+ /*0623:*/ 18, 14, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0628:*/ 0xe0,0x0c, /* ###.........##.. */
+ /*062a:*/ 0xf0,0x0c, /* ####........##.. */
+ /*062c:*/ 0xf0,0x0c, /* ####........##.. */
+ /*062e:*/ 0xd8,0x0c, /* ##.##.......##.. */
+ /*0630:*/ 0xdc,0x0c, /* ##.###......##.. */
+ /*0632:*/ 0xcc,0x0c, /* ##..##......##.. */
+ /*0634:*/ 0xce,0x0c, /* ##..###.....##.. */
+ /*0636:*/ 0xc6,0x0c, /* ##...##.....##.. */
+ /*0638:*/ 0xc7,0x0c, /* ##...###....##.. */
+ /*063a:*/ 0xc3,0x0c, /* ##....##....##.. */
+ /*063c:*/ 0xc3,0x8c, /* ##....###...##.. */
+ /*063e:*/ 0xc1,0x8c, /* ##.....##...##.. */
+ /*0640:*/ 0xc1,0xcc, /* ##.....###..##.. */
+ /*0642:*/ 0xc0,0xcc, /* ##......##..##.. */
+ /*0644:*/ 0xc0,0xec, /* ##......###.##.. */
+ /*0646:*/ 0xc0,0x6c, /* ##.......##.##.. */
+ /*0648:*/ 0xc0,0x3c, /* ##........####.. */
+ /*064a:*/ 0xc0,0x3c, /* ##........####.. */
+ /*064c:*/ 0xc0,0x1c, /* ##.........###.. */
+/* --- new character O (79) starting at offset 0x064e --- */
+ /*064e:*/ 18, 16, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0653:*/ 0x07,0xe0, /* .....######..... */
+ /*0655:*/ 0x1f,0xf8, /* ...##########... */
+ /*0657:*/ 0x3c,0x3c, /* ..####....####.. */
+ /*0659:*/ 0x70,0x0e, /* .###........###. */
+ /*065b:*/ 0x60,0x06, /* .##..........##. */
+ /*065d:*/ 0xe0,0x07, /* ###..........### */
+ /*065f:*/ 0xc0,0x03, /* ##............## */
+ /*0661:*/ 0xc0,0x03, /* ##............## */
+ /*0663:*/ 0xc0,0x03, /* ##............## */
+ /*0665:*/ 0xc0,0x03, /* ##............## */
+ /*0667:*/ 0xc0,0x03, /* ##............## */
+ /*0669:*/ 0xc0,0x03, /* ##............## */
+ /*066b:*/ 0xc0,0x03, /* ##............## */
+ /*066d:*/ 0xe0,0x07, /* ###..........### */
+ /*066f:*/ 0x60,0x06, /* .##..........##. */
+ /*0671:*/ 0x70,0x0e, /* .###........###. */
+ /*0673:*/ 0x3c,0x3c, /* ..####....####.. */
+ /*0675:*/ 0x1f,0xf8, /* ...##########... */
+ /*0677:*/ 0x07,0xe0, /* .....######..... */
+/* --- new character P (80) starting at offset 0x0679 --- */
+ /*0679:*/ 16, 13, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*067e:*/ 0xff,0xe0, /* ###########..... */
+ /*0680:*/ 0xff,0xf0, /* ############.... */
+ /*0682:*/ 0xc0,0x30, /* ##........##.... */
+ /*0684:*/ 0xc0,0x18, /* ##.........##... */
+ /*0686:*/ 0xc0,0x18, /* ##.........##... */
+ /*0688:*/ 0xc0,0x18, /* ##.........##... */
+ /*068a:*/ 0xc0,0x18, /* ##.........##... */
+ /*068c:*/ 0xc0,0x30, /* ##........##.... */
+ /*068e:*/ 0xff,0xf0, /* ############.... */
+ /*0690:*/ 0xff,0xe0, /* ###########..... */
+ /*0692:*/ 0xc0,0x00, /* ##.............. */
+ /*0694:*/ 0xc0,0x00, /* ##.............. */
+ /*0696:*/ 0xc0,0x00, /* ##.............. */
+ /*0698:*/ 0xc0,0x00, /* ##.............. */
+ /*069a:*/ 0xc0,0x00, /* ##.............. */
+ /*069c:*/ 0xc0,0x00, /* ##.............. */
+ /*069e:*/ 0xc0,0x00, /* ##.............. */
+ /*06a0:*/ 0xc0,0x00, /* ##.............. */
+ /*06a2:*/ 0xc0,0x00, /* ##.............. */
+/* --- new character Q (81) starting at offset 0x06a4 --- */
+ /*06a4:*/ 18, 16, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*06a9:*/ 0x07,0xe0, /* .....######..... */
+ /*06ab:*/ 0x1f,0xf8, /* ...##########... */
+ /*06ad:*/ 0x3c,0x3c, /* ..####....####.. */
+ /*06af:*/ 0x70,0x0e, /* .###........###. */
+ /*06b1:*/ 0x60,0x06, /* .##..........##. */
+ /*06b3:*/ 0xe0,0x07, /* ###..........### */
+ /*06b5:*/ 0xc0,0x03, /* ##............## */
+ /*06b7:*/ 0xc0,0x03, /* ##............## */
+ /*06b9:*/ 0xc0,0x03, /* ##............## */
+ /*06bb:*/ 0xc0,0x03, /* ##............## */
+ /*06bd:*/ 0xc0,0x03, /* ##............## */
+ /*06bf:*/ 0xc0,0x03, /* ##............## */
+ /*06c1:*/ 0xc0,0x03, /* ##............## */
+ /*06c3:*/ 0xe0,0x07, /* ###..........### */
+ /*06c5:*/ 0x60,0xe6, /* .##.....###..##. */
+ /*06c7:*/ 0x70,0x7e, /* .###.....######. */
+ /*06c9:*/ 0x3c,0x1c, /* ..####.....###.. */
+ /*06cb:*/ 0x1f,0xfe, /* ...############. */
+ /*06cd:*/ 0x07,0xe7, /* .....######..### */
+/* --- new character R (82) starting at offset 0x06cf --- */
+ /*06cf:*/ 17, 13, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*06d4:*/ 0xff,0xe0, /* ###########..... */
+ /*06d6:*/ 0xff,0xf0, /* ############.... */
+ /*06d8:*/ 0xc0,0x30, /* ##........##.... */
+ /*06da:*/ 0xc0,0x18, /* ##.........##... */
+ /*06dc:*/ 0xc0,0x18, /* ##.........##... */
+ /*06de:*/ 0xc0,0x18, /* ##.........##... */
+ /*06e0:*/ 0xc0,0x18, /* ##.........##... */
+ /*06e2:*/ 0xc0,0x30, /* ##........##.... */
+ /*06e4:*/ 0xff,0xf0, /* ############.... */
+ /*06e6:*/ 0xff,0xe0, /* ###########..... */
+ /*06e8:*/ 0xc0,0x70, /* ##.......###.... */
+ /*06ea:*/ 0xc0,0x30, /* ##........##.... */
+ /*06ec:*/ 0xc0,0x18, /* ##.........##... */
+ /*06ee:*/ 0xc0,0x18, /* ##.........##... */
+ /*06f0:*/ 0xc0,0x18, /* ##.........##... */
+ /*06f2:*/ 0xc0,0x18, /* ##.........##... */
+ /*06f4:*/ 0xc0,0x18, /* ##.........##... */
+ /*06f6:*/ 0xc0,0x18, /* ##.........##... */
+ /*06f8:*/ 0xc0,0x18, /* ##.........##... */
+/* --- new character S (83) starting at offset 0x06fa --- */
+ /*06fa:*/ 16, 14, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*06ff:*/ 0x07,0xc0, /* .....#####...... */
+ /*0701:*/ 0x1f,0xf0, /* ...#########.... */
+ /*0703:*/ 0x38,0x38, /* ..###.....###... */
+ /*0705:*/ 0x70,0x18, /* .###.......##... */
+ /*0707:*/ 0x60,0x18, /* .##........##... */
+ /*0709:*/ 0x60,0x00, /* .##............. */
+ /*070b:*/ 0x70,0x00, /* .###............ */
+ /*070d:*/ 0x3e,0x00, /* ..#####......... */
+ /*070f:*/ 0x0f,0xc0, /* ....######...... */
+ /*0711:*/ 0x01,0xf0, /* .......#####.... */
+ /*0713:*/ 0x00,0x78, /* .........####... */
+ /*0715:*/ 0x00,0x1c, /* ...........###.. */
+ /*0717:*/ 0x00,0x0c, /* ............##.. */
+ /*0719:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*071b:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*071d:*/ 0xe0,0x1c, /* ###........###.. */
+ /*071f:*/ 0x78,0x38, /* .####.....###... */
+ /*0721:*/ 0x3f,0xf0, /* ..##########.... */
+ /*0723:*/ 0x0f,0xc0, /* ....######...... */
+/* --- new character T (84) starting at offset 0x0725 --- */
+ /*0725:*/ 16, 14, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*072a:*/ 0xff,0xfc, /* ##############.. */
+ /*072c:*/ 0xff,0xfc, /* ##############.. */
+ /*072e:*/ 0x03,0x00, /* ......##........ */
+ /*0730:*/ 0x03,0x00, /* ......##........ */
+ /*0732:*/ 0x03,0x00, /* ......##........ */
+ /*0734:*/ 0x03,0x00, /* ......##........ */
+ /*0736:*/ 0x03,0x00, /* ......##........ */
+ /*0738:*/ 0x03,0x00, /* ......##........ */
+ /*073a:*/ 0x03,0x00, /* ......##........ */
+ /*073c:*/ 0x03,0x00, /* ......##........ */
+ /*073e:*/ 0x03,0x00, /* ......##........ */
+ /*0740:*/ 0x03,0x00, /* ......##........ */
+ /*0742:*/ 0x03,0x00, /* ......##........ */
+ /*0744:*/ 0x03,0x00, /* ......##........ */
+ /*0746:*/ 0x03,0x00, /* ......##........ */
+ /*0748:*/ 0x03,0x00, /* ......##........ */
+ /*074a:*/ 0x03,0x00, /* ......##........ */
+ /*074c:*/ 0x03,0x00, /* ......##........ */
+ /*074e:*/ 0x03,0x00, /* ......##........ */
+/* --- new character U (85) starting at offset 0x0750 --- */
+ /*0750:*/ 18, 14, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0755:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0757:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0759:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*075b:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*075d:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*075f:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0761:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0763:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0765:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0767:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0769:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*076b:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*076d:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*076f:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0771:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0773:*/ 0x60,0x18, /* .##........##... */
+ /*0775:*/ 0x70,0x38, /* .###......###... */
+ /*0777:*/ 0x3f,0xf0, /* ..##########.... */
+ /*0779:*/ 0x0f,0xc0, /* ....######...... */
+/* --- new character V (86) starting at offset 0x077b --- */
+ /*077b:*/ 17, 15, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0780:*/ 0xc0,0x06, /* ##...........##. */
+ /*0782:*/ 0xc0,0x06, /* ##...........##. */
+ /*0784:*/ 0xe0,0x0e, /* ###.........###. */
+ /*0786:*/ 0x60,0x0c, /* .##.........##.. */
+ /*0788:*/ 0x70,0x1c, /* .###.......###.. */
+ /*078a:*/ 0x30,0x18, /* ..##.......##... */
+ /*078c:*/ 0x30,0x18, /* ..##.......##... */
+ /*078e:*/ 0x38,0x38, /* ..###.....###... */
+ /*0790:*/ 0x18,0x30, /* ...##.....##.... */
+ /*0792:*/ 0x18,0x30, /* ...##.....##.... */
+ /*0794:*/ 0x1c,0x70, /* ...###...###.... */
+ /*0796:*/ 0x0c,0x60, /* ....##...##..... */
+ /*0798:*/ 0x0c,0x60, /* ....##...##..... */
+ /*079a:*/ 0x0e,0xe0, /* ....###.###..... */
+ /*079c:*/ 0x06,0xc0, /* .....##.##...... */
+ /*079e:*/ 0x06,0xc0, /* .....##.##...... */
+ /*07a0:*/ 0x03,0x80, /* ......###....... */
+ /*07a2:*/ 0x03,0x80, /* ......###....... */
+ /*07a4:*/ 0x03,0x80, /* ......###....... */
+/* --- new character W (87) starting at offset 0x07a6 --- */
+ /*07a6:*/ 22, 20, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*07ab:*/ 0xc0,0x60,0x30, /* ##.......##.......##.... */
+ /*07ae:*/ 0xc0,0x60,0x30, /* ##.......##.......##.... */
+ /*07b1:*/ 0xc0,0x60,0x30, /* ##.......##.......##.... */
+ /*07b4:*/ 0xc0,0xf0,0x30, /* ##......####......##.... */
+ /*07b7:*/ 0x60,0xf0,0x60, /* .##.....####.....##..... */
+ /*07ba:*/ 0x61,0x98,0x60, /* .##....##..##....##..... */
+ /*07bd:*/ 0x61,0x98,0x60, /* .##....##..##....##..... */
+ /*07c0:*/ 0x61,0x98,0x60, /* .##....##..##....##..... */
+ /*07c3:*/ 0x61,0x98,0x60, /* .##....##..##....##..... */
+ /*07c6:*/ 0x31,0x98,0xc0, /* ..##...##..##...##...... */
+ /*07c9:*/ 0x33,0x0c,0xc0, /* ..##..##....##..##...... */
+ /*07cc:*/ 0x33,0x0c,0xc0, /* ..##..##....##..##...... */
+ /*07cf:*/ 0x33,0x0c,0xc0, /* ..##..##....##..##...... */
+ /*07d2:*/ 0x1b,0x0d,0x80, /* ...##.##....##.##....... */
+ /*07d5:*/ 0x1b,0x0d,0x80, /* ...##.##....##.##....... */
+ /*07d8:*/ 0x1e,0x07,0x80, /* ...####......####....... */
+ /*07db:*/ 0x0e,0x07,0x00, /* ....###......###........ */
+ /*07de:*/ 0x0c,0x03,0x00, /* ....##........##........ */
+ /*07e1:*/ 0x0c,0x03,0x00, /* ....##........##........ */
+/* --- new character X (88) starting at offset 0x07e4 --- */
+ /*07e4:*/ 17, 15, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*07e9:*/ 0xc0,0x06, /* ##...........##. */
+ /*07eb:*/ 0xe0,0x0e, /* ###.........###. */
+ /*07ed:*/ 0x70,0x1c, /* .###.......###.. */
+ /*07ef:*/ 0x30,0x18, /* ..##.......##... */
+ /*07f1:*/ 0x18,0x30, /* ...##.....##.... */
+ /*07f3:*/ 0x1c,0x70, /* ...###...###.... */
+ /*07f5:*/ 0x0e,0xe0, /* ....###.###..... */
+ /*07f7:*/ 0x07,0xc0, /* .....#####...... */
+ /*07f9:*/ 0x03,0x80, /* ......###....... */
+ /*07fb:*/ 0x03,0x80, /* ......###....... */
+ /*07fd:*/ 0x07,0xc0, /* .....#####...... */
+ /*07ff:*/ 0x0e,0xe0, /* ....###.###..... */
+ /*0801:*/ 0x0c,0x60, /* ....##...##..... */
+ /*0803:*/ 0x1c,0x70, /* ...###...###.... */
+ /*0805:*/ 0x38,0x38, /* ..###.....###... */
+ /*0807:*/ 0x30,0x18, /* ..##.......##... */
+ /*0809:*/ 0x60,0x0c, /* .##.........##.. */
+ /*080b:*/ 0xe0,0x0e, /* ###.........###. */
+ /*080d:*/ 0xc0,0x06, /* ##...........##. */
+/* --- new character Y (89) starting at offset 0x080f --- */
+ /*080f:*/ 16, 14, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0814:*/ 0xc0,0x0c, /* ##..........##.. */
+ /*0816:*/ 0xe0,0x1c, /* ###........###.. */
+ /*0818:*/ 0x60,0x18, /* .##........##... */
+ /*081a:*/ 0x70,0x38, /* .###......###... */
+ /*081c:*/ 0x30,0x30, /* ..##......##.... */
+ /*081e:*/ 0x38,0x70, /* ..###....###.... */
+ /*0820:*/ 0x18,0x60, /* ...##....##..... */
+ /*0822:*/ 0x1c,0xe0, /* ...###..###..... */
+ /*0824:*/ 0x0c,0xc0, /* ....##..##...... */
+ /*0826:*/ 0x0f,0xc0, /* ....######...... */
+ /*0828:*/ 0x07,0x80, /* .....####....... */
+ /*082a:*/ 0x07,0x80, /* .....####....... */
+ /*082c:*/ 0x03,0x00, /* ......##........ */
+ /*082e:*/ 0x03,0x00, /* ......##........ */
+ /*0830:*/ 0x03,0x00, /* ......##........ */
+ /*0832:*/ 0x03,0x00, /* ......##........ */
+ /*0834:*/ 0x03,0x00, /* ......##........ */
+ /*0836:*/ 0x03,0x00, /* ......##........ */
+ /*0838:*/ 0x03,0x00, /* ......##........ */
+/* --- new character Z (90) starting at offset 0x083a --- */
+ /*083a:*/ 15, 13, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*083f:*/ 0xff,0xf8, /* #############... */
+ /*0841:*/ 0xff,0xf8, /* #############... */
+ /*0843:*/ 0x00,0x38, /* ..........###... */
+ /*0845:*/ 0x00,0x70, /* .........###.... */
+ /*0847:*/ 0x00,0xe0, /* ........###..... */
+ /*0849:*/ 0x01,0xc0, /* .......###...... */
+ /*084b:*/ 0x01,0xc0, /* .......###...... */
+ /*084d:*/ 0x03,0x80, /* ......###....... */
+ /*084f:*/ 0x07,0x00, /* .....###........ */
+ /*0851:*/ 0x07,0x00, /* .....###........ */
+ /*0853:*/ 0x0e,0x00, /* ....###......... */
+ /*0855:*/ 0x1c,0x00, /* ...###.......... */
+ /*0857:*/ 0x1c,0x00, /* ...###.......... */
+ /*0859:*/ 0x38,0x00, /* ..###........... */
+ /*085b:*/ 0x70,0x00, /* .###............ */
+ /*085d:*/ 0x70,0x00, /* .###............ */
+ /*085f:*/ 0xe0,0x00, /* ###............. */
+ /*0861:*/ 0xff,0xf8, /* #############... */
+ /*0863:*/ 0xff,0xf8, /* #############... */
+/* --- new character bracketleft (91) starting at offset 0x0865 --- */
+ /*0865:*/ 7, 4, 24, 2, -5, /* width and bbox (w,h,x,y) */
+ /*086a:*/ 0xf0, /* ####.... */
+ /*086b:*/ 0xf0, /* ####.... */
+ /*086c:*/ 0xc0, /* ##...... */
+ /*086d:*/ 0xc0, /* ##...... */
+ /*086e:*/ 0xc0, /* ##...... */
+ /*086f:*/ 0xc0, /* ##...... */
+ /*0870:*/ 0xc0, /* ##...... */
+ /*0871:*/ 0xc0, /* ##...... */
+ /*0872:*/ 0xc0, /* ##...... */
+ /*0873:*/ 0xc0, /* ##...... */
+ /*0874:*/ 0xc0, /* ##...... */
+ /*0875:*/ 0xc0, /* ##...... */
+ /*0876:*/ 0xc0, /* ##...... */
+ /*0877:*/ 0xc0, /* ##...... */
+ /*0878:*/ 0xc0, /* ##...... */
+ /*0879:*/ 0xc0, /* ##...... */
+ /*087a:*/ 0xc0, /* ##...... */
+ /*087b:*/ 0xc0, /* ##...... */
+ /*087c:*/ 0xc0, /* ##...... */
+ /*087d:*/ 0xc0, /* ##...... */
+ /*087e:*/ 0xc0, /* ##...... */
+ /*087f:*/ 0xc0, /* ##...... */
+ /*0880:*/ 0xf0, /* ####.... */
+ /*0881:*/ 0xf0, /* ####.... */
+/* --- new character backslash (92) starting at offset 0x0882 --- */
+ /*0882:*/ 7, 7, 19, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0887:*/ 0xc0, /* ##...... */
+ /*0888:*/ 0xc0, /* ##...... */
+ /*0889:*/ 0xc0, /* ##...... */
+ /*088a:*/ 0x60, /* .##..... */
+ /*088b:*/ 0x60, /* .##..... */
+ /*088c:*/ 0x60, /* .##..... */
+ /*088d:*/ 0x30, /* ..##.... */
+ /*088e:*/ 0x30, /* ..##.... */
+ /*088f:*/ 0x30, /* ..##.... */
+ /*0890:*/ 0x30, /* ..##.... */
+ /*0891:*/ 0x18, /* ...##... */
+ /*0892:*/ 0x18, /* ...##... */
+ /*0893:*/ 0x18, /* ...##... */
+ /*0894:*/ 0x0c, /* ....##.. */
+ /*0895:*/ 0x0c, /* ....##.. */
+ /*0896:*/ 0x0c, /* ....##.. */
+ /*0897:*/ 0x06, /* .....##. */
+ /*0898:*/ 0x06, /* .....##. */
+ /*0899:*/ 0x06, /* .....##. */
+/* --- new character bracketright (93) starting at offset 0x089a --- */
+ /*089a:*/ 7, 4, 24, 1, -5, /* width and bbox (w,h,x,y) */
+ /*089f:*/ 0xf0, /* ####.... */
+ /*08a0:*/ 0xf0, /* ####.... */
+ /*08a1:*/ 0x30, /* ..##.... */
+ /*08a2:*/ 0x30, /* ..##.... */
+ /*08a3:*/ 0x30, /* ..##.... */
+ /*08a4:*/ 0x30, /* ..##.... */
+ /*08a5:*/ 0x30, /* ..##.... */
+ /*08a6:*/ 0x30, /* ..##.... */
+ /*08a7:*/ 0x30, /* ..##.... */
+ /*08a8:*/ 0x30, /* ..##.... */
+ /*08a9:*/ 0x30, /* ..##.... */
+ /*08aa:*/ 0x30, /* ..##.... */
+ /*08ab:*/ 0x30, /* ..##.... */
+ /*08ac:*/ 0x30, /* ..##.... */
+ /*08ad:*/ 0x30, /* ..##.... */
+ /*08ae:*/ 0x30, /* ..##.... */
+ /*08af:*/ 0x30, /* ..##.... */
+ /*08b0:*/ 0x30, /* ..##.... */
+ /*08b1:*/ 0x30, /* ..##.... */
+ /*08b2:*/ 0x30, /* ..##.... */
+ /*08b3:*/ 0x30, /* ..##.... */
+ /*08b4:*/ 0x30, /* ..##.... */
+ /*08b5:*/ 0xf0, /* ####.... */
+ /*08b6:*/ 0xf0, /* ####.... */
+/* --- new character asciicircum (94) starting at offset 0x08b7 --- */
+ /*08b7:*/ 12, 10, 9, 1, 10, /* width and bbox (w,h,x,y) */
+ /*08bc:*/ 0x0c,0x00, /* ....##.......... */
+ /*08be:*/ 0x0c,0x00, /* ....##.......... */
+ /*08c0:*/ 0x1e,0x00, /* ...####......... */
+ /*08c2:*/ 0x12,0x00, /* ...#..#......... */
+ /*08c4:*/ 0x33,0x00, /* ..##..##........ */
+ /*08c6:*/ 0x61,0x80, /* .##....##....... */
+ /*08c8:*/ 0x61,0x80, /* .##....##....... */
+ /*08ca:*/ 0xc0,0xc0, /* ##......##...... */
+ /*08cc:*/ 0xc0,0xc0, /* ##......##...... */
+/* --- new character underscore (95) starting at offset 0x08ce --- */
+ /*08ce:*/ 14, 14, 2, 0, -5, /* width and bbox (w,h,x,y) */
+ /*08d3:*/ 0xff,0xfc, /* ##############.. */
+ /*08d5:*/ 0xff,0xfc, /* ##############.. */
+/* --- new character grave (96) starting at offset 0x08d7 --- */
+ /*08d7:*/ 7, 5, 4, 1, 15, /* width and bbox (w,h,x,y) */
+ /*08dc:*/ 0xc0, /* ##...... */
+ /*08dd:*/ 0x60, /* .##..... */
+ /*08de:*/ 0x30, /* ..##.... */
+ /*08df:*/ 0x18, /* ...##... */
+/* --- new character a (97) starting at offset 0x08e0 --- */
+ /*08e0:*/ 13, 11, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*08e5:*/ 0x1f,0x00, /* ...#####........ */
+ /*08e7:*/ 0x3f,0x80, /* ..#######....... */
+ /*08e9:*/ 0x61,0xc0, /* .##....###...... */
+ /*08eb:*/ 0x60,0xc0, /* .##.....##...... */
+ /*08ed:*/ 0x00,0xc0, /* ........##...... */
+ /*08ef:*/ 0x07,0xc0, /* .....#####...... */
+ /*08f1:*/ 0x3f,0xc0, /* ..########...... */
+ /*08f3:*/ 0x78,0xc0, /* .####...##...... */
+ /*08f5:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*08f7:*/ 0xc0,0xc0, /* ##......##...... */
+ /*08f9:*/ 0xc1,0xc0, /* ##.....###...... */
+ /*08fb:*/ 0xe3,0xc0, /* ###...####...... */
+ /*08fd:*/ 0x7e,0xe0, /* .######.###..... */
+ /*08ff:*/ 0x3c,0x60, /* ..####...##..... */
+/* --- new character b (98) starting at offset 0x0901 --- */
+ /*0901:*/ 14, 11, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0906:*/ 0xc0,0x00, /* ##.............. */
+ /*0908:*/ 0xc0,0x00, /* ##.............. */
+ /*090a:*/ 0xc0,0x00, /* ##.............. */
+ /*090c:*/ 0xc0,0x00, /* ##.............. */
+ /*090e:*/ 0xc0,0x00, /* ##.............. */
+ /*0910:*/ 0xcf,0x00, /* ##..####........ */
+ /*0912:*/ 0xdf,0x80, /* ##.######....... */
+ /*0914:*/ 0xf1,0xc0, /* ####...###...... */
+ /*0916:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*0918:*/ 0xc0,0x60, /* ##.......##..... */
+ /*091a:*/ 0xc0,0x60, /* ##.......##..... */
+ /*091c:*/ 0xc0,0x60, /* ##.......##..... */
+ /*091e:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0920:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0922:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0924:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*0926:*/ 0xf1,0xc0, /* ####...###...... */
+ /*0928:*/ 0xdf,0x80, /* ##.######....... */
+ /*092a:*/ 0xcf,0x00, /* ##..####........ */
+/* --- new character c (99) starting at offset 0x092c --- */
+ /*092c:*/ 12, 10, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0931:*/ 0x1f,0x00, /* ...#####........ */
+ /*0933:*/ 0x3f,0x80, /* ..#######....... */
+ /*0935:*/ 0x71,0xc0, /* .###...###...... */
+ /*0937:*/ 0x60,0xc0, /* .##.....##...... */
+ /*0939:*/ 0xc0,0x00, /* ##.............. */
+ /*093b:*/ 0xc0,0x00, /* ##.............. */
+ /*093d:*/ 0xc0,0x00, /* ##.............. */
+ /*093f:*/ 0xc0,0x00, /* ##.............. */
+ /*0941:*/ 0xc0,0x00, /* ##.............. */
+ /*0943:*/ 0xc0,0x00, /* ##.............. */
+ /*0945:*/ 0x60,0xc0, /* .##.....##...... */
+ /*0947:*/ 0x71,0xc0, /* .###...###...... */
+ /*0949:*/ 0x3f,0x80, /* ..#######....... */
+ /*094b:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character d (100) starting at offset 0x094d --- */
+ /*094d:*/ 14, 11, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0952:*/ 0x00,0x60, /* .........##..... */
+ /*0954:*/ 0x00,0x60, /* .........##..... */
+ /*0956:*/ 0x00,0x60, /* .........##..... */
+ /*0958:*/ 0x00,0x60, /* .........##..... */
+ /*095a:*/ 0x00,0x60, /* .........##..... */
+ /*095c:*/ 0x1e,0x60, /* ...####..##..... */
+ /*095e:*/ 0x3f,0x60, /* ..######.##..... */
+ /*0960:*/ 0x71,0xe0, /* .###...####..... */
+ /*0962:*/ 0x60,0xe0, /* .##.....###..... */
+ /*0964:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0966:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0968:*/ 0xc0,0x60, /* ##.......##..... */
+ /*096a:*/ 0xc0,0x60, /* ##.......##..... */
+ /*096c:*/ 0xc0,0x60, /* ##.......##..... */
+ /*096e:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0970:*/ 0x60,0xe0, /* .##.....###..... */
+ /*0972:*/ 0x71,0xe0, /* .###...####..... */
+ /*0974:*/ 0x3f,0x60, /* ..######.##..... */
+ /*0976:*/ 0x1e,0x60, /* ...####..##..... */
+/* --- new character e (101) starting at offset 0x0978 --- */
+ /*0978:*/ 13, 11, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*097d:*/ 0x0e,0x00, /* ....###......... */
+ /*097f:*/ 0x3f,0x80, /* ..#######....... */
+ /*0981:*/ 0x71,0xc0, /* .###...###...... */
+ /*0983:*/ 0x60,0xc0, /* .##.....##...... */
+ /*0985:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0987:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0989:*/ 0xff,0xe0, /* ###########..... */
+ /*098b:*/ 0xff,0xe0, /* ###########..... */
+ /*098d:*/ 0xc0,0x00, /* ##.............. */
+ /*098f:*/ 0xc0,0x00, /* ##.............. */
+ /*0991:*/ 0x60,0x60, /* .##......##..... */
+ /*0993:*/ 0x70,0xe0, /* .###....###..... */
+ /*0995:*/ 0x3f,0xc0, /* ..########...... */
+ /*0997:*/ 0x0f,0x00, /* ....####........ */
+/* --- new character f (102) starting at offset 0x0999 --- */
+ /*0999:*/ 8, 6, 19, 1, 0, /* width and bbox (w,h,x,y) */
+ /*099e:*/ 0x1c, /* ...###.. */
+ /*099f:*/ 0x3c, /* ..####.. */
+ /*09a0:*/ 0x30, /* ..##.... */
+ /*09a1:*/ 0x30, /* ..##.... */
+ /*09a2:*/ 0x30, /* ..##.... */
+ /*09a3:*/ 0xfc, /* ######.. */
+ /*09a4:*/ 0xfc, /* ######.. */
+ /*09a5:*/ 0x30, /* ..##.... */
+ /*09a6:*/ 0x30, /* ..##.... */
+ /*09a7:*/ 0x30, /* ..##.... */
+ /*09a8:*/ 0x30, /* ..##.... */
+ /*09a9:*/ 0x30, /* ..##.... */
+ /*09aa:*/ 0x30, /* ..##.... */
+ /*09ab:*/ 0x30, /* ..##.... */
+ /*09ac:*/ 0x30, /* ..##.... */
+ /*09ad:*/ 0x30, /* ..##.... */
+ /*09ae:*/ 0x30, /* ..##.... */
+ /*09af:*/ 0x30, /* ..##.... */
+ /*09b0:*/ 0x30, /* ..##.... */
+/* --- new character g (103) starting at offset 0x09b1 --- */
+ /*09b1:*/ 14, 11, 19, 1, -5, /* width and bbox (w,h,x,y) */
+ /*09b6:*/ 0x1e,0x60, /* ...####..##..... */
+ /*09b8:*/ 0x3f,0x60, /* ..######.##..... */
+ /*09ba:*/ 0x71,0xe0, /* .###...####..... */
+ /*09bc:*/ 0x60,0xe0, /* .##.....###..... */
+ /*09be:*/ 0xc0,0x60, /* ##.......##..... */
+ /*09c0:*/ 0xc0,0x60, /* ##.......##..... */
+ /*09c2:*/ 0xc0,0x60, /* ##.......##..... */
+ /*09c4:*/ 0xc0,0x60, /* ##.......##..... */
+ /*09c6:*/ 0xc0,0x60, /* ##.......##..... */
+ /*09c8:*/ 0xc0,0x60, /* ##.......##..... */
+ /*09ca:*/ 0x60,0xe0, /* .##.....###..... */
+ /*09cc:*/ 0x71,0xe0, /* .###...####..... */
+ /*09ce:*/ 0x3f,0x60, /* ..######.##..... */
+ /*09d0:*/ 0x1e,0x60, /* ...####..##..... */
+ /*09d2:*/ 0x00,0x60, /* .........##..... */
+ /*09d4:*/ 0xc0,0x60, /* ##.......##..... */
+ /*09d6:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*09d8:*/ 0x7f,0xc0, /* .#########...... */
+ /*09da:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character h (104) starting at offset 0x09dc --- */
+ /*09dc:*/ 13, 10, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*09e1:*/ 0xc0,0x00, /* ##.............. */
+ /*09e3:*/ 0xc0,0x00, /* ##.............. */
+ /*09e5:*/ 0xc0,0x00, /* ##.............. */
+ /*09e7:*/ 0xc0,0x00, /* ##.............. */
+ /*09e9:*/ 0xc0,0x00, /* ##.............. */
+ /*09eb:*/ 0xce,0x00, /* ##..###......... */
+ /*09ed:*/ 0xdf,0x80, /* ##.######....... */
+ /*09ef:*/ 0xf1,0x80, /* ####...##....... */
+ /*09f1:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*09f3:*/ 0xc0,0xc0, /* ##......##...... */
+ /*09f5:*/ 0xc0,0xc0, /* ##......##...... */
+ /*09f7:*/ 0xc0,0xc0, /* ##......##...... */
+ /*09f9:*/ 0xc0,0xc0, /* ##......##...... */
+ /*09fb:*/ 0xc0,0xc0, /* ##......##...... */
+ /*09fd:*/ 0xc0,0xc0, /* ##......##...... */
+ /*09ff:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0a01:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0a03:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0a05:*/ 0xc0,0xc0, /* ##......##...... */
+/* --- new character i (105) starting at offset 0x0a07 --- */
+ /*0a07:*/ 6, 2, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0a0c:*/ 0xc0, /* ##...... */
+ /*0a0d:*/ 0xc0, /* ##...... */
+ /*0a0e:*/ 0xc0, /* ##...... */
+ /*0a0f:*/ 0x00, /* ........ */
+ /*0a10:*/ 0x00, /* ........ */
+ /*0a11:*/ 0xc0, /* ##...... */
+ /*0a12:*/ 0xc0, /* ##...... */
+ /*0a13:*/ 0xc0, /* ##...... */
+ /*0a14:*/ 0xc0, /* ##...... */
+ /*0a15:*/ 0xc0, /* ##...... */
+ /*0a16:*/ 0xc0, /* ##...... */
+ /*0a17:*/ 0xc0, /* ##...... */
+ /*0a18:*/ 0xc0, /* ##...... */
+ /*0a19:*/ 0xc0, /* ##...... */
+ /*0a1a:*/ 0xc0, /* ##...... */
+ /*0a1b:*/ 0xc0, /* ##...... */
+ /*0a1c:*/ 0xc0, /* ##...... */
+ /*0a1d:*/ 0xc0, /* ##...... */
+ /*0a1e:*/ 0xc0, /* ##...... */
+/* --- new character j (106) starting at offset 0x0a1f --- */
+ /*0a1f:*/ 6, 4, 24, 0, -5, /* width and bbox (w,h,x,y) */
+ /*0a24:*/ 0x30, /* ..##.... */
+ /*0a25:*/ 0x30, /* ..##.... */
+ /*0a26:*/ 0x30, /* ..##.... */
+ /*0a27:*/ 0x00, /* ........ */
+ /*0a28:*/ 0x00, /* ........ */
+ /*0a29:*/ 0x30, /* ..##.... */
+ /*0a2a:*/ 0x30, /* ..##.... */
+ /*0a2b:*/ 0x30, /* ..##.... */
+ /*0a2c:*/ 0x30, /* ..##.... */
+ /*0a2d:*/ 0x30, /* ..##.... */
+ /*0a2e:*/ 0x30, /* ..##.... */
+ /*0a2f:*/ 0x30, /* ..##.... */
+ /*0a30:*/ 0x30, /* ..##.... */
+ /*0a31:*/ 0x30, /* ..##.... */
+ /*0a32:*/ 0x30, /* ..##.... */
+ /*0a33:*/ 0x30, /* ..##.... */
+ /*0a34:*/ 0x30, /* ..##.... */
+ /*0a35:*/ 0x30, /* ..##.... */
+ /*0a36:*/ 0x30, /* ..##.... */
+ /*0a37:*/ 0x30, /* ..##.... */
+ /*0a38:*/ 0x30, /* ..##.... */
+ /*0a39:*/ 0x30, /* ..##.... */
+ /*0a3a:*/ 0xf0, /* ####.... */
+ /*0a3b:*/ 0xe0, /* ###..... */
+/* --- new character k (107) starting at offset 0x0a3c --- */
+ /*0a3c:*/ 12, 10, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0a41:*/ 0xc0,0x00, /* ##.............. */
+ /*0a43:*/ 0xc0,0x00, /* ##.............. */
+ /*0a45:*/ 0xc0,0x00, /* ##.............. */
+ /*0a47:*/ 0xc0,0x00, /* ##.............. */
+ /*0a49:*/ 0xc0,0x00, /* ##.............. */
+ /*0a4b:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0a4d:*/ 0xc3,0x80, /* ##....###....... */
+ /*0a4f:*/ 0xc7,0x00, /* ##...###........ */
+ /*0a51:*/ 0xce,0x00, /* ##..###......... */
+ /*0a53:*/ 0xdc,0x00, /* ##.###.......... */
+ /*0a55:*/ 0xf8,0x00, /* #####........... */
+ /*0a57:*/ 0xfc,0x00, /* ######.......... */
+ /*0a59:*/ 0xce,0x00, /* ##..###......... */
+ /*0a5b:*/ 0xc6,0x00, /* ##...##......... */
+ /*0a5d:*/ 0xc7,0x00, /* ##...###........ */
+ /*0a5f:*/ 0xc3,0x80, /* ##....###....... */
+ /*0a61:*/ 0xc1,0x80, /* ##.....##....... */
+ /*0a63:*/ 0xc1,0xc0, /* ##.....###...... */
+ /*0a65:*/ 0xc0,0xc0, /* ##......##...... */
+/* --- new character l (108) starting at offset 0x0a67 --- */
+ /*0a67:*/ 6, 2, 19, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0a6c:*/ 0xc0, /* ##...... */
+ /*0a6d:*/ 0xc0, /* ##...... */
+ /*0a6e:*/ 0xc0, /* ##...... */
+ /*0a6f:*/ 0xc0, /* ##...... */
+ /*0a70:*/ 0xc0, /* ##...... */
+ /*0a71:*/ 0xc0, /* ##...... */
+ /*0a72:*/ 0xc0, /* ##...... */
+ /*0a73:*/ 0xc0, /* ##...... */
+ /*0a74:*/ 0xc0, /* ##...... */
+ /*0a75:*/ 0xc0, /* ##...... */
+ /*0a76:*/ 0xc0, /* ##...... */
+ /*0a77:*/ 0xc0, /* ##...... */
+ /*0a78:*/ 0xc0, /* ##...... */
+ /*0a79:*/ 0xc0, /* ##...... */
+ /*0a7a:*/ 0xc0, /* ##...... */
+ /*0a7b:*/ 0xc0, /* ##...... */
+ /*0a7c:*/ 0xc0, /* ##...... */
+ /*0a7d:*/ 0xc0, /* ##...... */
+ /*0a7e:*/ 0xc0, /* ##...... */
+/* --- new character m (109) starting at offset 0x0a7f --- */
+ /*0a7f:*/ 20, 16, 14, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0a84:*/ 0xce,0x3c, /* ##..###...####.. */
+ /*0a86:*/ 0xff,0x7e, /* ########.######. */
+ /*0a88:*/ 0xe3,0xc7, /* ###...####...### */
+ /*0a8a:*/ 0xc1,0x83, /* ##.....##.....## */
+ /*0a8c:*/ 0xc1,0x83, /* ##.....##.....## */
+ /*0a8e:*/ 0xc1,0x83, /* ##.....##.....## */
+ /*0a90:*/ 0xc1,0x83, /* ##.....##.....## */
+ /*0a92:*/ 0xc1,0x83, /* ##.....##.....## */
+ /*0a94:*/ 0xc1,0x83, /* ##.....##.....## */
+ /*0a96:*/ 0xc1,0x83, /* ##.....##.....## */
+ /*0a98:*/ 0xc1,0x83, /* ##.....##.....## */
+ /*0a9a:*/ 0xc1,0x83, /* ##.....##.....## */
+ /*0a9c:*/ 0xc1,0x83, /* ##.....##.....## */
+ /*0a9e:*/ 0xc1,0x83, /* ##.....##.....## */
+/* --- new character n (110) starting at offset 0x0aa0 --- */
+ /*0aa0:*/ 14, 10, 14, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0aa5:*/ 0xce,0x00, /* ##..###......... */
+ /*0aa7:*/ 0xdf,0x80, /* ##.######....... */
+ /*0aa9:*/ 0xf1,0x80, /* ####...##....... */
+ /*0aab:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*0aad:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0aaf:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0ab1:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0ab3:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0ab5:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0ab7:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0ab9:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0abb:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0abd:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0abf:*/ 0xc0,0xc0, /* ##......##...... */
+/* --- new character o (111) starting at offset 0x0ac1 --- */
+ /*0ac1:*/ 13, 11, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0ac6:*/ 0x1f,0x00, /* ...#####........ */
+ /*0ac8:*/ 0x3f,0x80, /* ..#######....... */
+ /*0aca:*/ 0x71,0xc0, /* .###...###...... */
+ /*0acc:*/ 0x60,0xc0, /* .##.....##...... */
+ /*0ace:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0ad0:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0ad2:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0ad4:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0ad6:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0ad8:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0ada:*/ 0x60,0xc0, /* .##.....##...... */
+ /*0adc:*/ 0x71,0xc0, /* .###...###...... */
+ /*0ade:*/ 0x3f,0x80, /* ..#######....... */
+ /*0ae0:*/ 0x1f,0x00, /* ...#####........ */
+/* --- new character p (112) starting at offset 0x0ae2 --- */
+ /*0ae2:*/ 14, 11, 19, 2, -5, /* width and bbox (w,h,x,y) */
+ /*0ae7:*/ 0xcf,0x00, /* ##..####........ */
+ /*0ae9:*/ 0xdf,0x80, /* ##.######....... */
+ /*0aeb:*/ 0xf1,0xc0, /* ####...###...... */
+ /*0aed:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*0aef:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0af1:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0af3:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0af5:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0af7:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0af9:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0afb:*/ 0xe0,0xc0, /* ###.....##...... */
+ /*0afd:*/ 0xf1,0xc0, /* ####...###...... */
+ /*0aff:*/ 0xdf,0x80, /* ##.######....... */
+ /*0b01:*/ 0xcf,0x00, /* ##..####........ */
+ /*0b03:*/ 0xc0,0x00, /* ##.............. */
+ /*0b05:*/ 0xc0,0x00, /* ##.............. */
+ /*0b07:*/ 0xc0,0x00, /* ##.............. */
+ /*0b09:*/ 0xc0,0x00, /* ##.............. */
+ /*0b0b:*/ 0xc0,0x00, /* ##.............. */
+/* --- new character q (113) starting at offset 0x0b0d --- */
+ /*0b0d:*/ 14, 11, 19, 1, -5, /* width and bbox (w,h,x,y) */
+ /*0b12:*/ 0x1e,0x60, /* ...####..##..... */
+ /*0b14:*/ 0x3f,0x60, /* ..######.##..... */
+ /*0b16:*/ 0x71,0xe0, /* .###...####..... */
+ /*0b18:*/ 0x60,0xe0, /* .##.....###..... */
+ /*0b1a:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0b1c:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0b1e:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0b20:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0b22:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0b24:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0b26:*/ 0x60,0xe0, /* .##.....###..... */
+ /*0b28:*/ 0x71,0xe0, /* .###...####..... */
+ /*0b2a:*/ 0x3f,0x60, /* ..######.##..... */
+ /*0b2c:*/ 0x1e,0x60, /* ...####..##..... */
+ /*0b2e:*/ 0x00,0x60, /* .........##..... */
+ /*0b30:*/ 0x00,0x60, /* .........##..... */
+ /*0b32:*/ 0x00,0x60, /* .........##..... */
+ /*0b34:*/ 0x00,0x60, /* .........##..... */
+ /*0b36:*/ 0x00,0x60, /* .........##..... */
+/* --- new character r (114) starting at offset 0x0b38 --- */
+ /*0b38:*/ 9, 6, 14, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0b3d:*/ 0xcc, /* ##..##.. */
+ /*0b3e:*/ 0xdc, /* ##.###.. */
+ /*0b3f:*/ 0xfc, /* ######.. */
+ /*0b40:*/ 0xe0, /* ###..... */
+ /*0b41:*/ 0xc0, /* ##...... */
+ /*0b42:*/ 0xc0, /* ##...... */
+ /*0b43:*/ 0xc0, /* ##...... */
+ /*0b44:*/ 0xc0, /* ##...... */
+ /*0b45:*/ 0xc0, /* ##...... */
+ /*0b46:*/ 0xc0, /* ##...... */
+ /*0b47:*/ 0xc0, /* ##...... */
+ /*0b48:*/ 0xc0, /* ##...... */
+ /*0b49:*/ 0xc0, /* ##...... */
+ /*0b4a:*/ 0xc0, /* ##...... */
+/* --- new character s (115) starting at offset 0x0b4b --- */
+ /*0b4b:*/ 12, 10, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0b50:*/ 0x3e,0x00, /* ..#####......... */
+ /*0b52:*/ 0x7f,0x80, /* .########....... */
+ /*0b54:*/ 0xe1,0xc0, /* ###....###...... */
+ /*0b56:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b58:*/ 0xc0,0x00, /* ##.............. */
+ /*0b5a:*/ 0xf8,0x00, /* #####........... */
+ /*0b5c:*/ 0x7f,0x00, /* .#######........ */
+ /*0b5e:*/ 0x0f,0x80, /* ....#####....... */
+ /*0b60:*/ 0x01,0xc0, /* .......###...... */
+ /*0b62:*/ 0x00,0xc0, /* ........##...... */
+ /*0b64:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b66:*/ 0xc1,0xc0, /* ##.....###...... */
+ /*0b68:*/ 0xff,0x80, /* #########....... */
+ /*0b6a:*/ 0x3f,0x00, /* ..######........ */
+/* --- new character t (116) starting at offset 0x0b6c --- */
+ /*0b6c:*/ 8, 6, 18, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0b71:*/ 0x30, /* ..##.... */
+ /*0b72:*/ 0x30, /* ..##.... */
+ /*0b73:*/ 0x30, /* ..##.... */
+ /*0b74:*/ 0x30, /* ..##.... */
+ /*0b75:*/ 0xfc, /* ######.. */
+ /*0b76:*/ 0xfc, /* ######.. */
+ /*0b77:*/ 0x30, /* ..##.... */
+ /*0b78:*/ 0x30, /* ..##.... */
+ /*0b79:*/ 0x30, /* ..##.... */
+ /*0b7a:*/ 0x30, /* ..##.... */
+ /*0b7b:*/ 0x30, /* ..##.... */
+ /*0b7c:*/ 0x30, /* ..##.... */
+ /*0b7d:*/ 0x30, /* ..##.... */
+ /*0b7e:*/ 0x30, /* ..##.... */
+ /*0b7f:*/ 0x30, /* ..##.... */
+ /*0b80:*/ 0x30, /* ..##.... */
+ /*0b81:*/ 0x3c, /* ..####.. */
+ /*0b82:*/ 0x1c, /* ...###.. */
+/* --- new character u (117) starting at offset 0x0b83 --- */
+ /*0b83:*/ 14, 10, 14, 2, 0, /* width and bbox (w,h,x,y) */
+ /*0b88:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b8a:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b8c:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b8e:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b90:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b92:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b94:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b96:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b98:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b9a:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0b9c:*/ 0xc1,0xc0, /* ##.....###...... */
+ /*0b9e:*/ 0x63,0xc0, /* .##...####...... */
+ /*0ba0:*/ 0x7e,0xc0, /* .######.##...... */
+ /*0ba2:*/ 0x1c,0xc0, /* ...###..##...... */
+/* --- new character v (118) starting at offset 0x0ba4 --- */
+ /*0ba4:*/ 13, 11, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0ba9:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0bab:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0bad:*/ 0xc0,0x60, /* ##.......##..... */
+ /*0baf:*/ 0x60,0xc0, /* .##.....##...... */
+ /*0bb1:*/ 0x60,0xc0, /* .##.....##...... */
+ /*0bb3:*/ 0x71,0xc0, /* .###...###...... */
+ /*0bb5:*/ 0x31,0x80, /* ..##...##....... */
+ /*0bb7:*/ 0x31,0x80, /* ..##...##....... */
+ /*0bb9:*/ 0x1b,0x00, /* ...##.##........ */
+ /*0bbb:*/ 0x1b,0x00, /* ...##.##........ */
+ /*0bbd:*/ 0x1b,0x00, /* ...##.##........ */
+ /*0bbf:*/ 0x0e,0x00, /* ....###......... */
+ /*0bc1:*/ 0x0e,0x00, /* ....###......... */
+ /*0bc3:*/ 0x0e,0x00, /* ....###......... */
+/* --- new character w (119) starting at offset 0x0bc5 --- */
+ /*0bc5:*/ 18, 18, 14, 0, 0, /* width and bbox (w,h,x,y) */
+ /*0bca:*/ 0xc0,0xc0,0xc0, /* ##......##......##...... */
+ /*0bcd:*/ 0xc0,0xc0,0xc0, /* ##......##......##...... */
+ /*0bd0:*/ 0x61,0xe1,0x80, /* .##....####....##....... */
+ /*0bd3:*/ 0x61,0xe1,0x80, /* .##....####....##....... */
+ /*0bd6:*/ 0x61,0xe1,0x80, /* .##....####....##....... */
+ /*0bd9:*/ 0x31,0x23,0x00, /* ..##...#..#...##........ */
+ /*0bdc:*/ 0x33,0x33,0x00, /* ..##..##..##..##........ */
+ /*0bdf:*/ 0x33,0x33,0x00, /* ..##..##..##..##........ */
+ /*0be2:*/ 0x1b,0x36,0x00, /* ...##.##..##.##......... */
+ /*0be5:*/ 0x1a,0x16,0x00, /* ...##.#....#.##......... */
+ /*0be8:*/ 0x1e,0x1e,0x00, /* ...####....####......... */
+ /*0beb:*/ 0x0e,0x1c,0x00, /* ....###....###.......... */
+ /*0bee:*/ 0x0c,0x0c,0x00, /* ....##......##.......... */
+ /*0bf1:*/ 0x0c,0x0c,0x00, /* ....##......##.......... */
+/* --- new character x (120) starting at offset 0x0bf4 --- */
+ /*0bf4:*/ 12, 10, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0bf9:*/ 0xc0,0xc0, /* ##......##...... */
+ /*0bfb:*/ 0xe1,0xc0, /* ###....###...... */
+ /*0bfd:*/ 0x61,0x80, /* .##....##....... */
+ /*0bff:*/ 0x33,0x00, /* ..##..##........ */
+ /*0c01:*/ 0x3f,0x00, /* ..######........ */
+ /*0c03:*/ 0x1e,0x00, /* ...####......... */
+ /*0c05:*/ 0x0c,0x00, /* ....##.......... */
+ /*0c07:*/ 0x1e,0x00, /* ...####......... */
+ /*0c09:*/ 0x1e,0x00, /* ...####......... */
+ /*0c0b:*/ 0x33,0x00, /* ..##..##........ */
+ /*0c0d:*/ 0x73,0x80, /* .###..###....... */
+ /*0c0f:*/ 0x61,0x80, /* .##....##....... */
+ /*0c11:*/ 0xe1,0xc0, /* ###....###...... */
+ /*0c13:*/ 0xc0,0xc0, /* ##......##...... */
+/* --- new character y (121) starting at offset 0x0c15 --- */
+ /*0c15:*/ 13, 12, 19, 0, -5, /* width and bbox (w,h,x,y) */
+ /*0c1a:*/ 0xc0,0x30, /* ##........##.... */
+ /*0c1c:*/ 0xc0,0x30, /* ##........##.... */
+ /*0c1e:*/ 0x60,0x30, /* .##.......##.... */
+ /*0c20:*/ 0x70,0x60, /* .###.....##..... */
+ /*0c22:*/ 0x30,0x60, /* ..##.....##..... */
+ /*0c24:*/ 0x38,0xe0, /* ..###...###..... */
+ /*0c26:*/ 0x18,0xc0, /* ...##...##...... */
+ /*0c28:*/ 0x18,0xc0, /* ...##...##...... */
+ /*0c2a:*/ 0x0d,0x80, /* ....##.##....... */
+ /*0c2c:*/ 0x0d,0x80, /* ....##.##....... */
+ /*0c2e:*/ 0x07,0x80, /* .....####....... */
+ /*0c30:*/ 0x07,0x00, /* .....###........ */
+ /*0c32:*/ 0x03,0x00, /* ......##........ */
+ /*0c34:*/ 0x03,0x00, /* ......##........ */
+ /*0c36:*/ 0x06,0x00, /* .....##......... */
+ /*0c38:*/ 0x06,0x00, /* .....##......... */
+ /*0c3a:*/ 0x0c,0x00, /* ....##.......... */
+ /*0c3c:*/ 0x3c,0x00, /* ..####.......... */
+ /*0c3e:*/ 0x38,0x00, /* ..###........... */
+/* --- new character z (122) starting at offset 0x0c40 --- */
+ /*0c40:*/ 12, 10, 14, 1, 0, /* width and bbox (w,h,x,y) */
+ /*0c45:*/ 0xff,0xc0, /* ##########...... */
+ /*0c47:*/ 0xff,0xc0, /* ##########...... */
+ /*0c49:*/ 0x01,0x80, /* .......##....... */
+ /*0c4b:*/ 0x03,0x00, /* ......##........ */
+ /*0c4d:*/ 0x07,0x00, /* .....###........ */
+ /*0c4f:*/ 0x0e,0x00, /* ....###......... */
+ /*0c51:*/ 0x0c,0x00, /* ....##.......... */
+ /*0c53:*/ 0x1c,0x00, /* ...###.......... */
+ /*0c55:*/ 0x38,0x00, /* ..###........... */
+ /*0c57:*/ 0x30,0x00, /* ..##............ */
+ /*0c59:*/ 0x60,0x00, /* .##............. */
+ /*0c5b:*/ 0xe0,0x00, /* ###............. */
+ /*0c5d:*/ 0xff,0xc0, /* ##########...... */
+ /*0c5f:*/ 0xff,0xc0, /* ##########...... */
+/* --- new character braceleft (123) starting at offset 0x0c61 --- */
+ /*0c61:*/ 8, 6, 24, 1, -5, /* width and bbox (w,h,x,y) */
+ /*0c66:*/ 0x0c, /* ....##.. */
+ /*0c67:*/ 0x18, /* ...##... */
+ /*0c68:*/ 0x30, /* ..##.... */
+ /*0c69:*/ 0x30, /* ..##.... */
+ /*0c6a:*/ 0x30, /* ..##.... */
+ /*0c6b:*/ 0x30, /* ..##.... */
+ /*0c6c:*/ 0x30, /* ..##.... */
+ /*0c6d:*/ 0x30, /* ..##.... */
+ /*0c6e:*/ 0x30, /* ..##.... */
+ /*0c6f:*/ 0x30, /* ..##.... */
+ /*0c70:*/ 0x60, /* .##..... */
+ /*0c71:*/ 0xc0, /* ##...... */
+ /*0c72:*/ 0xc0, /* ##...... */
+ /*0c73:*/ 0x60, /* .##..... */
+ /*0c74:*/ 0x30, /* ..##.... */
+ /*0c75:*/ 0x30, /* ..##.... */
+ /*0c76:*/ 0x30, /* ..##.... */
+ /*0c77:*/ 0x30, /* ..##.... */
+ /*0c78:*/ 0x30, /* ..##.... */
+ /*0c79:*/ 0x30, /* ..##.... */
+ /*0c7a:*/ 0x30, /* ..##.... */
+ /*0c7b:*/ 0x30, /* ..##.... */
+ /*0c7c:*/ 0x18, /* ...##... */
+ /*0c7d:*/ 0x0c, /* ....##.. */
+/* --- new character bar (124) starting at offset 0x0c7e --- */
+ /*0c7e:*/ 6, 2, 24, 2, -5, /* width and bbox (w,h,x,y) */
+ /*0c83:*/ 0xc0, /* ##...... */
+ /*0c84:*/ 0xc0, /* ##...... */
+ /*0c85:*/ 0xc0, /* ##...... */
+ /*0c86:*/ 0xc0, /* ##...... */
+ /*0c87:*/ 0xc0, /* ##...... */
+ /*0c88:*/ 0xc0, /* ##...... */
+ /*0c89:*/ 0xc0, /* ##...... */
+ /*0c8a:*/ 0xc0, /* ##...... */
+ /*0c8b:*/ 0xc0, /* ##...... */
+ /*0c8c:*/ 0xc0, /* ##...... */
+ /*0c8d:*/ 0xc0, /* ##...... */
+ /*0c8e:*/ 0xc0, /* ##...... */
+ /*0c8f:*/ 0xc0, /* ##...... */
+ /*0c90:*/ 0xc0, /* ##...... */
+ /*0c91:*/ 0xc0, /* ##...... */
+ /*0c92:*/ 0xc0, /* ##...... */
+ /*0c93:*/ 0xc0, /* ##...... */
+ /*0c94:*/ 0xc0, /* ##...... */
+ /*0c95:*/ 0xc0, /* ##...... */
+ /*0c96:*/ 0xc0, /* ##...... */
+ /*0c97:*/ 0xc0, /* ##...... */
+ /*0c98:*/ 0xc0, /* ##...... */
+ /*0c99:*/ 0xc0, /* ##...... */
+ /*0c9a:*/ 0xc0, /* ##...... */
+/* --- new character braceright (125) starting at offset 0x0c9b --- */
+ /*0c9b:*/ 8, 6, 24, 1, -5, /* width and bbox (w,h,x,y) */
+ /*0ca0:*/ 0xc0, /* ##...... */
+ /*0ca1:*/ 0x60, /* .##..... */
+ /*0ca2:*/ 0x30, /* ..##.... */
+ /*0ca3:*/ 0x30, /* ..##.... */
+ /*0ca4:*/ 0x30, /* ..##.... */
+ /*0ca5:*/ 0x30, /* ..##.... */
+ /*0ca6:*/ 0x30, /* ..##.... */
+ /*0ca7:*/ 0x30, /* ..##.... */
+ /*0ca8:*/ 0x30, /* ..##.... */
+ /*0ca9:*/ 0x30, /* ..##.... */
+ /*0caa:*/ 0x18, /* ...##... */
+ /*0cab:*/ 0x0c, /* ....##.. */
+ /*0cac:*/ 0x0c, /* ....##.. */
+ /*0cad:*/ 0x18, /* ...##... */
+ /*0cae:*/ 0x30, /* ..##.... */
+ /*0caf:*/ 0x30, /* ..##.... */
+ /*0cb0:*/ 0x30, /* ..##.... */
+ /*0cb1:*/ 0x30, /* ..##.... */
+ /*0cb2:*/ 0x30, /* ..##.... */
+ /*0cb3:*/ 0x30, /* ..##.... */
+ /*0cb4:*/ 0x30, /* ..##.... */
+ /*0cb5:*/ 0x30, /* ..##.... */
+ /*0cb6:*/ 0x60, /* .##..... */
+ /*0cb7:*/ 0xc0, /* ##...... */
+/* --- new character asciitilde (126) starting at offset 0x0cb8 --- */
+ /*0cb8:*/ 14, 10, 4, 2, 5, /* width and bbox (w,h,x,y) */
+ /*0cbd:*/ 0x70,0xc0, /* .###....##...... */
+ /*0cbf:*/ 0xfc,0xc0, /* ######..##...... */
+ /*0cc1:*/ 0xcf,0xc0, /* ##..######...... */
+ /*0cc3:*/ 0xc3,0x80, /* ##....###....... */
+};
+static const uint16_t font_helvR24_offsets[] = {
+0x0000 /* space */,
+ 0x0006 /* exclam */,
+ 0x001e /* quotedbl */,
+ 0x0029 /* numbersign */,
+ 0x0050 /* dollar */,
+ 0x007f /* percent */,
+ 0x00ba /* ampersand */,
+ 0x00e3 /* quotesingle */,
+ 0x00ee /* parenleft */,
+ 0x010b /* parenright */,
+ 0x0128 /* asterisk */,
+ 0x0134 /* plus */,
+ 0x0151 /* comma */,
+ 0x015c /* hyphen */,
+ 0x0163 /* period */,
+ 0x016b /* slash */,
+ 0x0183 /* zero */,
+ 0x01ac /* one */,
+ 0x01c3 /* two */,
+ 0x01ec /* three */,
+ 0x0215 /* four */,
+ 0x023e /* five */,
+ 0x0267 /* six */,
+ 0x0290 /* seven */,
+ 0x02b9 /* eight */,
+ 0x02e2 /* nine */,
+ 0x030b /* colon */,
+ 0x031e /* semicolon */,
+ 0x0334 /* less */,
+ 0x0351 /* equal */,
+ 0x0362 /* greater */,
+ 0x037f /* question */,
+ 0x03aa /* at */,
+ 0x03f4 /* A */,
+ 0x041f /* B */,
+ 0x044a /* C */,
+ 0x0475 /* D */,
+ 0x04a0 /* E */,
+ 0x04cb /* F */,
+ 0x04f6 /* G */,
+ 0x0521 /* H */,
+ 0x054c /* I */,
+ 0x0564 /* J */,
+ 0x058f /* K */,
+ 0x05ba /* L */,
+ 0x05e5 /* M */,
+ 0x0623 /* N */,
+ 0x064e /* O */,
+ 0x0679 /* P */,
+ 0x06a4 /* Q */,
+ 0x06cf /* R */,
+ 0x06fa /* S */,
+ 0x0725 /* T */,
+ 0x0750 /* U */,
+ 0x077b /* V */,
+ 0x07a6 /* W */,
+ 0x07e4 /* X */,
+ 0x080f /* Y */,
+ 0x083a /* Z */,
+ 0x0865 /* bracketleft */,
+ 0x0882 /* backslash */,
+ 0x089a /* bracketright */,
+ 0x08b7 /* asciicircum */,
+ 0x08ce /* underscore */,
+ 0x08d7 /* grave */,
+ 0x08e0 /* a */,
+ 0x0901 /* b */,
+ 0x092c /* c */,
+ 0x094d /* d */,
+ 0x0978 /* e */,
+ 0x0999 /* f */,
+ 0x09b1 /* g */,
+ 0x09dc /* h */,
+ 0x0a07 /* i */,
+ 0x0a1f /* j */,
+ 0x0a3c /* k */,
+ 0x0a67 /* l */,
+ 0x0a7f /* m */,
+ 0x0aa0 /* n */,
+ 0x0ac1 /* o */,
+ 0x0ae2 /* p */,
+ 0x0b0d /* q */,
+ 0x0b38 /* r */,
+ 0x0b4b /* s */,
+ 0x0b6c /* t */,
+ 0x0b83 /* u */,
+ 0x0ba4 /* v */,
+ 0x0bc5 /* w */,
+ 0x0bf4 /* x */,
+ 0x0c15 /* y */,
+ 0x0c40 /* z */,
+ 0x0c61 /* braceleft */,
+ 0x0c7e /* bar */,
+ 0x0c9b /* braceright */,
+ 0x0cb8 /* asciitilde */,
+ 0xffff /* (no glyph) */
+};
+const struct fb_font font_helvR24 = {
+ .height = 27,
+ .ascent = 22,
+ .firstchar = 32, /* space */
+ .lastchar = 127, /* ? */
+ .chardata = font_helvR24_data,
+ .charoffs = font_helvR24_offsets,
+};
diff --git a/Src/osmolib/src/target/firmware/include/calypso/sim.h b/Src/osmolib/src/target/firmware/include/calypso/sim.h
index b2a2164..5e33bdb 100644..100755
--- a/Src/osmolib/src/target/firmware/include/calypso/sim.h
+++ b/Src/osmolib/src/target/firmware/include/calypso/sim.h
@@ -147,8 +147,6 @@
/* 1 = SIM card insertion/extraction */
-#define SIM_DEBUG_OUTPUTDELAY 200 /* Output delay to minimize stress with some uart bugs */
-#define SIM_DEBUG 0 /* 0=Debug messages are off / 1=Debug messages are on */
#define SIM_OPERATION_DELAY 100 /* Time between operations like reset, vcc apply ect... */
@@ -164,24 +162,14 @@ void calypso_sim_powerdown(void); /* Powerdown simcard */
#define SIM_APDU_PUT 0 /* Transmit a data body to the card */
#define SIM_APDU_GET 1 /* Fetch data from the card eg. GET RESOPNSE */
-/* Transceive T0 Apdu to sim acording to GSM 11.11 Page 34 */
-int calypso_sim_transceive(uint8_t cla, /* Class (in GSM context mostly 0xA0 */
- uint8_t ins, /* Instruction */
- uint8_t p1, /* First parameter */
- uint8_t p2, /* Second parameter */
- uint8_t p3le, /* Length of the data that should be transceived */
- uint8_t *data, /* Data payload */
- uint8_t *status, /* Status word (2 byte array, see note 1) */
- uint8_t mode); /* Mode of operation: 1=GET, 0=PUT */
- /* Note 1: You can use a null-pointer (0) if you are not interested in
- the status word */
+void calypso_sim_init(void); /* Initialize simcard interface */
-/* Transmission of raw data */
-int calypso_sim_receive(uint8_t *data); /* Receive raw data through the sim interface */
-int calypso_sim_transmit(uint8_t *data, int length); /* Transmit raw data through the sim interface */
+/* handling sim events */
+void sim_handler(void);
-void calypso_sim_init(void); /* Initialize simcard interface */
+/* simm command from layer 23 */
+void sim_apdu(uint16_t len, uint8_t *data);
/* Known Bugs:
diff --git a/Src/osmolib/src/target/firmware/include/comm/timer.h b/Src/osmolib/src/target/firmware/include/comm/timer.h
index db7d1a5..1996f66 100644
--- a/Src/osmolib/src/target/firmware/include/comm/timer.h
+++ b/Src/osmolib/src/target/firmware/include/comm/timer.h
@@ -25,19 +25,21 @@
#include <osmocom/core/linuxlist.h>
+#define HZ 100
+
/**
* Timer management:
* - Create a struct osmo_timer_list
- * - Fill out timeout and use add_timer or
- * use schedule_timer to schedule a timer in
+ * - Fill out timeout and use osmo_timer_add or
+ * use osmo_timer_schedule to schedule a timer in
* x seconds and microseconds from now...
- * - Use del_timer to remove the timer
+ * - Use osmo_timer_del to remove the timer
*
* Internally:
* - We hook into select.c to give a timeval of the
* nearest timer. On already passed timers we give
* it a 0 to immediately fire after the select
- * - update_timers will call the callbacks and remove
+ * - osmo_timers_update will call the callbacks and remove
* the timers.
*
*/
@@ -58,18 +60,17 @@ extern unsigned long volatile jiffies;
/**
* timer management
*/
-void add_timer(struct osmo_timer_list *timer);
-void schedule_timer(struct osmo_timer_list *timer, int miliseconds);
-void del_timer(struct osmo_timer_list *timer);
-int timer_pending(struct osmo_timer_list *timer);
+void osmo_timer_add(struct osmo_timer_list *timer);
+void osmo_timer_schedule(struct osmo_timer_list *timer, int miliseconds);
+void osmo_timer_del(struct osmo_timer_list *timer);
+int osmo_timer_pending(struct osmo_timer_list *timer);
/**
* internal timer list management
*/
-void prepare_timers(void);
-int update_timers(void);
-int timer_check(void);
+int osmo_timers_update(void);
+int osmo_timers_check(void);
void timer_init(void);
diff --git a/Src/osmolib/src/target/firmware/include/fb/fb_bw8.h b/Src/osmolib/src/target/firmware/include/fb/fb_bw8.h
new file mode 100644
index 0000000..c77fa71
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/include/fb/fb_bw8.h
@@ -0,0 +1,51 @@
+#ifndef FB_BW8_H
+#define FB_BW8_H
+
+/* 8bit monochrome framebuffer, organized with 8 stacked pixels
+ per byte, backed by local memory. fb_bw8.c lists functions that
+ are common to simmilar organized displays. */
+
+/*
+ Sketch of Memory Layout
+ Left Upper Corner of Display
+
+ col0 col2
+ col1
+ +-------------
+ 1st row: | A0 B0 C0
+ 2nd row: | A1 B1 C1
+ ...
+ 7th row: | A6 B6 C6
+ 8th row: | A7 B7 C7
+ 9th row: | Q0 R0 S0
+ 10th row: | Q1 R1 S1 ...
+ ...
+
+ Backing store (and internal display memory?) looks like...
+
+ uint8_t mem[] = { A, B, C, .... Q, R, S, ... }
+
+ We work on a in-memory copy of the framebuffer and only
+ update the physical display on demand. The damage window
+ has two corners, left upper inclusive x1,y1 and right
+ lower x2,y2 exclusive. So dirty pixels are defined to
+ be x1 <= x_pixel < x2 and y1 <= y_pixel < y2.
+*/
+
+/* data specific to a bw8-type framebuffer as described above */
+
+struct fb_bw8 {
+ uint8_t *mem; /* set to backingstore memory */
+ uint16_t damage_x1,damage_y1; /* current damage window, ul */
+ uint16_t damage_x2,damage_y2; /* current damage window, lr */
+};
+
+extern struct fb_bw8 *fb_bw8; /* symbol defined by the specific LCD driver */
+
+extern void fb_bw8_clear();
+extern void fb_bw8_boxto(uint16_t x,uint16_t y); /* draw a box from cursor to x,y */
+extern void fb_bw8_lineto(uint16_t x,uint16_t y); /* draw a line from cursor to x,y */
+
+extern int fb_bw8_putstr(char *str,int maxwidth);
+
+#endif
diff --git a/Src/osmolib/src/target/firmware/include/fb/fb_rgb332.h b/Src/osmolib/src/target/firmware/include/fb/fb_rgb332.h
new file mode 100644
index 0000000..4df44e4
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/include/fb/fb_rgb332.h
@@ -0,0 +1,47 @@
+#ifndef FB_RGB332_H
+#define FB_RGB332_H
+
+/* RGB framebuffer with 1 byte per pixel, bits mapped as RRRGGGBB */
+
+struct fb_rgb332 {
+ uint8_t *mem; /* set to backingstore memory */
+ uint16_t damage_x1,damage_y1; /* current damage window, ul (incl) */
+ uint16_t damage_x2,damage_y2; /* current damage window, lr (excl) */
+};
+
+extern void fb_rgb332_clear();
+
+/* draw a box from cursor to x,y */
+extern void fb_rgb332_boxto(uint16_t x,uint16_t y);
+/* draw a line from cursor to x,y */
+extern void fb_rgb332_lineto(uint16_t x,uint16_t y);
+
+/* put string str onto framebuffer with line (bottom
+ left pixel of, e.g. "m") starting at cursor.
+ Maximum width consumed is maxwidth, actual width
+ needed is returned */
+extern int fb_rgb332_putstr(char *str,int maxwidth);
+
+extern struct fb_rgb332 *fb_rgb332;
+
+/* this convenience function can be used if you choose to
+ * back a RGB565 display with a RGB332 framebuffer to conserve
+ * ARM memory. It converts a rgb332 value to rgb565 as indicated
+ * in the comments. */
+
+static inline uint16_t
+rgb332_to_565(uint8_t rgb332){
+
+ uint8_t red = (rgb332 & 0xe0) >> 5 ; // rrr. .... -> .... .rrr
+ uint8_t green = ((rgb332 & 0x1c) >> 2); // ...g gg.. -> .... .ggg
+ uint8_t blue = rgb332 & 0x03; // .... ..bb -> .... ..bb
+
+ red = (red << 2) | (red >> 1); /* .....210 -> ...21021 */
+ green = (green << 3) | (green); /* .....210 -> ..210210 */
+ blue = (blue << 3) | (blue << 1) | (blue >> 1); /* ......10 -> ...10101 */
+
+ /* rrrrrggg gggbbbbb */
+ return (red << 11) | (green << 5) | blue;
+}
+
+#endif
diff --git a/Src/osmolib/src/target/firmware/include/fb/font.h b/Src/osmolib/src/target/firmware/include/fb/font.h
new file mode 100644
index 0000000..40a6974
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/include/fb/font.h
@@ -0,0 +1,81 @@
+#ifndef _FB_FONT_H
+#define _FB_FONT_H
+
+#include <stdint.h>
+#include <unistd.h>
+
+/*
+ Example:
+ Font Helvetica 14
+
+
+ Character W ('X' and '.' is the character font data)
+
+ X.....X......&...
+ X.....X......X...
+ X....X.X.....X...
+ .X...X.X....X....
+ .X...X.X....X....
+ .X...X.X....X....
+ ..X.X....X.X.....
+ ..X.X....X.X.....
+ ..X.X....X.X.....
+ ...X......X......
+ @%..X......X...$..
+ <---dwidth---->
+
+ @ is the cursor position (origin) for this character
+ $ is the cursor position (origin) for the next character
+ % is the character boundingbox origin,
+ & is the character boundingbox top right corner
+
+ */
+
+/* data for char c is found by getting the index into the
+ chardata array from the charoffs array.
+
+ if charoffs[c] == FB_FONT_NOCHAR, then this glyph does
+ not exist! Better use the convenience function fb_font_get_char below! */
+
+#define FB_FONT_NOCHAR 0xffff
+
+struct fb_font {
+ int8_t height; /* total height of font */
+ int8_t ascent; /* topmost pixel is "ascend" above
+ current cursor position y */
+ uint8_t firstchar,lastchar; /* range of characters in font (iso8859-1) */
+ uint8_t const *chardata;
+ uint16_t const *charoffs; /* byte offsets relative to chardata */
+ uint8_t const *widths; /* widths for characters */
+};
+
+struct fb_char {
+ int8_t width;
+ int8_t bbox_w,bbox_h,bbox_x,bbox_y;
+ uint8_t data[0];
+};
+
+/* there are currently 6 fonts available, Helvetica 8, 14, 24 point
+ in bold and regular shapes. The following enum has to match the
+ order of the array fb_fonts in framebuffer.c!
+*/
+
+enum fb_font_id {
+// FB_FONT_4X6,
+// FB_FONT_5X8,
+ FB_FONT_HELVR08,
+// FB_FONT_HELVR14
+// FB_FONT_HELVR24,
+// FB_FONT_HELVB08,
+ FB_FONT_HELVB14,
+// FB_FONT_HELVB24,
+ FB_FONT_C64,
+};
+
+extern const struct fb_font *fb_fonts[]; // note: has to match fb_font_id enum!
+
+extern const struct fb_char *
+fb_font_get_char(const struct fb_font *fnt,unsigned char c);
+
+#endif
+
diff --git a/Src/osmolib/src/target/firmware/include/fb/framebuffer.h b/Src/osmolib/src/target/firmware/include/fb/framebuffer.h
new file mode 100644
index 0000000..e765b36
--- /dev/null
+++ b/Src/osmolib/src/target/firmware/include/fb/framebuffer.h
@@ -0,0 +1,128 @@
+#ifndef _FB_FRAMEBUFFER_H
+#define _FB_FRAMEBUFFER_H
+
+#include <fb/font.h>
+#include <stdint.h>
+
+/* color is encoded as <special><red><green><blue> */
+/* if a color is "special", then the RGB components most likely
+ don't make sense. Use "special" colours when you have to
+ mask out bits with transparency or you have to encode
+ colours in a fixed color palette... */
+
+#define FB_COLOR_WHITE 0x00ffffffU
+#define FB_COLOR_BLACK 0x00000000U
+#define FB_COLOR_TRANSP 0x01ffffffU
+
+#define FB_COLOR_RGB(r,g,b) ((((r) & 0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))
+#define FB_COLOR_RED FB_COLOR_RGB(0xff,0x00,0x00)
+#define FB_COLOR_GREEN FB_COLOR_RGB(0x00,0xff,0x00)
+#define FB_COLOR_BLUE FB_COLOR_RGB(0x00,0x00,0xff)
+
+/* encode */
+
+/* decode */
+#define FB_COLOR_IS_SPECIAL(v) (!!((v) & 0xff000000U))
+#define FB_COLOR_TO_R(v) (((v)>>16) & 0xff)
+#define FB_COLOR_TO_G(v) (((v)>> 8) & 0xff)
+#define FB_COLOR_TO_B(v) ( (v) & 0xff)
+
+struct framebuffer {
+ char name[8]; // keep it short!
+ void (*init)(); // (re)initialize
+ void (*clear)(); // clear display
+ void (*boxto)(uint16_t x,uint16_t y); // draw box to xy
+ void (*lineto)(uint16_t x,uint16_t y); // draw line to xy
+ int (*putstr)(char *c,int maxwidth); // put text in current font to fb
+ void (*flush)(); // flush changes
+
+ uint16_t width,height; // width/height of fb
+ uint16_t cursor_x,cursor_y; // current cursor
+ uint32_t fg_color,bg_color; // current fg/bg color
+ enum fb_font_id font; // current font
+};
+
+/* there is a single framebuffer, the specific driver defines
+ the "framebuffer" symbol */
+extern struct framebuffer *framebuffer;
+
+static inline void
+fb_init(){
+ framebuffer->init();
+}
+
+static inline void
+fb_clear(){
+ framebuffer->clear();
+}
+
+static inline void
+fb_boxto(uint16_t x,uint16_t y){
+ framebuffer->boxto(x,y);
+}
+
+static inline void
+fb_lineto(uint16_t x,uint16_t y){
+ framebuffer->lineto(x,y);
+}
+
+static inline int
+fb_putstr(char *str,int maxwidth){
+ return framebuffer->putstr(str,maxwidth);
+}
+
+static inline void
+fb_flush(){
+ framebuffer->flush();
+}
+
+static inline void
+fb_gotoxy(uint16_t x,uint16_t y){
+ framebuffer->cursor_x = x;
+ framebuffer->cursor_y = y;
+}
+
+static inline void
+fb_setfg(uint32_t color){
+ framebuffer->fg_color = color;
+}
+
+static inline void
+fb_setbg(uint32_t color){
+ framebuffer->bg_color = color;
+}
+
+static inline void
+fb_setfont(enum fb_font_id fid){
+ framebuffer->font = fid;
+}
+
+/* utility function: limit coordinates to area of framebuffer */
+static inline void
+fb_limit_fb_range(uint16_t *x,uint16_t *y){
+ if(*x >= framebuffer->width)
+ *x = framebuffer->width - 1;
+ if(*y >= framebuffer->height)
+ *y = framebuffer->height - 1;
+}
+
+/* utility function: limit box coordinates to area of framebuffer
+ and make sure that x1y1 is left upper edge, x2y2 is right lower */
+static inline void
+fb_sanitize_box(uint16_t *x1,uint16_t *y1,uint16_t *x2,uint16_t *y2){
+ fb_limit_fb_range(x1,y1);
+ fb_limit_fb_range(x2,y2);
+ if(*x1 > *x2){
+ uint16_t tmp = *x1;
+ *x1 = *x2;
+ *x2 = tmp;
+ }
+ if(*y1 > *y2){
+ uint16_t tmp = *y1;
+ *y1 = *y2;
+ *y2 = tmp;
+ }
+}
+
+#endif
+
diff --git a/Src/osmolib/src/target/firmware/include/layer1/async.h b/Src/osmolib/src/target/firmware/include/layer1/async.h
index a9fa08d..de996a6 100644
--- a/Src/osmolib/src/target/firmware/include/layer1/async.h
+++ b/Src/osmolib/src/target/firmware/include/layer1/async.h
@@ -44,6 +44,9 @@ void l1a_mftask_enable(enum mframe_task task);
/* Disable a repeating multiframe task */
void l1a_mftask_disable(enum mframe_task task);
+/* Set the mask for repeating multiframe tasks */
+void l1a_mftask_set(uint32_t tasks);
+
/* Set TCH mode */
uint8_t l1a_tch_mode_set(uint8_t mode);
diff --git a/Src/osmolib/src/target/firmware/include/layer1/l23_api.h b/Src/osmolib/src/target/firmware/include/layer1/l23_api.h
index 9b10b62..e4a3fd0 100644
--- a/Src/osmolib/src/target/firmware/include/layer1/l23_api.h
+++ b/Src/osmolib/src/target/firmware/include/layer1/l23_api.h
@@ -6,9 +6,12 @@
#include <l1ctl_proto.h>
void l1a_l23api_init(void);
+void l1a_l23_handler(void);
void l1_queue_for_l2(struct msgb *msg);
struct msgb *l1ctl_msgb_alloc(uint8_t msg_type);
struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr, uint16_t arfcn);
+extern void (*l1a_l23_tx_cb)(struct msgb *msg);
+void l1a_l23_rx(uint8_t dlci, struct msgb *msg);
void l1ctl_tx_reset(uint8_t msg_type, uint8_t reset_type);
diff --git a/Src/osmolib/src/target/firmware/include/layer1/sync.h b/Src/osmolib/src/target/firmware/include/layer1/sync.h
index aa03c82..dae85a1 100644
--- a/Src/osmolib/src/target/firmware/include/layer1/sync.h
+++ b/Src/osmolib/src/target/firmware/include/layer1/sync.h
@@ -151,6 +151,7 @@ struct l1s_state {
uint8_t pos;
uint8_t running;
uint16_t band_arfcn[64];
+ uint8_t tn[64];
uint8_t level[64];
} neigh_pm;
};
diff --git a/Src/osmolib/src/target/firmware/include/rf/trf6151.h b/Src/osmolib/src/target/firmware/include/rf/trf6151.h
index f0891b6..c1eaf3b 100644
--- a/Src/osmolib/src/target/firmware/include/rf/trf6151.h
+++ b/Src/osmolib/src/target/firmware/include/rf/trf6151.h
@@ -22,7 +22,9 @@ int trf6151_set_gain(uint8_t dbm);
uint8_t trf6151_get_gain(void);
/* Request the PLL to be tuned to the given frequency */
-void trf6151_set_arfcn(uint16_t arfcn, int uplink);
+/* arfcn must have ARFCN_UPLINK flag set if you want uplink ! */
+/* tx selects the TX path only and doesn't set UL band ! */
+void trf6151_set_arfcn(uint16_t arfcn, int tx);
enum trf6151_mode {
TRF6151_IDLE,
diff --git a/Src/osmolib/src/target/firmware/layer1/l23_api.c b/Src/osmolib/src/target/firmware/layer1/l23_api.c
index 11f07cd..1c4459e 100644
--- a/Src/osmolib/src/target/firmware/layer1/l23_api.c
+++ b/Src/osmolib/src/target/firmware/layer1/l23_api.c
@@ -29,6 +29,8 @@
#include <debug.h>
#include <byteorder.h>
+#include <asm/system.h>
+
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <comm/sercomm.h>
@@ -38,18 +40,28 @@
#include <layer1/mframe_sched.h>
#include <layer1/prim.h>
#include <layer1/tpu_window.h>
+#include <layer1/sched_gsmtime.h>
#include <abb/twl3025.h>
#include <rf/trf6151.h>
+#include <calypso/sim.h>
+#include <calypso/dsp.h>
#include <l1ctl_proto.h>
/* the size we will allocate struct msgb* for HDLC */
#define L3_MSG_HEAD 4
-#define L3_MSG_SIZE (sizeof(struct l1ctl_hdr)+sizeof(struct l1ctl_info_dl)+sizeof(struct l1ctl_traffic_ind) + L3_MSG_HEAD)
+#define L3_MSG_DATA 200
+#define L3_MSG_SIZE (L3_MSG_HEAD + sizeof(struct l1ctl_hdr) + L3_MSG_DATA)
+
+void (*l1a_l23_tx_cb)(struct msgb *msg) = NULL;
void l1_queue_for_l2(struct msgb *msg)
{
+ if (l1a_l23_tx_cb) {
+ l1a_l23_tx_cb(msg);
+ return;
+ }
/* forward via serial for now */
sercomm_sendmsg(SC_DLCI_L1A_L23, msg);
}
@@ -395,7 +407,7 @@ static void l1ctl_rx_pm_req(struct msgb *msg)
l1s.pm.range.arfcn_start, l1s.pm.range.arfcn_end);
break;
}
-
+ l1s_reset_hw(); /* must reset, otherwise measurement results are delayed */
l1s_pm_test(1, l1s.pm.range.arfcn_next);
}
@@ -520,8 +532,10 @@ static void l1ctl_rx_neigh_pm_req(struct msgb *msg)
/* now reset pointer and fill list */
l1s.neigh_pm.pos = 0;
l1s.neigh_pm.running = 0;
- for (i = 0; i < pm_req->n; i++)
+ for (i = 0; i < pm_req->n; i++) {
l1s.neigh_pm.band_arfcn[i] = ntohs(pm_req->band_arfcn[i]);
+ l1s.neigh_pm.tn[i] = pm_req->tn[i];
+ }
printf("L1CTL_NEIGH_PM_REQ new list with %u entries\n", pm_req->n);
l1s.neigh_pm.n = pm_req->n; /* atomic */
@@ -552,10 +566,49 @@ static void l1ctl_rx_traffic_req(struct msgb *msg)
l1a_txq_msgb_enq(&l1s.tx_queue[L1S_CHAN_TRAFFIC], msg);
}
+static void l1ctl_sim_req(struct msgb *msg)
+{
+ uint16_t len = msg->len - sizeof(struct l1ctl_hdr);
+ uint8_t *data = msg->data + sizeof(struct l1ctl_hdr);
+
+#if 1 /* for debugging only */
+ {
+ int i;
+ printf("SIM Request (%u): ", len);
+ for (i = 0; i < len; i++)
+ printf("%02x ", data[i]);
+ puts("\n");
+ }
+#endif
+
+ sim_apdu(len, data);
+}
+
+static struct llist_head l23_rx_queue = LLIST_HEAD_INIT(l23_rx_queue);
+
/* callback from SERCOMM when L2 sends a message to L1 */
-static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
+void l1a_l23_rx(uint8_t dlci, struct msgb *msg)
{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
+ unsigned long flags;
+
+ local_firq_save(flags);
+ msgb_enqueue(&l23_rx_queue, msg);
+ local_irq_restore(flags);
+}
+
+void l1a_l23_handler(void)
+{
+ struct msgb *msg;
+ struct l1ctl_hdr *l1h;
+ unsigned long flags;
+
+ local_firq_save(flags);
+ msg = msgb_dequeue(&l23_rx_queue);
+ local_irq_restore(flags);
+ if (!msg)
+ return;
+
+ l1h = (struct l1ctl_hdr *) msg->data;
#if 0
{
@@ -619,6 +672,9 @@ static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
l1ctl_rx_traffic_req(msg);
/* we have to keep the msgb, not free it! */
goto exit_nofree;
+ case L1CTL_SIM_REQ:
+ l1ctl_sim_req(msg);
+ break;
}
exit_msgbfree:
@@ -629,5 +685,6 @@ exit_nofree:
void l1a_l23api_init(void)
{
- sercomm_register_rx_cb(SC_DLCI_L1A_L23, l1a_l23_rx_cb);
+ sercomm_register_rx_cb(SC_DLCI_L1A_L23, l1a_l23_rx);
}
+
diff --git a/Src/osmolib/src/target/firmware/layer1/mframe_sched.c b/Src/osmolib/src/target/firmware/layer1/mframe_sched.c
index 6281c3d..2367d42 100644
--- a/Src/osmolib/src/target/firmware/layer1/mframe_sched.c
+++ b/Src/osmolib/src/target/firmware/layer1/mframe_sched.c
@@ -200,7 +200,11 @@ static const struct mframe_sched_item mf_sdcch8_7[] = {
/* Measurement for MF 51 */
static const struct mframe_sched_item mf_neigh_pm51[] = {
- { .sched_set = NEIGH_PM , .modulo = 51, .frame_nr = 50 },
+ { .sched_set = NEIGH_PM , .modulo = 51, .frame_nr = 0 },
+ { .sched_set = NEIGH_PM , .modulo = 51, .frame_nr = 10 },
+ { .sched_set = NEIGH_PM , .modulo = 51, .frame_nr = 20 },
+ { .sched_set = NEIGH_PM , .modulo = 51, .frame_nr = 30 },
+ { .sched_set = NEIGH_PM , .modulo = 51, .frame_nr = 40 },
{ .sched_set = NULL }
};
diff --git a/Src/osmolib/src/target/firmware/layer1/prim_fbsb.c b/Src/osmolib/src/target/firmware/layer1/prim_fbsb.c
index 7affd75..e849240 100644
--- a/Src/osmolib/src/target/firmware/layer1/prim_fbsb.c
+++ b/Src/osmolib/src/target/firmware/layer1/prim_fbsb.c
@@ -30,6 +30,7 @@
#include <debug.h>
#include <memory.h>
#include <byteorder.h>
+#include <rffe.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/core/msgb.h>
#include <calypso/dsp_api.h>
@@ -47,6 +48,7 @@
#include <layer1/mframe_sched.h>
#include <layer1/tpu_window.h>
#include <layer1/l23_api.h>
+#include <layer1/agc.h>
#include <l1ctl_proto.h>
diff --git a/Src/osmolib/src/target/firmware/layer1/prim_freq.c b/Src/osmolib/src/target/firmware/layer1/prim_freq.c
index 88bc453..ca6dc9e 100644
--- a/Src/osmolib/src/target/firmware/layer1/prim_freq.c
+++ b/Src/osmolib/src/target/firmware/layer1/prim_freq.c
@@ -45,6 +45,7 @@
#include <layer1/tdma_sched.h>
#include <layer1/tpu_window.h>
#include <layer1/l23_api.h>
+#include <layer1/sched_gsmtime.h>
#include <l1ctl_proto.h>
diff --git a/Src/osmolib/src/target/firmware/layer1/prim_pm.c b/Src/osmolib/src/target/firmware/layer1/prim_pm.c
index c2d85ac..1630600 100644
--- a/Src/osmolib/src/target/firmware/layer1/prim_pm.c
+++ b/Src/osmolib/src/target/firmware/layer1/prim_pm.c
@@ -118,10 +118,11 @@ static int l1s_pm_resp(uint8_t num_meas, __unused uint8_t p2,
pmr->pm[1] = 0;
if (l1s.pm.mode == 1) {
- if (l1s.pm.range.arfcn_next <= l1s.pm.range.arfcn_end) {
+ if (l1s.pm.range.arfcn_next != l1s.pm.range.arfcn_end) {
/* schedule PM for next ARFCN in range */
+ l1s.pm.range.arfcn_next =
+ (l1s.pm.range.arfcn_next+1) & 0xfbff;
l1s_pm_test(1, l1s.pm.range.arfcn_next);
- l1s.pm.range.arfcn_next++;
} else {
/* we have finished, flush the msgb to L2 */
struct l1ctl_hdr *l1h = l1s.pm.msg->l1h;
@@ -174,7 +175,8 @@ static int l1s_neigh_pm_cmd(uint8_t num_meas,
* num_meas > 1 */
/* do measurement dummy, in case l1s.neigh_pm.n == 0 */
l1s_rx_win_ctrl((l1s.neigh_pm.n) ?
- l1s.neigh_pm.band_arfcn[l1s.neigh_pm.pos] : 0, L1_RXWIN_PW, 0);
+ l1s.neigh_pm.band_arfcn[l1s.neigh_pm.pos] : 0,
+ L1_RXWIN_PW, l1s.neigh_pm.tn[l1s.neigh_pm.pos]);
/* restore last gain */
rffe_set_gain(last_gain);
@@ -217,6 +219,7 @@ static int l1s_neigh_pm_resp(__unused uint8_t p1, __unused uint8_t p2,
mi = (struct l1ctl_neigh_pm_ind *)
msgb_put(msg, sizeof(*mi));
mi->band_arfcn = htons(l1s.neigh_pm.band_arfcn[i]);
+ mi->tn = l1s.neigh_pm.tn[i];
mi->pm[0] = l1s.neigh_pm.level[i];
mi->pm[1] = 0;
}
diff --git a/Src/osmolib/src/target/firmware/layer1/prim_rach.c b/Src/osmolib/src/target/firmware/layer1/prim_rach.c
index 47f7424..27e89ab 100644
--- a/Src/osmolib/src/target/firmware/layer1/prim_rach.c
+++ b/Src/osmolib/src/target/firmware/layer1/prim_rach.c
@@ -46,6 +46,7 @@
#include <layer1/tdma_sched.h>
#include <layer1/tpu_window.h>
#include <layer1/l23_api.h>
+#include <layer1/sched_gsmtime.h>
#include <l1ctl_proto.h>
@@ -73,7 +74,7 @@ static int l1s_tx_rach_cmd(__unused uint8_t p1, __unused uint8_t p2, __unused ui
dsp_api.db_w->d_task_ra = RACH_DSP_TASK;
- l1s_tx_win_ctrl(l1s.serving_cell.arfcn, L1_TXWIN_AB, 0, 3);
+ l1s_tx_win_ctrl(l1s.serving_cell.arfcn | ARFCN_UPLINK, L1_TXWIN_AB, 0, 3);
return 0;
}
diff --git a/Src/osmolib/src/target/firmware/layer1/prim_rx_nb.c b/Src/osmolib/src/target/firmware/layer1/prim_rx_nb.c
index 7eb4548..ade23a0 100644
--- a/Src/osmolib/src/target/firmware/layer1/prim_rx_nb.c
+++ b/Src/osmolib/src/target/firmware/layer1/prim_rx_nb.c
@@ -29,6 +29,7 @@
#include <debug.h>
#include <memory.h>
#include <byteorder.h>
+#include <rffe.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/core/msgb.h>
#include <calypso/dsp_api.h>
@@ -48,6 +49,7 @@
#include <layer1/l23_api.h>
#include <layer1/rfch.h>
#include <layer1/prim.h>
+#include <layer1/agc.h>
#include <l1ctl_proto.h>
diff --git a/Src/osmolib/src/target/firmware/layer1/prim_tch.c b/Src/osmolib/src/target/firmware/layer1/prim_tch.c
index 96858fb..292ca10 100644
--- a/Src/osmolib/src/target/firmware/layer1/prim_tch.c
+++ b/Src/osmolib/src/target/firmware/layer1/prim_tch.c
@@ -479,7 +479,7 @@ skip_tx_traffic:
l1s_rx_win_ctrl(arfcn, L1_RXWIN_NB, 0);
dsp_load_tx_task(TCHT_DSP_TASK, 0, tsc); /* burst_id unused for TCH */
- l1s_tx_win_ctrl(arfcn, L1_TXWIN_NB, 0, 3);
+ l1s_tx_win_ctrl(arfcn | ARFCN_UPLINK, L1_TXWIN_NB, 0, 3);
return 0;
}
@@ -738,7 +738,7 @@ static int l1s_tch_a_cmd(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
l1s_rx_win_ctrl(arfcn, L1_RXWIN_NB, 0);
dsp_load_tx_task(TCHA_DSP_TASK, 0, tsc); /* burst_id unused for TCHA */
- l1s_tx_win_ctrl(arfcn, L1_TXWIN_NB, 0, 3);
+ l1s_tx_win_ctrl(arfcn, L1_TXWIN_NB | ARFCN_UPLINK, 0, 3);
return 0;
}
diff --git a/Src/osmolib/src/target/firmware/layer1/prim_tx_nb.c b/Src/osmolib/src/target/firmware/layer1/prim_tx_nb.c
index 3038178..df13c75 100644
--- a/Src/osmolib/src/target/firmware/layer1/prim_tx_nb.c
+++ b/Src/osmolib/src/target/firmware/layer1/prim_tx_nb.c
@@ -123,7 +123,7 @@ static int l1s_tx_cmd(uint8_t p1, uint8_t burst_id, uint16_t p3)
dsp_load_tx_task(DUL_DSP_TASK, burst_id, tsc);
- l1s_tx_win_ctrl(arfcn, L1_TXWIN_NB, 0, 3);
+ l1s_tx_win_ctrl(arfcn | ARFCN_UPLINK, L1_TXWIN_NB, 0, 3);
return 0;
}
diff --git a/Src/osmolib/src/target/firmware/layer1/tpu_window.c b/Src/osmolib/src/target/firmware/layer1/tpu_window.c
index 2fdb048..f4e76c1 100644
--- a/Src/osmolib/src/target/firmware/layer1/tpu_window.c
+++ b/Src/osmolib/src/target/firmware/layer1/tpu_window.c
@@ -33,6 +33,7 @@
#include <layer1/sync.h>
#include <layer1/tpu_window.h>
+#include <layer1/rfch.h>
/* all units in GSM quarter-bits (923.1ns) */
#define L1_TDMA_LENGTH_Q 5000
diff --git a/Src/osmolib/src/target/firmware/rf/mt6139.c b/Src/osmolib/src/target/firmware/rf/mt6139.c
index a9a6d32..d48e652 100644
--- a/Src/osmolib/src/target/firmware/rf/mt6139.c
+++ b/Src/osmolib/src/target/firmware/rf/mt6139.c
@@ -39,13 +39,13 @@ static void mt6139_compute_pll(uint32_t f_vco_100khz,
/* To compute Nint, we assume Nfrac is zero */
*nint = (fvco_100khz / (10 * 2 * 26)) - (0 / 130);
- if (nint > 127)
+ if (*nint > 127)
printf("VCO Frequency %u kHz is out of spec\n", f_vco_100khz);
/* Compute Nfract using the pre-computed Nint */
/* Nfrac = ( (Fvco/2*26) - Nint) * 130 */
/* Nfrac = ( (Fvco*130)/(2*26) - (Nint * 130) */
- *nfrac = (f_vco_100khz*130)/(52*10) - (nint * 130);
+ *nfrac = (f_vco_100khz*130)/(52*10) - (*nint * 130);
}
/* Set ARFCN. Takes 2 reg_write, i.e. 8 TPU instructions */
diff --git a/Src/osmolib/src/target/firmware/rf/trf6151.c b/Src/osmolib/src/target/firmware/rf/trf6151.c
index 5360402..96210fc 100644
--- a/Src/osmolib/src/target/firmware/rf/trf6151.c
+++ b/Src/osmolib/src/target/firmware/rf/trf6151.c
@@ -428,12 +428,16 @@ static void trf6151_band_select(enum trf6151_gsm_band band)
}
/* Set ARFCN. Takes 2 reg_write, i.e. 8 TPU instructions */
-void trf6151_set_arfcn(uint16_t arfcn, int uplink)
+void trf6151_set_arfcn(uint16_t arfcn, int tx)
{
uint32_t freq_khz;
uint16_t pll_config;
+ int uplink;
enum trf6151_gsm_band pll_band;
+ uplink = !!(arfcn & ARFCN_UPLINK);
+ arfcn != ~ARFCN_UPLINK;
+
switch (gsm_arfcn2band(arfcn)) {
case GSM_BAND_850:
case GSM_BAND_900:
@@ -452,7 +456,7 @@ void trf6151_set_arfcn(uint16_t arfcn, int uplink)
freq_khz = gsm_arfcn2freq10(arfcn, uplink) * 100;
printd("ARFCN %u -> %u kHz\n", arfcn, freq_khz);
- if (uplink == 0)
+ if (!tx)
trf6151_pll_rx(freq_khz, &pll_config, &pll_band);
else
trf6151_pll_tx(freq_khz, &pll_config, &pll_band);
@@ -512,7 +516,7 @@ uint8_t trf6151_get_gain(void)
void trf6151_test(uint16_t arfcn)
{
- /* Select ARFCN 871 downlink */
+ /* Select ARFCN downlink */
trf6151_set_arfcn(arfcn, 0);
trf6151_set_mode(TRF6151_RX);
@@ -532,7 +536,7 @@ void trf6151_test(uint16_t arfcn)
void trf6151_tx_test(uint16_t arfcn)
{
/* Select ARFCN uplink */
- trf6151_set_arfcn(arfcn, 1);
+ trf6151_set_arfcn(arfcn | ARFCN_UPLINK, 1);
trf6151_set_mode(TRF6151_TX);
tpu_enq_wait(TRF6151_RX_PLL_DELAY);
diff --git a/Src/osmolib/src/target_dsp/calypso/bin2cfile.py b/Src/osmolib/src/target_dsp/calypso/bin2cfile.py
index 9456a6a..9456a6a 100644..100755
--- a/Src/osmolib/src/target_dsp/calypso/bin2cfile.py
+++ b/Src/osmolib/src/target_dsp/calypso/bin2cfile.py
diff --git a/Src/osmolib/src/target_dsp/calypso/dump2coff.py b/Src/osmolib/src/target_dsp/calypso/dump2coff.py
index 67a49e8..67a49e8 100644..100755
--- a/Src/osmolib/src/target_dsp/calypso/dump2coff.py
+++ b/Src/osmolib/src/target_dsp/calypso/dump2coff.py