mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-bts.git
synced 2025-11-06 15:13:26 +00:00
Compare commits
290 Commits
1.0.1
...
keith/lc15
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9192c6c6c2 | ||
|
|
ae4d85d891 | ||
|
|
dbb5addf7d | ||
|
|
e2f9d0eabe | ||
|
|
4e07b83a64 | ||
|
|
f1efd727fb | ||
|
|
e36fbca15f | ||
|
|
5914d76d5c | ||
|
|
cb4340b8a4 | ||
|
|
58d79e88ad | ||
|
|
6a5039674f | ||
|
|
3f35ab258d | ||
|
|
f9e7ccce27 | ||
|
|
2b948a3d17 | ||
|
|
1f932689fc | ||
|
|
7364ef15d9 | ||
|
|
24f98a0df9 | ||
|
|
6ea3b28321 | ||
|
|
eba074e081 | ||
|
|
5184576572 | ||
|
|
ac61baed2e | ||
|
|
aea29c7249 | ||
|
|
52d7eafcea | ||
|
|
cb69d607c9 | ||
|
|
d4f67591c7 | ||
|
|
8969adc5d9 | ||
|
|
a0403d3769 | ||
|
|
e7d835ca8c | ||
|
|
113712c728 | ||
|
|
e5711efbb5 | ||
|
|
f9115ae67a | ||
|
|
b54f1bf122 | ||
|
|
ee8f4b0a91 | ||
|
|
24e702b7d0 | ||
|
|
66c17cfc2d | ||
|
|
a2392f0f9e | ||
|
|
e1766f1b7d | ||
|
|
7544f5a45b | ||
|
|
99ba515985 | ||
|
|
397a43c38a | ||
|
|
e571fd60e6 | ||
|
|
80f9b84a64 | ||
|
|
bd3eabc13e | ||
|
|
6bb700e9d2 | ||
|
|
e3a4530919 | ||
|
|
0d8cd8ce39 | ||
|
|
3cb61d902c | ||
|
|
a070e863e2 | ||
|
|
1d9f6efccb | ||
|
|
522fc939e0 | ||
|
|
595eb576fc | ||
|
|
5c5ad3cb4a | ||
|
|
ae5e1d7110 | ||
|
|
19857fbdaa | ||
|
|
8a98255fb5 | ||
|
|
b37b3263a9 | ||
|
|
c693067b7e | ||
|
|
d0a2caa021 | ||
|
|
38c12e9df9 | ||
|
|
2149b0ff47 | ||
|
|
f0e66d90f8 | ||
|
|
e717aec2f7 | ||
|
|
869091011c | ||
|
|
18bfa91a26 | ||
|
|
e5e1226301 | ||
|
|
d8d459c7e2 | ||
|
|
d93669289b | ||
|
|
80f2bc4855 | ||
|
|
000b13ef52 | ||
|
|
a9d88af594 | ||
|
|
132987daf4 | ||
|
|
3533c3f6ad | ||
|
|
725b3158e2 | ||
|
|
5a60287e44 | ||
|
|
1e9d4feba5 | ||
|
|
a456f2bd15 | ||
|
|
be1651bb51 | ||
|
|
e4abc63e42 | ||
|
|
583f2b86c9 | ||
|
|
fc5f20a713 | ||
|
|
b378fccef1 | ||
|
|
b58fb35754 | ||
|
|
8ff35d3c91 | ||
|
|
5fee4d1ff5 | ||
|
|
a4c54b531c | ||
|
|
df51be6329 | ||
|
|
d73832bc35 | ||
|
|
2cbdeba5cf | ||
|
|
43a8ed2b55 | ||
|
|
d8284eec63 | ||
|
|
eb43c947c1 | ||
|
|
29e47ffc20 | ||
|
|
d7103f9172 | ||
|
|
91fc2b9e30 | ||
|
|
e83c1196b8 | ||
|
|
1c6a56fb97 | ||
|
|
dc4d36d7bb | ||
|
|
b6be055e6b | ||
|
|
ca574b19d3 | ||
|
|
9e1f0e1a13 | ||
|
|
96cb0c54a9 | ||
|
|
4b72ee924c | ||
|
|
520954cd93 | ||
|
|
accbf5bc73 | ||
|
|
972c243146 | ||
|
|
41c7b05283 | ||
|
|
0772cd0460 | ||
|
|
df5b813c0f | ||
|
|
76837bddb7 | ||
|
|
16da58d0c0 | ||
|
|
ccf9498865 | ||
|
|
35d4291a5e | ||
|
|
c91997b2cc | ||
|
|
474eeed78d | ||
|
|
a1f2b6931b | ||
|
|
b86e9260e8 | ||
|
|
3061e1d14a | ||
|
|
ec228cc08c | ||
|
|
e6a72c2b80 | ||
|
|
454b034521 | ||
|
|
9d5acaad5c | ||
|
|
af2a8a6c81 | ||
|
|
faf861b881 | ||
|
|
2588b2abf6 | ||
|
|
f53fde91a3 | ||
|
|
cb57028d52 | ||
|
|
fc917d91bf | ||
|
|
258856b329 | ||
|
|
ca8aa07127 | ||
|
|
f9e67f44d4 | ||
|
|
b4d8f5cf13 | ||
|
|
cb0cb897ad | ||
|
|
e8e864b219 | ||
|
|
89f06e6c54 | ||
|
|
160b624da8 | ||
|
|
291468694b | ||
|
|
e6372cff1b | ||
|
|
aa54224e56 | ||
|
|
4ff47ff39a | ||
|
|
b777c0f3ec | ||
|
|
9649a42d5a | ||
|
|
db6c786350 | ||
|
|
37ea11e072 | ||
|
|
33ed0f8876 | ||
|
|
2131a7931e | ||
|
|
af6f39025f | ||
|
|
1ea7fd0609 | ||
|
|
dc48fd8810 | ||
|
|
54e104496a | ||
|
|
01cc8c0d21 | ||
|
|
55dbafc497 | ||
|
|
139b8caa79 | ||
|
|
e059aa3db7 | ||
|
|
04e980dd10 | ||
|
|
7d1d294807 | ||
|
|
3f2283cd3c | ||
|
|
a99c41bac5 | ||
|
|
b06cd9f439 | ||
|
|
d1e7d0dafa | ||
|
|
b5c23092c7 | ||
|
|
f2271d0888 | ||
|
|
5b9212d6c5 | ||
|
|
876edd5e35 | ||
|
|
5a3eb6470d | ||
|
|
46d62b984a | ||
|
|
1ff0a2addd | ||
|
|
8ea9ba6af8 | ||
|
|
b24ef23570 | ||
|
|
01c539284e | ||
|
|
2dec9fff1c | ||
|
|
8576477de1 | ||
|
|
a52c78dd3e | ||
|
|
f6b6c48c8b | ||
|
|
aaca1217be | ||
|
|
8ec940ce9a | ||
|
|
9d083ab236 | ||
|
|
e50903df9d | ||
|
|
e05279a296 | ||
|
|
5abae93dad | ||
|
|
34711de016 | ||
|
|
1e96e31c10 | ||
|
|
347fea69a0 | ||
|
|
9ef6fa0798 | ||
|
|
0cb2829f17 | ||
|
|
dfa3bb8a10 | ||
|
|
b8265c63cc | ||
|
|
7f1b61df5f | ||
|
|
f2419bf8c3 | ||
|
|
03e3fae639 | ||
|
|
095654d361 | ||
|
|
b1a9a77727 | ||
|
|
839b0f264f | ||
|
|
bf5d8eed11 | ||
|
|
29aee05f75 | ||
|
|
b07e271994 | ||
|
|
482564b422 | ||
|
|
590b23ce3c | ||
|
|
d7be09caf8 | ||
|
|
57f9a279e0 | ||
|
|
519f588715 | ||
|
|
396dc59ae8 | ||
|
|
0f9595f462 | ||
|
|
067824841f | ||
|
|
89bfea63c9 | ||
|
|
5567d71d39 | ||
|
|
0b682f4997 | ||
|
|
dde2f1d5cf | ||
|
|
8294368b23 | ||
|
|
7240062b75 | ||
|
|
1873a30a4a | ||
|
|
bac9224b3b | ||
|
|
d96fd011d6 | ||
|
|
2f251843f9 | ||
|
|
ad7b8bee71 | ||
|
|
c6c2aa9ecd | ||
|
|
a7ee918284 | ||
|
|
5b1c1b2184 | ||
|
|
5f9e42a891 | ||
|
|
9354474b0f | ||
|
|
27ee75e4c0 | ||
|
|
038a1fa047 | ||
|
|
5efbd4e862 | ||
|
|
40b1b4b20d | ||
|
|
57e26c3e16 | ||
|
|
ab5eff60e1 | ||
|
|
19bd4f818d | ||
|
|
d16b69f29e | ||
|
|
43033e6923 | ||
|
|
d16322f5ed | ||
|
|
77b98d4a16 | ||
|
|
d1e9ded94d | ||
|
|
b873b91c5f | ||
|
|
ac3924e093 | ||
|
|
73d174e35f | ||
|
|
720971c6a0 | ||
|
|
620c74b7fe | ||
|
|
a89581b22d | ||
|
|
668d20cc1d | ||
|
|
45a8d4b2be | ||
|
|
41723e1508 | ||
|
|
945c09381d | ||
|
|
a5a03d6b35 | ||
|
|
891ba1568a | ||
|
|
c49df5d144 | ||
|
|
749b878eb1 | ||
|
|
2f5e7093bf | ||
|
|
dd7cc3cc7c | ||
|
|
7b96b8832f | ||
|
|
eac4d23421 | ||
|
|
a4332be9e9 | ||
|
|
6bc6d78b36 | ||
|
|
965b911583 | ||
|
|
708adf1a1f | ||
|
|
3dd90a09e4 | ||
|
|
fc17dc763f | ||
|
|
f748c4530c | ||
|
|
b509023d34 | ||
|
|
de3262fd27 | ||
|
|
5eddf98dfc | ||
|
|
b3fb33adea | ||
|
|
d8afcc143a | ||
|
|
6b5bbee25f | ||
|
|
546056c9c8 | ||
|
|
f3fa1d384d | ||
|
|
45b9021eb8 | ||
|
|
b3e7a888c9 | ||
|
|
3713b59368 | ||
|
|
f788aefe6f | ||
|
|
12d362fe09 | ||
|
|
fa8b9e2aa3 | ||
|
|
de9e2092c9 | ||
|
|
3933e930c3 | ||
|
|
906357c5e2 | ||
|
|
e160ac6ea5 | ||
|
|
96bded3ebd | ||
|
|
ccc7ba17c0 | ||
|
|
055c29bc6b | ||
|
|
e57a62deee | ||
|
|
268ba55a6e | ||
|
|
742dad5b69 | ||
|
|
02231177a9 | ||
|
|
893e499e0c | ||
|
|
3c89e2c36a | ||
|
|
9c9232c993 | ||
|
|
5c205639f1 | ||
|
|
3bf27cefbb | ||
|
|
e8ebbe300c | ||
|
|
e1dade0471 | ||
|
|
5a266511bf | ||
|
|
a4649308eb |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -47,6 +47,11 @@ src/osmo-bts-octphy/osmo-bts-octphy
|
||||
src/osmo-bts-virtual/osmo-bts-virtual
|
||||
src/osmo-bts-omldummy/osmo-bts-omldummy
|
||||
|
||||
src/osmo-bts-oc2g/osmo-bts-oc2g
|
||||
src/osmo-bts-oc2g/oc2gbts-mgr
|
||||
src/osmo-bts-oc2g/oc2gbts-util
|
||||
src/osmo-bts-oc2g/misc/.dirstamp
|
||||
|
||||
tests/atconfig
|
||||
tests/package.m4
|
||||
tests/agch/agch_test
|
||||
@@ -57,6 +62,7 @@ tests/meas/meas_test
|
||||
tests/misc/misc_test
|
||||
tests/handover/handover_test
|
||||
tests/tx_power/tx_power_test
|
||||
tests/ta_control/ta_control_test
|
||||
tests/testsuite
|
||||
tests/testsuite.log
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ SUBDIRS = include src tests doc contrib
|
||||
|
||||
# package the contrib and doc
|
||||
EXTRA_DIST = \
|
||||
contrib/dump_docs.py contrib/screenrc-l1fwd \
|
||||
contrib/l1fwd.init contrib/screenrc-sysmobts contrib/respawn.sh \
|
||||
contrib/dump_docs.py \
|
||||
git-version-gen .version \
|
||||
README.md
|
||||
|
||||
|
||||
11
README.md
11
README.md
@@ -20,7 +20,7 @@ Several kinds of BTS hardware are supported:
|
||||
* sysmocom sysmoBTS
|
||||
* Octasic octphy
|
||||
* Nutaq litecell 1.5
|
||||
* software-defined radio based osmo-bts-trx (e.g. USRP B210, UmTRX)
|
||||
* software-defined radio based osmo-bts-trx (e.g. USRP B210, UmTRX, LimeSDR)
|
||||
|
||||
Homepage
|
||||
--------
|
||||
@@ -45,7 +45,7 @@ We provide a
|
||||
as well as a
|
||||
[VTY Reference Manual](http://ftp.osmocom.org/docs/latest/osmobsc-vty-reference.pdf)
|
||||
and a
|
||||
[Abis refrence MAnual](http://ftp.osmocom.org/docs/latest/osmobts-abis.pdf)
|
||||
[Abis reference MAnual](http://ftp.osmocom.org/docs/latest/osmobts-abis.pdf)
|
||||
describing the OsmoBTS specific A-bis dialect.
|
||||
|
||||
Mailing List
|
||||
@@ -117,10 +117,3 @@ osmo-bts-octphy
|
||||
* no clear indication of nominal transmit power, various power related
|
||||
computations are likely off
|
||||
* no OML attribute validation during bts_model_check_oml()
|
||||
|
||||
osmo-bts-trx
|
||||
------------
|
||||
|
||||
* TCH/F_PDCH cannel not working as voice (https://osmocom.org/issues/1865)
|
||||
* No BER value delivered to OsmoPCU (https://osmocom.org/issues/1855)
|
||||
* No 11bit RACH support (https://osmocom.org/issues/1854)
|
||||
|
||||
17
configure.ac
17
configure.ac
@@ -62,14 +62,14 @@ then
|
||||
fi
|
||||
|
||||
dnl checks for libraries
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.12.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.12.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.12.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 0.12.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 0.12.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 0.12.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.5.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.5.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 1.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 1.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.6.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.6.0)
|
||||
|
||||
AC_MSG_CHECKING([whether to enable support for sysmobts calibration tool])
|
||||
AC_ARG_ENABLE(sysmobts-calib,
|
||||
@@ -382,6 +382,7 @@ AC_OUTPUT(
|
||||
tests/sysmobts/Makefile
|
||||
tests/misc/Makefile
|
||||
tests/handover/Makefile
|
||||
tests/ta_control/Makefile
|
||||
tests/tx_power/Makefile
|
||||
tests/power/Makefile
|
||||
tests/meas/Makefile
|
||||
|
||||
@@ -10,7 +10,7 @@ env = os.environ
|
||||
env['L1FWD_BTS_HOST'] = '127.0.0.1'
|
||||
|
||||
bts_proc = subprocess.Popen(["./src/osmo-bts-sysmo/sysmobts-remote",
|
||||
"-c", "./doc/examples/sysmo/osmo-bts.cfg"], env = env,
|
||||
"-c", "./doc/examples/sysmo/osmo-bts-sysmo.cfg"], env = env,
|
||||
stdin=None, stdout=None)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
@@ -57,4 +57,6 @@ build_bts() {
|
||||
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
|
||||
$MAKE -C "$base/doc/manuals" publish
|
||||
fi
|
||||
|
||||
$MAKE maintainer-clean
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: l1fwd
|
||||
# Required-Start:
|
||||
# Required-Stop: $local_fs
|
||||
# Default-Start: 5
|
||||
# Default-Stop: 0 6
|
||||
# Short-Description: Start screen session with l1fwd software
|
||||
# Description:
|
||||
### END INIT INFO
|
||||
|
||||
. /etc/default/rcS
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
/usr/bin/screen -d -m -c /etc/osmocom/screenrc-l1fwd
|
||||
;;
|
||||
stop)
|
||||
echo "This script doesn't support stop"
|
||||
exit 1
|
||||
;;
|
||||
restart|reload|force-reload)
|
||||
exit 0
|
||||
;;
|
||||
show)
|
||||
;;
|
||||
*)
|
||||
echo "Usage: sysmobts {start|stop|show|reload|restart}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
PID=$$
|
||||
echo "-1000" > /proc/$PID/oom_score_adj
|
||||
|
||||
trap "{ kill 0; kill -2 0; }" EXIT
|
||||
|
||||
while [ -f $1 ]; do
|
||||
(echo "0" > /proc/self/oom_score_adj && exec nice -n -20 $*) &
|
||||
LAST_PID=$!
|
||||
wait $LAST_PID
|
||||
sleep 10s
|
||||
done
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
PID=$$
|
||||
echo "-1000" > /proc/$PID/oom_score_adj
|
||||
|
||||
trap "kill 0" EXIT
|
||||
|
||||
while [ -e /etc/passwd ]; do
|
||||
cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0
|
||||
sleep 2s
|
||||
cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0
|
||||
sleep 1s
|
||||
echo "0" > /sys/class/leds/activity_led/brightness
|
||||
(echo "0" > /proc/self/oom_score_adj && exec nice -n -20 $*) &
|
||||
LAST_PID=$!
|
||||
wait $LAST_PID
|
||||
sleep 10s
|
||||
done
|
||||
@@ -1,3 +0,0 @@
|
||||
chdir /tmp
|
||||
screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/l1fwd-proxy
|
||||
detach
|
||||
@@ -1,5 +0,0 @@
|
||||
chdir /tmp
|
||||
screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/osmo-bts-sysmo -c /etc/osmocom/osmo-bts.cfg -r 1 -M
|
||||
screen -t PCU 1 /etc/osmocom/respawn-only.sh /usr/bin/osmo-pcu -c /etc/osmocom/osmo-pcu.cfg -e
|
||||
screen -t MGR 2 /etc/osmocom/respawn-only.sh /usr/bin/sysmobts-mgr -n -c /etc/osmocom/sysmobts-mgr.cfg
|
||||
detach
|
||||
@@ -24,5 +24,9 @@ if ENABLE_LC15BTS
|
||||
SYSTEMD_SERVICES += osmo-bts-lc15.service lc15bts-mgr.service
|
||||
endif
|
||||
|
||||
if ENABLE_OC2GBTS
|
||||
SYSTEMD_SERVICES += osmo-bts-oc2g.service oc2gbts-mgr.service
|
||||
endif
|
||||
|
||||
systemdsystemunit_DATA = $(SYSTEMD_SERVICES)
|
||||
endif # HAVE_SYSTEMD
|
||||
|
||||
@@ -3,11 +3,8 @@ Description=osmo-bts for LC15 / sysmoBTS 2100
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
|
||||
ExecStartPre=/bin/sh -c 'echo 1 > /sys/class/leds/usr1/brightness'
|
||||
ExecStart=/usr/bin/osmo-bts-lc15 -t 2 -s -c /etc/osmocom/osmo-bts-lc15.cfg -M
|
||||
ExecStopPost=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
|
||||
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/usr1/brightness'
|
||||
RuntimeDirectory=osmo-bts
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
RestartPreventExitStatus=1
|
||||
|
||||
@@ -3,11 +3,8 @@ Description=osmo-bts for OC-2G
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
|
||||
ExecStartPre=/bin/sh -c 'echo 1 > /sys/class/leds/usr1/brightness'
|
||||
ExecStart=/usr/bin/osmo-bts-oc2g -s -c /etc/osmocom/osmo-bts.cfg -M
|
||||
ExecStopPost=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
|
||||
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/usr1/brightness'
|
||||
ExecStart=/usr/bin/osmo-bts-oc2g -s -c /etc/osmocom/osmo-bts-oc2g.cfg -M
|
||||
RuntimeDirectory=osmo-bts
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
RestartPreventExitStatus=1
|
||||
|
||||
532
debian/changelog
vendored
532
debian/changelog
vendored
@@ -1,3 +1,535 @@
|
||||
osmo-bts (1.2.0) unstable; urgency=medium
|
||||
|
||||
[ Oliver Smith ]
|
||||
* Cosmetic: virtual: l1sap.c: fix typos
|
||||
* virtual: set link quality for GSMTAP_CHANNEL_RACH
|
||||
* pcu_sock: fix endian-swapped CellID
|
||||
* gitignore: add oc2g generated files
|
||||
* log: set L1 SAPI log context
|
||||
* vty: add "logging filter l1-sapi"
|
||||
* vty.c: don't ignore get_string_value() errors
|
||||
* vty.c: avoid coverity BAD_SHIFT issues
|
||||
* osmo-bts-virtual.cfg: ms-power-control dsp -> osmo
|
||||
|
||||
[ Harald Welte ]
|
||||
* ETWS Primary Notification via P1 Rest Octets
|
||||
* pcu_interface: Forward ETWS Primary Notification to PCU
|
||||
* doc: Update Abis manual RSL section with ETWS related infomration
|
||||
* osmo-bts-trx/scheduler: prevent uninitialized memory access
|
||||
* osmo-bts-trx: migrate to new generic ECU abstraction
|
||||
* rach_pass_filter(): Add information about channel type
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* common/rsl.c: fix possible NULL-pointer dereference
|
||||
* osmo-bts-trx/scheduler: fix tx_tch_common(): do not send AMR BFI twice
|
||||
* osmo-bts-trx/scheduler: add FIXME note about FACCH/H and BFI
|
||||
* osmo-bts-trx/scheduler: fix: check rc of osmo_ecu_frame_out()
|
||||
* scheduler: fix handling of PTCCH/U and PTCCH/D logical channels
|
||||
* osmo-bts-trx/scheduler: also detect TSC for Access Bursts on PDCH
|
||||
* common/l1sap: increase ToA precision for packet Access Bursts
|
||||
* L1SAP: use RSL_CHAN_* definitions from libosmogsm
|
||||
* L1SAP: also consider RSL_CHAN_OSMO_CBCH8 as CBCH
|
||||
* L1SAP: clarify debug messages in rach_pass_filter()
|
||||
* L1SAP: do not pass unused parameter to l1sap_handover_rach()
|
||||
* L1SAP: refactor handling of Access Bursts on PDCH
|
||||
* L1SAP: properly handle 11-bit encoded RACH.ind in gsmtap_ph_rach()
|
||||
* L1SAP: use the actual ARFCN for outgoing PCUIF messages
|
||||
* L1SAP: fix gsmtap_pdch(): there can be no DATA.ind on PTCCH/U
|
||||
* L1SAP: use GSMTAP_CHANNEL_PDTCH for PDTCH blocks by default
|
||||
* L1SAP: there can be no DATA.ind primitives on PTCCH/U, reject them
|
||||
* README.md: update osmo-bts-trx specific limitations
|
||||
* osmo-bts-trx/scheduler: fix: print the last frame number in rx_data_fn()
|
||||
* osmo-bts-trx: general handling of NOPE / IDLE indications
|
||||
* osmo-bts-trx/trx_if.c: fix: always initialize bi->burst_len for NOPE.ind
|
||||
* osmo-bts-trx/trx_if.c: also print both RSSI and ToA256 for NOPE.ind
|
||||
* osmo-bts-trx/trx_if.c: fix: NOPE.ind also contains C/I field
|
||||
* pcuif_proto.h: extend RACH.ind with TRX and timeslot number fields
|
||||
* common/vty.c: fix: properly assert() the result of get_string_value()
|
||||
* common/abis.c: pass gsm_bts_trx to e1inp_sign_link_create()
|
||||
* common/abis.c: use tall_bts_ctx as talloc-context for libosmo_abis_init()
|
||||
* osmo-bts-trx/vty: ensure backwards compatibility with older config files
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* bts-trx: Log case where no SETFORMAT is sent
|
||||
* bts-trx: Change super verbose IDLE ind not-supported line to DEBUG
|
||||
* doc: bts-models.adoc: Fix typos in rts-advance section
|
||||
* bts-trx: vty: Use API to get poweron state
|
||||
* bts.h: Remove non-existent function definitions
|
||||
* scheduler.c: Move some message log level to DEBUG
|
||||
* scheduler: Use OSMO_ASSERT instead of abort
|
||||
* l1sap: Log conn dropped due to radio link counter timeout
|
||||
* struct gsm_bts: Add model_priv pointer handing bts_model specific data
|
||||
* bts-trx: Allocate struct osmo_trx_clock_state as part of bts-trx private data
|
||||
* bts-trx: vty: Print phy link state in cmd 'show transceiver'
|
||||
* bts-trx: trx_set_bts(): Avoid double loop by checking current trx
|
||||
* bts-trx: Rework code handling poweron state
|
||||
* bts-trx: Don't reset transceiver_available in scheduler_trx.c
|
||||
* bts-trx: Get rid of messy transceiver_available state handler
|
||||
* bts-trx: Drop unused func check_transceiver_availability()
|
||||
* bts-trx: Log TRXC and TRXD socket recv()/send() failures
|
||||
* bts-trx: Time out if no clock ind recvd after RSP POWERON
|
||||
* cosmetic: bts-trx: document variable power level
|
||||
* bts-trx: loops.c: Take into account RSL CHAN ACT ms power level limits
|
||||
* loops.h: Fix missing include for struct l1sched_trx
|
||||
* power_control.c: Take into account RSL CHAN ACT ms power level limits
|
||||
* cosmetic: l1sap.c: Fix typo
|
||||
* rsl: Assign recv pwr to lchan's max ms power
|
||||
* bts-trx: Implement MS Power control loop calculations using dBm instead of ctl levels
|
||||
* rsl: Fix logged value in rx MS Power Control
|
||||
* cosmetic: Fix trailing whitespace
|
||||
* Change gsm_bts_trx field to bool and rename it
|
||||
* Change gsm_lchan field fixed to bool
|
||||
* rsl: Remove unneeded duplicate reset on some lchan fields
|
||||
* Move and rename gsm_lchan.ms_power field
|
||||
* bts-trx: loops.c: Avoid always clamping MS power to MS power class 1
|
||||
* power_control.c: Apply latests improvements from loops.c
|
||||
* power_control.c: Log rx current and target signal levels
|
||||
* power_control.c: Fix ms pwr ctrl skipped if MS doesn't support announced MS Power Level
|
||||
* Introduce BTS feature BTS_FEAT_MS_PWR_CTRL_DSP
|
||||
* power_control.c: Don't use announced MS Power level as input for loop calculations
|
||||
* power_control.c: Limit speed of announced MS Power Level value changes
|
||||
* scheduler_trx.c: cast ptrdiff value to fix printf format
|
||||
* bts-trx: Drop low layer MS Power Control Loop algo
|
||||
* rsl_rx_chan_act: Apply bitmask when parsing IE MS_POWER
|
||||
* rsl: Clarify when autnonoums MS Power Ctrl Loop is used
|
||||
* power_control.c: Log maximum allowed MS Power Level
|
||||
* power_control.c: Clarify loop algo vars and use correct ones during log
|
||||
* l1sap: is_fille_frame(): verify len of data compared
|
||||
|
||||
[ Martin Hauke ]
|
||||
* Fix common misspellings and typos
|
||||
* Rename variable: CALIB_SUCESS -> CALIB_SUCCESS
|
||||
|
||||
[ Philipp Maier ]
|
||||
* scheduler_trx: use gsm0502_fn_remap() to calculate frame number
|
||||
* scheduler_trx: initalize n_errors, n_bursts_bits, n_bits_total
|
||||
* scheduler_trx.c: avoid division by zero when calculating BER
|
||||
* rsl: ensure measurement reports are sent
|
||||
* l1sap.c: ensure ms power control loop is running
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Fri, 03 Jan 2020 17:18:44 +0100
|
||||
|
||||
osmo-bts (1.1.0) unstable; urgency=medium
|
||||
|
||||
[ Daniel Willmann ]
|
||||
* Rename oc2g config file to match new naming scheme
|
||||
* dump_docs: Use new config file naming scheme
|
||||
* systemd: Install OC2G service files with autotools
|
||||
* doc/examples: Install OC2G config files with autotools
|
||||
* osmo-bts-oc2g: Fix status LED responsibilities
|
||||
* osmo-bts-lc15: Change LED behaviour to be the same as oc2g
|
||||
* manuals: Add script to regenerate counter/vty documentation
|
||||
* manuals: Add counter documentation
|
||||
* manuals: Update vty documentation
|
||||
|
||||
[ Harald Welte ]
|
||||
* Bump version: 0.8.1.199-5c93-dirty → 1.0.0
|
||||
* scheduler_trx: Fix erroneous multiply-by-four
|
||||
* OML: some more comments on what functions do
|
||||
* OML: Return attributes in ACK/NACK messages
|
||||
* OML: Ensure MOs are initialized with valid "Administrative State'
|
||||
* OML: Don't overwrite MO instance before oml_tx_failure_event_rep()
|
||||
* OML: remove double-logging on oml_tx_failure_event_rep()
|
||||
* OML: send proper OML alerts in case of errors
|
||||
* OML: Reduce code duplication in down_mom/down_fom
|
||||
* OML: Report short messages even for invalid TRX numbers in down_fom()
|
||||
* OML: Use 'const struct abis_oml_mo *' whenever users only read
|
||||
* OML: Reject segmented OML messages
|
||||
* OML: Properly reject short messages and truncate over-long messages
|
||||
* OML: Work around OsmoBSC sending "GET ATTRIBUTES" with short length
|
||||
* OML: Store merged attributes of IPA OML Managed Objects
|
||||
* OML: Don't advertise baseband transceiver as UNLOCKED at startup
|
||||
* OC-2G: Nominal transmit power is 25 dBm, not 40
|
||||
* rsl.c: Add missing #include of gsm0808.h
|
||||
* Forward GPRS SUSPEND REQ from DCCH to PCU socket
|
||||
* handle NULL return from rate_ctr_group_alloc()
|
||||
* rsl: Send RSL Error Report in case of unknown/unsupported msg_type
|
||||
* rsl: Include Channel Nr and Link ID in Error reports whenever possible
|
||||
* RSL: Reject RLL messages for lchans that are not active yet
|
||||
* RSL: Fix off-by-one error when parsing SACCH INFO IE in RSL CHAN ACT
|
||||
* cbch: Implement handling of "Schedule" message
|
||||
* cbch: Refactor get_smscb_block() / remove smscb_msg.next_seg
|
||||
* cbch: Log every RSL SMSCB COMMAND with type and number of blocks
|
||||
* cbch: Implement support for DEFAULT message
|
||||
* cbch: Fix memory leak and send error message on invalid SMSCB command
|
||||
* cbch: Support Extended CBCH
|
||||
* cbch: Keep SMSCB queue length counter
|
||||
* manual: We now support RSL CBCH LOAD INDICATION
|
||||
* manual: SMSCB BROADCAST COMMAND has no limitations anymore
|
||||
* README.md: Mention LimeSDR as SDR device
|
||||
* sysmo: Fix "nominal power" / BS power display in VTY
|
||||
* cbch: Add counters; queue length limits and CBCH LOAD reporting
|
||||
* cbch: Improve verbosity and extend logging; Always indicate BASIC/EXTD CBCH
|
||||
* Use LOGPLCHAN whenever possible
|
||||
* rsl.adoc: DELETE INDICATION is implemented since Feb '18
|
||||
* RSL: Fix logic about fixed/dynamic MS power control in MS POWER COMMAND
|
||||
* rsl: Implement parsing of BS Power Control message
|
||||
* rsl: MS POWER COCNTROL isn't (only) about "forcing" power levels
|
||||
* load_indication: Fix missing re-set of RACH parameters
|
||||
* l1sap: Correctly count RACH slots in calc_exprd_rach_frames()
|
||||
* l1sap: Fix calculation of expired RACH slots in case of missing frame numbers
|
||||
* oml: Print more context from FOM Header or using MO
|
||||
* oml: Have one generic log message for all transmitted messages
|
||||
* Add severity to OML FAILURE EVENT REPORT
|
||||
* Fix passing of RR SUSPEND REQ from DCCH to PCU socket
|
||||
* clear GPRS indicator in SI3 while PCU is disconnected
|
||||
* trx: Update documentation for fn-advance and rts-advance
|
||||
* l1sap: Compute statistics on FN advance in PH-RTS.ind
|
||||
* [correctly] use the LAPDm T200 values received via OML
|
||||
* Update T200 timer default values
|
||||
* lapdm: Use new libosmocore API to ensure per-channel-type N200 values
|
||||
* sysmo/l1_if.c: Annotate fall-through in switch statement
|
||||
* osmo-bts-trx: Don't increment rssi_valid_count twice
|
||||
* osmo-bts-trx: Don't attemtp to adjust MS power if fixed
|
||||
* scheduler_trx: Handle negative return of gsm0503_tch_hr_decode()
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* common/vty.c: fix 'cfg_phy_no_inst_cmd' command description
|
||||
* common/oml.c: fix: properly push abis_nm_ipa_magic
|
||||
* common/pcu_sock.c: fix possible memleaks in pcu_sock_read()
|
||||
* common/oml.c: constify argument 'trx' of handle_attrs_trx()
|
||||
* common/oml.c: use proper NACK reason in oml_tx_attr_resp()
|
||||
* common/oml.c: use proper OML object for Get Attribute Response
|
||||
* common/oml.c: fix total length calculation in cleanup_attr_msg()
|
||||
* common/l1sap.c: fix: add missing new line to a debug message
|
||||
* common/rsl.c: fix size argument in memcmp() call
|
||||
* common/rsl.c: fix unaligned pointers in rsl_add_rtp_stats()
|
||||
* common/paging.c: fix unaligned pointer access
|
||||
* common/oml.c: introduce and use both LOGPFOH and DEBUGPFOH
|
||||
* common/oml.c: use proper format specifier for uint16_t
|
||||
* common/oml.c: fix broken debug print in down_mom()
|
||||
* common/oml.c: refactor Get Attribute Response message generation
|
||||
* common/oml.c: fix: properly encode NM_ATT_SW_CONFIG
|
||||
* osmo-bts-trx: distinguish 11-bit Access Bursts by synch. sequence
|
||||
* osmo-bts-sysmo: fix: indicate BTS_FEAT_CBCH support on OML
|
||||
* README.md: remove OS#1865 from 'Known limitations'
|
||||
* common/rsl.c: fix NULL-pointer dereference in rsl_rx_rll()
|
||||
* osmo-bts-trx/trx_if.c: dropping Tx bursts is a noticeable event
|
||||
* osmo-bts-trx/l1_if.h: drop unused ho_rach_detect from trx_l1h
|
||||
* osmo-bts/scheduler.h: cosmetic: use bool for ho_rach_detect
|
||||
* common/rsl.c: RSL_IE_HANDO_REF is mandatory for handover CHAN ACT
|
||||
* common/bts.c: bts_supports_cm(): take care about GSM48_CMODE_SIGN
|
||||
* Use #define RSL_CHAN_RACH for RSL Channel Number of RACH
|
||||
* common/scheduler.c: refactor description of TRXC_* lchans
|
||||
* osmo-bts-trx/trx_if.c: use osmo_loadXXbe() for TDMA FN and ToA256
|
||||
* osmo-bts-trx/trx_if.c: rename and clarify TRX_MAX_BURST_LEN
|
||||
* osmo-bts-trx/trx_if.c: introduce TRXD header version handling
|
||||
* osmo-bts-trx/trx_if.c: introduce TRXD header version 0x01 support
|
||||
* osmo-bts-trx/trx_if.c: drop RSSI / ToA debugging code
|
||||
* osmo-bts-trx/trx_if.c: properly describe TRXD messages in logs
|
||||
* osmo-bts-trx/trx_if.c: add TRXD header version negotiation
|
||||
* osmo-bts-trx/trx_if.c: encode actual TRXD header version
|
||||
* osmo-bts-trx/scheduler: pass trx_ul_burst_ind to lchan handlers
|
||||
* osmo-bts/scheduler: provide actual C/I values to OsmoPCU
|
||||
* osmo-bts-trx/scheduler: rx_rach_fn(): use optional TSC info from TRX
|
||||
* osmo-bts-trx/scheduler: rx_rach_fn(): clarify handover RACH handling
|
||||
* osmo-bts-trx/scheduler: rx_rach_fn(): enrich debug message
|
||||
* common/rsl.c: fix: properly handle SI3 Rest Octets
|
||||
* Clarify and refactor link quality (C/I) handling
|
||||
* Move Access Burst link quality handling to L1SAP
|
||||
* osmo-bts-trx/scheduler: rx_rach_fn(): provide actual C/I ratio to L1SAP
|
||||
* osmo-bts-trx/scheduler: rx_data_fn(): provide actual C/I ratio to L1SAP
|
||||
|
||||
[ Max ]
|
||||
* osmo-bts-trx: add extended (11-bit) RACH support
|
||||
* Log lchan kind on PCU-related error
|
||||
* Enable statsd support
|
||||
* Make gsm_pchan2chan_nr() static
|
||||
* Constify pcu_rx_*() parameters
|
||||
|
||||
[ Philipp Maier ]
|
||||
* scheduler_trx: use stored fn for pdtch data indications
|
||||
* oc2g: remove unused define constant FACTORY_ROM_PATH
|
||||
* lc15: remove unused define constant FACTORY_ROM_PATH
|
||||
* oml: make oml_tx_failure_event_rep() public
|
||||
* oc2gbts_mgr_vty: remove calls to vty_install_default()
|
||||
* oc2g: l1if: delay trx initialization to avoid race condition
|
||||
* oc2gbts_mgr: use msgb_talloc_ctx_init() instead of msgb_set_talloc_ctx()
|
||||
* oc2g: generate failure event report in case of bad calibration
|
||||
* oc2g: change log level for calibration file errors to FATAL
|
||||
* vty: add function gsmnet_from_vty() to vty.h
|
||||
* main: remove wrong call to oml_fail_rep() on SIGUSR1/2 and SIGABRT
|
||||
* oml: use oml_tx_failure_event_rep() instead of oml_fail_rep()
|
||||
* oml: use oml_tx_failure_event_rep() instead of signals to SS_FAIL
|
||||
* l1_if: add include for missing header file
|
||||
* oc2gbts_mgr_calib: don't use fsync() on *FILE pointer
|
||||
* oc2gbts_mgr_calib: do not return NULL on integer function
|
||||
* oc2gbts_mgr: use osmo_init_logging2() instead of osmo_init_logging()
|
||||
* pcu_sock: use %zu conversion specifier for printing sizeof() result
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* oc2g: Fix compilation error (comment mark inside comment)
|
||||
* oc2g: Add get_hwversion_desc to header file
|
||||
* oc2g: Cleanup of get_hwversion_desc
|
||||
* oc2g: led_sleep_cb: pass correct ptr to llist_move_tail
|
||||
* oc2g: fsync requires fd instead of file stream
|
||||
* oc2g: Remove unused variables
|
||||
* oc2g: Remove unused static function
|
||||
* oc2g: vty: Compilation error fixes due to commented code
|
||||
* contrib: Remove deprecated screen script helpers
|
||||
* bts-trx: trx_if.c: Introduce logging macro LOGPPHI
|
||||
* gsm_data_shared.h: Remove unused loc_list from struct gsm_bts
|
||||
* bts: Bypass T200 DCCH values for CCCH
|
||||
* bts-trx: Introduce VTY command osmotrx trxd-max-version
|
||||
* trx: Use LOGPPHI instead of LOGP in some more messages
|
||||
* Remove undefined param passed to {logging,osmo_stats}_vty_add_cmds
|
||||
* configure.ac: Require libosmocore 1.2.0
|
||||
|
||||
[ Alexander Huemer ]
|
||||
* Remove 11-bit RACH support from 'Known Limitations'
|
||||
|
||||
[ Oliver Smith ]
|
||||
* debian: create -doc subpackage with pdf manuals
|
||||
* Revert "debian: create -doc subpackage with pdf manuals"
|
||||
* debian: create -doc subpackage with pdf manuals
|
||||
* contrib/jenkins.sh: run "make maintainer-clean"
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
* lc15,sysmo,oc2g: fix dsp-trace-flag command
|
||||
|
||||
[ Eric Wild ]
|
||||
* revert changes to T200
|
||||
* RSL: Fix fixed MS power control in RSL CHAN ACTIV
|
||||
|
||||
[ Thorsten Alteholz ]
|
||||
* fix spelling stuff mentioned by lintian
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Wed, 07 Aug 2019 15:59:02 +0200
|
||||
|
||||
osmo-bts (1.0.0) unstable; urgency=medium
|
||||
|
||||
[ Stefan Sperling ]
|
||||
* let osmo-bts log a special notice if OML connection is closed early
|
||||
* log reception of PCU_IF_MSG_PAG_REQ messages from osmo-pcu
|
||||
* update sysinfo copies in all lchans upon SACCH FILL
|
||||
* preserve lchan-specific SI overrides on SACCH FILL
|
||||
* fix timespec subtraction in compute_elapsed_us()
|
||||
* fix conditions for sending fill frames during RTS IND
|
||||
* send TCH/F fill frames in DTX mode (WIP)
|
||||
* Revert "send TCH/F fill frames in DTX mode (WIP)"
|
||||
* prevent potential NULL dereference in virtbts's tx_tchh_fn
|
||||
* properly initialize si3 in test_is_ccch_for_agch_setup()
|
||||
* add missing check of osmo_wqueue_enqueue() return value
|
||||
|
||||
[ Harald Welte ]
|
||||
* scheduler_trx: Add reminders to use libosmocore functions
|
||||
* cosmetic: it's n_r in check_for_first_ciphrd(), not n_s
|
||||
* Add min/max/std-dev measurement reporting for TOA256
|
||||
* debian/rules: Don't overwrite .tarball-version
|
||||
* CBCH: Fix rejecting SMS-CB related RSL messages
|
||||
* [sysmo,lc15]: Consider CBCH channel combinations in chan_nr_by_sapi()
|
||||
* CBCH: Move processing via L1SAP
|
||||
* CBCH: Implement CBCH support for osmo-bts-{trx,virtual}
|
||||
* CBCH: Use llist_first_entry_or_null() instead of reinventing it
|
||||
* l1sap/scheduler: Consistently print chan_nr as hex number
|
||||
* CBCH: Fix CBCH via L1SAP for osmo-bts-{sysmo,octphy,litecell15}
|
||||
* get_lchan_by_chan_nr(): Fix resolution of CBCH
|
||||
* CBCH: Add FIXME comments on queue overflow/underflow handling
|
||||
* CBCH: sprinkle some OMSO_ASSERT() and guard against talloc failure
|
||||
* CBCH: Fix CBCH implementation for osmo-bts-trx
|
||||
* CBCH: Some more scheduler_mframe cleanup
|
||||
* ensure all config file examples are well-formed
|
||||
* lc15bts_mgr_vty: Ensure writing well-formed config files
|
||||
* paging_test: Fix AGCH/PCH split test for second half of 102 multiframe
|
||||
* Fix computing CCCH block number from frame number
|
||||
* sysmo, virtual: properly handle BS-AG-BLKS-RES as received from BSC
|
||||
* scheduler_trx.c: Switch to osmo_timerfd() of libosmocore >= 0.12.0
|
||||
* initial checkin of manuals to public repo
|
||||
* Add link to Asciidoc source code of manual
|
||||
* spelling: message discriminator, not descriminator
|
||||
* osmobts-abis: Add Revision log regarding dynamic cannels
|
||||
* Documentation on AMR RTP in case of DTX
|
||||
* rtp-amr.adoc: TCH/AFS Uplink
|
||||
* rtp-amr.adoc: TCH/AFS Downlink: Inhibiting
|
||||
* rtp-amr: TCH/AHS Uplink: FACCH/H During DTX
|
||||
* rtp-amr.adoc: New TCH/AHS downlink chapters
|
||||
* rtp-amr.adoc: Fixes to Message Sequence Charts
|
||||
* update osmo-bts-virtual documentation, now that code is merged
|
||||
* vty-ref: Update URI of docbook 5.0 schema
|
||||
* osmo-bts-trx/loops.c: Add comments documenting TA + MS power control loop
|
||||
* osmo-bts-trx/loops.[ch]: Make functions "void" if they always return 0
|
||||
* osmo-bts-trx/loops.c: Use lchan name based logging
|
||||
* osmo-bts-trx/loops.c: Make code control flow more readable
|
||||
|
||||
[ Philipp Maier ]
|
||||
* rtp: make port range configurable, assign correct port numbers
|
||||
* octphy: add support for 16x oversampling mode
|
||||
* cosmetic: separate measurement testcase definitions
|
||||
* cosmetic: unify measurement sample handling in one function
|
||||
* measurement: make sure state is reset on chan act.
|
||||
* measurement: make sure measurement interval end is detected
|
||||
* measurement: fix measurement interval end detection
|
||||
* osmo_mcast_sock: make sure SO_REUSEADDR is applied
|
||||
* cosmetic: fix sourcecode formatting
|
||||
* cosmetic: remove wrong comment
|
||||
* measurement: add unit tests for is_meas_complete()
|
||||
* measurement: fix sub frame table for TCH/H, SS1
|
||||
* measurement: add unit tests for ts45008_83_is_sub()
|
||||
* measurement: fix is_meas_overdue() and increase testcoverage
|
||||
* cosmetic: rename *_meas_rep_fn10* to *_meas_rep_fn10*_by_*s
|
||||
* cosmetic: test_is_meas_overdue() does not test is_meas_complete()
|
||||
* measurement: substitue missing measurements
|
||||
* measurement: add SUB measurements in test_lchan_meas_process_measurement
|
||||
* paging: add unit-test to check different bs_ag_blks_res settings
|
||||
* measurement: display fn_mod when measuremnet is added
|
||||
* cosmetic: fix typo in comment
|
||||
* measurement: remove missed interval end detection
|
||||
* measurement: fix unit-test test_lchan_meas_process_measurement
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* bts.c: Log name of RR msg type instead of value
|
||||
* bts.c: Add missing include for gsm48_rr_msg_name
|
||||
* bts_agch_enqueue: Decrease queue len hard_limit from 1000 to 100
|
||||
* compact AGCH queue: Drop too msg diff than IMM_ASS_REJ
|
||||
* Send DELETE_IND when dropping Imm Assign pending message
|
||||
* lc15: Use correct type for hLayer1 field
|
||||
* lc15: Fix incorrect cast of hLayer1
|
||||
* pcu_sock: Log event pcu_sock created
|
||||
* l1_if.c: Move decl of vars used in conditional macro
|
||||
* sysmo: vty: Add missing include for lchan_deactivate
|
||||
* sysmo: Fix memcmp in RF-MUTE.req for superfemto < 3.6.0
|
||||
* sysmo: l1if_mute_rf: Declare vars inside ifdef section
|
||||
* sysmo: l1_if.c: Avoid decl of unused vars and funcs with femtobts_v2.7 build
|
||||
* sysmo: calib_file.c: Avoid decl of unused vars and funcs with femtobts_v2.7 build
|
||||
* jenkins_*.sh: add --enable-werror to configure flags
|
||||
* doc: Move calypsoBTS example into trx subdir
|
||||
* build: Install example cfg files
|
||||
* debian: Package installed example doc files
|
||||
* Remove unneeded direct libortp dependency
|
||||
* debian: Make osmo-bts-* packages conflict with old osmo-bts package
|
||||
* debian: Create dbg package for osm-bts-virtual
|
||||
* rsl: Use value_string to print encryption algo name
|
||||
* l1sap: add_l1sap_header: Compact msgb_push ret assignment
|
||||
* sched: Log RX->RTP packet like we do in add_l1sap_header
|
||||
* scheduler: Log error on fn jump
|
||||
* trx: scheduler: Keep RTP clock up to date while in DTXu pause
|
||||
* Move systemd service to contrib/systemd
|
||||
* Install systemd services with autotools
|
||||
* Install sample cfg file to /etc/osmocom
|
||||
* doc/examples/Makefile: Install bts-mgr cfg files used by systemd services
|
||||
* lc15: vty: Add missing include for lchan_deactivate
|
||||
* lc15: fsync requires fd instead of file stream
|
||||
* lc15: rewrite and refactor code to print hwversion description
|
||||
* lc15: led_sleep_cb: pass correct ptr to llist_move_tail
|
||||
* abis: inp_s_cbfn: Improve logging signal related information
|
||||
* lchan_meas_check_compute: Log value during incorrect num of SUB measurementes detected
|
||||
* l1sap: Log name of chan_nr instead of hex value
|
||||
* rsl_rx_chan-activ: Improve logging information
|
||||
* gsm_pchan2chan_nr: Fix conversion of CCCH_LCHAN
|
||||
* Convert lchan CCCH_LCHAN to chan_nr BCCH and viceversa
|
||||
* {oc2g,sysmo}-mgr-calib: Fix build against gpsd >= 3.18
|
||||
* bts: Allocate TRX for BTS dynamically, deprecate -t
|
||||
* bts-trx: trx_if: Use struct to store CTRL msg parsed responses
|
||||
* bts-trx: setup timer once at creation time
|
||||
* common: Implement OML for trx_set_available(1)
|
||||
* bts-trx: Allow re-try without exit if POWERON fails in osmo-trx
|
||||
* bts: Fix TRX0 param initialization
|
||||
* rsl: Log lchan state during dynts PDCH->TCH
|
||||
* rsl: Avoid sending ipa PDCH DEACT NACK followed by ACK
|
||||
* bts-trx: early return on POWERON success
|
||||
* cosmetic: fix whitespace
|
||||
* bts_model: Allow TS connect to be processed asynchronously
|
||||
* OsmoBTS/chapters/configuration.adoc: Add bts index in example
|
||||
* OsmoBTS: Update osmotrx ip to diff between local and remote
|
||||
* rtp-amr: Describe requirement to recieve all PH-DATA.ind events
|
||||
* rtp-amr: Fix typo and trailing whitespace
|
||||
* Allow easily disabling GFDL references
|
||||
* OsmoBTS: bts-models: Add Lime Microsystems devices as supported osmo-trx
|
||||
* Introduce chapter trx_if.adoc and add it to OsmoTRX and OsmoBTS
|
||||
* bts: Fix typo
|
||||
* oc2g: Fix headers missing during make distcheck
|
||||
* bts-trx: (n)ack PDCH DEACT only after TRX answered SETSLOT
|
||||
* sysmobts_mgr: Prepare code for gpsd < 2.96 support
|
||||
* sysmobts_mgr: Add support for gpsd < 2.96
|
||||
* rsl: Send PDCH ACT NACK if TCH chan is still active
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* Clarify frame loss counter for l1sched_chan_state
|
||||
* osmo-bts-trx/l1_if.c: cosmetic: fix typo in debug msg
|
||||
* common/rsl.c: tweak log message in lapdm_rll_tx_cb()
|
||||
* contrib/jenkins_*.sh: drop rudimentary '--with-osmo-pcu'
|
||||
* common/pcu_sock.c: cosmetic: explicitly address lchan
|
||||
* common/scheduler.c: track TDMA frame loss per logical channels
|
||||
* common/vty.c: fix deprecated osmo_str2lower() usage
|
||||
* Fix deprecated gsm_arfcn2band(), use gsm_arfcn2band_rc()
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
* cosmetic: abis.c: typo "exixt"
|
||||
* fix ip.access dyn TS for osmo-bts-trx
|
||||
* fix RSL Chan Mode Modif for dyn TS
|
||||
* vty: mark 'rtp bind-ip' deprecated, not hidden
|
||||
* Importing history from osmo-gsm-manuals
|
||||
* OsmoBTS: typo x2 ('Objects Classes' -> 'Object Classes')
|
||||
* OsmoBTS: fix typos, streamline language style
|
||||
* OsmoBTS: s/content of this attribute/this attribute/
|
||||
* OsmoBTS: explain IEs marked 'ignored' *and* 'Received'
|
||||
* abis/oml.doc: remove duplicate sentence part
|
||||
* OsmoBTS: typos
|
||||
* OsmoBTS: wording tweak
|
||||
* OsmoBTS: hardware support: remove dup, tweak wording
|
||||
* Document dynamic channels on Abis, both IPA and Osmocom style
|
||||
* OsmoBTS/abis/rsl: fix subtitle for ladder diagram of osmo dyn switchover
|
||||
* OsmoBTS/abis/dyn_ts_osmocom_style.msc: adjust PDCH Act ack
|
||||
* OsmoBTS/abis/rsl.adoc: fix missing section header
|
||||
* OsmoBTS/chapters/dynamic-timeslots.adoc: Remove obsolete links
|
||||
* osmobts-usermanual.adoc: fix link to abis.adoc chapter
|
||||
* OsmoBTS/chapters/configuration.adoc: fix index numbering
|
||||
* OsmoBTS/abis/rsl: cosmetic: 'IPA style'
|
||||
* OsmoBTS/abis/rsl: add missing info for Osmocom Dyn Channels
|
||||
* make clean: also remove generated image files
|
||||
* add 'make check' target
|
||||
* OsmoBTS/abis/rsl: combine separate dyn ts sections
|
||||
* fix 'make clean': shell glob, ignore failure
|
||||
* OsmoBTS/abis/rsl: split dyn TS ladder diagrams to fit on page
|
||||
* fix build: abis: re-add dependencies
|
||||
* dynamic timeslots: add BSC level config instructions
|
||||
* refactor Makefile build rules, don't use the FORCE
|
||||
|
||||
[ Keith Whyte ]
|
||||
* log: add error log for RSL Chan Mode Modif
|
||||
* fix handling of odd pchans in bts_supports_cm()
|
||||
|
||||
[ Omar Ramadan ]
|
||||
* Add OC-2G BTS sources
|
||||
|
||||
[ Max ]
|
||||
* osmo-bts-trx: print TRX socket addresses in 'show transceiver'
|
||||
* Fix type mismatch
|
||||
* Drop unused function
|
||||
* Add OsmoBTS control interface description
|
||||
* Move RTP AMR doc to top level
|
||||
* Add DTX implementation details to RTP AMR
|
||||
* Sync DTX FSM with OsmoBTS code
|
||||
|
||||
[ Holger Hans Peter Freyther ]
|
||||
* OsmoBTS: Fix the author name and mail address
|
||||
|
||||
[ Jonathan Brielmaier ]
|
||||
* fix various typos across all manuals
|
||||
|
||||
[ Daniel Willmann ]
|
||||
* Add section about configuring power-ramping
|
||||
* OsmoBTS: Print VTY command in fixed-width font
|
||||
* OsmoBTS: Fix typo
|
||||
|
||||
[ Alexander Couzens ]
|
||||
* OsmoBTS: add vty reference documentation
|
||||
* OsmoBTS: generate osmobts-abis.pdf again
|
||||
|
||||
[ Ivaylo Kostov ]
|
||||
* BSC,BTS: add diagrams of PCU-BTS-NITB-SGSN relationships
|
||||
|
||||
[ Philipp ]
|
||||
* Describe how to run multiple instances of osmo-nitb and osmo-bts
|
||||
|
||||
[ Oliver Smith ]
|
||||
* build manuals moved here from osmo-gsm-manuals.git
|
||||
* Fix DISTCHECK_CONFIGURE_FLAGS override
|
||||
* contrib/jenkins_*.sh: build and publish manuals
|
||||
* contrib: fix makedistcheck with disabled systemd
|
||||
|
||||
-- Harald Welte <laforge@gnumonks.org> Sun, 20 Jan 2019 21:13:37 +0100
|
||||
|
||||
osmo-bts (0.8.1) unstable; urgency=medium
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
|
||||
12
debian/control
vendored
12
debian/control
vendored
@@ -11,7 +11,8 @@ Build-Depends: debhelper (>= 9),
|
||||
libosmocore-dev,
|
||||
libosmo-abis-dev,
|
||||
libgps-dev,
|
||||
txt2man
|
||||
txt2man,
|
||||
osmo-gsm-manuals-dev
|
||||
Standards-Version: 3.9.8
|
||||
Vcs-Browser: http://git.osmocom.org/osmo-bts/
|
||||
Vcs-Git: git://git.osmocom.org/osmo-bts
|
||||
@@ -48,3 +49,12 @@ Priority: extra
|
||||
Depends: osmo-bts-virtual (= ${binary:Version}), ${misc:Depends}
|
||||
Description: Debug symbols for the osmo-bts-virtual
|
||||
Make debugging possible
|
||||
|
||||
Package: osmo-bts-doc
|
||||
Architecture: all
|
||||
Section: doc
|
||||
Priority: optional
|
||||
Depends: ${misc:Depends}
|
||||
Description: ${misc:Package} PDF documentation
|
||||
Various manuals: user manual, VTY reference manual and/or
|
||||
protocol/interface manuals.
|
||||
|
||||
1
debian/osmo-bts-doc.install
vendored
Normal file
1
debian/osmo-bts-doc.install
vendored
Normal file
@@ -0,0 +1 @@
|
||||
usr/share/doc/osmo-bts-doc/*.pdf
|
||||
6
debian/rules
vendored
6
debian/rules
vendored
@@ -16,7 +16,7 @@ override_dh_strip:
|
||||
dh_strip --package=osmo-bts-trx --dbg-package=osmo-bts-trx-dbg
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- --enable-trx --with-systemdsystemunitdir=/lib/systemd/system
|
||||
dh_auto_configure -- --enable-trx --with-systemdsystemunitdir=/lib/systemd/system --enable-manuals
|
||||
|
||||
override_dh_clean:
|
||||
dh_clean
|
||||
@@ -26,3 +26,7 @@ override_dh_clean:
|
||||
# Print test results in case of a failure
|
||||
override_dh_auto_test:
|
||||
dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
|
||||
|
||||
# Don't create .pdf.gz files (barely saves space and they can't be opened directly by most pdf readers)
|
||||
override_dh_compress:
|
||||
dh_compress -X.pdf
|
||||
|
||||
@@ -4,7 +4,7 @@ h2. generic
|
||||
|
||||
h3. trx.0.thermal-attenuation
|
||||
|
||||
The idea of this paramter is to attenuate the system output power as part of
|
||||
The idea of this parameter is to attenuate the system output power as part of
|
||||
thermal management. In some cases the PA might be passing a critical level,
|
||||
so an external control process can use this attribute to reduce the system
|
||||
output power.
|
||||
|
||||
@@ -42,5 +42,14 @@ EXTRA_DIST += $(doc_lc15_DATA)
|
||||
OSMOCONF_FILES += litecell15/osmo-bts-lc15.cfg litecell15/lc15bts-mgr.cfg
|
||||
endif
|
||||
|
||||
if ENABLE_OC2GBTS
|
||||
doc_oc2gdir = $(docdir)/examples/osmo-bts-oc2g
|
||||
doc_oc2g_DATA = \
|
||||
oc2g/osmo-bts-oc2g.cfg \
|
||||
oc2g/oc2gbts-mgr.cfg
|
||||
EXTRA_DIST += $(doc_oc2g_DATA)
|
||||
OSMOCONF_FILES += oc2g/osmo-bts-oc2g.cfg oc2g/oc2gbts-mgr.cfg
|
||||
endif
|
||||
|
||||
osmoconfdir = $(sysconfdir)/osmocom
|
||||
osmoconf_DATA = $(OSMOCONF_FILES)
|
||||
|
||||
@@ -22,7 +22,6 @@ line vty
|
||||
!
|
||||
phy 0
|
||||
instance 0
|
||||
osmotrx rx-gain 1
|
||||
osmotrx ip local 127.0.0.1
|
||||
osmotrx ip remote 127.0.0.1
|
||||
osmotrx timing-advance-loop
|
||||
|
||||
@@ -21,7 +21,6 @@ line vty
|
||||
!
|
||||
phy 0
|
||||
instance 0
|
||||
osmotrx rx-gain 1
|
||||
osmotrx ip local 127.0.0.1
|
||||
osmotrx ip remote 127.0.0.1
|
||||
bts 0
|
||||
|
||||
@@ -57,5 +57,5 @@ bts 0
|
||||
power-ramp max-initial 23000 mdBm
|
||||
power-ramp step-size 2000 mdB
|
||||
power-ramp step-interval 1
|
||||
ms-power-control dsp
|
||||
ms-power-control osmo
|
||||
phy 0 instance 0
|
||||
|
||||
@@ -6,6 +6,7 @@ EXTRA_DIST = dtx.dot \
|
||||
osmobts-vty-reference.xml \
|
||||
rtp-amr.adoc \
|
||||
rtp-amr-docinfo.xml \
|
||||
regen_doc.sh \
|
||||
abis \
|
||||
chapters \
|
||||
vty
|
||||
@@ -20,5 +21,6 @@ if BUILD_MANUALS
|
||||
VTY_REFERENCE = osmobts-vty-reference.xml
|
||||
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc
|
||||
|
||||
OSMO_REPOSITORY = osmo-bts
|
||||
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.common.inc
|
||||
endif
|
||||
|
||||
@@ -39,15 +39,18 @@ Specific additions and limitations apply, see the linked sections.
|
||||
| 8.4.11 | - | MODE MODIFY NEGATIVE ACKNOWLEDGE | -> | Sent
|
||||
| 8.4.14 | - | RF CHANNEL RELEASE | <- | Received
|
||||
| 8.4.15 | <<MS_POWER_CONTROL>> | MS POWER CONTROL | <- | Received
|
||||
| 8.4.16 | - | BS POWER CONTROL | <- | Received
|
||||
| 8.4.19 | - | RF CHANNEL RELEASE ACKNOWLEDGE | -> | Sent
|
||||
| 8.4.20 | <<SACCH_INFO_MODIFY>> | SACCH INFO MODIFY | <- | Received
|
||||
5+<| *COMMON CHANNEL MANAGEMENT MESSAGES*
|
||||
| 8.5.1 | <<BCCH_INFORMATION>> | BCCH INFORMATION | <- | Received
|
||||
| 8.5.2 | - | CCCH LOAD INDICATION | -> | Sent
|
||||
| 8.5.3 | <<CHANNEL_REQUIRED>> | CHANNEL REQUIRED | -> | Sent
|
||||
| 8.5.4 | - | DELETE INDICATION | -> | Sent
|
||||
| 8.5.5 | <<PAGING_COMMAND>> | PAGING COMMAND | <- | Received
|
||||
| 8.5.6 | - | IMMEDIATE ASSIGN COMMAND | <- | Received
|
||||
| 8.5.8 | <<SMS_BROADCAST_COMMAND>> | SMS BROADCAST COMMAND | <- | Received
|
||||
| 8.5.8 | - | SMS BROADCAST COMMAND | <- | Received
|
||||
| 8.5.9 | - | CBCH LOAD INDICATION | -> | Sent
|
||||
5+<| *TRX MANAGEMENT MESSAGES*
|
||||
| 8.6.1 | <<RF_RESOURCE_INDICATION>> | RF RESOURCE INDICATION | -> | Sent
|
||||
| 8.6.2 | <<SACCH_FILLING>> | SACCH FILLING | <- | Received
|
||||
@@ -78,6 +81,8 @@ Specific additions and limitations apply, see the linked sections.
|
||||
.3+.| <<pdch_deact>> | <<rsl_pdch_deact>> | RSL PDCH Deactivation | <- | Received
|
||||
| <<rsl_pdch_deact_ack>> | RSL PDCH Deactivation ACK | -> | Sent
|
||||
| <<rsl_pdch_deact_nack>> | RSL PDCH Deactivation NACK | -> | Sent
|
||||
5+<| *COMMON CHANNEL MANAGEMENT MESSAGES*
|
||||
.3+.| <<etws>> | <<OSMO_ETWS_CMD>> | Osmocom ETWS Command | <- | Received
|
||||
|===
|
||||
|
||||
==== Messages Not Implemented by OsmoBTS
|
||||
@@ -89,7 +94,6 @@ Specific additions and limitations apply, see the linked sections.
|
||||
2+<| *DEDICATED CHANNEL MANAGEMENT MESSAGES*
|
||||
| 8.4.12 | PHYSICAL CONTEXT REQUEST
|
||||
| 8.4.13 | PHYSICAL CONTEXT CONFIRM
|
||||
| 8.4.16 | BS POWER CONTROL
|
||||
| 8.4.17 | PREPROCESS CONFIGURE
|
||||
| 8.4.18 | PREPROCESSED MEASUREMENT RESULT
|
||||
| 8.4.21 | TALKER DETECTION
|
||||
@@ -104,9 +108,7 @@ Specific additions and limitations apply, see the linked sections.
|
||||
| 8.4.30 | TFO REPORT
|
||||
| 8.4.31 | TFO MODIFICATION REQUEST
|
||||
2+<| *COMMON CHANNEL MANAGEMENT MESSAGES*
|
||||
| 8.5.4 | DELETE INDICATION
|
||||
| 8.5.7 | SMS BROADCAST REQUEST
|
||||
| 8.5.9 | CBCH LOAD INDICATION
|
||||
| 8.5.10 | NOTIFICATION COMMAND
|
||||
2+<| *TRX MANAGEMENT MESSAGES*
|
||||
| 8.6.3 | OVERLOAD
|
||||
@@ -238,18 +240,6 @@ Conforms to 3GPP TS 08.58 § 8.5.5, with these limitations:
|
||||
NOTE: If adding the identity to the paging queue fails, the BSC is not notified
|
||||
in any way.
|
||||
|
||||
[[SMS_BROADCAST_COMMAND]]
|
||||
=== SMS Broadcast Command
|
||||
|
||||
Conforms to 3GPP TS 08.58 § 8.5.8, with these limitations:
|
||||
|
||||
._Broadcast Command_ message IE details
|
||||
[options="header",cols="10%,30%,60%"]
|
||||
|===
|
||||
| TS 08.58 § | IE Name | Handling
|
||||
| 9.3.44 | SMSCB Channel Indicator | _ignored_
|
||||
|===
|
||||
|
||||
|
||||
[[RF_RESOURCE_INDICATION]]
|
||||
==== RF Resource Indication
|
||||
@@ -356,7 +346,7 @@ See <<rsl_dlcx_ind_msg>>
|
||||
In the classic data model established by ETSI/3GPP for A-bis, each
|
||||
timeslot (channel) is configured using a static channel combination by
|
||||
means of A-bis OML. Particularly in presence of GPRS services, this
|
||||
is very unflexible and leads to inefficient use of air interface
|
||||
is very inflexible and leads to inefficient use of air interface
|
||||
resources.
|
||||
|
||||
As such, several methods have been implemented to overcome this
|
||||
@@ -433,9 +423,9 @@ The activation of PDCH is performed by using the regular 'RSL CHANNEL ACTIVATE'
|
||||
procedure according to <<CHANNEL_ACTIVATION>>, with these modifications:
|
||||
|
||||
* The 'C-bits' part of the 'Channel Number' IE take the non-standard binary
|
||||
value 11000 (C5 thru C1 as seen in 3GPP TS 08.58 § 9.3.1).
|
||||
value 11000 (C5 through C1 as seen in 3GPP TS 08.58 § 9.3.1).
|
||||
* The 'A-bits' part of the 'Activation Type' IE take the non-standard binary
|
||||
value 1111, with an additional fourth bit (add A4 to A3 thru A1 as seen in
|
||||
value 1111, with an additional fourth bit (add A4 to A3 through A1 as seen in
|
||||
3GPP TS 08.58 § 9.3.3; all remaining reserved bits as well as the 'R' bit are
|
||||
coded as zero).
|
||||
* The normally mandatory 'Channel Mode' IE is omitted; none of the optional IEs
|
||||
@@ -467,6 +457,25 @@ include::dyn_ts_osmocom_style1.msc[]
|
||||
include::dyn_ts_osmocom_style2.msc[]
|
||||
----
|
||||
|
||||
[[etws]]
|
||||
=== ETWS (Earthquake and Tsunami Warning System)
|
||||
|
||||
ETWS as specified in 3GPP TS 23.041 includes not only notification via
|
||||
SMSCB, but also so-called Primary Notifications (PN). The ETWS PN are
|
||||
transmitted
|
||||
|
||||
* by the BSC to all subscribers with active dedicated channels
|
||||
* by the BTS on the PCH to all subscribers in idle mode
|
||||
* by the PCU on the PACCH to all subscribers with active TBF
|
||||
|
||||
Unfortunately, 3GPP forgot to update their specifications with any
|
||||
information as to how the ETWS PN is transmitted from BSC to BTS in
|
||||
a portable way, and Osmocom had to invent their own non-standard
|
||||
signaling for it.
|
||||
|
||||
See <<OSMO_ETWS_CMD>> for the Osmocom implementation.
|
||||
|
||||
|
||||
=== Message Formats and Contents
|
||||
|
||||
[[rsl_crcx_msg]]
|
||||
@@ -766,6 +775,32 @@ on a IPA style dynamic TCH/F+PDCH channel.
|
||||
|
||||
NOTE:: This message is *not* used by Osmocom style dynamic channels
|
||||
|
||||
[[OSMO_ETWS_CMD]]
|
||||
==== Osmocom ETWS Command
|
||||
|
||||
This message is sent by the BSC to transfer the ETWS Primary Notification (PN)
|
||||
from BSC to BTS and enable/disable transmission of ETWS PN by the BTS. For more
|
||||
information about ETWS, see 3GPP TS 23.041.
|
||||
|
||||
If the ETWS PN length is > 0, the BTS will immediately start transmission
|
||||
of the received ETWS PN on the PCH using P1 Rest Octets. It will also forward
|
||||
he ETWS PN to the PCU to enable the PCU to transmit it via PACCH on active TBF.
|
||||
|
||||
If the ETWS PN length is 0, the BTS will stop any ETWS PN broadcast via the PCH.
|
||||
|
||||
The Channel Number IE is set to the Downlink CCCH (PCH).
|
||||
|
||||
[options="header"]
|
||||
[cols="30%,25%,15%,15%,15%"]
|
||||
|===
|
||||
| INFORMATION ELEMENT | REFERENCE | PRESENCE | FORMAT | LENGTH
|
||||
| Message discriminator | 08.58 9.1 | M | V | 1
|
||||
| Message type | <<own_msg_types>> | M | V | 1
|
||||
| Channel number | 08.58 9.3.1 | M | TV | 2
|
||||
| SMSCB Message | 08.58 9.3.42 | M | TLV | 2-58
|
||||
|===
|
||||
|
||||
|
||||
=== Information Element Codings
|
||||
|
||||
[[own_msg_types]]
|
||||
@@ -788,6 +823,7 @@ indicated in 3GPP TS 08.58 Section 9.1:
|
||||
| 0x77 | Delete Connection (DLCX) | <<rsl_dlcx_msg>>
|
||||
| 0x78 | Delete Connection (DLCX) ACK | <<rsl_dlcx_msg_ack>>
|
||||
| 0x79 | Delete Connection (DLCX) NACK | <<rsl_dlcx_msg_nack>>
|
||||
| 0x7f | Osmocom ETWS Command | <<OSMO_ETWS_CMD>>
|
||||
| 0x48 | PDCH Activate | <<rsl_pdch_act>>
|
||||
| 0x49 | PDCH Activate ACK | <<rsl_pdch_act_ack>>
|
||||
| 0x4a | PDCH Activate NACK | <<rsl_pdch_act_nack>>
|
||||
|
||||
@@ -245,10 +245,53 @@ local (OsmoBTS) or remote (OsmoTRX) side of the UDP flows.
|
||||
Set the number of frames to be transmitted to transceiver in advance of
|
||||
current GSM frame number.
|
||||
|
||||
GSM is a TDMA (time division multiple access) system on the radio
|
||||
interface. OsmoTRX is the "clock master" of that in the Osmocom
|
||||
implementation. It informs OsmoBTS of the current GSM frame
|
||||
number. However, as there is non-zero delays (UDP packet trnsmission
|
||||
delay, operating system scheduler delay on both OsmoTRX and OsmoBTS
|
||||
side, ...), OsmoBTS must compensate for that delay by "advancing"
|
||||
the clock a certain amount of time.
|
||||
|
||||
In other words, if OsmoTRX informs us that the current frame number is N,
|
||||
we advance it by `fn-advance` and transmit burst data for
|
||||
`N + fn-advance` towards OsmoTRX.
|
||||
|
||||
The fn-advance should be kept as low as possible to avoid additional
|
||||
delays to the user voice plane as well as to improve the performance
|
||||
of the control plane (LAPDm) as well as GPRS.
|
||||
|
||||
However, fn-advance must be kept sufficiently high to ensure no
|
||||
underruns on the OsmoTRX side.
|
||||
|
||||
The detailed value will depend on your underlying computer systems,
|
||||
operating system and related tuning parameters. Running OsmoTRX
|
||||
on a remote host will inevitably require a higher fn-advance then
|
||||
running it on the same machine, where the UDP packetes are just passed
|
||||
over the loopback device.
|
||||
|
||||
The default value for `fn-advance` is 20 (corresponding to 92
|
||||
milliseconds).
|
||||
|
||||
===== `osmotrx rts-advance <0-30>`
|
||||
|
||||
Set the number of frames to be requested from PCU in advance of current
|
||||
frame number. Do not change this unless you have a good reason!
|
||||
Set the number of frames to be requested from L1SAP in advance of current
|
||||
frame number and fn-advance.
|
||||
|
||||
The value specified as `rts-advance` is added to the current GSM frame
|
||||
number as reported by OsmoTRX *and* the `osmotrx fn-advance` in order
|
||||
to generate the PH-RTS.ind (ready to send indications) across the L1SAP
|
||||
interface inside osmo-bts. This will trigger the Layer 2 (LAPDm for
|
||||
the control plane, RTP for the voice plane, and OsmoPCU for GPRS) to
|
||||
generate a MAC block and input it into the osmo-bts-trx TDMA scheduler.
|
||||
|
||||
If OsmoTRX reported N as the current frame number, the actual frame number
|
||||
reported on L1SAP to higher layers will be computed as follows:
|
||||
|
||||
N + fn-advance + rts-advance
|
||||
|
||||
The default value of `rts-advance` is 5 (corresponding to 23 milliseconds).
|
||||
Do not change this unless you have a good reason!
|
||||
|
||||
===== `osmotrx rx-gain <0-50>`
|
||||
|
||||
@@ -400,7 +443,7 @@ configuration at the BTS configuration file is (as always) very minimal,
|
||||
as in the GSM network architecture provides almost all relevant
|
||||
configuration to the BTS from the BSC.
|
||||
|
||||
An example configuratin file is provided as part of the osmo-bts source
|
||||
An example configuration file is provided as part of the osmo-bts source
|
||||
code: `doc/examples/virtual/osmobts-virtual.cfg`
|
||||
|
||||
For more information see
|
||||
|
||||
@@ -14,7 +14,7 @@ OsmoBTS software.
|
||||
|
||||
=== Command Line Options
|
||||
|
||||
Ths OsmoBTS executables (`osmo-bts-sysmo`, `osmo-bts-trx`,
|
||||
The OsmoBTS executables (`osmo-bts-sysmo`, `osmo-bts-trx`,
|
||||
`osmo-bts-octphy`, `osmo-bts-litecell15`, ...) share the following
|
||||
generic command line options:
|
||||
|
||||
|
||||
4
doc/manuals/chapters/counters.adoc
Normal file
4
doc/manuals/chapters/counters.adoc
Normal file
@@ -0,0 +1,4 @@
|
||||
[[counters]]
|
||||
== Counters
|
||||
|
||||
include::./counters_generated.adoc[]
|
||||
64
doc/manuals/chapters/counters_generated.adoc
Normal file
64
doc/manuals/chapters/counters_generated.adoc
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
// autogenerated by show asciidoc counters
|
||||
These counters and their description based on OsmoBTS 0.8.1.346-33ed (OsmoBTS).
|
||||
|
||||
=== Rate Counters
|
||||
|
||||
// generating tables for rate_ctr_group
|
||||
// rate_ctr_group table E1 Input subsystem
|
||||
.e1inp - E1 Input subsystem
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description
|
||||
| hdlc:abort | <<e1inp_hdlc:abort>> | HDLC abort
|
||||
| hdlc:bad_fcs | <<e1inp_hdlc:bad_fcs>> | HLDC Bad FCS
|
||||
| hdlc:overrun | <<e1inp_hdlc:overrun>> | HDLC Overrun
|
||||
| alarm | <<e1inp_alarm>> | Alarm
|
||||
| removed | <<e1inp_removed>> | Line removed
|
||||
|===
|
||||
// rate_ctr_group table cell broadcast channel
|
||||
.cbch - cell broadcast channel
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description
|
||||
| cbch:rcvd_queued | <<cbch_cbch:rcvd_queued>> | Received + queued CBCH messages (Abis)
|
||||
| cbch:rcvd_dropped | <<cbch_cbch:rcvd_dropped>> | Received + dropped CBCH messages (Abis)
|
||||
| cbch:sent_single | <<cbch_cbch:sent_single>> | Sent single CBCH messages (Um)
|
||||
| cbch:sent_default | <<cbch_cbch:sent_default>> | Sent default CBCH messages (Um)
|
||||
| cbch:sent_null | <<cbch_cbch:sent_null>> | Sent NULL CBCH messages (Um)
|
||||
|===
|
||||
// rate_ctr_group table cell broadcast channel
|
||||
.cbch - cell broadcast channel
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description
|
||||
| cbch:rcvd_queued | <<cbch_cbch:rcvd_queued>> | Received + queued CBCH messages (Abis)
|
||||
| cbch:rcvd_dropped | <<cbch_cbch:rcvd_dropped>> | Received + dropped CBCH messages (Abis)
|
||||
| cbch:sent_single | <<cbch_cbch:sent_single>> | Sent single CBCH messages (Um)
|
||||
| cbch:sent_default | <<cbch_cbch:sent_default>> | Sent default CBCH messages (Um)
|
||||
| cbch:sent_null | <<cbch_cbch:sent_null>> | Sent NULL CBCH messages (Um)
|
||||
|===
|
||||
// rate_ctr_group table base transceiver station
|
||||
.bts - base transceiver station
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description
|
||||
| paging:rcvd | <<bts_paging:rcvd>> | Received paging requests (Abis)
|
||||
| paging:drop | <<bts_paging:drop>> | Dropped paging requests (Abis)
|
||||
| paging:sent | <<bts_paging:sent>> | Sent paging requests (Um)
|
||||
| rach:rcvd | <<bts_rach:rcvd>> | Received RACH requests (Um)
|
||||
| rach:drop | <<bts_rach:drop>> | Dropped RACH requests (Um)
|
||||
| rach:handover | <<bts_rach:handover>> | Received RACH requests (Handover)
|
||||
| rach:cs | <<bts_rach:cs>> | Received RACH requests (CS/Abis)
|
||||
| rach:ps | <<bts_rach:ps>> | Received RACH requests (PS/PCU)
|
||||
| agch:rcvd | <<bts_agch:rcvd>> | Received AGCH requests (Abis)
|
||||
| agch:sent | <<bts_agch:sent>> | Sent AGCH requests (Abis)
|
||||
| agch:delete | <<bts_agch:delete>> | Sent AGCH DELETE IND (Abis)
|
||||
|===
|
||||
== Osmo Stat Items
|
||||
|
||||
// generating tables for osmo_stat_items
|
||||
== Osmo Counters
|
||||
|
||||
// generating tables for osmo_counters
|
||||
// there are no ungrouped osmo_counters
|
||||
@@ -38,7 +38,7 @@ Typical configurations either use OsmoBTS with OsmoBSC, or with
|
||||
OsmoNITB, as can be seen in the following figures.
|
||||
|
||||
[[fig-gsm-classic]]
|
||||
.Classic GSM archtiecture using OsmoBTS with OsmoBTS components
|
||||
.Classic GSM architecture using OsmoBTS with OsmoBTS components
|
||||
[graphviz]
|
||||
----
|
||||
digraph G {
|
||||
|
||||
@@ -14,6 +14,10 @@ include::{srcdir}/chapters/interfaces.adoc[]
|
||||
|
||||
include::{srcdir}/chapters/control.adoc[]
|
||||
|
||||
include::./common/chapters/counters-overview.adoc[]
|
||||
|
||||
include::{srcdir}/chapters/counters.adoc[]
|
||||
|
||||
include::./common/chapters/vty.adoc[]
|
||||
|
||||
include::./common/chapters/logging.adoc[]
|
||||
|
||||
17
doc/manuals/regen_doc.sh
Executable file
17
doc/manuals/regen_doc.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
if [ -z "$DOCKER_PLAYGROUND" ]; then
|
||||
echo "You need to set DOCKER_PLAYGROUND"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCRIPT=$(realpath "$0")
|
||||
MANUAL_DIR=$(dirname "$SCRIPT")
|
||||
|
||||
COMMIT=${COMMIT:-$(git log -1 --format=format:%H)}
|
||||
|
||||
cd "$DOCKER_PLAYGROUND/scripts" || exit 1
|
||||
|
||||
OSMO_BTS_BRANCH=$COMMIT ./regen_doc.sh osmo-bts 4241 \
|
||||
"$MANUAL_DIR/chapters/counters_generated.adoc" \
|
||||
"$MANUAL_DIR/vty/bts_vty_reference.xml"
|
||||
@@ -95,10 +95,10 @@ msc {
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_FIRST)"];
|
||||
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
@@ -110,10 +110,10 @@ msc {
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
|
||||
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
|
||||
}
|
||||
@@ -123,7 +123,7 @@ ULSF2:: As per 3GPP TS 05.03 section 3.9.2.4 The last 4 bursts shall not be tran
|
||||
the SID_FIRST frame is immediately followed by a speech frame. It has been observed that some phone
|
||||
does not transmit the last 4 bursts even if it is not followed by a speech frame.
|
||||
|
||||
ULSU2:: There must be exactly two supressed voice frames between the
|
||||
ULSU2:: There must be exactly two suppressed voice frames between the
|
||||
SID_FIRST and the SID_UPDATE, i.e. there's 60ms between SID_FIRST and
|
||||
SID_UPDATE.
|
||||
|
||||
@@ -152,52 +152,52 @@ msc {
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
|
||||
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
@@ -208,10 +208,10 @@ msc {
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
|
||||
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
|
||||
}
|
||||
@@ -254,10 +254,10 @@ msc {
|
||||
...;
|
||||
--- [label="Once voice is active again"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
@@ -345,10 +345,10 @@ msc {
|
||||
...;
|
||||
--- [label="FACCH/F Frame During DTX"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
@@ -368,10 +368,10 @@ msc {
|
||||
phy => bts [label="PH-DATA.ind FACCH/F"];
|
||||
bts => mgw [label="FACCH/F"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst", id="ULSF2"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst", id="ULSF2"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_FIRST)"];
|
||||
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
|
||||
...;
|
||||
@@ -382,7 +382,7 @@ ULSF2:: The sub-blocks 5-8 of SID_FIRST are not transmitted, as all
|
||||
information bits are contained in sub-blocks 1-4 only
|
||||
|
||||
Note:: It has been observed with some phones that the SID_FIRST is not sent following the FACCH/F
|
||||
frame. If this case occures the No Data Frame and SID_UPDATE order resumes.
|
||||
frame. If this case occurs the No Data Frame and SID_UPDATE order resumes.
|
||||
|
||||
=== TCH/AFS Downlink (Network to MS)
|
||||
|
||||
@@ -660,10 +660,10 @@ msc {
|
||||
phy => bts [label="PH-RTS.ind (TCH)"];
|
||||
phy <= bts [label="PH-EMPTY-FRAME.req (FACCH/F)"];
|
||||
phy <= bts [label="PH-EMPTY-FRAME.req (TCH/F)"];
|
||||
ms x- phy [label="Supressed burst"];
|
||||
ms x- phy [label="Supressed burst"];
|
||||
ms x- phy [label="Supressed burst"];
|
||||
ms x- phy [label="Supressed burst"];
|
||||
ms x- phy [label="Suppressed burst"];
|
||||
ms x- phy [label="Suppressed burst"];
|
||||
ms x- phy [label="Suppressed burst"];
|
||||
ms x- phy [label="Suppressed burst"];
|
||||
}
|
||||
----
|
||||
|
||||
@@ -738,8 +738,8 @@ msc {
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"];
|
||||
bts => mgw [label="RTP (AMR FT=0..7,Q=1)"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP1", id="ULSF1"];
|
||||
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
|
||||
|
||||
@@ -753,8 +753,8 @@ msc {
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
|
||||
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
|
||||
}
|
||||
@@ -764,7 +764,7 @@ ULSF1:: Only SID_FIRST_P1 contains information so it must be the only one transm
|
||||
|
||||
NOTE:: It has been observed that not all phones transmit SID_FIRST_P2 so the PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP2 is not guaranteed to be sent to the BTS.
|
||||
|
||||
ULSU1:: There must be exactly two supressed voice frames between the
|
||||
ULSU1:: There must be exactly two suppressed voice frames between the
|
||||
SID_FIRST and the SID_UPDATE, i.e. there's 60ms between SID_FIRST and
|
||||
SID_UPDATE.
|
||||
|
||||
@@ -795,33 +795,33 @@ msc {
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
|
||||
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
@@ -834,8 +834,8 @@ msc {
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
|
||||
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
|
||||
}
|
||||
@@ -999,8 +999,8 @@ msc {
|
||||
...;
|
||||
ms .. mgw [label="FACCH/H during DTX operation"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
@@ -1026,8 +1026,8 @@ msc {
|
||||
phy => bts [label="PH-DATA.ind with empty payload"];
|
||||
bts -x mgw [label="Suppressed RTP frame"];
|
||||
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Supressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
ms -x phy [label="Suppressed L1 burst"];
|
||||
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP1"];
|
||||
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ The start-up procedure of OsmoBTS can be described as follows:
|
||||
| common | bts_controlif_setup() | Initialization of Control Interface
|
||||
| bts-specific | bts_model_ctrl_cmds_install()
|
||||
| common | telnet_init() | Initialization of telnet interface
|
||||
| common | pcu_sock_init() | Initializaiton of PCU socket
|
||||
| common | pcu_sock_init() | Initialization of PCU socket
|
||||
| common | main() | Installation of signal handlers
|
||||
| common | abis_open() | Start of the A-bis connection to BSC
|
||||
| common | phy_links_open() | Iterate over list of configured PHY links
|
||||
|
||||
@@ -2,4 +2,4 @@ noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h gsm_data_shared.h logging.h
|
||||
oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h \
|
||||
handover.h msg_utils.h tx_power.h control_if.h cbch.h l1sap.h \
|
||||
power_control.h scheduler.h scheduler_backend.h phy_link.h \
|
||||
dtx_dl_amr_fsm.h
|
||||
dtx_dl_amr_fsm.h ta_control.h
|
||||
|
||||
@@ -30,16 +30,9 @@ int bts_init(struct gsm_bts *bts);
|
||||
int bts_trx_init(struct gsm_bts_trx *trx);
|
||||
void bts_shutdown(struct gsm_bts *bts, const char *reason);
|
||||
|
||||
struct gsm_bts *create_bts(uint8_t num_trx, char *id);
|
||||
int create_ms(struct gsm_bts_trx *trx, int maskc, uint8_t *maskv_tx,
|
||||
uint8_t *maskv_rx);
|
||||
void destroy_bts(struct gsm_bts *bts);
|
||||
int work_bts(struct gsm_bts *bts);
|
||||
int bts_link_estab(struct gsm_bts *bts);
|
||||
int trx_link_estab(struct gsm_bts_trx *trx);
|
||||
int trx_set_available(struct gsm_bts_trx *trx, int avail);
|
||||
void bts_new_si(void *arg);
|
||||
void bts_setup_slot(struct gsm_bts_trx_ts *slot, uint8_t comb);
|
||||
|
||||
int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg);
|
||||
struct msgb *bts_agch_dequeue(struct gsm_bts *bts);
|
||||
@@ -48,6 +41,7 @@ int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt
|
||||
int is_ag_res);
|
||||
|
||||
uint8_t *bts_sysinfo_get(struct gsm_bts *bts, const struct gsm_time *g_time);
|
||||
void regenerate_si3_restoctets(struct gsm_bts *bts);
|
||||
uint8_t *lchan_sacch_get(struct gsm_lchan *lchan);
|
||||
int lchan_init_lapdm(struct gsm_lchan *lchan);
|
||||
|
||||
@@ -55,7 +49,7 @@ void load_timer_start(struct gsm_bts *bts);
|
||||
uint8_t num_agch(struct gsm_bts_trx *trx, const char * arg);
|
||||
void bts_update_status(enum bts_global_status which, int on);
|
||||
|
||||
int trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx);
|
||||
bool trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx);
|
||||
|
||||
struct gsm_time *get_time(struct gsm_bts *bts);
|
||||
|
||||
@@ -64,5 +58,6 @@ int bts_main(int argc, char **argv);
|
||||
int bts_supports_cm(struct gsm_bts *bts, enum gsm_phys_chan_config pchan,
|
||||
enum gsm48_chan_mode cm);
|
||||
|
||||
#endif /* _BTS_H */
|
||||
int32_t bts_get_avg_fn_advance(struct gsm_bts *bts);
|
||||
|
||||
#endif /* _BTS_H */
|
||||
|
||||
@@ -6,10 +6,17 @@
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
|
||||
enum {
|
||||
CBCH_CTR_RCVD_QUEUED,
|
||||
CBCH_CTR_RCVD_DROPPED,
|
||||
CBCH_CTR_SENT_SINGLE,
|
||||
CBCH_CTR_SENT_DEFAULT,
|
||||
CBCH_CTR_SENT_NULL,
|
||||
};
|
||||
|
||||
/* incoming SMS broadcast command from RSL */
|
||||
int bts_process_smscb_cmd(struct gsm_bts *bts,
|
||||
struct rsl_ie_cb_cmd_type cmd_type,
|
||||
uint8_t msg_len, const uint8_t *msg);
|
||||
int bts_process_smscb_cmd(struct gsm_bts *bts, struct rsl_ie_cb_cmd_type cmd_type,
|
||||
bool extended_cbch, uint8_t msg_len, const uint8_t *msg);
|
||||
|
||||
/* call-back from bts model specific code when it wants to obtain a CBCH
|
||||
* block for a given gsm_time. outbuf must have 23 bytes of space. */
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <osmocom/gsm/rxlev_stat.h>
|
||||
#include <osmocom/gsm/sysinfo.h>
|
||||
#include <osmocom/gsm/meas_rep.h>
|
||||
#include <osmocom/gsm/gsm48_rest_octets.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
#include <osmocom/gsm/protocol/gsm_08_58.h>
|
||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||
@@ -198,9 +199,6 @@ struct gsm_lchan {
|
||||
/* State */
|
||||
enum gsm_lchan_state state;
|
||||
const char *broken_reason;
|
||||
/* Power levels for MS and BTS */
|
||||
uint8_t bs_power;
|
||||
uint8_t ms_power;
|
||||
/* Encryption information */
|
||||
struct {
|
||||
uint8_t alg_id;
|
||||
@@ -249,7 +247,7 @@ struct gsm_lchan {
|
||||
} si;
|
||||
struct {
|
||||
uint8_t flags;
|
||||
/* RSL measurment result number, 0 at lchan_act */
|
||||
/* RSL measurement result number, 0 at lchan_act */
|
||||
uint8_t res_nr;
|
||||
/* current Tx power level of the BTS */
|
||||
uint8_t bts_tx_pwr;
|
||||
@@ -322,15 +320,16 @@ struct gsm_lchan {
|
||||
/* power handling */
|
||||
struct {
|
||||
uint8_t current;
|
||||
uint8_t fixed;
|
||||
uint8_t max;
|
||||
bool fixed;
|
||||
} ms_power_ctrl;
|
||||
/* Power levels for BTS */
|
||||
uint8_t bs_power;
|
||||
|
||||
struct msgb *pending_rel_ind_msg;
|
||||
|
||||
/* ECU (Error Concealment Unit) state */
|
||||
union {
|
||||
struct osmo_ecu_fr_state fr;
|
||||
} ecu_state;
|
||||
struct osmo_ecu_state *ecu_state;
|
||||
};
|
||||
|
||||
static inline uint8_t lchan_get_ta(const struct gsm_lchan *lchan)
|
||||
@@ -418,7 +417,7 @@ struct gsm_bts_trx {
|
||||
|
||||
|
||||
struct trx_power_params power_params;
|
||||
int ms_power_control;
|
||||
bool ms_pwr_ctl_soft; /* is power control loop done by osmocom software? */
|
||||
|
||||
struct {
|
||||
void *l1h;
|
||||
@@ -478,6 +477,13 @@ enum gsm_bts_features {
|
||||
BTS_FEAT_SPEECH_F_EFR,
|
||||
BTS_FEAT_SPEECH_F_AMR,
|
||||
BTS_FEAT_SPEECH_H_AMR,
|
||||
BTS_FEAT_ETWS_PN,
|
||||
BTS_FEAT_MS_PWR_CTRL_DSP,
|
||||
/* When the feature is set then the measurement data is included in
|
||||
* (PRIM_PH_DATA) and struct ph_tch_param (PRIM_TCH). Otherwise the
|
||||
* measurement data is passed using a separate MPH INFO MEAS IND.
|
||||
* (See also ticket: OS#2977) */
|
||||
BTS_FEAT_MEAS_PAYLOAD_COMB,
|
||||
_NUM_BTS_FEAT
|
||||
};
|
||||
|
||||
@@ -539,6 +545,14 @@ struct gprs_rlc_cfg {
|
||||
uint8_t initial_mcs;
|
||||
};
|
||||
|
||||
struct bts_smscb_state {
|
||||
struct llist_head queue; /* list of struct smscb_msg */
|
||||
int queue_len;
|
||||
struct rate_ctr_group *ctrs;
|
||||
struct smscb_msg *cur_msg; /* current SMS-CB */
|
||||
struct smscb_msg *default_msg; /* default broadcast message; NULL if none */
|
||||
};
|
||||
|
||||
/* The amount of time within which a sudden disconnect of a newly established
|
||||
* OML connection will cause a special warning to be logged. */
|
||||
#define OSMO_BTS_OML_CONN_EARLY_DISCONNECT 10 /* in seconds */
|
||||
@@ -548,10 +562,7 @@ struct gsm_bts {
|
||||
/* list header in net->bts_list */
|
||||
struct llist_head list;
|
||||
|
||||
/* Geographical location of the BTS */
|
||||
struct llist_head loc_list;
|
||||
|
||||
/* number of ths BTS in network */
|
||||
/* number of the BTS in network */
|
||||
uint8_t nr;
|
||||
/* human readable name / description */
|
||||
char *description;
|
||||
@@ -612,8 +623,12 @@ struct gsm_bts {
|
||||
/* offsets used while generating SI2quater */
|
||||
size_t e_offset;
|
||||
size_t u_offset;
|
||||
/* decoded SI3 rest octets - *unmodified* as received from BSC */
|
||||
struct osmo_gsm48_si_ro_info si3_ro_decoded;
|
||||
/* is SI3 GPRS Indicator currently disabled due to lack of PCU connection? */
|
||||
bool si3_gprs_ind_disabled;
|
||||
|
||||
/* ip.accesss Unit ID's have Site/BTS/TRX layout */
|
||||
/* ip.access Unit ID's have Site/BTS/TRX layout */
|
||||
union {
|
||||
struct {
|
||||
uint16_t site_id;
|
||||
@@ -708,6 +723,15 @@ struct gsm_bts {
|
||||
uint64_t pch_msgs;
|
||||
} agch_queue;
|
||||
|
||||
struct {
|
||||
uint8_t *prim_notif; /* ETWS primary notification (NULL if none) */
|
||||
ssize_t prim_notif_len; /* Length of prim_notif; expected 56 bytes */
|
||||
uint8_t page_size;
|
||||
uint8_t num_pages; /* total number of pages */
|
||||
uint8_t next_page; /* next page number to be sent */
|
||||
bool pni; /* Primary Notification Identifier */
|
||||
} etws;
|
||||
|
||||
struct paging_state *paging_state;
|
||||
char *bsc_oml_host;
|
||||
struct llist_head oml_queue;
|
||||
@@ -717,6 +741,7 @@ struct gsm_bts {
|
||||
uint16_t rtp_port_range_start;
|
||||
uint16_t rtp_port_range_end;
|
||||
uint16_t rtp_port_range_next;
|
||||
int rtp_ip_dscp;
|
||||
|
||||
struct {
|
||||
uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */
|
||||
@@ -725,6 +750,14 @@ struct gsm_bts {
|
||||
uint8_t tc4_ctr;
|
||||
} si;
|
||||
struct gsm_time gsm_time;
|
||||
/* frame number statistics (FN in PH-RTS.ind vs. PH-DATA.ind */
|
||||
struct {
|
||||
int32_t min; /* minimum observed */
|
||||
int32_t max; /* maximum observed */
|
||||
int32_t avg256; /* accumulator */
|
||||
uint32_t avg_count; /* number of samples accumulated in avg256 */
|
||||
uint32_t avg_window; /* number of averages in avg_count */
|
||||
} fn_stats;
|
||||
/* Radio Link Timeout counter. -1 disables timeout for
|
||||
* lab/measurement purpose */
|
||||
int radio_link_timeout;
|
||||
@@ -734,31 +767,29 @@ struct gsm_bts {
|
||||
/* used by the sysmoBTS to adjust band */
|
||||
uint8_t auto_band;
|
||||
|
||||
struct {
|
||||
struct llist_head queue; /* list of struct smscb_msg */
|
||||
struct smscb_msg *cur_msg; /* current SMS-CB */
|
||||
} smscb_state;
|
||||
/* State for SMSCB (Cell Broadcast) for BASIC and EXTENDED channel */
|
||||
struct bts_smscb_state smscb_basic;
|
||||
struct bts_smscb_state smscb_extended;
|
||||
int smscb_queue_tgt_len; /* ideal/target queue length */
|
||||
int smscb_queue_max_len; /* maximum queue length */
|
||||
int smscb_queue_hyst; /* hysteresis for CBCH load indications */
|
||||
|
||||
float min_qual_rach; /* minimum quality for RACH bursts */
|
||||
float min_qual_norm; /* minimum quality for normal daata */
|
||||
int16_t min_qual_rach; /* minimum link quality (in centiBels) for Access Bursts */
|
||||
int16_t min_qual_norm; /* minimum link quality (in centiBels) for Normal Bursts */
|
||||
uint16_t max_ber10k_rach; /* Maximum permitted RACH BER in 0.01% */
|
||||
|
||||
struct {
|
||||
char *sock_path;
|
||||
} pcu;
|
||||
|
||||
void *model_priv; /* Allocated by bts_model, contains model specific data pointer */
|
||||
#ifdef ENABLE_LC15BTS
|
||||
/* specific to LC15 BTS */
|
||||
struct {
|
||||
uint32_t last_fn;
|
||||
struct timeval tv_clock;
|
||||
struct osmo_timer_list fn_timer;
|
||||
} vbts;
|
||||
#ifdef ENABLE_OC2GBTS
|
||||
/* specific to Open Cellular 2G BTS */
|
||||
struct {
|
||||
uint8_t led_ctrl_mode; /* 0: control by BTS, 1: not control by BTS */
|
||||
struct llist_head ceased_alarm_list; /* ceased alarm list*/
|
||||
unsigned int rtp_drift_thres_ms; /* RTP timestamp drift detection threshold */
|
||||
} oc2g;
|
||||
uint8_t led_ctrl_mode; /* 0: control by BTS, 1: not control by BTS */
|
||||
struct llist_head ceased_alarm_list; /* ceased alarm list*/
|
||||
unsigned int rtp_drift_thres_ms; /* RTP timestamp drift detection threshold */
|
||||
} lc15;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -818,8 +849,6 @@ void *
|
||||
gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
|
||||
const struct abis_om_obj_inst *obj_inst);
|
||||
|
||||
uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
|
||||
uint8_t ts_nr, uint8_t lchan_nr);
|
||||
uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan);
|
||||
uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
|
||||
enum gsm_phys_chan_config as_pchan);
|
||||
@@ -851,4 +880,6 @@ uint8_t ts_subslots(struct gsm_bts_trx_ts *ts);
|
||||
bool ts_is_tch(struct gsm_bts_trx_ts *ts);
|
||||
const char *gsm_trx_unit_id(struct gsm_bts_trx *trx);
|
||||
|
||||
int lchan2ecu_codec(const struct gsm_lchan *lchan);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define L1SAP_H
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
#include <osmocom/gsm/protocol/gsm_08_58.h>
|
||||
|
||||
/* lchan link ID */
|
||||
#define LID_SACCH 0x40
|
||||
@@ -15,16 +16,27 @@
|
||||
#define L1SAP_CHAN2SS_BCCH(chan_nr) (CCCH_LCHAN)
|
||||
|
||||
/* logical channel from chan_nr + link_id */
|
||||
#define L1SAP_IS_LINK_SACCH(link_id) ((link_id & 0xC0) == LID_SACCH)
|
||||
#define L1SAP_IS_CHAN_TCHF(chan_nr) ((chan_nr & 0xf8) == 0x08)
|
||||
#define L1SAP_IS_CHAN_TCHH(chan_nr) ((chan_nr & 0xf0) == 0x10)
|
||||
#define L1SAP_IS_CHAN_SDCCH4(chan_nr) ((chan_nr & 0xe0) == 0x20)
|
||||
#define L1SAP_IS_CHAN_SDCCH8(chan_nr) ((chan_nr & 0xc0) == 0x40)
|
||||
#define L1SAP_IS_CHAN_BCCH(chan_nr) ((chan_nr & 0xf8) == 0x80)
|
||||
#define L1SAP_IS_CHAN_RACH(chan_nr) ((chan_nr & 0xf8) == 0x88)
|
||||
#define L1SAP_IS_CHAN_AGCH_PCH(chan_nr) ((chan_nr & 0xf8) == 0x90)
|
||||
#define L1SAP_IS_CHAN_PDCH(chan_nr) ((chan_nr & 0xf8) == 0xc0)
|
||||
#define L1SAP_IS_CHAN_CBCH(chan_nr) ((chan_nr & 0xf8) == 0xc8)
|
||||
#define L1SAP_IS_LINK_SACCH(link_id) \
|
||||
((link_id & 0xC0) == LID_SACCH)
|
||||
#define L1SAP_IS_CHAN_TCHF(chan_nr) \
|
||||
((chan_nr & 0xf8) == RSL_CHAN_Bm_ACCHs)
|
||||
#define L1SAP_IS_CHAN_TCHH(chan_nr) \
|
||||
((chan_nr & 0xf0) == RSL_CHAN_Lm_ACCHs)
|
||||
#define L1SAP_IS_CHAN_SDCCH4(chan_nr) \
|
||||
((chan_nr & 0xe0) == RSL_CHAN_SDCCH4_ACCH)
|
||||
#define L1SAP_IS_CHAN_SDCCH8(chan_nr) \
|
||||
((chan_nr & 0xc0) == RSL_CHAN_SDCCH8_ACCH)
|
||||
#define L1SAP_IS_CHAN_BCCH(chan_nr) \
|
||||
((chan_nr & 0xf8) == RSL_CHAN_BCCH)
|
||||
#define L1SAP_IS_CHAN_RACH(chan_nr) \
|
||||
((chan_nr & 0xf8) == RSL_CHAN_RACH)
|
||||
#define L1SAP_IS_CHAN_AGCH_PCH(chan_nr) \
|
||||
((chan_nr & 0xf8) == RSL_CHAN_PCH_AGCH)
|
||||
#define L1SAP_IS_CHAN_PDCH(chan_nr) \
|
||||
((chan_nr & 0xf8) == RSL_CHAN_OSMO_PDCH)
|
||||
#define L1SAP_IS_CHAN_CBCH(chan_nr) \
|
||||
((chan_nr & 0xf8) == RSL_CHAN_OSMO_CBCH4) \
|
||||
|| ((chan_nr & 0xf8) == RSL_CHAN_OSMO_CBCH8)
|
||||
|
||||
/* rach type from ra */
|
||||
#define L1SAP_IS_PACKET_RACH(ra) ((ra & 0xf0) == 0x70 && (ra & 0x0f) != 0x0f)
|
||||
@@ -71,7 +83,7 @@ int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap);
|
||||
|
||||
/* pcu (socket interface) sends us a data request primitive */
|
||||
int l1sap_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn,
|
||||
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len);
|
||||
uint16_t arfcn, uint8_t block_nr, const uint8_t *data, uint8_t len);
|
||||
|
||||
/* call-back function for incoming RTP */
|
||||
void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
|
||||
@@ -84,6 +96,37 @@ int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr);
|
||||
int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr);
|
||||
int l1sap_chan_modify(struct gsm_bts_trx *trx, uint8_t chan_nr);
|
||||
|
||||
enum l1sap_common_sapi {
|
||||
L1SAP_COMMON_SAPI_UNKNOWN,
|
||||
/* alphabetic order */
|
||||
L1SAP_COMMON_SAPI_AGCH,
|
||||
L1SAP_COMMON_SAPI_BCCH,
|
||||
L1SAP_COMMON_SAPI_CBCH,
|
||||
L1SAP_COMMON_SAPI_FACCH_F,
|
||||
L1SAP_COMMON_SAPI_FACCH_H,
|
||||
L1SAP_COMMON_SAPI_FCCH,
|
||||
L1SAP_COMMON_SAPI_IDLE,
|
||||
L1SAP_COMMON_SAPI_NCH,
|
||||
L1SAP_COMMON_SAPI_PACCH,
|
||||
L1SAP_COMMON_SAPI_PAGCH,
|
||||
L1SAP_COMMON_SAPI_PBCCH,
|
||||
L1SAP_COMMON_SAPI_PCH,
|
||||
L1SAP_COMMON_SAPI_PDTCH,
|
||||
L1SAP_COMMON_SAPI_PNCH,
|
||||
L1SAP_COMMON_SAPI_PPCH,
|
||||
L1SAP_COMMON_SAPI_PRACH,
|
||||
L1SAP_COMMON_SAPI_PTCCH,
|
||||
L1SAP_COMMON_SAPI_RACH,
|
||||
L1SAP_COMMON_SAPI_SACCH,
|
||||
L1SAP_COMMON_SAPI_SCH,
|
||||
L1SAP_COMMON_SAPI_SDCCH,
|
||||
L1SAP_COMMON_SAPI_TCH_F,
|
||||
L1SAP_COMMON_SAPI_TCH_H,
|
||||
};
|
||||
|
||||
extern uint16_t l1sap_log_ctx_sapi;
|
||||
extern const struct value_string l1sap_common_sapi_names[];
|
||||
|
||||
extern const struct value_string gsmtap_sapi_names[];
|
||||
extern struct gsmtap_inst *gsmtap;
|
||||
extern uint32_t gsmtap_sapi_mask;
|
||||
@@ -91,7 +134,8 @@ extern uint8_t gsmtap_sapi_acch;
|
||||
|
||||
int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg,
|
||||
struct gsm_lchan *lchan, uint8_t chan_nr, uint32_t fn,
|
||||
uint16_t ber10k, int16_t lqual_cb);
|
||||
uint16_t ber10k, int16_t lqual_cb, int8_t rssi,
|
||||
int16_t ta_offs, uint8_t is_sub);
|
||||
|
||||
#define msgb_l1sap_prim(msg) ((struct osmo_phsap_prim *)(msg)->l1h)
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@ int down_oml(struct gsm_bts *bts, struct msgb *msg);
|
||||
|
||||
struct msgb *oml_msgb_alloc(void);
|
||||
int oml_send_msg(struct msgb *msg, int is_mauf);
|
||||
int oml_mo_send_msg(struct gsm_abis_mo *mo, struct msgb *msg, uint8_t msg_type);
|
||||
int oml_mo_opstart_ack(struct gsm_abis_mo *mo);
|
||||
int oml_mo_opstart_nack(struct gsm_abis_mo *mo, uint8_t nack_cause);
|
||||
int oml_mo_statechg_ack(struct gsm_abis_mo *mo);
|
||||
int oml_mo_statechg_nack(struct gsm_abis_mo *mo, uint8_t nack_cause);
|
||||
int oml_mo_send_msg(const struct gsm_abis_mo *mo, struct msgb *msg, uint8_t msg_type);
|
||||
int oml_mo_opstart_ack(const struct gsm_abis_mo *mo);
|
||||
int oml_mo_opstart_nack(const struct gsm_abis_mo *mo, uint8_t nack_cause);
|
||||
int oml_mo_statechg_ack(const struct gsm_abis_mo *mo);
|
||||
int oml_mo_statechg_nack(const struct gsm_abis_mo *mo, uint8_t nack_cause);
|
||||
|
||||
/* Change the state and send STATE CHG REP */
|
||||
int oml_mo_state_chg(struct gsm_abis_mo *mo, int op_state, int avail_state);
|
||||
@@ -31,20 +31,19 @@ int oml_mo_rf_lock_chg(struct gsm_abis_mo *mo, uint8_t mute_state[8],
|
||||
int success);
|
||||
|
||||
/* Transmit STATE CHG REP even if there was no state change */
|
||||
int oml_tx_state_changed(struct gsm_abis_mo *mo);
|
||||
int oml_tx_state_changed(const struct gsm_abis_mo *mo);
|
||||
|
||||
int oml_mo_tx_sw_act_rep(struct gsm_abis_mo *mo);
|
||||
int oml_mo_tx_sw_act_rep(const struct gsm_abis_mo *mo);
|
||||
|
||||
int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause);
|
||||
|
||||
int oml_mo_fom_ack_nack(struct gsm_abis_mo *mo, uint8_t orig_msg_type,
|
||||
int oml_mo_fom_ack_nack(const struct gsm_abis_mo *mo, uint8_t orig_msg_type,
|
||||
uint8_t cause);
|
||||
|
||||
/* Configure LAPDm T200 timers for this lchan according to OML */
|
||||
int oml_set_lchan_t200(struct gsm_lchan *lchan);
|
||||
extern const unsigned int oml_default_t200_ms[7];
|
||||
|
||||
/* Transmit failure event report */
|
||||
void oml_fail_rep(uint16_t cause_value, const char *fmt, ...);
|
||||
int oml_tx_failure_event_rep(const struct gsm_abis_mo *mo, enum abis_nm_severity severity,
|
||||
uint16_t cause_value, const char *fmt, ...);
|
||||
|
||||
#endif // _OML_H */
|
||||
|
||||
@@ -5,16 +5,19 @@ extern int pcu_direct;
|
||||
|
||||
int pcu_tx_info_ind(void);
|
||||
int pcu_tx_si13(const struct gsm_bts *bts, bool enable);
|
||||
int pcu_tx_app_info_req(struct gsm_bts *bts, uint8_t app_type, uint8_t len, const uint8_t *app_data);
|
||||
int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
||||
uint16_t arfcn, uint8_t block_nr);
|
||||
int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
||||
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len,
|
||||
int8_t rssi, uint16_t ber10k, int16_t bto, int16_t lqual);
|
||||
int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
|
||||
uint8_t is_11bit, enum ph_burst_type burst_type);
|
||||
int pcu_tx_rach_ind(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
|
||||
int16_t qta, uint16_t ra, uint32_t fn, uint8_t is_11bit,
|
||||
enum ph_burst_type burst_type, uint8_t sapi);
|
||||
int pcu_tx_time_ind(uint32_t fn);
|
||||
int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed);
|
||||
int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len);
|
||||
int pcu_tx_susp_req(struct gsm_lchan *lchan, uint32_t tlli, const uint8_t *ra_id, uint8_t cause);
|
||||
|
||||
int pcu_sock_init(const char *path);
|
||||
void pcu_sock_exit(void);
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#define PCU_IF_MSG_DATA_REQ 0x00 /* send data to given channel */
|
||||
#define PCU_IF_MSG_DATA_CNF 0x01 /* confirm (e.g. transmission on PCH) */
|
||||
#define PCU_IF_MSG_DATA_IND 0x02 /* receive data from given channel */
|
||||
#define PCU_IF_MSG_SUSP_REQ 0x03 /* BTS forwards GPRS SUSP REQ to PCU */
|
||||
#define PCU_IF_MSG_APP_INFO_REQ 0x04 /* BTS asks PCU to tranmit APP INFO via PACCH */
|
||||
#define PCU_IF_MSG_RTS_REQ 0x10 /* ready to send request */
|
||||
#define PCU_IF_MSG_DATA_CNF_DT 0x11 /* confirm (with direct tlli) */
|
||||
#define PCU_IF_MSG_RACH_IND 0x22 /* receive RACH */
|
||||
@@ -106,6 +108,8 @@ struct gsm_pcu_if_rach_ind {
|
||||
uint16_t arfcn;
|
||||
uint8_t is_11bit;
|
||||
uint8_t burst_type;
|
||||
uint8_t trx_nr;
|
||||
uint8_t ts_nr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct gsm_pcu_if_info_trx {
|
||||
@@ -171,6 +175,20 @@ struct gsm_pcu_if_pag_req {
|
||||
uint8_t identity_lv[9];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* BTS tells PCU to [once] send given application data via PACCH to all UE with active TBF */
|
||||
struct gsm_pcu_if_app_info_req {
|
||||
uint8_t application_type; /* 4bit field, see TS 44.060 11.2.47 */
|
||||
uint8_t len; /* length of data */
|
||||
uint8_t data[162]; /* random size choice; ETWS needs 56 bytes */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* BTS tells PCU about a GPRS SUSPENSION REQUEST received on DCCH */
|
||||
struct gsm_pcu_if_susp_req {
|
||||
uint32_t tlli;
|
||||
uint8_t ra_id[6];
|
||||
uint8_t cause;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct gsm_pcu_if {
|
||||
/* context based information */
|
||||
uint8_t msg_type; /* message type */
|
||||
@@ -182,6 +200,7 @@ struct gsm_pcu_if {
|
||||
struct gsm_pcu_if_data data_cnf;
|
||||
struct gsm_pcu_if_data_cnf_dt data_cnf_dt;
|
||||
struct gsm_pcu_if_data data_ind;
|
||||
struct gsm_pcu_if_susp_req susp_req;
|
||||
struct gsm_pcu_if_rts_req rts_req;
|
||||
struct gsm_pcu_if_rach_ind rach_ind;
|
||||
struct gsm_pcu_if_txt_ind txt_ind;
|
||||
@@ -189,6 +208,7 @@ struct gsm_pcu_if {
|
||||
struct gsm_pcu_if_act_req act_req;
|
||||
struct gsm_pcu_if_time_ind time_ind;
|
||||
struct gsm_pcu_if_pag_req pag_req;
|
||||
struct gsm_pcu_if_app_info_req app_info_req;
|
||||
} u;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
@@ -44,15 +44,16 @@ struct phy_link {
|
||||
uint16_t base_port_local;
|
||||
uint16_t base_port_remote;
|
||||
struct osmo_fd trx_ofd_clk;
|
||||
bool trx_ta_loop;
|
||||
bool trx_ms_power_loop;
|
||||
int8_t trx_target_rssi;
|
||||
uint32_t clock_advance;
|
||||
uint32_t rts_advance;
|
||||
bool use_legacy_setbsic;
|
||||
uint8_t trxd_hdr_ver_max; /* Maximum TRXD header version to negotiate */
|
||||
bool powered; /* last POWERON (true) or POWEROFF (false) confirmed */
|
||||
bool poweronoff_sent; /* is there a POWERON/POWEROFF in transit? (one or the other based on ->powered) */
|
||||
} osmotrx;
|
||||
struct {
|
||||
char *mcast_dev; /* Network device for multicast */
|
||||
int ttl; /* TTL of transmitted udp multicast */
|
||||
char *bts_mcast_group; /* BTS are listening to this group */
|
||||
uint16_t bts_mcast_port;
|
||||
char *ms_mcast_group; /* MS are listening to this group */
|
||||
@@ -156,6 +157,8 @@ struct phy_link *phy_link_by_num(int num);
|
||||
struct phy_link *phy_link_create(void *ctx, int num);
|
||||
void phy_link_destroy(struct phy_link *plink);
|
||||
void phy_link_state_set(struct phy_link *plink, enum phy_link_state state);
|
||||
enum phy_link_state phy_link_state_get(struct phy_link *plink);
|
||||
const char *phy_link_state_name(enum phy_link_state state);
|
||||
int phy_links_open(void);
|
||||
|
||||
struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num);
|
||||
@@ -166,10 +169,12 @@ const char *phy_instance_name(struct phy_instance *pinst);
|
||||
|
||||
void phy_user_statechg_notif(struct phy_instance *pinst, enum phy_link_state link_state);
|
||||
|
||||
static inline struct phy_instance *trx_phy_instance(struct gsm_bts_trx *trx)
|
||||
static inline struct phy_instance *trx_phy_instance(const struct gsm_bts_trx *trx)
|
||||
{
|
||||
OSMO_ASSERT(trx);
|
||||
return trx->role_bts.l1h;
|
||||
}
|
||||
|
||||
int bts_model_phy_link_open(struct phy_link *plink);
|
||||
|
||||
#define LOGPPHI(pinst, section, lvl, fmt, args...) LOGP(section, lvl, "%s: " fmt, phy_instance_name(pinst), ##args)
|
||||
|
||||
@@ -43,4 +43,8 @@ void cb_ts_disconnected(struct gsm_bts_trx_ts *ts);
|
||||
void cb_ts_connected(struct gsm_bts_trx_ts *ts, int rc);
|
||||
void ipacc_dyn_pdch_complete(struct gsm_bts_trx_ts *ts, int rc);
|
||||
|
||||
int rsl_tx_cbch_load_indication(struct gsm_bts *bts, bool ext_cbch, bool overflow, uint8_t amount);
|
||||
|
||||
int rsl_tx_meas_res(struct gsm_lchan *lchan, uint8_t *l3, int l3_len, const struct lapdm_entity *le);
|
||||
|
||||
#endif // _RSL_H */
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
/* Whether a logical channel must be activated automatically */
|
||||
#define TRX_CHAN_FLAG_AUTO_ACTIVE (1 << 0)
|
||||
/* Whether a logical channel belongs to PDCH (packet switched data) */
|
||||
#define TRX_CHAN_FLAG_PDCH (1 << 1)
|
||||
|
||||
/* FIXME: we should actually activate 'auto-active' channels */
|
||||
#define TRX_CHAN_IS_ACTIVE(state, chan) \
|
||||
(trx_chan_desc[chan].flags & TRX_CHAN_FLAG_AUTO_ACTIVE || (state)->active)
|
||||
|
||||
/* These types define the different channels on a multiframe.
|
||||
* Each channel has queues and can be activated individually.
|
||||
*/
|
||||
@@ -51,8 +60,6 @@ enum trx_chan_type {
|
||||
_TRX_CHAN_MAX
|
||||
};
|
||||
|
||||
extern const struct value_string trx_chan_type_names[];
|
||||
|
||||
#define GSM_BURST_LEN 148
|
||||
#define GPRS_BURST_LEN GSM_BURST_LEN
|
||||
#define EGPRS_BURST_LEN 444
|
||||
@@ -72,11 +79,13 @@ struct l1sched_chan_state {
|
||||
uint32_t ul_first_fn; /* fn of first burst */
|
||||
uint8_t ul_mask; /* mask of received bursts */
|
||||
|
||||
/* RSSI / TOA */
|
||||
/* measurements */
|
||||
uint8_t rssi_num; /* number of RSSI values */
|
||||
float rssi_sum; /* sum of RSSI values */
|
||||
uint8_t toa_num; /* number of TOA values */
|
||||
int32_t toa256_sum; /* sum of TOA values (1/256 symbol) */
|
||||
uint8_t ci_cb_num; /* number of C/I values */
|
||||
int32_t ci_cb_sum; /* sum of C/I values (in centiBels) */
|
||||
|
||||
/* loss detection */
|
||||
uint8_t lost_frames; /* how many L2 frames were lost */
|
||||
@@ -112,17 +121,12 @@ struct l1sched_chan_state {
|
||||
|
||||
/* measurements */
|
||||
struct {
|
||||
uint8_t clock; /* cyclic clock counter */
|
||||
int8_t rssi[32]; /* last RSSI values */
|
||||
int rssi_count; /* received RSSI values */
|
||||
int rssi_valid_count; /* number of stored value */
|
||||
int rssi_got_burst; /* any burst received so far */
|
||||
int32_t toa256_sum; /* sum of TOA values (1/256 symbol) */
|
||||
int toa_num; /* number of TOA value */
|
||||
} meas;
|
||||
|
||||
/* handover */
|
||||
uint8_t ho_rach_detect; /* if rach detection is on */
|
||||
bool ho_rach_detect; /* if rach detection is on */
|
||||
};
|
||||
|
||||
struct l1sched_ts {
|
||||
@@ -166,9 +170,11 @@ int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
|
||||
/*! \brief PHY informs us of new (current) GSM frame number */
|
||||
int trx_sched_clock(struct gsm_bts *bts, uint32_t fn);
|
||||
|
||||
/*! \brief handle an UL burst received by PHY */
|
||||
int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
sbit_t *bits, uint16_t nbits, int8_t rssi, int16_t toa);
|
||||
/*! \brief PHY informs us clock indications should start to be received */
|
||||
int trx_sched_clock_started(struct gsm_bts *bts);
|
||||
|
||||
/*! \brief PHY informs us no more clock indications should be received anymore */
|
||||
int trx_sched_clock_stopped(struct gsm_bts *bts);
|
||||
|
||||
/*! \brief set multiframe scheduler to given physical channel config */
|
||||
int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn,
|
||||
@@ -224,4 +230,34 @@ int find_sched_mframe_idx(enum gsm_phys_chan_config pchan, uint8_t tn);
|
||||
bool trx_sched_is_sacch_fn(struct gsm_bts_trx_ts *ts, uint32_t fn, bool uplink);
|
||||
extern const struct trx_sched_multiframe trx_sched_multiframes[];
|
||||
|
||||
#define TRX_BI_F_NOPE_IND (1 << 0)
|
||||
#define TRX_BI_F_MOD_TYPE (1 << 1)
|
||||
#define TRX_BI_F_TS_INFO (1 << 2)
|
||||
#define TRX_BI_F_CI_CB (1 << 3)
|
||||
|
||||
/*! UL burst indication with the corresponding meta info */
|
||||
struct trx_ul_burst_ind {
|
||||
/* Field presence bitmask (see TRX_BI_F_*) */
|
||||
uint8_t flags;
|
||||
|
||||
/* Mandatory fields */
|
||||
uint32_t fn; /*!< TDMA frame number */
|
||||
uint8_t tn; /*!< TDMA time-slot number */
|
||||
int16_t toa256; /*!< Timing of Arrival in units of 1/256 of symbol */
|
||||
int8_t rssi; /*!< Received Signal Strength Indication */
|
||||
|
||||
/* Optional fields (defined by flags) */
|
||||
enum trx_burst_type bt; /*!< Modulation type */
|
||||
uint8_t tsc_set; /*!< Training Sequence Set */
|
||||
uint8_t tsc; /*!< Training Sequence Code */
|
||||
int16_t ci_cb; /*!< Carrier-to-Interference ratio (in centiBels) */
|
||||
|
||||
/*! Burst soft-bits buffer */
|
||||
sbit_t burst[EGPRS_BURST_LEN];
|
||||
size_t burst_len;
|
||||
};
|
||||
|
||||
/*! Handle an UL burst received by PHY */
|
||||
int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi);
|
||||
|
||||
#endif /* TRX_SCHEDULER_H */
|
||||
|
||||
@@ -13,30 +13,28 @@ typedef ubit_t *trx_sched_dl_func(struct l1sched_trx *l1t, uint8_t tn,
|
||||
uint32_t fn, enum trx_chan_type chan,
|
||||
uint8_t bid, uint16_t *nbits);
|
||||
|
||||
typedef int trx_sched_ul_func(struct l1sched_trx *l1t, uint8_t tn,
|
||||
uint32_t fn, enum trx_chan_type chan,
|
||||
uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, int16_t toa256);
|
||||
typedef int trx_sched_ul_func(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
uint8_t bid, const struct trx_ul_burst_ind *bi);
|
||||
|
||||
struct trx_chan_desc {
|
||||
/*! \brief Is this on a PDCH (PS) ? */
|
||||
int pdch;
|
||||
/*! \brief TRX Channel Type */
|
||||
enum trx_chan_type chan;
|
||||
/*! \brief Human-readable name */
|
||||
const char *name;
|
||||
/*! \brief Human-readable description */
|
||||
const char *desc;
|
||||
/*! \brief Channel Number (like in RSL) */
|
||||
uint8_t chan_nr;
|
||||
/*! \brief Link ID (like in RSL) */
|
||||
uint8_t link_id;
|
||||
/*! \brief Human-readable name */
|
||||
const char *name;
|
||||
/*! \brief function to call when we want to generate RTS.req to L2 */
|
||||
trx_sched_rts_func *rts_fn;
|
||||
/*! \brief function to call when DATA.req received from L2 */
|
||||
trx_sched_dl_func *dl_fn;
|
||||
/*! \brief function to call when burst received from PHY */
|
||||
trx_sched_ul_func *ul_fn;
|
||||
/*! \brief is this channel automatically active at start? */
|
||||
int auto_active;
|
||||
/*! \brief function to call when NOPE.ind received from PHY */
|
||||
trx_sched_ul_func *nope_fn;
|
||||
/*! \brief channel flags, see TRX_CHAN_FLAG_* */
|
||||
uint8_t flags;
|
||||
};
|
||||
extern const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX];
|
||||
|
||||
@@ -56,7 +54,8 @@ int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum osmo_ph_pres_info_type presence_info);
|
||||
|
||||
int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len);
|
||||
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len,
|
||||
int16_t ta_offs_256bits, uint16_t ber10k, float rssi);
|
||||
|
||||
ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
@@ -72,21 +71,16 @@ ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, int16_t toa256);
|
||||
int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, int16_t toa256);
|
||||
int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, int16_t toa256);
|
||||
int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, int16_t toa256);
|
||||
int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, int16_t toa256);
|
||||
int rx_rach_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
uint8_t bid, const struct trx_ul_burst_ind *bi);
|
||||
int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
uint8_t bid, const struct trx_ul_burst_ind *bi);
|
||||
int rx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
uint8_t bid, const struct trx_ul_burst_ind *bi);
|
||||
int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
uint8_t bid, const struct trx_ul_burst_ind *bi);
|
||||
int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
uint8_t bid, const struct trx_ul_burst_ind *bi);
|
||||
|
||||
const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
|
||||
uint32_t fn, uint16_t *nbits);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
enum sig_subsys {
|
||||
SS_GLOBAL,
|
||||
SS_FAIL,
|
||||
};
|
||||
|
||||
enum signals_global {
|
||||
|
||||
5
include/osmo-bts/ta_control.h
Normal file
5
include/osmo-bts/ta_control.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
void lchan_ms_ta_ctrl(struct gsm_lchan *lchan);
|
||||
@@ -25,7 +25,9 @@ struct phy_instance *vty_get_phy_instance(struct vty *vty, int phy_nr, int inst_
|
||||
int bts_vty_go_parent(struct vty *vty);
|
||||
int bts_vty_is_config_node(struct vty *vty, int node);
|
||||
|
||||
int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat);
|
||||
int bts_vty_init(struct gsm_bts *bts);
|
||||
|
||||
struct gsm_network *gsmnet_from_vty(struct vty *v);
|
||||
|
||||
extern struct vty_app_info bts_vty_info;
|
||||
|
||||
|
||||
@@ -6,12 +6,16 @@ if ENABLE_LC15BTS
|
||||
AM_CFLAGS += -DENABLE_LC15BTS
|
||||
endif
|
||||
|
||||
if ENABLE_LC15BTS
|
||||
AM_CFLAGS += -DENABLE_LC15BTS
|
||||
endif
|
||||
|
||||
noinst_LIBRARIES = libbts.a libl1sched.a
|
||||
libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
|
||||
rsl.c vty.c paging.c measurement.c amr.c lchan.c \
|
||||
load_indication.c pcu_sock.c handover.c msg_utils.c \
|
||||
tx_power.c bts_ctrl_commands.c bts_ctrl_lookup.c \
|
||||
l1sap.c cbch.c power_control.c main.c phy_link.c \
|
||||
dtx_dl_amr_fsm.c scheduler_mframe.c
|
||||
dtx_dl_amr_fsm.c scheduler_mframe.c ta_control.c
|
||||
|
||||
libl1sched_a_SOURCES = scheduler.c
|
||||
|
||||
@@ -108,12 +108,11 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
|
||||
e1inp_ts_config_sign(&line->ts[E1INP_SIGN_OML-1], line);
|
||||
sign_link = g_bts->oml_link =
|
||||
e1inp_sign_link_create(&line->ts[E1INP_SIGN_OML-1],
|
||||
E1INP_SIGN_OML, NULL, 255, 0);
|
||||
E1INP_SIGN_OML, g_bts->c0, 255, 0);
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &g_bts->oml_conn_established_timestamp) != 0)
|
||||
memset(&g_bts->oml_conn_established_timestamp, 0,
|
||||
sizeof(g_bts->oml_conn_established_timestamp));
|
||||
drain_oml_queue(g_bts);
|
||||
sign_link->trx = g_bts->c0;
|
||||
bts_link_estab(g_bts);
|
||||
break;
|
||||
default:
|
||||
@@ -129,8 +128,8 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
|
||||
e1inp_ts_config_sign(&line->ts[type-1], line);
|
||||
sign_link = trx->rsl_link =
|
||||
e1inp_sign_link_create(&line->ts[type-1],
|
||||
E1INP_SIGN_RSL, NULL, 0, 0);
|
||||
sign_link->trx = trx;
|
||||
E1INP_SIGN_RSL, trx,
|
||||
trx->rsl_tei, 0);
|
||||
trx_link_estab(trx);
|
||||
break;
|
||||
}
|
||||
@@ -173,7 +172,7 @@ static void sign_link_down(struct e1inp_line *line)
|
||||
}
|
||||
|
||||
|
||||
/* callback for incoming mesages from A-bis/IP */
|
||||
/* callback for incoming messages from A-bis/IP */
|
||||
static int sign_link_cb(struct msgb *msg)
|
||||
{
|
||||
struct e1inp_sign_link *link = msg->dst;
|
||||
@@ -212,7 +211,7 @@ uint32_t get_signlink_remote_ip(struct e1inp_sign_link *link)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we assume that the soket is AF_INET. As Abis/IP contains
|
||||
/* we assume that the socket is AF_INET. As Abis/IP contains
|
||||
* lots of hard-coded IPv4 addresses, this safe */
|
||||
OSMO_ASSERT(sin.sin_family == AF_INET);
|
||||
|
||||
@@ -260,7 +259,7 @@ void abis_init(struct gsm_bts *bts)
|
||||
g_bts = bts;
|
||||
|
||||
oml_init(&bts->mo);
|
||||
libosmo_abis_init(NULL);
|
||||
libosmo_abis_init(tall_bts_ctx);
|
||||
|
||||
osmo_signal_register_handler(SS_L_INPUT, &inp_s_cbfn, bts);
|
||||
}
|
||||
@@ -270,7 +269,7 @@ struct e1inp_line *abis_open(struct gsm_bts *bts, char *dst_host,
|
||||
{
|
||||
struct e1inp_line *line;
|
||||
|
||||
/* patch in various data from VTY and othe sources */
|
||||
/* patch in various data from VTY and other sources */
|
||||
line_ops.cfg.ipa.addr = dst_host;
|
||||
osmo_get_macaddr(bts_dev_info.mac_addr, "eth0");
|
||||
bts_dev_info.site_id = bts->ip_access.site_id;
|
||||
|
||||
124
src/common/bts.c
124
src/common/bts.c
@@ -49,9 +49,10 @@
|
||||
#include <osmo-bts/oml.h>
|
||||
#include <osmo-bts/signal.h>
|
||||
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||
#include <osmo-bts/cbch.h>
|
||||
|
||||
#define MIN_QUAL_RACH 5.0f /* at least 5 dB C/I */
|
||||
#define MIN_QUAL_NORM -0.5f /* at least -1 dB C/I */
|
||||
#define MIN_QUAL_RACH 50 /* minimum link quality (in centiBels) for Access Bursts */
|
||||
#define MIN_QUAL_NORM -5 /* minimum link quality (in centiBels) for Normal Bursts */
|
||||
|
||||
static void bts_update_agch_max_queue_length(struct gsm_bts *bts);
|
||||
|
||||
@@ -105,6 +106,22 @@ static const struct rate_ctr_group_desc bts_ctrg_desc = {
|
||||
bts_ctr_desc
|
||||
};
|
||||
|
||||
static const struct rate_ctr_desc cbch_ctr_desc[] = {
|
||||
[CBCH_CTR_RCVD_QUEUED] = {"cbch:rcvd_queued", "Received + queued CBCH messages (Abis)" },
|
||||
[CBCH_CTR_RCVD_DROPPED] = {"cbch:rcvd_dropped", "Received + dropped CBCH messages (Abis)" },
|
||||
|
||||
[CBCH_CTR_SENT_SINGLE] = {"cbch:sent_single", "Sent single CBCH messages (Um)" },
|
||||
[CBCH_CTR_SENT_DEFAULT] = {"cbch:sent_default", "Sent default CBCH messages (Um)" },
|
||||
[CBCH_CTR_SENT_NULL] = {"cbch:sent_null", "Sent NULL CBCH messages (Um)" },
|
||||
};
|
||||
static const struct rate_ctr_group_desc cbch_ctrg_desc = {
|
||||
"cbch",
|
||||
"cell broadcast channel",
|
||||
OSMO_STATS_CLASS_GLOBAL,
|
||||
ARRAY_SIZE(cbch_ctr_desc),
|
||||
cbch_ctr_desc
|
||||
};
|
||||
|
||||
/* Initialize the BTS data structures, called before config
|
||||
* file reading */
|
||||
int bts_init(struct gsm_bts *bts)
|
||||
@@ -122,6 +139,10 @@ int bts_init(struct gsm_bts *bts)
|
||||
bts->agch_queue.length = 0;
|
||||
|
||||
bts->ctrs = rate_ctr_group_alloc(bts, &bts_ctrg_desc, bts->nr);
|
||||
if (!bts->ctrs) {
|
||||
llist_del(&bts->list);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* enable management with default levels,
|
||||
* raise threshold to GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DISABLE to
|
||||
@@ -138,6 +159,7 @@ int bts_init(struct gsm_bts *bts)
|
||||
bts->rtp_port_range_start = 16384;
|
||||
bts->rtp_port_range_end = 17407;
|
||||
bts->rtp_port_range_next = bts->rtp_port_range_start;
|
||||
bts->rtp_ip_dscp = -1;
|
||||
|
||||
/* configurable via OML */
|
||||
bts->load.ccch.load_ind_period = 112;
|
||||
@@ -171,6 +193,9 @@ int bts_init(struct gsm_bts *bts)
|
||||
tall_rtp_ctx = talloc_pool(tall_bts_ctx, 262144);
|
||||
osmo_rtp_init(tall_rtp_ctx);
|
||||
|
||||
/* features implemented in 'common', available for all models */
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_ETWS_PN);
|
||||
|
||||
rc = bts_model_init(bts);
|
||||
if (rc < 0) {
|
||||
llist_del(&bts->list);
|
||||
@@ -186,13 +211,27 @@ int bts_init(struct gsm_bts *bts)
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
INIT_LLIST_HEAD(&bts->smscb_state.queue);
|
||||
INIT_LLIST_HEAD(&bts->smscb_basic.queue);
|
||||
bts->smscb_basic.ctrs = rate_ctr_group_alloc(bts, &cbch_ctrg_desc, 0);
|
||||
OSMO_ASSERT(bts->smscb_basic.ctrs);
|
||||
INIT_LLIST_HEAD(&bts->smscb_extended.queue);
|
||||
bts->smscb_extended.ctrs = rate_ctr_group_alloc(bts, &cbch_ctrg_desc, 1);
|
||||
OSMO_ASSERT(bts->smscb_extended.ctrs);
|
||||
bts->smscb_queue_max_len = 15;
|
||||
bts->smscb_queue_tgt_len = 2;
|
||||
bts->smscb_queue_hyst = 2;
|
||||
|
||||
INIT_LLIST_HEAD(&bts->oml_queue);
|
||||
|
||||
/* register DTX DL FSM */
|
||||
rc = osmo_fsm_register(&dtx_dl_amr_fsm);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
|
||||
bts->fn_stats.min = INT32_MAX;
|
||||
bts->fn_stats.max = INT32_MIN;
|
||||
bts->fn_stats.avg_count = 0;
|
||||
bts->fn_stats.avg_window = 256;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -218,6 +257,10 @@ int bts_trx_init(struct gsm_bts_trx *trx)
|
||||
tpp->ramp.step_size_mdB = to_mdB(2);
|
||||
tpp->ramp.step_interval_sec = 1;
|
||||
|
||||
/* IF BTS model doesn't DSP/HW support MS Power Control Loop, enable osmo algo by default: */
|
||||
if (!gsm_bts_has_feature(trx->bts, BTS_FEAT_MS_PWR_CTRL_DSP))
|
||||
trx->ms_pwr_ctl_soft = true;
|
||||
|
||||
rc = bts_model_trx_init(trx);
|
||||
if (rc < 0) {
|
||||
llist_del(&trx->list);
|
||||
@@ -254,7 +297,7 @@ void bts_shutdown(struct gsm_bts *bts, const char *reason)
|
||||
bts_model_trx_close(trx);
|
||||
}
|
||||
|
||||
/* shedule a timer to make sure select loop logic can run again
|
||||
/* schedule a timer to make sure select loop logic can run again
|
||||
* to dispatch any pending primitives */
|
||||
osmo_timer_schedule(&shutdown_timer, 3, 0);
|
||||
}
|
||||
@@ -309,10 +352,13 @@ int trx_link_estab(struct gsm_bts_trx *trx)
|
||||
rc = rsl_tx_rf_res(trx);
|
||||
else
|
||||
rc = bts_model_trx_deact_rf(trx);
|
||||
if (rc < 0)
|
||||
oml_fail_rep(OSMO_EVT_MAJ_RSL_FAIL,
|
||||
link ? "Failed to establish RSL link (%d)" :
|
||||
"Failed to deactivate RF (%d)", rc);
|
||||
if (rc < 0) {
|
||||
oml_tx_failure_event_rep(&trx->bb_transc.mo, NM_SEVER_MAJOR, OSMO_EVT_MAJ_RSL_FAIL,
|
||||
link ?
|
||||
"Failed to establish RSL link (%d)" :
|
||||
"Failed to deactivate RF (%d)", rc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -339,15 +385,56 @@ int trx_set_available(struct gsm_bts_trx *trx, int avail)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* prepare the per-SAPI T200 arrays for a given lchan */
|
||||
static int t200_by_lchan(int *t200_ms_dcch, int *t200_ms_acch, struct gsm_lchan *lchan)
|
||||
{
|
||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
|
||||
/* we have to compensate for the "RTS advance" due to the asynchronous interface between
|
||||
* the BTS (LAPDm) and the PHY/L1 (OsmoTRX or DSP in case of osmo-bts-{sysmo,lc15,oc2g,octphy} */
|
||||
int32_t fn_advance = bts_get_avg_fn_advance(bts);
|
||||
int32_t fn_advance_us = fn_advance * 4615;
|
||||
int fn_advance_ms = fn_advance_us / 1000;
|
||||
|
||||
t200_ms_acch[DL_SAPI0] = bts->t200_ms[T200_SACCH_SDCCH] + fn_advance_ms;
|
||||
t200_ms_acch[DL_SAPI3] = bts->t200_ms[T200_SACCH_SDCCH] + fn_advance_ms;
|
||||
|
||||
switch (lchan->type) {
|
||||
case GSM_LCHAN_SDCCH:
|
||||
t200_ms_dcch[DL_SAPI0] = bts->t200_ms[T200_SDCCH] + fn_advance_ms;
|
||||
t200_ms_dcch[DL_SAPI3] = bts->t200_ms[T200_SDCCH_SAPI3] + fn_advance_ms;
|
||||
break;
|
||||
case GSM_LCHAN_TCH_F:
|
||||
t200_ms_dcch[DL_SAPI0] = bts->t200_ms[T200_FACCH_F] + fn_advance_ms;
|
||||
t200_ms_dcch[DL_SAPI3] = bts->t200_ms[T200_FACCH_F] + fn_advance_ms;
|
||||
break;
|
||||
case GSM_LCHAN_TCH_H:
|
||||
t200_ms_dcch[DL_SAPI0] = bts->t200_ms[T200_FACCH_H] + fn_advance_ms;
|
||||
t200_ms_dcch[DL_SAPI3] = bts->t200_ms[T200_FACCH_H] + fn_advance_ms;
|
||||
break;
|
||||
default:
|
||||
/* Channels such as CCCH don't use lapdm DL, and hence no T200 is needed */
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lchan_init_lapdm(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct lapdm_channel *lc = &lchan->lapdm_ch;
|
||||
int t200_ms_dcch[_NR_DL_SAPI], t200_ms_acch[_NR_DL_SAPI];
|
||||
|
||||
lapdm_channel_init(lc, LAPDM_MODE_BTS);
|
||||
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
|
||||
lapdm_channel_set_l1(lc, NULL, lchan);
|
||||
if (t200_by_lchan(t200_ms_dcch, t200_ms_acch, lchan) == 0) {
|
||||
LOGPLCHAN(lchan, DLLAPD, LOGL_DEBUG,
|
||||
"Setting T200 D0=%u, D3=%u, S0=%u, S3=%u (all in ms)\n",
|
||||
t200_ms_dcch[DL_SAPI0], t200_ms_dcch[DL_SAPI3],
|
||||
t200_ms_acch[DL_SAPI0], t200_ms_acch[DL_SAPI3]);
|
||||
lapdm_channel_init2(lc, LAPDM_MODE_BTS, t200_ms_dcch, t200_ms_acch, lchan->type);
|
||||
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
|
||||
lapdm_channel_set_l1(lc, NULL, lchan);
|
||||
}
|
||||
/* We still need to set Rx callback to receive RACH requests: */
|
||||
lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
|
||||
oml_set_lchan_t200(lchan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -509,7 +596,7 @@ static int try_merge_imm_ass_rej(struct gsm48_imm_ass_rej *old_rej,
|
||||
return 0;
|
||||
|
||||
/* GSM 08.58, 5.7
|
||||
* -> The BTS may combine serveral IMM.ASS.REJ messages
|
||||
* -> The BTS may combine several IMM.ASS.REJ messages
|
||||
* -> Identical request refs in one message may be squeezed
|
||||
*
|
||||
* GSM 04.08, 9.1.20.2
|
||||
@@ -587,7 +674,7 @@ struct msgb *bts_agch_dequeue(struct gsm_bts *bts)
|
||||
/*
|
||||
* Remove lower prio messages if the queue has grown too long.
|
||||
*
|
||||
* \return 0 iff the number of messages in the queue would fit into the AGCH
|
||||
* \return 0 if the number of messages in the queue would fit into the AGCH
|
||||
* reserved part of the CCCH.
|
||||
*/
|
||||
static void compact_agch_queue(struct gsm_bts *bts)
|
||||
@@ -696,9 +783,9 @@ int bts_supports_cipher(struct gsm_bts *bts, int rsl_cipher)
|
||||
return sup > 0;
|
||||
}
|
||||
|
||||
int trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx)
|
||||
bool trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx)
|
||||
{
|
||||
return trx->ms_power_control == 1;
|
||||
return trx->ms_pwr_ctl_soft;
|
||||
}
|
||||
|
||||
struct gsm_time *get_time(struct gsm_bts *bts)
|
||||
@@ -711,6 +798,11 @@ int bts_supports_cm(struct gsm_bts *bts, enum gsm_phys_chan_config pchan,
|
||||
{
|
||||
enum gsm_bts_features feature = _NUM_BTS_FEAT;
|
||||
|
||||
/* We assume that signalling support is mandatory,
|
||||
* there is no BTS_FEAT_* definition to check that. */
|
||||
if (cm == GSM48_CMODE_SIGN)
|
||||
return 1;
|
||||
|
||||
/* Before the requested pchan/cm combination can be checked, we need to
|
||||
* convert it to a feature identifier we can check */
|
||||
switch (pchan) {
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <osmo-bts/oml.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
|
||||
static struct gsm_bts *g_bts;
|
||||
|
||||
CTRL_CMD_DEFINE(therm_att, "thermal-attenuation");
|
||||
static int get_therm_att(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
@@ -75,7 +77,7 @@ CTRL_CMD_DEFINE_WO_NOVRF(oml_alert, "oml-alert");
|
||||
static int set_oml_alert(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
/* Note: we expect signal dispatch to be synchronous */
|
||||
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_EXT_ALARM, cmd->value);
|
||||
oml_tx_failure_event_rep(&g_bts->mo, NM_SEVER_INDETERMINATE, OSMO_EVT_EXT_ALARM, cmd->value);
|
||||
|
||||
cmd->reply = "OK";
|
||||
|
||||
@@ -88,6 +90,7 @@ int bts_ctrl_cmds_install(struct gsm_bts *bts)
|
||||
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_therm_att);
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_oml_alert);
|
||||
g_bts = bts;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Cell Broadcast routines */
|
||||
|
||||
/* (C) 2014 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2014,2018-2019 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -26,16 +26,60 @@
|
||||
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/cbch.h>
|
||||
#include <osmo-bts/rsl.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
|
||||
/* internal representation of one SMS-CB message (e.g. in the pending queue */
|
||||
struct smscb_msg {
|
||||
struct llist_head list; /* list in smscb_state.queue */
|
||||
|
||||
bool is_schedule; /* is this a schedule message? */
|
||||
uint8_t msg[GSM412_MSG_LEN]; /* message buffer */
|
||||
uint8_t next_seg; /* next segment number */
|
||||
uint8_t num_segs; /* total number of segments */
|
||||
};
|
||||
|
||||
/* determine if current queue length differs more than permitted hysteresis from target
|
||||
* queue length. If it does, send CBCH LOAD IND */
|
||||
static void check_and_send_cbch_load(struct gsm_bts *bts, struct bts_smscb_state *bts_ss)
|
||||
{
|
||||
int delta = bts_ss->queue_len - bts->smscb_queue_tgt_len;
|
||||
bool extended_cbch = false;
|
||||
|
||||
if (bts_ss == &bts->smscb_extended)
|
||||
extended_cbch = true;
|
||||
|
||||
if (abs(delta) < bts->smscb_queue_hyst)
|
||||
return;
|
||||
|
||||
if (delta < 0) {
|
||||
/* Underrun */
|
||||
rsl_tx_cbch_load_indication(bts, extended_cbch, false, OSMO_MIN(15, -delta));
|
||||
} else {
|
||||
/* Overrun */
|
||||
rsl_tx_cbch_load_indication(bts, extended_cbch, true, OSMO_MIN(15, delta));
|
||||
}
|
||||
}
|
||||
|
||||
/* determine SMSCB state by tb number */
|
||||
static struct bts_smscb_state *bts_smscb_state(struct gsm_bts *bts, uint8_t tb)
|
||||
{
|
||||
if (tb < 4)
|
||||
return &bts->smscb_basic;
|
||||
else if (tb < 8)
|
||||
return &bts->smscb_extended;
|
||||
else
|
||||
OSMO_ASSERT(0);
|
||||
}
|
||||
|
||||
static const char *tb_to_chan_str(uint8_t tb)
|
||||
{
|
||||
if (tb < 4)
|
||||
return "CBCH-BASIC";
|
||||
else
|
||||
return "CBCH-EXTENDED";
|
||||
}
|
||||
|
||||
/* construct a SMSCB NULL block in the user-provided output buffer at 'out' */
|
||||
static int get_smscb_null_block(uint8_t *out)
|
||||
{
|
||||
struct gsm412_block_type *block_type = (struct gsm412_block_type *) out;
|
||||
@@ -50,17 +94,28 @@ static int get_smscb_null_block(uint8_t *out)
|
||||
}
|
||||
|
||||
/* get the next block of the current CB message */
|
||||
static int get_smscb_block(struct gsm_bts *bts, uint8_t *out)
|
||||
static int get_smscb_block(struct bts_smscb_state *bts_ss, uint8_t *out, uint8_t tb,
|
||||
const struct gsm_time *g_time)
|
||||
{
|
||||
int to_copy;
|
||||
struct gsm412_block_type *block_type;
|
||||
struct smscb_msg *msg = bts->smscb_state.cur_msg;
|
||||
struct smscb_msg *msg = bts_ss->cur_msg;
|
||||
uint8_t block_nr = tb % 4;
|
||||
const char *chan_name = tb_to_chan_str(tb);
|
||||
|
||||
if (!msg) {
|
||||
/* No message: Send NULL mesage */
|
||||
/* No message: Send NULL block */
|
||||
DEBUGPGT(DLSMS, g_time, "%s: No cur_msg; requesting NULL block\n", chan_name);
|
||||
return get_smscb_null_block(out);
|
||||
}
|
||||
OSMO_ASSERT(block_nr < 4);
|
||||
|
||||
if (block_nr >= msg->num_segs) {
|
||||
/* Higher block number than this message has blocks: Send NULL block */
|
||||
DEBUGPGT(DLSMS, g_time, "%s: cur_msg has only %u blocks; requesting NULL block\n",
|
||||
chan_name, msg->num_segs);
|
||||
return get_smscb_null_block(out);
|
||||
}
|
||||
OSMO_ASSERT(msg->next_seg < 4);
|
||||
|
||||
block_type = (struct gsm412_block_type *) out++;
|
||||
|
||||
@@ -69,27 +124,37 @@ static int get_smscb_block(struct gsm_bts *bts, uint8_t *out)
|
||||
block_type->lpd = 1;
|
||||
|
||||
/* determine how much data to copy */
|
||||
to_copy = GSM412_MSG_LEN - (msg->next_seg * GSM412_BLOCK_LEN);
|
||||
to_copy = GSM412_MSG_LEN - (block_nr * GSM412_BLOCK_LEN);
|
||||
if (to_copy > GSM412_BLOCK_LEN)
|
||||
to_copy = GSM412_BLOCK_LEN;
|
||||
to_copy = GSM412_BLOCK_LEN;
|
||||
OSMO_ASSERT(to_copy >= 0);
|
||||
|
||||
/* copy data and increment index */
|
||||
memcpy(out, &msg->msg[msg->next_seg * GSM412_BLOCK_LEN], to_copy);
|
||||
memcpy(out, &msg->msg[block_nr * GSM412_BLOCK_LEN], to_copy);
|
||||
|
||||
/* set + increment sequence number */
|
||||
block_type->seq_nr = msg->next_seg++;
|
||||
if (block_nr == 0 && msg->is_schedule)
|
||||
block_type->seq_nr = 8; /* first schedule block */
|
||||
else
|
||||
block_type->seq_nr = block_nr;
|
||||
|
||||
/* determine if this is the last block */
|
||||
if (block_type->seq_nr + 1 == msg->num_segs)
|
||||
if (block_nr + 1 == msg->num_segs)
|
||||
block_type->lb = 1;
|
||||
else
|
||||
block_type->lb = 0;
|
||||
|
||||
if (block_type->lb == 1) {
|
||||
/* remove/release the message memory */
|
||||
talloc_free(bts->smscb_state.cur_msg);
|
||||
bts->smscb_state.cur_msg = NULL;
|
||||
if (block_nr == 4) {
|
||||
if (msg != bts_ss->default_msg) {
|
||||
DEBUGPGT(DLSMS, g_time, "%s: deleting fully-transmitted message %p\n",
|
||||
chan_name, msg);
|
||||
/* delete any fully-transmitted normal message (or superseded default) */
|
||||
talloc_free(bts_ss->cur_msg);
|
||||
bts_ss->cur_msg = NULL;
|
||||
} else {
|
||||
DEBUGPGT(DLSMS, g_time, "%s: keeping fully-transmitted default message %p\n",
|
||||
chan_name, msg);
|
||||
}
|
||||
}
|
||||
|
||||
return block_type->lb;
|
||||
@@ -102,18 +167,34 @@ static const uint8_t last_block_rsl2um[4] = {
|
||||
[RSL_CB_CMD_LASTBLOCK_3] = 3,
|
||||
};
|
||||
|
||||
static const struct value_string rsl_cb_cmd_names[] = {
|
||||
{ RSL_CB_CMD_TYPE_NORMAL, "NORMAL" },
|
||||
{ RSL_CB_CMD_TYPE_SCHEDULE, "SCHEDULE" },
|
||||
{ RSL_CB_CMD_TYPE_DEFAULT, "DEFAULT" },
|
||||
{ RSL_CB_CMD_TYPE_NULL, "NULL" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
/* incoming SMS broadcast command from RSL */
|
||||
int bts_process_smscb_cmd(struct gsm_bts *bts,
|
||||
struct rsl_ie_cb_cmd_type cmd_type,
|
||||
uint8_t msg_len, const uint8_t *msg)
|
||||
int bts_process_smscb_cmd(struct gsm_bts *bts, struct rsl_ie_cb_cmd_type cmd_type,
|
||||
bool extended_cbch, uint8_t msg_len, const uint8_t *msg)
|
||||
{
|
||||
struct smscb_msg *scm;
|
||||
struct bts_smscb_state *bts_ss;
|
||||
const char *chan_name;
|
||||
|
||||
if (extended_cbch) {
|
||||
chan_name = tb_to_chan_str(4);
|
||||
bts_ss = &bts->smscb_extended;
|
||||
} else {
|
||||
chan_name = tb_to_chan_str(0);
|
||||
bts_ss = &bts->smscb_basic;
|
||||
}
|
||||
|
||||
if (msg_len > sizeof(scm->msg)) {
|
||||
LOGP(DLSMS, LOGL_ERROR,
|
||||
"Cannot process SMSCB of %u bytes (max %zu)\n",
|
||||
msg_len, sizeof(scm->msg));
|
||||
LOGP(DLSMS, LOGL_ERROR, "%s: Cannot process SMSCB of %u bytes (max %zu)\n",
|
||||
chan_name, msg_len, sizeof(scm->msg));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -123,42 +204,86 @@ int bts_process_smscb_cmd(struct gsm_bts *bts,
|
||||
|
||||
/* initialize entire message with default padding */
|
||||
memset(scm->msg, GSM_MACBLOCK_PADDING, sizeof(scm->msg));
|
||||
/* next segment is first segment */
|
||||
scm->next_seg = 0;
|
||||
|
||||
if (cmd_type.command == RSL_CB_CMD_TYPE_SCHEDULE)
|
||||
scm->is_schedule = true;
|
||||
|
||||
scm->num_segs = last_block_rsl2um[cmd_type.last_block&3];
|
||||
memcpy(scm->msg, msg, msg_len);
|
||||
|
||||
LOGP(DLSMS, LOGL_INFO, "RSL SMSCB COMMAND (chan=%s, type=%s, num_blocks=%u)\n",
|
||||
chan_name, get_value_string(rsl_cb_cmd_names, cmd_type.command), scm->num_segs);
|
||||
|
||||
switch (cmd_type.command) {
|
||||
case RSL_CB_CMD_TYPE_NORMAL:
|
||||
case RSL_CB_CMD_TYPE_SCHEDULE:
|
||||
case RSL_CB_CMD_TYPE_NULL:
|
||||
scm->num_segs = last_block_rsl2um[cmd_type.last_block&3];
|
||||
memcpy(scm->msg, msg, msg_len);
|
||||
/* def_bcast is ignored */
|
||||
/* def_bcast is ignored as per Section 9.3.41 of 3GPP TS 48.058 */
|
||||
/* limit queue size and optionally send CBCH LOAD Information (overflow) via RSL */
|
||||
if (bts_ss->queue_len >= bts->smscb_queue_max_len) {
|
||||
LOGP(DLSMS, LOGL_NOTICE, "RSL SMSCB COMMAND (chan=%s, type=%s): OVERFLOW\n",
|
||||
chan_name, get_value_string(rsl_cb_cmd_names, cmd_type.command));
|
||||
rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_RCVD_DROPPED);
|
||||
talloc_free(scm);
|
||||
break;
|
||||
}
|
||||
llist_add_tail(&scm->list, &bts_ss->queue);
|
||||
bts_ss->queue_len++;
|
||||
check_and_send_cbch_load(bts, bts_ss);
|
||||
rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_RCVD_QUEUED);
|
||||
break;
|
||||
case RSL_CB_CMD_TYPE_DEFAULT:
|
||||
/* use def_bcast, ignore command */
|
||||
/* def_bcast == 0: normal mess */
|
||||
/* old default msg will be free'd in get_smscb_block() if it is currently in transit
|
||||
* and we set a new default_msg here */
|
||||
if (bts_ss->cur_msg && bts_ss->cur_msg == bts_ss->default_msg)
|
||||
talloc_free(bts_ss->cur_msg);
|
||||
if (cmd_type.def_bcast == RSL_CB_CMD_DEFBCAST_NORMAL)
|
||||
/* def_bcast == 0: normal message */
|
||||
bts_ss->default_msg = scm;
|
||||
else {
|
||||
/* def_bcast == 1: NULL message */
|
||||
bts_ss->default_msg = NULL;
|
||||
talloc_free(scm);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
talloc_free(scm);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
llist_add_tail(&scm->list, &bts->smscb_state.queue);
|
||||
/* FIXME: limit queue size and optionally send CBCH LOAD Information (overflow) via RSL */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct smscb_msg *select_next_smscb(struct gsm_bts *bts)
|
||||
static struct smscb_msg *select_next_smscb(struct gsm_bts *bts, uint8_t tb)
|
||||
{
|
||||
struct bts_smscb_state *bts_ss = bts_smscb_state(bts, tb);
|
||||
const char *chan_name = tb_to_chan_str(tb);
|
||||
struct smscb_msg *msg;
|
||||
|
||||
msg = llist_first_entry_or_null(&bts->smscb_state.queue, struct smscb_msg, list);
|
||||
if (!msg) {
|
||||
/* FIXME: send CBCH LOAD Information (underflow) via RSL */
|
||||
return NULL;
|
||||
msg = llist_first_entry_or_null(&bts_ss->queue, struct smscb_msg, list);
|
||||
if (msg) {
|
||||
llist_del(&msg->list);
|
||||
bts_ss->queue_len--;
|
||||
check_and_send_cbch_load(bts, bts_ss);
|
||||
DEBUGP(DLSMS, "%s: %s: Dequeued msg\n", __func__, chan_name);
|
||||
rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_SENT_SINGLE);
|
||||
return msg;
|
||||
}
|
||||
|
||||
llist_del(&msg->list);
|
||||
/* send CBCH LOAD Information (underflow) via RSL */
|
||||
check_and_send_cbch_load(bts, bts_ss);
|
||||
|
||||
return msg;
|
||||
/* choose the default message, if any */
|
||||
msg = bts_ss->default_msg;
|
||||
if (msg) {
|
||||
DEBUGP(DLSMS, "%s: %s: Using default msg\n", __func__, chan_name);
|
||||
rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_SENT_DEFAULT);
|
||||
return msg;
|
||||
}
|
||||
|
||||
DEBUGP(DLSMS, "%s: %s: No queued msg nor default\n", __func__, chan_name);
|
||||
rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_SENT_NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* call-back from bts model specific code when it wants to obtain a CBCH
|
||||
@@ -166,10 +291,13 @@ static struct smscb_msg *select_next_smscb(struct gsm_bts *bts)
|
||||
int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time)
|
||||
{
|
||||
uint32_t fn = gsm_gsmtime2fn(g_time);
|
||||
struct bts_smscb_state *bts_ss;
|
||||
/* According to 05.02 Section 6.5.4 */
|
||||
uint32_t tb = (fn / 51) % 8;
|
||||
int rc = 0;
|
||||
|
||||
bts_ss = bts_smscb_state(bts, tb);
|
||||
|
||||
/* The multiframes used for the basic cell broadcast channel
|
||||
* shall be those in * which TB = 0,1,2 and 3. The multiframes
|
||||
* used for the extended cell broadcast channel shall be those
|
||||
@@ -181,16 +309,14 @@ int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time)
|
||||
|
||||
switch (tb) {
|
||||
case 0:
|
||||
case 4:
|
||||
/* select a new SMSCB message */
|
||||
bts->smscb_state.cur_msg = select_next_smscb(bts);
|
||||
rc = get_smscb_block(bts, outbuf);
|
||||
bts_ss->cur_msg = select_next_smscb(bts, tb);
|
||||
rc = get_smscb_block(bts_ss, outbuf, tb, g_time);
|
||||
break;
|
||||
case 1: case 2: case 3:
|
||||
rc = get_smscb_block(bts, outbuf);
|
||||
break;
|
||||
case 4: case 5: case 6: case 7:
|
||||
/* always send NULL frame in extended CBCH for now */
|
||||
rc = get_smscb_null_block(outbuf);
|
||||
case 5: case 6: case 7:
|
||||
rc = get_smscb_block(bts_ss, outbuf, tb, g_time);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/abis_nm.h>
|
||||
#include <osmocom/core/statistics.h>
|
||||
#include <osmocom/codec/ecu.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
@@ -38,6 +39,7 @@ void gsm_abis_mo_reset(struct gsm_abis_mo *mo)
|
||||
{
|
||||
mo->nm_state.operational = NM_OPSTATE_NULL;
|
||||
mo->nm_state.availability = NM_AVSTATE_POWER_OFF;
|
||||
mo->nm_state.administrative = NM_STATE_LOCKED;
|
||||
}
|
||||
|
||||
static void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts,
|
||||
@@ -105,6 +107,9 @@ const struct value_string gsm_bts_features_descs[] = {
|
||||
{ BTS_FEAT_SPEECH_F_EFR, "Fullrate speech EFR" },
|
||||
{ BTS_FEAT_SPEECH_F_AMR, "Fullrate speech AMR" },
|
||||
{ BTS_FEAT_SPEECH_H_AMR, "Halfrate speech AMR" },
|
||||
{ BTS_FEAT_ETWS_PN, "ETWS Primary Notification on PCH" },
|
||||
{ BTS_FEAT_MS_PWR_CTRL_DSP, "DSP/HW based MS Power Control Loop" },
|
||||
{ BTS_FEAT_MEAS_PAYLOAD_COMB, "Measurement and Payload data combined"},
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
@@ -222,10 +227,10 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
|
||||
|
||||
trx->bts = bts;
|
||||
trx->nr = bts->num_trx++;
|
||||
trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;
|
||||
|
||||
gsm_mo_init(&trx->mo, bts, NM_OC_RADIO_CARRIER,
|
||||
bts->nr, trx->nr, 0xff);
|
||||
|
||||
gsm_mo_init(&trx->bb_transc.mo, bts, NM_OC_BASEB_TRANSC,
|
||||
bts->nr, trx->nr, 0xff);
|
||||
|
||||
@@ -569,7 +574,7 @@ gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
|
||||
}
|
||||
|
||||
/* See Table 10.5.25 of GSM04.08 */
|
||||
uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
|
||||
static uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
|
||||
uint8_t ts_nr, uint8_t lchan_nr)
|
||||
{
|
||||
uint8_t cbits, chan_nr;
|
||||
@@ -691,7 +696,7 @@ struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
*rc = -EINVAL;
|
||||
|
||||
if (cbits == 0x01) {
|
||||
lch_idx = 0; /* TCH/F */
|
||||
lch_idx = 0; /* TCH/F */
|
||||
if (ts->pchan != GSM_PCHAN_TCH_F &&
|
||||
ts->pchan != GSM_PCHAN_PDCH &&
|
||||
ts->pchan != GSM_PCHAN_TCH_F_PDCH &&
|
||||
@@ -805,3 +810,24 @@ const struct value_string lchan_ciph_state_names[] = {
|
||||
{ LCHAN_CIPH_RXTX_CONF, "RXTX_CONF" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* determine the ECU codec constant for the codec used by given lchan */
|
||||
int lchan2ecu_codec(const struct gsm_lchan *lchan)
|
||||
{
|
||||
struct gsm_bts_trx_ts *ts = lchan->ts;
|
||||
|
||||
switch (lchan->tch_mode) {
|
||||
case GSM48_CMODE_SPEECH_V1:
|
||||
if (ts_pchan(ts) == GSM_PCHAN_TCH_H)
|
||||
return OSMO_ECU_CODEC_HR;
|
||||
else
|
||||
return OSMO_ECU_CODEC_FR;
|
||||
break;
|
||||
case GSM48_CMODE_SPEECH_EFR:
|
||||
return OSMO_ECU_CODEC_EFR;
|
||||
case GSM48_CMODE_SPEECH_AMR:
|
||||
return OSMO_ECU_CODEC_AMR;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,9 +44,7 @@ static int ho_tx_phys_info(struct gsm_lchan *lchan)
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
LOGP(DHO, LOGL_INFO,
|
||||
"%s Sending PHYSICAL INFORMATION to MS.\n",
|
||||
gsm_lchan_name(lchan));
|
||||
LOGPLCHAN(lchan, DHO, LOGL_INFO, "Sending PHYSICAL INFORMATION to MS.\n");
|
||||
|
||||
/* Build RSL UNITDATA REQUEST message with 04.08 PHYS INFO */
|
||||
msg->l3h = msg->data;
|
||||
@@ -68,20 +66,18 @@ static void ho_t3105_cb(void *data)
|
||||
struct gsm_lchan *lchan = data;
|
||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
|
||||
LOGP(DHO, LOGL_INFO, "%s T3105 timeout (%d resends left)\n",
|
||||
gsm_lchan_name(lchan), bts->ny1 - lchan->ho.phys_info_count);
|
||||
LOGPLCHAN(lchan, DHO, LOGL_INFO, "T3105 timeout (%d resends left)\n",
|
||||
bts->ny1 - lchan->ho.phys_info_count);
|
||||
|
||||
if (lchan->state != LCHAN_S_ACTIVE) {
|
||||
LOGP(DHO, LOGL_NOTICE,
|
||||
"%s is in not active. It is in state %s. Ignoring\n",
|
||||
gsm_lchan_name(lchan), gsm_lchans_name(lchan->state));
|
||||
LOGPLCHAN(lchan, DHO, LOGL_NOTICE, "is in not active. It is in state %s. Ignoring\n",
|
||||
gsm_lchans_name(lchan->state));
|
||||
return;
|
||||
}
|
||||
|
||||
if (lchan->ho.phys_info_count >= bts->ny1) {
|
||||
/* HO Abort */
|
||||
LOGP(DHO, LOGL_NOTICE, "%s NY1 reached, sending CONNection "
|
||||
"FAILure to BSC.\n", gsm_lchan_name(lchan));
|
||||
LOGPLCHAN(lchan, DHO, LOGL_NOTICE, "NY1 reached, sending CONNection FAILure to BSC.\n");
|
||||
rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
|
||||
return;
|
||||
}
|
||||
@@ -98,23 +94,21 @@ void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
|
||||
|
||||
/* Ignore invalid handover ref */
|
||||
if (lchan->ho.ref != ra) {
|
||||
LOGP(DHO, LOGL_INFO, "%s RACH on dedicated channel received, but "
|
||||
"ra=0x%02x != expected ref=0x%02x. (This is no bug)\n",
|
||||
gsm_lchan_name(lchan), ra, lchan->ho.ref);
|
||||
LOGPLCHAN(lchan, DHO, LOGL_INFO, "RACH on dedicated channel received, but "
|
||||
"ra=0x%02x != expected ref=0x%02x. (This is no bug)\n", ra, lchan->ho.ref);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore handover on channels other than DCCH and SACCH */
|
||||
if (lchan->type != GSM_LCHAN_SDCCH && lchan->type != GSM_LCHAN_TCH_H &&
|
||||
lchan->type != GSM_LCHAN_TCH_F) {
|
||||
LOGP(DHO, LOGL_ERROR, "%s handover RACH received on %s?!\n",
|
||||
gsm_lchan_name(lchan), gsm_lchant_name(lchan->type));
|
||||
LOGPLCHAN(lchan, DHO, LOGL_ERROR, "handover RACH received on %s?!\n",
|
||||
gsm_lchant_name(lchan->type));
|
||||
return;
|
||||
}
|
||||
|
||||
LOGP(DHO, LOGL_NOTICE,
|
||||
"%s RACH on dedicated channel type %s received with TA=%u, ref=%u\n",
|
||||
gsm_lchan_name(lchan), gsm_lchant_name(lchan->type), acc_delay, ra);
|
||||
LOGPLCHAN(lchan, DHO, LOGL_NOTICE, "RACH on dedicated channel type %s received with "
|
||||
"TA=%u, ref=%u\n", gsm_lchant_name(lchan->type), acc_delay, ra);
|
||||
|
||||
/* Set timing advance */
|
||||
lchan->rqd_ta = acc_delay;
|
||||
@@ -122,9 +116,7 @@ void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
|
||||
/* Stop handover detection, wait for valid frame */
|
||||
lchan->ho.active = HANDOVER_WAIT_FRAME;
|
||||
if (l1sap_chan_modify(lchan->ts->trx, gsm_lchan2chan_nr(lchan)) != 0) {
|
||||
LOGP(DHO, LOGL_ERROR,
|
||||
"%s failed to modify channel after handover\n",
|
||||
gsm_lchan_name(lchan));
|
||||
LOGPLCHAN(lchan, DHO, LOGL_ERROR, "failed to modify channel after handover\n");
|
||||
rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
|
||||
return;
|
||||
}
|
||||
@@ -137,19 +129,16 @@ void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
|
||||
ho_tx_phys_info(lchan);
|
||||
|
||||
/* Start T3105 */
|
||||
LOGP(DHO, LOGL_DEBUG,
|
||||
"%s Starting T3105 with %u ms\n",
|
||||
gsm_lchan_name(lchan), bts->t3105_ms);
|
||||
LOGPLCHAN(lchan, DHO, LOGL_DEBUG, "Starting T3105 with %u ms\n", bts->t3105_ms);
|
||||
lchan->ho.t3105.cb = ho_t3105_cb;
|
||||
lchan->ho.t3105.data = lchan;
|
||||
osmo_timer_schedule(&lchan->ho.t3105, 0, bts->t3105_ms * 1000);
|
||||
}
|
||||
|
||||
/* received frist valid data frame on dedicated channel */
|
||||
/* received first valid data frame on dedicated channel */
|
||||
void handover_frame(struct gsm_lchan *lchan)
|
||||
{
|
||||
LOGP(DHO, LOGL_INFO,
|
||||
"%s First valid frame detected\n", gsm_lchan_name(lchan));
|
||||
LOGPLCHAN(lchan, DHO, LOGL_INFO, "First valid frame detected\n");
|
||||
handover_reset(lchan);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,9 +114,8 @@ get_active_lchan_by_chan_nr(struct gsm_bts_trx *trx, unsigned int chan_nr)
|
||||
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr);
|
||||
|
||||
if (lchan && lchan->state != LCHAN_S_ACTIVE) {
|
||||
LOGP(DL1P, LOGL_NOTICE, "%s: assuming active lchan, but "
|
||||
"state is %s\n", gsm_lchan_name(lchan),
|
||||
gsm_lchans_name(lchan->state));
|
||||
LOGPLCHAN(lchan, DL1P, LOGL_NOTICE, "assuming active lchan, but state is %s\n",
|
||||
gsm_lchans_name(lchan->state));
|
||||
return NULL;
|
||||
}
|
||||
return lchan;
|
||||
@@ -139,9 +138,9 @@ static uint32_t fn_ms_adj(uint32_t fn, const struct gsm_lchan *lchan)
|
||||
r -= r % GSM_RTP_DURATION;
|
||||
|
||||
if (r != GSM_RTP_DURATION)
|
||||
LOGP(DRTP, LOGL_ERROR, "RTP clock out of sync with lower layer:"
|
||||
" %"PRIu32" vs %d (%"PRIu32"->%"PRIu32")\n",
|
||||
r, GSM_RTP_DURATION, lchan->tch.last_fn, fn);
|
||||
LOGPLCHAN(lchan, DRTP, LOGL_ERROR, "RTP clock out of sync with lower layer:"
|
||||
" %"PRIu32" vs %d (%"PRIu32"->%"PRIu32")\n",
|
||||
r, GSM_RTP_DURATION, lchan->tch.last_fn, fn);
|
||||
}
|
||||
return GSM_RTP_DURATION;
|
||||
}
|
||||
@@ -161,7 +160,7 @@ static void queue_limit_to(const char *prefix, struct llist_head *queue, unsigne
|
||||
}
|
||||
|
||||
/* allocate a msgb containing a osmo_phsap_prim + optional l2 data
|
||||
* in order to wrap femtobts header arround l2 data, there must be enough space
|
||||
* in order to wrap femtobts header around l2 data, there must be enough space
|
||||
* in front and behind data pointer */
|
||||
struct msgb *l1sap_msgb_alloc(unsigned int l2_len)
|
||||
{
|
||||
@@ -177,14 +176,19 @@ struct msgb *l1sap_msgb_alloc(unsigned int l2_len)
|
||||
return msg;
|
||||
}
|
||||
|
||||
/* Enclose rmsg into an osmo_phsap primitive and hand it over to the higher
|
||||
* layers. The phsap primitive also contains measurement information. The
|
||||
* parameters rssi, ta_offs and is_sub are only needed when the measurement
|
||||
* information is passed along with the TCH data. When separate measurement
|
||||
* indications are used, those last three parameters may be set to zero. */
|
||||
int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg,
|
||||
struct gsm_lchan *lchan, uint8_t chan_nr, uint32_t fn,
|
||||
uint16_t ber10k, int16_t lqual_cb)
|
||||
uint16_t ber10k, int16_t lqual_cb, int8_t rssi,
|
||||
int16_t ta_offs, uint8_t is_sub)
|
||||
{
|
||||
struct osmo_phsap_prim *l1sap;
|
||||
|
||||
LOGP(DL1P, LOGL_DEBUG, "%s Rx -> RTP: %s\n",
|
||||
gsm_lchan_name(lchan), osmo_hexdump(rmsg->data, rmsg->len));
|
||||
LOGPLCHAN(lchan, DL1P, LOGL_DEBUG, "Rx -> RTP: %s\n", osmo_hexdump(rmsg->data, rmsg->len));
|
||||
|
||||
rmsg->l2h = rmsg->data;
|
||||
rmsg->l1h = msgb_push(rmsg, sizeof(*l1sap));
|
||||
@@ -196,6 +200,10 @@ int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg,
|
||||
l1sap->u.tch.ber10k = ber10k;
|
||||
l1sap->u.tch.lqual_cb = lqual_cb;
|
||||
|
||||
l1sap->u.tch.rssi = rssi;
|
||||
l1sap->u.tch.ta_offs_256bits = ta_offs;
|
||||
l1sap->u.tch.is_sub = is_sub;
|
||||
|
||||
return l1sap_up(trx, l1sap);
|
||||
}
|
||||
|
||||
@@ -259,6 +267,85 @@ int bts_check_for_ciph_cmd(struct msgb *msg, struct gsm_lchan *lchan,
|
||||
return check_for_ciph_cmd(msg, lchan, chan_nr);
|
||||
}
|
||||
|
||||
uint16_t l1sap_log_ctx_sapi;
|
||||
|
||||
const struct value_string l1sap_common_sapi_names[] = {
|
||||
{ L1SAP_COMMON_SAPI_UNKNOWN, "UNKNOWN" },
|
||||
/* alphabetic order */
|
||||
{ L1SAP_COMMON_SAPI_AGCH, "AGCH" },
|
||||
{ L1SAP_COMMON_SAPI_BCCH, "BCCH" },
|
||||
{ L1SAP_COMMON_SAPI_CBCH, "CBCH" },
|
||||
{ L1SAP_COMMON_SAPI_FACCH_F, "FACCH/F" },
|
||||
{ L1SAP_COMMON_SAPI_FACCH_H, "FACCH/H" },
|
||||
{ L1SAP_COMMON_SAPI_FCCH, "FCCH" },
|
||||
{ L1SAP_COMMON_SAPI_IDLE, "IDLE" },
|
||||
{ L1SAP_COMMON_SAPI_NCH, "NCH" },
|
||||
{ L1SAP_COMMON_SAPI_PACCH, "PACCH" },
|
||||
{ L1SAP_COMMON_SAPI_PAGCH, "PAGCH" },
|
||||
{ L1SAP_COMMON_SAPI_PBCCH, "PBCCH" },
|
||||
{ L1SAP_COMMON_SAPI_PCH, "PCH" },
|
||||
{ L1SAP_COMMON_SAPI_PDTCH, "PDTCH" },
|
||||
{ L1SAP_COMMON_SAPI_PNCH, "PNCH" },
|
||||
{ L1SAP_COMMON_SAPI_PPCH, "PPCH" },
|
||||
{ L1SAP_COMMON_SAPI_PRACH, "PRACH" },
|
||||
{ L1SAP_COMMON_SAPI_PTCCH, "PTCCH" },
|
||||
{ L1SAP_COMMON_SAPI_RACH, "RACH" },
|
||||
{ L1SAP_COMMON_SAPI_SACCH, "SACCH" },
|
||||
{ L1SAP_COMMON_SAPI_SCH, "SCH" },
|
||||
{ L1SAP_COMMON_SAPI_SDCCH, "SDCCH" },
|
||||
{ L1SAP_COMMON_SAPI_TCH_F, "TCH/F" },
|
||||
{ L1SAP_COMMON_SAPI_TCH_H, "TCH/H" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static enum l1sap_common_sapi get_common_sapi_ph_data(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
||||
{
|
||||
uint8_t link_id = l1sap->u.data.link_id;
|
||||
uint8_t chan_nr = l1sap->u.data.chan_nr;
|
||||
uint32_t u32Fn = l1sap->u.data.fn;
|
||||
|
||||
if (L1SAP_IS_CHAN_TCHF(chan_nr))
|
||||
return L1SAP_COMMON_SAPI_TCH_F;
|
||||
|
||||
if (L1SAP_IS_CHAN_TCHH(chan_nr))
|
||||
return L1SAP_COMMON_SAPI_TCH_H;
|
||||
|
||||
if (L1SAP_IS_CHAN_SDCCH4(chan_nr) || L1SAP_IS_CHAN_SDCCH8(chan_nr))
|
||||
return L1SAP_COMMON_SAPI_SDCCH;
|
||||
|
||||
if (L1SAP_IS_CHAN_BCCH(chan_nr))
|
||||
return L1SAP_COMMON_SAPI_BCCH;
|
||||
|
||||
if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr))
|
||||
/* The sapi depends on DSP configuration, not on the actual SYSTEM INFORMATION 3. */
|
||||
return ((l1sap_fn2ccch_block(u32Fn) >= num_agch(trx, "PH-DATA-REQ"))
|
||||
? L1SAP_COMMON_SAPI_PCH
|
||||
: L1SAP_COMMON_SAPI_AGCH);
|
||||
|
||||
if (L1SAP_IS_CHAN_CBCH(chan_nr))
|
||||
return L1SAP_COMMON_SAPI_CBCH;
|
||||
|
||||
if (L1SAP_IS_LINK_SACCH(link_id))
|
||||
return L1SAP_COMMON_SAPI_SACCH;
|
||||
|
||||
return L1SAP_COMMON_SAPI_UNKNOWN;
|
||||
}
|
||||
|
||||
static enum l1sap_common_sapi get_common_sapi_by_trx_prim(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
||||
{
|
||||
/* Only downlink prims are relevant */
|
||||
switch (OSMO_PRIM_HDR(&l1sap->oph)) {
|
||||
case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST):
|
||||
if (ts_is_pdch(&trx->ts[L1SAP_CHAN2TS(l1sap->u.data.chan_nr)]))
|
||||
return ((L1SAP_IS_PTCCH(l1sap->u.data.fn))
|
||||
? L1SAP_COMMON_SAPI_PTCCH
|
||||
: L1SAP_COMMON_SAPI_PDTCH);
|
||||
return get_common_sapi_ph_data(trx, l1sap);
|
||||
default:
|
||||
return L1SAP_COMMON_SAPI_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
struct gsmtap_inst *gsmtap = NULL;
|
||||
uint32_t gsmtap_sapi_mask = 0;
|
||||
uint8_t gsmtap_sapi_acch = 0;
|
||||
@@ -335,15 +422,10 @@ static int gsmtap_pdch(struct osmo_phsap_prim *l1sap, uint8_t *chan_type,
|
||||
if (L1SAP_IS_PTCCH(fn)) {
|
||||
*chan_type = GSMTAP_CHANNEL_PTCCH;
|
||||
*ss = L1SAP_FN2PTCCHBLOCK(fn);
|
||||
if (l1sap->oph.primitive == PRIM_OP_INDICATION) {
|
||||
OSMO_ASSERT(len > 0);
|
||||
if ((*data[0]) == 7)
|
||||
return -EINVAL;
|
||||
(*data)++;
|
||||
(*len)--;
|
||||
}
|
||||
} else
|
||||
*chan_type = GSMTAP_CHANNEL_PACCH;
|
||||
} else {
|
||||
/* TODO: distinguish PACCH */
|
||||
*chan_type = GSMTAP_CHANNEL_PDTCH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -351,20 +433,29 @@ static int gsmtap_pdch(struct osmo_phsap_prim *l1sap, uint8_t *chan_type,
|
||||
static int gsmtap_ph_rach(struct osmo_phsap_prim *l1sap, uint8_t *chan_type,
|
||||
uint8_t *tn, uint8_t *ss, uint32_t *fn, uint8_t **data, unsigned int *len)
|
||||
{
|
||||
uint8_t chan_nr;
|
||||
uint8_t chan_nr = l1sap->u.rach_ind.chan_nr;
|
||||
|
||||
*chan_type = GSMTAP_CHANNEL_RACH;
|
||||
*fn = l1sap->u.rach_ind.fn;
|
||||
*tn = L1SAP_CHAN2TS(l1sap->u.rach_ind.chan_nr);
|
||||
chan_nr = l1sap->u.rach_ind.chan_nr;
|
||||
*tn = L1SAP_CHAN2TS(chan_nr);
|
||||
|
||||
if (L1SAP_IS_CHAN_TCHH(chan_nr))
|
||||
*ss = L1SAP_CHAN2SS_TCHH(chan_nr);
|
||||
else if (L1SAP_IS_CHAN_SDCCH4(chan_nr))
|
||||
*ss = L1SAP_CHAN2SS_SDCCH4(chan_nr);
|
||||
else if (L1SAP_IS_CHAN_SDCCH8(chan_nr))
|
||||
*ss = L1SAP_CHAN2SS_SDCCH8(chan_nr);
|
||||
else if (L1SAP_IS_CHAN_PDCH(chan_nr)) {
|
||||
if (L1SAP_IS_PTCCH(*fn)) {
|
||||
/* TODO: calculate sub-slot from frame-number */
|
||||
*chan_type = GSMTAP_CHANNEL_PTCCH;
|
||||
} else {
|
||||
*chan_type = GSMTAP_CHANNEL_PDTCH;
|
||||
}
|
||||
}
|
||||
|
||||
*data = (uint8_t *)&l1sap->u.rach_ind.ra;
|
||||
*len = 1;
|
||||
*len = (l1sap->u.rach_ind.is_11bit) ? 2 : 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -377,6 +468,9 @@ static const uint8_t paging_fill[GSM_MACBLOCK_LEN] = {
|
||||
|
||||
static bool is_fill_frame(uint8_t chan_type, const uint8_t *data, unsigned int len)
|
||||
{
|
||||
if (len != GSM_MACBLOCK_LEN)
|
||||
return false;
|
||||
|
||||
switch (chan_type) {
|
||||
case GSMTAP_CHANNEL_AGCH:
|
||||
if (!memcmp(data, fill_frame, GSM_MACBLOCK_LEN))
|
||||
@@ -486,10 +580,7 @@ static unsigned int calc_exprd_rach_frames(struct gsm_bts *bts, uint32_t fn)
|
||||
rach_frames_expired = 1;
|
||||
}
|
||||
|
||||
/* Each Frame has room for 4 RACH slots, since RACH
|
||||
* slots are short enough to fit into a single radio
|
||||
* burst, so we need to multiply the final result by 4 */
|
||||
return rach_frames_expired * 4;
|
||||
return rach_frames_expired;
|
||||
}
|
||||
|
||||
/* time information received from bts model */
|
||||
@@ -498,6 +589,7 @@ static int l1sap_info_time_ind(struct gsm_bts *bts,
|
||||
struct info_time_ind_param *info_time_ind)
|
||||
{
|
||||
int frames_expired;
|
||||
int i;
|
||||
|
||||
DEBUGPFN(DL1P, info_time_ind->fn, "Rx MPH_INFO time ind\n");
|
||||
|
||||
@@ -518,8 +610,10 @@ static int l1sap_info_time_ind(struct gsm_bts *bts,
|
||||
|
||||
/* increment number of RACH slots that have passed by since the
|
||||
* last time indication */
|
||||
bts->load.rach.total +=
|
||||
calc_exprd_rach_frames(bts, info_time_ind->fn) * frames_expired;
|
||||
for (i = 0; i < frames_expired; i++) {
|
||||
uint32_t fn = (info_time_ind->fn + GSM_HYPERFRAME - i) % GSM_HYPERFRAME;
|
||||
bts->load.rach.total += calc_exprd_rach_frames(bts, fn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -530,8 +624,8 @@ static inline void set_ms_to_data(struct gsm_lchan *lchan, int16_t data, bool se
|
||||
return;
|
||||
|
||||
if (data + 63 > 255) { /* According to 3GPP TS 48.058 §9.3.37 Timing Offset field cannot exceed 255 */
|
||||
LOGP(DL1P, LOGL_ERROR, "Attempting to set invalid Timing Offset value %d (MS TO = %u)!\n",
|
||||
data, set_ms_to);
|
||||
LOGPLCHAN(lchan, DL1P, LOGL_ERROR, "Attempting to set invalid Timing Offset value "
|
||||
"%d (MS TO = %u)!\n", data, set_ms_to);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -545,45 +639,96 @@ static inline void set_ms_to_data(struct gsm_lchan *lchan, int16_t data, bool se
|
||||
}
|
||||
|
||||
/* measurement information received from bts model */
|
||||
static int l1sap_info_meas_ind(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap,
|
||||
struct info_meas_ind_param *info_meas_ind)
|
||||
static void process_l1sap_meas_data(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap,
|
||||
enum osmo_ph_prim ind_type)
|
||||
{
|
||||
struct bts_ul_meas ulm;
|
||||
struct gsm_lchan *lchan;
|
||||
struct info_meas_ind_param *info_meas_ind;
|
||||
struct ph_data_param *ph_data_ind;
|
||||
struct ph_tch_param *ph_tch_ind;
|
||||
uint8_t chan_nr;
|
||||
uint32_t fn;
|
||||
uint8_t inv_rssi;
|
||||
uint8_t is_sub;
|
||||
int16_t ta_offs_256bits;
|
||||
uint16_t ber10k;
|
||||
const char *ind_name;
|
||||
|
||||
lchan = get_active_lchan_by_chan_nr(trx, info_meas_ind->chan_nr);
|
||||
if (!lchan) {
|
||||
LOGPFN(DL1P, LOGL_ERROR, info_meas_ind->fn,
|
||||
"No lchan for MPH INFO MEAS IND (chan_nr=%s)\n", rsl_chan_nr_str(info_meas_ind->chan_nr));
|
||||
return 0;
|
||||
switch (ind_type) {
|
||||
case PRIM_MPH_INFO:
|
||||
/* (legacy way, see also OS#2977) */
|
||||
info_meas_ind = &l1sap->u.info.u.meas_ind;
|
||||
chan_nr = info_meas_ind->chan_nr;
|
||||
fn = info_meas_ind->fn;
|
||||
inv_rssi = info_meas_ind->inv_rssi;
|
||||
is_sub = info_meas_ind->is_sub;
|
||||
ta_offs_256bits = info_meas_ind->ta_offs_256bits;
|
||||
ber10k = info_meas_ind->ber10k;
|
||||
ind_name = "MPH INFO";
|
||||
break;
|
||||
case PRIM_TCH:
|
||||
ph_tch_ind = &l1sap->u.tch;
|
||||
if (ph_tch_ind->rssi == 0)
|
||||
return;
|
||||
chan_nr = ph_tch_ind->chan_nr;
|
||||
fn = ph_tch_ind->fn;
|
||||
inv_rssi = abs(ph_tch_ind->rssi);
|
||||
is_sub = ph_tch_ind->is_sub;
|
||||
ta_offs_256bits = ph_tch_ind->ta_offs_256bits;
|
||||
ber10k = ph_tch_ind->ber10k;
|
||||
ind_name = "TCH";
|
||||
break;
|
||||
case PRIM_PH_DATA:
|
||||
ph_data_ind = &l1sap->u.data;
|
||||
if (ph_data_ind->rssi == 0)
|
||||
return;
|
||||
chan_nr = ph_data_ind->chan_nr;
|
||||
fn = ph_data_ind->fn;
|
||||
inv_rssi = abs(ph_data_ind->rssi);
|
||||
is_sub = ph_data_ind->is_sub;
|
||||
ta_offs_256bits = ph_data_ind->ta_offs_256bits;
|
||||
ber10k = ph_data_ind->ber10k;
|
||||
ind_name = "DATA";
|
||||
break;
|
||||
default:
|
||||
OSMO_ASSERT(false);
|
||||
}
|
||||
|
||||
DEBUGPFN(DL1P, info_meas_ind->fn,
|
||||
"%s MPH_INFO meas ind, ta_offs_256bits=%d, ber10k=%d, inv_rssi=%u\n",
|
||||
gsm_lchan_name(lchan), info_meas_ind->ta_offs_256bits,
|
||||
info_meas_ind->ber10k, info_meas_ind->inv_rssi);
|
||||
lchan = get_active_lchan_by_chan_nr(trx, chan_nr);
|
||||
if (!lchan) {
|
||||
LOGPFN(DL1P, LOGL_ERROR, fn,
|
||||
"No lchan for %s MEAS IND (chan_nr=%s)\n",
|
||||
ind_name, rsl_chan_nr_str(chan_nr));
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGPFN(DL1P, fn,
|
||||
"%s %s meas ind, ta_offs_256bits=%d, ber10k=%d, inv_rssi=%u\n",
|
||||
gsm_lchan_name(lchan), ind_name, ta_offs_256bits, ber10k,
|
||||
inv_rssi);
|
||||
|
||||
/* in the GPRS case we are not interested in measurement
|
||||
* processing. The PCU will take care of it */
|
||||
if (lchan->type == GSM_LCHAN_PDTCH)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
memset(&ulm, 0, sizeof(ulm));
|
||||
ulm.ta_offs_256bits = info_meas_ind->ta_offs_256bits;
|
||||
ulm.ber10k = info_meas_ind->ber10k;
|
||||
ulm.inv_rssi = info_meas_ind->inv_rssi;
|
||||
ulm.is_sub = info_meas_ind->is_sub;
|
||||
ulm.ta_offs_256bits = ta_offs_256bits;
|
||||
ulm.ber10k = ber10k;
|
||||
ulm.inv_rssi = inv_rssi;
|
||||
ulm.is_sub = is_sub;
|
||||
|
||||
/* we assume that symbol period is 1 bit: */
|
||||
set_ms_to_data(lchan, info_meas_ind->ta_offs_256bits / 256, true);
|
||||
set_ms_to_data(lchan, ta_offs_256bits / 256, true);
|
||||
|
||||
lchan_meas_process_measurement(lchan, &ulm, info_meas_ind->fn);
|
||||
lchan_meas_process_measurement(lchan, &ulm, fn);
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* any L1 MPH_INFO indication prim recevied from bts model */
|
||||
/* any L1 MPH_INFO indication prim received from bts model */
|
||||
static int l1sap_mph_info_ind(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap, struct mph_info_param *info)
|
||||
{
|
||||
@@ -601,7 +746,12 @@ static int l1sap_mph_info_ind(struct gsm_bts_trx *trx,
|
||||
&info->u.time_ind);
|
||||
break;
|
||||
case PRIM_INFO_MEAS:
|
||||
rc = l1sap_info_meas_ind(trx, l1sap, &info->u.meas_ind);
|
||||
/* We should never get an INFO_IND with PRIM_INFO_MEAS
|
||||
* when BTS_FEAT_MEAS_PAYLOAD_COMB is enabled */
|
||||
if (gsm_bts_has_feature(trx->bts, BTS_FEAT_MEAS_PAYLOAD_COMB))
|
||||
OSMO_ASSERT(false);
|
||||
|
||||
process_l1sap_meas_data(trx, l1sap, PRIM_MPH_INFO);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_NOTICE, "unknown MPH_INFO ind type %d\n",
|
||||
@@ -617,12 +767,10 @@ static int l1sap_info_act_cnf(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap,
|
||||
struct info_act_cnf_param *info_act_cnf)
|
||||
{
|
||||
struct gsm_lchan *lchan;
|
||||
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, info_act_cnf->chan_nr);
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "activate confirm chan_nr=%s trx=%d\n",
|
||||
rsl_chan_nr_str(info_act_cnf->chan_nr), trx->nr);
|
||||
|
||||
lchan = get_lchan_by_chan_nr(trx, info_act_cnf->chan_nr);
|
||||
LOGPLCHAN(lchan, DL1C, LOGL_INFO, "activate confirm chan_nr=%s trx=%d\n",
|
||||
rsl_chan_nr_str(info_act_cnf->chan_nr), trx->nr);
|
||||
|
||||
rsl_tx_chan_act_acknack(lchan, info_act_cnf->cause);
|
||||
|
||||
@@ -642,12 +790,10 @@ static int l1sap_info_rel_cnf(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap,
|
||||
struct info_act_cnf_param *info_act_cnf)
|
||||
{
|
||||
struct gsm_lchan *lchan;
|
||||
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, info_act_cnf->chan_nr);
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "deactivate confirm chan_nr=%s trx=%d\n",
|
||||
rsl_chan_nr_str(info_act_cnf->chan_nr), trx->nr);
|
||||
|
||||
lchan = get_lchan_by_chan_nr(trx, info_act_cnf->chan_nr);
|
||||
LOGPLCHAN(lchan, DL1C, LOGL_INFO, "deactivate confirm chan_nr=%s trx=%d\n",
|
||||
rsl_chan_nr_str(info_act_cnf->chan_nr), trx->nr);
|
||||
|
||||
rsl_tx_rf_rel_ack(lchan);
|
||||
|
||||
@@ -661,7 +807,7 @@ static int l1sap_info_rel_cnf(struct gsm_bts_trx *trx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* any L1 MPH_INFO confirm prim recevied from bts model */
|
||||
/* any L1 MPH_INFO confirm prim received from bts model */
|
||||
static int l1sap_mph_info_cnf(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap, struct mph_info_param *info)
|
||||
{
|
||||
@@ -721,10 +867,37 @@ static int lchan_pdtch_ph_rts_ind_loop(struct gsm_lchan *lchan,
|
||||
int is_ccch_for_agch(struct gsm_bts_trx *trx, uint32_t fn) {
|
||||
/* Note: The number of available access grant channels is set by the
|
||||
* parameter BS_AG_BLKS_RES via system information type 3. This SI is
|
||||
* transfered to osmo-bts via RSL */
|
||||
* transferred to osmo-bts via RSL */
|
||||
return l1sap_fn2ccch_block(fn) < num_agch(trx, "PH-RTS-IND");
|
||||
}
|
||||
|
||||
/* return the measured average of frame numbers that the RTS clock is running in advance */
|
||||
int32_t bts_get_avg_fn_advance(struct gsm_bts *bts)
|
||||
{
|
||||
if (bts->fn_stats.avg_count == 0)
|
||||
return 0;
|
||||
return bts->fn_stats.avg256 / bts->fn_stats.avg_count;
|
||||
}
|
||||
|
||||
static void l1sap_update_fnstats(struct gsm_bts *bts, uint32_t rts_fn)
|
||||
{
|
||||
int32_t delta = (rts_fn + GSM_HYPERFRAME - bts->gsm_time.fn) % GSM_HYPERFRAME;
|
||||
|
||||
if (delta < bts->fn_stats.min)
|
||||
bts->fn_stats.min = delta;
|
||||
if (delta > bts->fn_stats.max)
|
||||
bts->fn_stats.max = delta;
|
||||
|
||||
if (bts->fn_stats.avg_count > bts->fn_stats.avg_window) {
|
||||
/* reset and start old average and new sample */
|
||||
bts->fn_stats.avg256 = (bts->fn_stats.avg256 / bts->fn_stats.avg_count) + delta;
|
||||
bts->fn_stats.avg_count = 2;
|
||||
} else {
|
||||
bts->fn_stats.avg256 += delta;
|
||||
bts->fn_stats.avg_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* PH-RTS-IND prim received from bts model */
|
||||
static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap, struct ph_data_param *rts_ind)
|
||||
@@ -751,6 +924,8 @@ static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
|
||||
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-RTS.ind chan_nr=%s link_id=0x%02xd\n", rsl_chan_nr_str(chan_nr), link_id);
|
||||
|
||||
l1sap_update_fnstats(trx->bts, fn);
|
||||
|
||||
/* reuse PH-RTS.ind for PH-DATA.req */
|
||||
if (!msg) {
|
||||
LOGPGT(DL1P, LOGL_FATAL, &g_time, "RTS without msg to be reused. Please fix!\n");
|
||||
@@ -770,10 +945,10 @@ static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
|
||||
} else {
|
||||
/* forward RTS.ind to PCU */
|
||||
if (L1SAP_IS_PTCCH(rts_ind->fn)) {
|
||||
pcu_tx_rts_req(&trx->ts[tn], 1, fn, 1 /* ARFCN */,
|
||||
pcu_tx_rts_req(&trx->ts[tn], 1, fn, trx->arfcn,
|
||||
L1SAP_FN2PTCCHBLOCK(fn));
|
||||
} else {
|
||||
pcu_tx_rts_req(&trx->ts[tn], 0, fn, 0 /* ARFCN */,
|
||||
pcu_tx_rts_req(&trx->ts[tn], 0, fn, trx->arfcn,
|
||||
L1SAP_FN2MACBLOCK(fn));
|
||||
}
|
||||
/* return early, PCU takes care of rest */
|
||||
@@ -894,15 +1069,15 @@ static bool rtppayload_is_valid(struct gsm_lchan *lchan, struct msgb *resp_msg)
|
||||
* don't support it. */
|
||||
if(lchan->tch_mode == GSM48_CMODE_SPEECH_AMR &&
|
||||
!rtppayload_is_octet_aligned(resp_msg->data, resp_msg->len)) {
|
||||
LOGP(DL1P, LOGL_NOTICE,
|
||||
"%s RTP->L1: Dropping unexpected AMR encoding (bw-efficient?) %s\n",
|
||||
gsm_lchan_name(lchan), osmo_hexdump(resp_msg->data, resp_msg->len));
|
||||
LOGPLCHAN(lchan, DL1P, LOGL_NOTICE,
|
||||
"RTP->L1: Dropping unexpected AMR encoding (bw-efficient?) %s\n",
|
||||
osmo_hexdump(resp_msg->data, resp_msg->len));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* TCH-RTS-IND prim recevied from bts model */
|
||||
/* TCH-RTS-IND prim received from bts model */
|
||||
static int l1sap_tch_rts_ind(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap, struct ph_tch_param *rts_ind)
|
||||
{
|
||||
@@ -1003,8 +1178,12 @@ static void radio_link_timeout(struct gsm_lchan *lchan, int bad_frame)
|
||||
lchan->s--;
|
||||
DEBUGP(DMEAS, "%s counting down radio link counter S=%d\n",
|
||||
gsm_lchan_name(lchan), lchan->s);
|
||||
if (lchan->s == 0)
|
||||
if (lchan->s == 0) {
|
||||
LOGPLCHAN(lchan, DMEAS, LOGL_NOTICE,
|
||||
"radio link counter timeout S=%d, dropping conn\n",
|
||||
lchan->s);
|
||||
rsl_tx_conn_fail(lchan, RSL_ERR_RADIO_LINK_FAIL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1078,11 +1257,26 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind chan_nr=%s link_id=0x%02x len=%d\n",
|
||||
rsl_chan_nr_str(chan_nr), link_id, len);
|
||||
|
||||
/* Actually, there can be no DATA.ind on PTCCH/U (rather RACH.ind instead),
|
||||
* but some BTS models with buggy implementation may still be sending them
|
||||
* to us. Let's keep this for backwards compatibility. */
|
||||
if (L1SAP_IS_CHAN_PDCH(chan_nr) && L1SAP_IS_PTCCH(fn)) {
|
||||
LOGPGT(DL1P, LOGL_NOTICE, &g_time, "There can be no DATA.ind on PTCCH/U. "
|
||||
"This is probably a bug of the BTS model you're using, please fix!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The ph_data_param contained in the l1sap primitive may contain
|
||||
* measurement data. If this data is present, forward it for
|
||||
* processing */
|
||||
if (gsm_bts_has_feature(trx->bts, BTS_FEAT_MEAS_PAYLOAD_COMB))
|
||||
process_l1sap_meas_data(trx, l1sap, PRIM_PH_DATA);
|
||||
|
||||
if (ts_is_pdch(&trx->ts[tn])) {
|
||||
lchan = get_lchan_by_chan_nr(trx, chan_nr);
|
||||
if (!lchan)
|
||||
LOGPGT(DL1P, LOGL_ERROR, &g_time, "No lchan for chan_nr=%s\n", rsl_chan_nr_str(chan_nr));
|
||||
if (lchan && lchan->loopback && !L1SAP_IS_PTCCH(fn)) {
|
||||
if (lchan && lchan->loopback) {
|
||||
/* we are in loopback mode (for BER testing)
|
||||
* mode and need to enqeue the frame to be
|
||||
* returned in downlink */
|
||||
@@ -1097,21 +1291,14 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
|
||||
/* don't send bad frames to PCU */
|
||||
if (len == 0)
|
||||
return -EINVAL;
|
||||
if (L1SAP_IS_PTCCH(fn)) {
|
||||
pcu_tx_data_ind(&trx->ts[tn], PCU_IF_SAPI_PTCCH, fn,
|
||||
0 /* ARFCN */, L1SAP_FN2PTCCHBLOCK(fn),
|
||||
data, len, rssi, data_ind->ber10k,
|
||||
data_ind->ta_offs_256bits/64,
|
||||
data_ind->lqual_cb);
|
||||
} else {
|
||||
/* drop incomplete UL block */
|
||||
if (pr_info != PRES_INFO_BOTH)
|
||||
return 0;
|
||||
/* PDTCH / PACCH frame handling */
|
||||
pcu_tx_data_ind(&trx->ts[tn], PCU_IF_SAPI_PDTCH, fn, 0 /* ARFCN */,
|
||||
L1SAP_FN2MACBLOCK(fn), data, len, rssi, data_ind->ber10k,
|
||||
data_ind->ta_offs_256bits/64, data_ind->lqual_cb);
|
||||
}
|
||||
/* drop incomplete UL block */
|
||||
if (pr_info != PRES_INFO_BOTH)
|
||||
return 0;
|
||||
|
||||
/* PDTCH / PACCH frame handling */
|
||||
pcu_tx_data_ind(&trx->ts[tn], PCU_IF_SAPI_PDTCH, fn, trx->arfcn,
|
||||
L1SAP_FN2MACBLOCK(fn), data, len, rssi, data_ind->ber10k,
|
||||
data_ind->ta_offs_256bits/64, data_ind->lqual_cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1123,8 +1310,19 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
|
||||
|
||||
/* bad frame */
|
||||
if (len == 0) {
|
||||
if (L1SAP_IS_LINK_SACCH(link_id))
|
||||
if (L1SAP_IS_LINK_SACCH(link_id)) {
|
||||
/* In case we loose a SACCH block, we must take care
|
||||
* that the related measurement report is sent via RSL.
|
||||
* This is a fallback method. The report will also
|
||||
* lack the measurement report from the MS side. See
|
||||
* also rsl.c:lapdm_rll_tx_cb() */
|
||||
LOGPGT(DL1P, LOGL_INFO, &g_time, "Lost SACCH block, faking meas reports and ms pwr\n");
|
||||
le = &lchan->lapdm_ch.lapdm_acch;
|
||||
rsl_tx_meas_res(lchan, NULL, 0, le);
|
||||
|
||||
radio_link_timeout(lchan, 1);
|
||||
lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, data_ind->rssi);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1142,7 +1340,7 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
|
||||
}
|
||||
/* Some brilliant engineer decided that the ordering of
|
||||
* fields on the Um interface is different from the
|
||||
* order of fields in RLS. See TS 04.04 (Chapter 7.2)
|
||||
* order of fields in RSL. See TS 04.04 (Chapter 7.2)
|
||||
* vs. TS 08.58 (Chapter 9.3.10). */
|
||||
lchan->meas.l1_info[0] = data[0] << 3;
|
||||
lchan->meas.l1_info[0] |= ((data[0] >> 5) & 1) << 2;
|
||||
@@ -1157,8 +1355,7 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
|
||||
l1sap_tx_ciph_req(lchan->ts->trx, chan_nr, 1, 0);
|
||||
|
||||
/* SDCCH, SACCH and FACCH all go to LAPDm */
|
||||
msgb_pull(msg, (msg->l2h - msg->data));
|
||||
msg->l1h = NULL;
|
||||
msgb_pull_to_l2(msg);
|
||||
lapdm_phsap_up(&l1sap->oph, le);
|
||||
|
||||
/* don't free, because we forwarded data */
|
||||
@@ -1181,7 +1378,7 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
|
||||
|
||||
gsm_fn2gsmtime(&g_time, fn);
|
||||
|
||||
LOGPGT(DL1P, LOGL_INFO, &g_time, "Rx TCH.ind chan_nr=%s\n", rsl_chan_nr_str(chan_nr));
|
||||
LOGPGT(DL1P, LOGL_DEBUG, &g_time, "Rx TCH.ind chan_nr=%s\n", rsl_chan_nr_str(chan_nr));
|
||||
|
||||
lchan = get_active_lchan_by_chan_nr(trx, chan_nr);
|
||||
if (!lchan) {
|
||||
@@ -1189,13 +1386,19 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
|
||||
return 0;
|
||||
}
|
||||
|
||||
msgb_pull(msg, sizeof(*l1sap));
|
||||
/* The ph_tch_param contained in the l1sap primitive may contain
|
||||
* measurement data. If this data is present, forward it for
|
||||
* processing */
|
||||
if (gsm_bts_has_feature(trx->bts, BTS_FEAT_MEAS_PAYLOAD_COMB))
|
||||
process_l1sap_meas_data(trx, l1sap, PRIM_TCH);
|
||||
|
||||
msgb_pull_to_l2(msg);
|
||||
|
||||
/* Low level layers always call us when TCH content is expected, even if
|
||||
* the content is not available due to decoding issues. Content not
|
||||
* available is expected as empty payload. We also check if quality is
|
||||
* good enough. */
|
||||
if (msg->len && tch_ind->lqual_cb / 10 >= bts->min_qual_norm) {
|
||||
if (msg->len && tch_ind->lqual_cb >= bts->min_qual_norm) {
|
||||
/* hand msg to RTP code for transmission */
|
||||
if (lchan->abis_ip.rtp_socket)
|
||||
osmo_rtp_send_frame_ext(lchan->abis_ip.rtp_socket,
|
||||
@@ -1225,14 +1428,15 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
|
||||
|
||||
#define RACH_MIN_TOA256 -2 * 256
|
||||
|
||||
static bool rach_pass_filter(struct ph_rach_ind_param *rach_ind, struct gsm_bts *bts)
|
||||
static bool rach_pass_filter(struct ph_rach_ind_param *rach_ind, struct gsm_bts *bts,
|
||||
const char *chan_name)
|
||||
{
|
||||
int16_t toa256 = rach_ind->acc_delay_256bits;
|
||||
|
||||
/* Check for RACH exceeding BER threshold (ghost RACH) */
|
||||
if (rach_ind->ber10k > bts->max_ber10k_rach) {
|
||||
LOGPFN(DL1C, LOGL_INFO, rach_ind->fn, "Ignoring RACH request: "
|
||||
"BER10k(%u) > BER10k_MAX(%u)\n",
|
||||
LOGPFN(DL1C, LOGL_DEBUG, rach_ind->fn, "Ignoring an Access Burst on %s: "
|
||||
"BER10k(%u) > BER10k_MAX(%u)\n", chan_name,
|
||||
rach_ind->ber10k, bts->max_ber10k_rach);
|
||||
return false;
|
||||
}
|
||||
@@ -1243,21 +1447,28 @@ static bool rach_pass_filter(struct ph_rach_ind_param *rach_ind, struct gsm_bts
|
||||
* according to maximal allowed Timing Advance value.
|
||||
*/
|
||||
if (toa256 < RACH_MIN_TOA256 || toa256 > bts->max_ta * 256) {
|
||||
LOGPFN(DL1C, LOGL_INFO, rach_ind->fn, "Ignoring RACH request: "
|
||||
"ToA(%d) exceeds the allowed range (%d..%d)\n",
|
||||
LOGPFN(DL1C, LOGL_DEBUG, rach_ind->fn, "Ignoring an Access Burst on %s: "
|
||||
"ToA(%d) exceeds the allowed range (%d..%d)\n", chan_name,
|
||||
toa256, RACH_MIN_TOA256, bts->max_ta * 256);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Link quality defined by C/I (Carrier-to-Interference ratio) */
|
||||
if (rach_ind->lqual_cb < bts->min_qual_rach) {
|
||||
LOGPFN(DL1C, LOGL_DEBUG, rach_ind->fn, "Ignoring an Access Burst on %s: "
|
||||
"link quality (%d) below the minimum (%d)\n", chan_name,
|
||||
rach_ind->lqual_cb, bts->min_qual_rach);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Special case where handover RACH is detected */
|
||||
static int l1sap_handover_rach(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap, struct ph_rach_ind_param *rach_ind)
|
||||
static int l1sap_handover_rach(struct gsm_bts_trx *trx, struct ph_rach_ind_param *rach_ind)
|
||||
{
|
||||
/* Filter out noise / interference / ghosts */
|
||||
if (!rach_pass_filter(rach_ind, trx->bts)) {
|
||||
if (!rach_pass_filter(rach_ind, trx->bts, "handover")) {
|
||||
rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_DROP);
|
||||
return 0;
|
||||
}
|
||||
@@ -1269,6 +1480,33 @@ static int l1sap_handover_rach(struct gsm_bts_trx *trx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Special case for Access Bursts on PDTCH/U or PTCCH/U */
|
||||
static int l1sap_pdch_rach(struct gsm_bts_trx *trx, struct ph_rach_ind_param *rach_ind)
|
||||
{
|
||||
/* Filter out noise / interference / ghosts */
|
||||
if (!rach_pass_filter(rach_ind, trx->bts, "PDCH"))
|
||||
return -EAGAIN;
|
||||
|
||||
/* PTCCH/U (Packet Timing Advance Control Channel) */
|
||||
if (L1SAP_IS_PTCCH(rach_ind->fn)) {
|
||||
LOGPFN(DL1P, LOGL_DEBUG, rach_ind->fn,
|
||||
/* TODO: calculate and print Timing Advance Index */
|
||||
"Access Burst for continuous Timing Advance control (toa256=%d)\n",
|
||||
rach_ind->acc_delay_256bits);
|
||||
|
||||
/* QTA: Timing Advance in units of 1/4 of a symbol */
|
||||
pcu_tx_rach_ind(trx->bts->nr, trx->nr, rach_ind->chan_nr & 0x07,
|
||||
rach_ind->acc_delay_256bits >> 6,
|
||||
rach_ind->ra, rach_ind->fn, rach_ind->is_11bit,
|
||||
rach_ind->burst_type, PCU_IF_SAPI_PTCCH);
|
||||
return 0;
|
||||
} else { /* The MS may acknowledge DL data by 4 consequent Access Bursts */
|
||||
LOGPFN(DL1P, LOGL_NOTICE, rach_ind->fn,
|
||||
"Access Bursts on PDTCH/U are not (yet) supported\n");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
/* RACH received from bts model */
|
||||
static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap, struct ph_rach_ind_param *rach_ind)
|
||||
@@ -1276,12 +1514,19 @@ static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
struct lapdm_channel *lc;
|
||||
|
||||
DEBUGPFN(DL1P, rach_ind->fn, "Rx PH-RA.ind");
|
||||
DEBUGPFN(DL1P, rach_ind->fn, "Rx PH-RA.ind\n");
|
||||
|
||||
/* check for handover access burst on dedicated channels */
|
||||
if (!L1SAP_IS_CHAN_RACH(rach_ind->chan_nr)) {
|
||||
/* Check the origin of an Access Burst */
|
||||
switch (rach_ind->chan_nr & 0xf8) {
|
||||
case RSL_CHAN_RACH:
|
||||
/* CS or PS RACH, to be handled in this function */
|
||||
break;
|
||||
case RSL_CHAN_OSMO_PDCH:
|
||||
/* TODO: do we need to count Access Bursts on PDCH? */
|
||||
return l1sap_pdch_rach(trx, rach_ind);
|
||||
default:
|
||||
rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_HO);
|
||||
return l1sap_handover_rach(trx, l1sap, rach_ind);
|
||||
return l1sap_handover_rach(trx, rach_ind);
|
||||
}
|
||||
|
||||
rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_RCVD);
|
||||
@@ -1291,7 +1536,7 @@ static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
|
||||
bts->load.rach.busy++;
|
||||
|
||||
/* Filter out noise / interference / ghosts */
|
||||
if (!rach_pass_filter(rach_ind, bts)) {
|
||||
if (!rach_pass_filter(rach_ind, bts, "CCCH")) {
|
||||
rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_DROP);
|
||||
return 0;
|
||||
}
|
||||
@@ -1313,9 +1558,11 @@ static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
|
||||
LOGPFN(DL1P, LOGL_INFO, rach_ind->fn, "RACH for packet access (toa=%d, ra=%d)\n",
|
||||
rach_ind->acc_delay, rach_ind->ra);
|
||||
|
||||
pcu_tx_rach_ind(bts, rach_ind->acc_delay << 2,
|
||||
rach_ind->ra, rach_ind->fn,
|
||||
rach_ind->is_11bit, rach_ind->burst_type);
|
||||
/* QTA: Timing Advance in units of 1/4 of a symbol */
|
||||
pcu_tx_rach_ind(bts->nr, trx->nr, rach_ind->chan_nr & 0x07,
|
||||
rach_ind->acc_delay_256bits >> 6,
|
||||
rach_ind->ra, rach_ind->fn, rach_ind->is_11bit,
|
||||
rach_ind->burst_type, PCU_IF_SAPI_RACH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1364,8 +1611,10 @@ int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
||||
default:
|
||||
LOGP(DL1P, LOGL_NOTICE, "unknown prim %d op %d\n",
|
||||
l1sap->oph.primitive, l1sap->oph.operation);
|
||||
oml_fail_rep(OSMO_EVT_MAJ_UKWN_MSG, "unknown prim %d op %d",
|
||||
l1sap->oph.primitive, l1sap->oph.operation);
|
||||
oml_tx_failure_event_rep(&trx->mo, NM_SEVER_MAJOR, OSMO_EVT_MAJ_UKWN_MSG,
|
||||
"unknown prim %d op %d",
|
||||
l1sap->oph.primitive,
|
||||
l1sap->oph.operation);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1379,6 +1628,9 @@ int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
||||
/* any L1 prim sent to bts model */
|
||||
static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
||||
{
|
||||
l1sap_log_ctx_sapi = get_common_sapi_by_trx_prim(trx, l1sap);
|
||||
log_set_context(LOG_CTX_L1_SAPI, &l1sap_log_ctx_sapi);
|
||||
|
||||
if (OSMO_PRIM_HDR(&l1sap->oph) ==
|
||||
OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST))
|
||||
to_gsmtap(trx, l1sap);
|
||||
@@ -1388,7 +1640,7 @@ static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
||||
|
||||
/* pcu (socket interface) sends us a data request primitive */
|
||||
int l1sap_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn,
|
||||
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len)
|
||||
uint16_t arfcn, uint8_t block_nr, const uint8_t *data, uint8_t len)
|
||||
{
|
||||
struct msgb *msg;
|
||||
struct osmo_phsap_prim *l1sap;
|
||||
@@ -1467,8 +1719,8 @@ int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *
|
||||
struct gsm48_chan_desc *cd;
|
||||
int rc;
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "activating channel chan_nr=%s trx=%d\n",
|
||||
rsl_chan_nr_str(chan_nr), trx->nr);
|
||||
LOGPLCHAN(lchan, DL1C, LOGL_INFO, "activating channel chan_nr=%s trx=%d\n",
|
||||
rsl_chan_nr_str(chan_nr), trx->nr);
|
||||
|
||||
/* osmo-pcu calls this without a valid 'tp' parameter, so we
|
||||
* need to make sure ew don't crash here */
|
||||
@@ -1481,8 +1733,8 @@ int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *
|
||||
* one one TRX, so we need to make sure not to activate
|
||||
* channels with a different TSC!! */
|
||||
if (cd->h0.tsc != (lchan->ts->trx->bts->bsic & 7)) {
|
||||
LOGP(DL1C, LOGL_ERROR, "lchan TSC %u != BSIC-TSC %u\n",
|
||||
cd->h0.tsc, lchan->ts->trx->bts->bsic & 7);
|
||||
LOGPLCHAN(lchan, DL1C, LOGL_ERROR, "lchan TSC %u != BSIC-TSC %u\n",
|
||||
cd->h0.tsc, lchan->ts->trx->bts->bsic & 7);
|
||||
return -RSL_ERR_SERV_OPT_UNIMPL;
|
||||
}
|
||||
}
|
||||
@@ -1515,8 +1767,8 @@ int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *
|
||||
int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr)
|
||||
{
|
||||
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr);
|
||||
LOGP(DL1C, LOGL_INFO, "deactivating channel chan_nr=%s trx=%d\n",
|
||||
rsl_chan_nr_str(chan_nr), trx->nr);
|
||||
LOGPLCHAN(lchan, DL1C, LOGL_INFO, "deactivating channel chan_nr=%s trx=%d\n",
|
||||
rsl_chan_nr_str(chan_nr), trx->nr);
|
||||
|
||||
if (lchan->tch.dtx.dl_amr_fsm) {
|
||||
osmo_fsm_inst_free(lchan->tch.dtx.dl_amr_fsm);
|
||||
@@ -1531,8 +1783,8 @@ int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr)
|
||||
{
|
||||
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr);
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "deactivating sacch chan_nr=%s trx=%d\n",
|
||||
rsl_chan_nr_str(chan_nr), trx->nr);
|
||||
LOGPLCHAN(lchan, DL1C, LOGL_INFO, "deactivating sacch chan_nr=%s trx=%d\n",
|
||||
rsl_chan_nr_str(chan_nr), trx->nr);
|
||||
|
||||
lchan->sacch_deact = 1;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ static void reset_load_counters(struct gsm_bts *bts)
|
||||
{
|
||||
/* re-set the counters */
|
||||
bts->load.ccch.pch_used = bts->load.ccch.pch_total = 0;
|
||||
bts->load.rach.busy = bts->load.rach.access = bts->load.rach.total = 0;
|
||||
}
|
||||
|
||||
static void load_timer_cb(void *data)
|
||||
@@ -51,7 +52,7 @@ static void load_timer_cb(void *data)
|
||||
uint16_t buffer_space = paging_buffer_space(bts->paging_state);
|
||||
rsl_tx_ccch_load_ind_pch(bts, buffer_space);
|
||||
} else {
|
||||
/* This is an extenstion of TS 08.58. We don't only
|
||||
/* This is an extension of TS 08.58. We don't only
|
||||
* send load indications if the load is above threshold,
|
||||
* but we also explicitly indicate that we are below
|
||||
* threshold by using the magic value 0xffff */
|
||||
|
||||
@@ -144,7 +144,21 @@ static struct log_info_cat bts_log_info_cat[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int osmo_bts_filter_fn(const struct log_context *ctx, struct log_target *tgt)
|
||||
{
|
||||
uint8_t *sapi = ctx->ctx[LOG_CTX_L1_SAPI];
|
||||
uint16_t *sapi_mask = tgt->filter_data[LOG_FLT_L1_SAPI];
|
||||
|
||||
if ((tgt->filter_map & (1 << LOG_FLT_L1_SAPI)) != 0
|
||||
&& sapi_mask && sapi
|
||||
&& (*sapi_mask & (1 << *sapi)) != 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct log_info bts_log_info = {
|
||||
.filter_fn = osmo_bts_filter_fn,
|
||||
.cat = bts_log_info_cat,
|
||||
.num_cat = ARRAY_SIZE(bts_log_info_cat),
|
||||
};
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocom/core/stats.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/vty/telnet_interface.h>
|
||||
@@ -182,8 +183,9 @@ static void signal_handler(int signal)
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
if (!quit) {
|
||||
oml_fail_rep(OSMO_EVT_CRIT_PROC_STOP,
|
||||
"BTS: SIGINT received -> shutdown");
|
||||
oml_tx_failure_event_rep(&bts->mo,
|
||||
NM_SEVER_CRITICAL, OSMO_EVT_CRIT_PROC_STOP,
|
||||
"BTS: SIGINT received -> shutdown");
|
||||
bts_shutdown(bts, "SIGINT");
|
||||
}
|
||||
quit++;
|
||||
@@ -191,9 +193,6 @@ static void signal_handler(int signal)
|
||||
case SIGABRT:
|
||||
case SIGUSR1:
|
||||
case SIGUSR2:
|
||||
oml_fail_rep(OSMO_EVT_CRIT_PROC_STOP,
|
||||
"BTS: signal %d (%s) received", signal,
|
||||
strsignal(signal));
|
||||
talloc_report_full(tall_bts_ctx, stderr);
|
||||
break;
|
||||
default:
|
||||
@@ -236,6 +235,7 @@ int bts_main(int argc, char **argv)
|
||||
bts_vty_info.tall_ctx = tall_bts_ctx;
|
||||
|
||||
osmo_init_logging2(tall_bts_ctx, &bts_log_info);
|
||||
osmo_stats_init(tall_bts_ctx);
|
||||
vty_init(&bts_vty_info);
|
||||
ctrl_vty_init(tall_bts_ctx);
|
||||
rate_ctr_init(tall_bts_ctx);
|
||||
@@ -249,7 +249,7 @@ int bts_main(int argc, char **argv)
|
||||
}
|
||||
|
||||
e1inp_vty_init();
|
||||
bts_vty_init(bts, &bts_log_info);
|
||||
bts_vty_init(bts);
|
||||
|
||||
/* enable realtime priority for us */
|
||||
if (rt_prio != -1) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <osmo-bts/measurement.h>
|
||||
#include <osmo-bts/scheduler.h>
|
||||
#include <osmo-bts/rsl.h>
|
||||
#include <osmo-bts/ta_control.h>
|
||||
|
||||
/* Tables as per TS 45.008 Section 8.3 */
|
||||
static const uint8_t ts45008_83_tch_f[] = { 52, 53, 54, 55, 56, 57, 58, 59 };
|
||||
@@ -340,7 +341,7 @@ int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm, uint32_t
|
||||
}
|
||||
|
||||
/* We expect the lower layers to mark AMR SID_UPDATE frames already as such.
|
||||
* In this function, we only deal with the comon logic as per the TS 45.008 tables */
|
||||
* In this function, we only deal with the common logic as per the TS 45.008 tables */
|
||||
if (!ulm->is_sub)
|
||||
ulm->is_sub = ts45008_83_is_sub(lchan, fn, false);
|
||||
|
||||
@@ -655,14 +656,14 @@ int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
ber_full_sum = ber_full_sum / num_ul_meas;
|
||||
|
||||
if (!irssi_full_sum)
|
||||
ber_full_sum = MEASUREMENT_DUMMY_IRSSI;
|
||||
irssi_full_sum = MEASUREMENT_DUMMY_IRSSI;
|
||||
else
|
||||
irssi_full_sum = irssi_full_sum / num_ul_meas_actual;
|
||||
|
||||
if (!num_ul_meas_actual)
|
||||
ta256b_sum = lchan->meas.ms_toa256;
|
||||
else
|
||||
ta256b_sum = ta256b_sum / num_ul_meas_actual;
|
||||
ta256b_sum = ta256b_sum / (signed)num_ul_meas_actual;
|
||||
|
||||
if (!num_meas_sub)
|
||||
ber_sub_sum = MEASUREMENT_DUMMY_BER;
|
||||
@@ -696,9 +697,14 @@ int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
|
||||
lchan_meas_compute_extended(lchan);
|
||||
|
||||
/* Compute new ta_req value. This has to be done here since the value
|
||||
* in lchan->meas.num_ul_meas together with lchan->meas.ms_toa256
|
||||
* is needed for the computation. */
|
||||
lchan_ms_ta_ctrl(lchan);
|
||||
|
||||
lchan->meas.num_ul_meas = 0;
|
||||
|
||||
/* return 1 to indicte that the computation has been done and the next
|
||||
/* return 1 to indicate that the computation has been done and the next
|
||||
* interval begins. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -203,8 +203,8 @@ int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl,
|
||||
|
||||
rc = osmo_amr_rtp_dec(rtp_pl, rtp_pl_len, &cmr, &cmi, &ft, &bfi, &sti);
|
||||
if (rc < 0) {
|
||||
LOGP(DRTP, LOGL_ERROR, "failed to decode AMR RTP (length %zu, "
|
||||
"%p)\n", rtp_pl_len, rtp_pl);
|
||||
LOGPLCHAN(lchan, DRTP, LOGL_ERROR, "failed to decode AMR RTP (length %zu, "
|
||||
"%p)\n", rtp_pl_len, rtp_pl);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl,
|
||||
}
|
||||
|
||||
if (ft != AMR_NO_DATA) {
|
||||
LOGP(DRTP, LOGL_ERROR, "unsupported AMR FT 0x%02x\n", ft);
|
||||
LOGPLCHAN(lchan, DRTP, LOGL_ERROR, "unsupported AMR FT 0x%02x\n", ft);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
@@ -505,9 +505,9 @@ uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn)
|
||||
return lchan->tch.dtx.len + 1;
|
||||
}
|
||||
|
||||
LOGP(DL1C, LOGL_DEBUG, "Have to send %s frame on TCH but SID buffer "
|
||||
"is empty - sent nothing\n",
|
||||
get_value_string(gsm48_chan_mode_names, lchan->tch_mode));
|
||||
LOGPLCHAN(lchan, DL1C, LOGL_DEBUG, "Have to send %s frame on TCH but SID buffer "
|
||||
"is empty - sent nothing\n",
|
||||
get_value_string(gsm48_chan_mode_names, lchan->tch_mode));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
646
src/common/oml.c
646
src/common/oml.c
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@
|
||||
|
||||
/* TODO:
|
||||
* eMLPP priprity
|
||||
* add P1/P2/P3 rest octets
|
||||
* add P2/P3 rest octets
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -274,11 +274,86 @@ int paging_add_imm_ass(struct paging_state *ps, const uint8_t *data,
|
||||
|
||||
#define L2_PLEN(len) (((len - 1) << 2) | 0x01)
|
||||
|
||||
/* abstract representation of P1 rest octets; we only implement those parts we need for now */
|
||||
struct p1_rest_octets {
|
||||
bool packet_page_ind[2];
|
||||
bool r8_present;
|
||||
struct {
|
||||
bool prio_ul_access;
|
||||
bool etws_present;
|
||||
struct {
|
||||
bool is_first;
|
||||
uint8_t page_nr;
|
||||
const uint8_t *page;
|
||||
size_t page_bytes;
|
||||
} etws;
|
||||
} r8;
|
||||
};
|
||||
|
||||
/* 3GPP TS 44.018 10.5.2.23 append a segment/page of an ETWS primary notification to given bitvec */
|
||||
static void append_etws_prim_notif(struct bitvec *bv, bool is_first, uint8_t page_nr,
|
||||
const uint8_t *etws, ssize_t etws_len)
|
||||
{
|
||||
OSMO_ASSERT(etws_len < 128/8);
|
||||
|
||||
/* ETWS primary Notification struct
|
||||
* 0 NNNN / 1 NNNN
|
||||
* PNI n
|
||||
* LEN nnnnnnn (at least 13 bits before paylod)
|
||||
* number of bits (LEN; up to 128) */
|
||||
|
||||
if (is_first)
|
||||
bitvec_set_bit(bv, 0);
|
||||
else
|
||||
bitvec_set_bit(bv, 1);
|
||||
bitvec_set_uint(bv, page_nr, 4); /* Segment Number / Total Number */
|
||||
bitvec_set_bit(bv, 0); /* PNI to distinguish different ETWS */
|
||||
bitvec_set_uint(bv, etws_len*8, 7); /* length of payload in number of bits */
|
||||
bitvec_set_bytes(bv, etws, etws_len);
|
||||
|
||||
/* 17 bytes = 136bit - (11+13) = 112 bits = 14 bytes per PT1
|
||||
* => at least 4x PT1 RO for complete primary notification (56 bytes) */
|
||||
}
|
||||
|
||||
/* 3GPP TS 44.018 10.5.2.23 append P1 Rest Octets to given bit-vector */
|
||||
static void append_p1_rest_octets(struct bitvec *bv, const struct p1_rest_octets *p1ro)
|
||||
{
|
||||
/* Paging 1 RO (at least 10 bits before ETWS struct) */
|
||||
bitvec_set_bit(bv, L); /* no NLN */
|
||||
bitvec_set_bit(bv, L); /* no Priority1 */
|
||||
bitvec_set_bit(bv, L); /* no Priority2 */
|
||||
bitvec_set_bit(bv, L); /* no Group Call Info */
|
||||
if (p1ro->packet_page_ind[0])
|
||||
bitvec_set_bit(bv, H); /* Packet Page Indication 1 */
|
||||
else
|
||||
bitvec_set_bit(bv, L); /* Packet Page Indication 1 */
|
||||
if (p1ro->packet_page_ind[1])
|
||||
bitvec_set_bit(bv, H); /* Packet Page Indication 2 */
|
||||
else
|
||||
bitvec_set_bit(bv, L); /* Packet Page Indication 2 */
|
||||
|
||||
bitvec_set_bit(bv, L); /* No Release 6 additions */
|
||||
bitvec_set_bit(bv, L); /* No Release 7 additions */
|
||||
|
||||
if (p1ro->r8_present) {
|
||||
bitvec_set_bit(bv, H); /* Release 8 */
|
||||
bitvec_set_bit(bv, p1ro->r8.prio_ul_access); /* Priority Uplink Access */
|
||||
if (p1ro->r8.etws_present) {
|
||||
bitvec_set_bit(bv, 1); /* ETWS present */
|
||||
append_etws_prim_notif(bv, p1ro->r8.etws.is_first, p1ro->r8.etws.page_nr,
|
||||
p1ro->r8.etws.page, p1ro->r8.etws.page_bytes);
|
||||
} else
|
||||
bitvec_set_bit(bv, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int fill_paging_type_1(uint8_t *out_buf, const uint8_t *identity1_lv,
|
||||
uint8_t chan1, const uint8_t *identity2_lv,
|
||||
uint8_t chan2)
|
||||
uint8_t chan2, const struct p1_rest_octets *p1ro)
|
||||
{
|
||||
struct gsm48_paging1 *pt1 = (struct gsm48_paging1 *) out_buf;
|
||||
struct bitvec bv;
|
||||
unsigned int paging_len;
|
||||
uint8_t *cur;
|
||||
|
||||
memset(out_buf, 0, sizeof(*pt1));
|
||||
@@ -294,7 +369,19 @@ static int fill_paging_type_1(uint8_t *out_buf, const uint8_t *identity1_lv,
|
||||
|
||||
pt1->l2_plen = L2_PLEN(cur - out_buf);
|
||||
|
||||
return cur - out_buf;
|
||||
paging_len = cur - out_buf;
|
||||
|
||||
memset(&bv, 0, sizeof(bv));
|
||||
bv.data = cur;
|
||||
bv.data_len = GSM_MACBLOCK_LEN - paging_len;
|
||||
|
||||
if (p1ro)
|
||||
append_p1_rest_octets(&bv, p1ro);
|
||||
|
||||
/* pad to the end of the MAC block */
|
||||
bitvec_spare_padding(&bv, bv.data_len *8);
|
||||
|
||||
return GSM_MACBLOCK_LEN;
|
||||
}
|
||||
|
||||
static int fill_paging_type_2(uint8_t *out_buf, const uint8_t *tmsi1_lv,
|
||||
@@ -302,7 +389,9 @@ static int fill_paging_type_2(uint8_t *out_buf, const uint8_t *tmsi1_lv,
|
||||
uint8_t cneed2, const uint8_t *identity3_lv)
|
||||
{
|
||||
struct gsm48_paging2 *pt2 = (struct gsm48_paging2 *) out_buf;
|
||||
uint32_t tmsi;
|
||||
uint8_t *cur;
|
||||
int rc;
|
||||
|
||||
memset(out_buf, 0, sizeof(*pt2));
|
||||
|
||||
@@ -311,8 +400,12 @@ static int fill_paging_type_2(uint8_t *out_buf, const uint8_t *tmsi1_lv,
|
||||
pt2->pag_mode = GSM48_PM_NORMAL;
|
||||
pt2->cneed1 = cneed1;
|
||||
pt2->cneed2 = cneed2;
|
||||
tmsi_mi_to_uint(&pt2->tmsi1, tmsi1_lv);
|
||||
tmsi_mi_to_uint(&pt2->tmsi2, tmsi2_lv);
|
||||
rc = tmsi_mi_to_uint(&tmsi, tmsi1_lv);
|
||||
if (rc == 0)
|
||||
pt2->tmsi1 = tmsi;
|
||||
rc = tmsi_mi_to_uint(&tmsi, tmsi2_lv);
|
||||
if (rc == 0)
|
||||
pt2->tmsi2 = tmsi;
|
||||
cur = out_buf + sizeof(*pt2);
|
||||
|
||||
if (identity3_lv)
|
||||
@@ -329,6 +422,8 @@ static int fill_paging_type_3(uint8_t *out_buf, const uint8_t *tmsi1_lv, uint8_t
|
||||
const uint8_t *tmsi4_lv, uint8_t cneed4)
|
||||
{
|
||||
struct gsm48_paging3 *pt3 = (struct gsm48_paging3 *) out_buf;
|
||||
uint32_t tmsi;
|
||||
int rc;
|
||||
|
||||
memset(out_buf, 0, sizeof(*pt3));
|
||||
|
||||
@@ -337,10 +432,18 @@ static int fill_paging_type_3(uint8_t *out_buf, const uint8_t *tmsi1_lv, uint8_t
|
||||
pt3->pag_mode = GSM48_PM_NORMAL;
|
||||
pt3->cneed1 = cneed1;
|
||||
pt3->cneed2 = cneed2;
|
||||
tmsi_mi_to_uint(&pt3->tmsi1, tmsi1_lv);
|
||||
tmsi_mi_to_uint(&pt3->tmsi2, tmsi2_lv);
|
||||
tmsi_mi_to_uint(&pt3->tmsi3, tmsi3_lv);
|
||||
tmsi_mi_to_uint(&pt3->tmsi4, tmsi4_lv);
|
||||
rc = tmsi_mi_to_uint(&tmsi, tmsi1_lv);
|
||||
if (rc == 0)
|
||||
pt3->tmsi1 = tmsi;
|
||||
rc = tmsi_mi_to_uint(&tmsi, tmsi2_lv);
|
||||
if (rc == 0)
|
||||
pt3->tmsi2 = tmsi;
|
||||
rc = tmsi_mi_to_uint(&tmsi, tmsi3_lv);
|
||||
if (rc == 0)
|
||||
pt3->tmsi3 = tmsi;
|
||||
rc = tmsi_mi_to_uint(&tmsi, tmsi4_lv);
|
||||
if (rc == 0)
|
||||
pt3->tmsi4 = tmsi;
|
||||
|
||||
/* The structure definition in libosmocore is wrong. It includes as last
|
||||
* byte some invalid definition of chneed3/chneed4, so we must do this by hand
|
||||
@@ -390,16 +493,43 @@ static void sort_pr_tmsi_imsi(struct paging_record *pr[], unsigned int n)
|
||||
}
|
||||
}
|
||||
|
||||
static void build_p1_rest_octets(struct p1_rest_octets *p1ro, struct gsm_bts *bts)
|
||||
{
|
||||
memset(p1ro, 0, sizeof(*p1ro));
|
||||
p1ro->packet_page_ind[0] = false;
|
||||
p1ro->packet_page_ind[1] = false;
|
||||
p1ro->r8_present = true;
|
||||
p1ro->r8.prio_ul_access = false;
|
||||
p1ro->r8.etws_present = true;
|
||||
unsigned int offset = bts->etws.page_size * bts->etws.next_page;
|
||||
|
||||
if (bts->etws.next_page == 0) {
|
||||
p1ro->r8.etws.is_first = true;
|
||||
p1ro->r8.etws.page_nr = bts->etws.num_pages;
|
||||
} else {
|
||||
p1ro->r8.etws.is_first = false;
|
||||
p1ro->r8.etws.page_nr = bts->etws.next_page + 1;
|
||||
}
|
||||
p1ro->r8.etws.page = bts->etws.prim_notif + offset;
|
||||
/* last page may be smaller than first pages */
|
||||
if (bts->etws.next_page < bts->etws.num_pages-1)
|
||||
p1ro->r8.etws.page_bytes = bts->etws.page_size;
|
||||
else
|
||||
p1ro->r8.etws.page_bytes = bts->etws.prim_notif_len - offset;
|
||||
bts->etws.next_page = (bts->etws.next_page + 1) % bts->etws.num_pages;
|
||||
}
|
||||
|
||||
/* generate paging message for given gsm time */
|
||||
int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *gt,
|
||||
int *is_empty)
|
||||
{
|
||||
struct llist_head *group_q;
|
||||
struct gsm_bts *bts = ps->bts;
|
||||
int group;
|
||||
int len;
|
||||
|
||||
*is_empty = 0;
|
||||
ps->bts->load.ccch.pch_total += 1;
|
||||
bts->load.ccch.pch_total += 1;
|
||||
|
||||
group = get_pag_subch_nr(ps, gt);
|
||||
if (group < 0) {
|
||||
@@ -411,11 +541,15 @@ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *g
|
||||
|
||||
group_q = &ps->paging_queue[group];
|
||||
|
||||
/* There is nobody to be paged, send Type1 with two empty ID */
|
||||
if (llist_empty(group_q)) {
|
||||
if (ps->bts->etws.prim_notif) {
|
||||
struct p1_rest_octets p1ro;
|
||||
build_p1_rest_octets(&p1ro, bts);
|
||||
len = fill_paging_type_1(out_buf, empty_id_lv, 0, NULL, 0, &p1ro);
|
||||
} else if (llist_empty(group_q)) {
|
||||
/* There is nobody to be paged, send Type1 with two empty ID */
|
||||
//DEBUGP(DPAG, "Tx PAGING TYPE 1 (empty)\n");
|
||||
len = fill_paging_type_1(out_buf, empty_id_lv, 0,
|
||||
NULL, 0);
|
||||
NULL, 0, NULL);
|
||||
*is_empty = 1;
|
||||
} else {
|
||||
struct paging_record *pr[4];
|
||||
@@ -423,7 +557,7 @@ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *g
|
||||
time_t now = time(NULL);
|
||||
unsigned int i, num_imsi = 0;
|
||||
|
||||
ps->bts->load.ccch.pch_used += 1;
|
||||
bts->load.ccch.pch_used += 1;
|
||||
|
||||
/* get (if we have) up to four paging records */
|
||||
for (i = 0; i < ARRAY_SIZE(pr); i++) {
|
||||
@@ -493,7 +627,7 @@ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *g
|
||||
len = fill_paging_type_1(out_buf,
|
||||
pr[0]->u.paging.identity_lv,
|
||||
pr[0]->u.paging.chan_needed,
|
||||
NULL, 0);
|
||||
NULL, 0, NULL);
|
||||
} else {
|
||||
/* 2 (any type) or
|
||||
* 3 or 4, of which only 2 will be sent */
|
||||
@@ -502,7 +636,7 @@ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *g
|
||||
pr[0]->u.paging.identity_lv,
|
||||
pr[0]->u.paging.chan_needed,
|
||||
pr[1]->u.paging.identity_lv,
|
||||
pr[1]->u.paging.chan_needed);
|
||||
pr[1]->u.paging.chan_needed, NULL);
|
||||
if (num_pr >= 3) {
|
||||
/* re-add #4 for next time */
|
||||
llist_add(&pr[2]->list, group_q);
|
||||
@@ -519,7 +653,7 @@ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *g
|
||||
/* skip those that we might have re-added above */
|
||||
if (pr[i] == NULL)
|
||||
continue;
|
||||
rate_ctr_inc2(ps->bts->ctrs, BTS_CTR_PAGING_SENT);
|
||||
rate_ctr_inc2(bts->ctrs, BTS_CTR_PAGING_SENT);
|
||||
/* check if we can expire the paging record,
|
||||
* or if we need to re-queue it */
|
||||
if (pr[i]->u.paging.expiration_time <= now) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pcu_sock.c: Connect from PCU via unix domain socket */
|
||||
|
||||
/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2008-2019 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2009-2012 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* (C) 2012 by Holger Hans Peter Freyther
|
||||
* All Rights Reserved
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <osmo-bts/rsl.h>
|
||||
#include <osmo-bts/signal.h>
|
||||
#include <osmo-bts/l1sap.h>
|
||||
#include <osmo-bts/oml.h>
|
||||
|
||||
uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
|
||||
|
||||
@@ -258,7 +259,7 @@ static int pcu_if_signal_cb(unsigned int subsys, unsigned int signal,
|
||||
bts->si_buf[SYSINFO_TYPE_3];
|
||||
osmo_plmn_from_bcd(si3->lai.digits, &net->plmn);
|
||||
bts->location_area_code = ntohs(si3->lai.lac);
|
||||
bts->cell_identity = si3->cell_identity;
|
||||
bts->cell_identity = ntohs(si3->cell_identity);
|
||||
avail_lai = 1;
|
||||
break;
|
||||
case S_NEW_NSE_ATTR:
|
||||
@@ -289,6 +290,27 @@ static int pcu_if_signal_cb(unsigned int subsys, unsigned int signal,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcu_tx_app_info_req(struct gsm_bts *bts, uint8_t app_type, uint8_t len, const uint8_t *app_data)
|
||||
{
|
||||
struct gsm_pcu_if_app_info_req *ai_req;
|
||||
struct gsm_pcu_if *pcu_prim;
|
||||
struct msgb *msg;
|
||||
|
||||
if (app_type & 0xF0 || len > sizeof(ai_req->data))
|
||||
return -EINVAL;
|
||||
|
||||
msg = pcu_msgb_alloc(PCU_IF_MSG_APP_INFO_REQ, bts->nr);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
pcu_prim = (struct gsm_pcu_if *) msg->data;
|
||||
ai_req = &pcu_prim->u.app_info_req;
|
||||
|
||||
ai_req->application_type = app_type;
|
||||
ai_req->len = len;
|
||||
memcpy(ai_req->data, app_data, ai_req->len);
|
||||
|
||||
return pcu_sock_send(&bts_gsmnet, msg);
|
||||
}
|
||||
|
||||
int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
||||
uint16_t arfcn, uint8_t block_nr)
|
||||
@@ -329,8 +351,8 @@ int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t sapi, uint32_t fn,
|
||||
LOGP(DPCU, LOGL_DEBUG, "Sending data indication: sapi=%s arfcn=%d block=%d data=%s\n",
|
||||
sapi_string[sapi], arfcn, block_nr, osmo_hexdump(data, len));
|
||||
|
||||
if (lqual / 10 < bts->min_qual_norm) {
|
||||
LOGP(DPCU, LOGL_DEBUG, "Link quality %"PRId16" is below threshold %f, dropping packet\n",
|
||||
if (lqual < bts->min_qual_norm) {
|
||||
LOGP(DPCU, LOGL_DEBUG, "Link quality %"PRId16" is below threshold %d, dropping packet\n",
|
||||
lqual, bts->min_qual_norm);
|
||||
return 0;
|
||||
}
|
||||
@@ -357,8 +379,9 @@ int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t sapi, uint32_t fn,
|
||||
return pcu_sock_send(&bts_gsmnet, msg);
|
||||
}
|
||||
|
||||
int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
|
||||
uint8_t is_11bit, enum ph_burst_type burst_type)
|
||||
int pcu_tx_rach_ind(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
|
||||
int16_t qta, uint16_t ra, uint32_t fn, uint8_t is_11bit,
|
||||
enum ph_burst_type burst_type, uint8_t sapi)
|
||||
{
|
||||
struct msgb *msg;
|
||||
struct gsm_pcu_if *pcu_prim;
|
||||
@@ -367,18 +390,20 @@ int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
|
||||
LOGP(DPCU, LOGL_INFO, "Sending RACH indication: qta=%d, ra=%d, "
|
||||
"fn=%d\n", qta, ra, fn);
|
||||
|
||||
msg = pcu_msgb_alloc(PCU_IF_MSG_RACH_IND, bts->nr);
|
||||
msg = pcu_msgb_alloc(PCU_IF_MSG_RACH_IND, bts_nr);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
pcu_prim = (struct gsm_pcu_if *) msg->data;
|
||||
rach_ind = &pcu_prim->u.rach_ind;
|
||||
|
||||
rach_ind->sapi = PCU_IF_SAPI_RACH;
|
||||
rach_ind->sapi = sapi;
|
||||
rach_ind->ra = ra;
|
||||
rach_ind->qta = qta;
|
||||
rach_ind->fn = fn;
|
||||
rach_ind->is_11bit = is_11bit;
|
||||
rach_ind->burst_type = burst_type;
|
||||
rach_ind->trx_nr = trx_nr;
|
||||
rach_ind->ts_nr = ts_nr;
|
||||
|
||||
return pcu_sock_send(&bts_gsmnet, msg);
|
||||
}
|
||||
@@ -465,8 +490,25 @@ int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len)
|
||||
return pcu_sock_send(&bts_gsmnet, msg);
|
||||
}
|
||||
|
||||
/* forward data from a RR GPRS SUSPEND REQ towards PCU */
|
||||
int pcu_tx_susp_req(struct gsm_lchan *lchan, uint32_t tlli, const uint8_t *ra_id, uint8_t cause)
|
||||
{
|
||||
struct msgb *msg;
|
||||
struct gsm_pcu_if *pcu_prim;
|
||||
|
||||
msg = pcu_msgb_alloc(PCU_IF_MSG_SUSP_REQ, lchan->ts->trx->bts->nr);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
pcu_prim = (struct gsm_pcu_if *) msg->data;
|
||||
pcu_prim->u.susp_req.tlli = tlli;
|
||||
memcpy(pcu_prim->u.susp_req.ra_id, ra_id, sizeof(pcu_prim->u.susp_req.ra_id));
|
||||
pcu_prim->u.susp_req.cause = cause;
|
||||
|
||||
return pcu_sock_send(&bts_gsmnet, msg);
|
||||
}
|
||||
|
||||
static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
|
||||
struct gsm_pcu_if_data *data_req)
|
||||
const struct gsm_pcu_if_data *data_req)
|
||||
{
|
||||
uint8_t is_ptcch;
|
||||
struct gsm_bts_trx *trx;
|
||||
@@ -538,7 +580,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
|
||||
}
|
||||
|
||||
static int pcu_rx_pag_req(struct gsm_bts *bts, uint8_t msg_type,
|
||||
struct gsm_pcu_if_pag_req *pag_req)
|
||||
const struct gsm_pcu_if_pag_req *pag_req)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
@@ -577,16 +619,20 @@ static int pcu_rx_txt_ind(struct gsm_bts *bts,
|
||||
case PCU_VERSION:
|
||||
LOGP(DPCU, LOGL_INFO, "OsmoPCU version %s connected\n",
|
||||
txt->text);
|
||||
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_PCU_VERS, txt->text);
|
||||
oml_tx_failure_event_rep(&bts->gprs.cell.mo, NM_SEVER_CEASED, OSMO_EVT_PCU_VERS, txt->text);
|
||||
osmo_strlcpy(bts->pcu_version, txt->text, MAX_VERSION_LENGTH);
|
||||
|
||||
/* patch SI3 to advertise GPRS, *if* the SI3 sent by BSC said so */
|
||||
regenerate_si3_restoctets(bts);
|
||||
|
||||
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_13))
|
||||
return pcu_tx_si13(bts, true);
|
||||
|
||||
LOGP(DPCU, LOGL_INFO, "SI13 is not available on PCU connection\n");
|
||||
break;
|
||||
case PCU_OML_ALERT:
|
||||
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_EXT_ALARM, txt->text);
|
||||
oml_tx_failure_event_rep(&bts->gprs.cell.mo, NM_SEVER_INDETERMINATE, OSMO_EVT_EXT_ALARM,
|
||||
txt->text);
|
||||
break;
|
||||
default:
|
||||
LOGP(DPCU, LOGL_ERROR, "Unknown TXT_IND type %u received\n",
|
||||
@@ -598,7 +644,7 @@ static int pcu_rx_txt_ind(struct gsm_bts *bts,
|
||||
}
|
||||
|
||||
static int pcu_rx_act_req(struct gsm_bts *bts,
|
||||
struct gsm_pcu_if_act_req *act_req)
|
||||
const struct gsm_pcu_if_act_req *act_req)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_lchan *lchan;
|
||||
@@ -655,7 +701,7 @@ static int pcu_rx(struct gsm_network *net, uint8_t msg_type,
|
||||
rc = pcu_rx_txt_ind(bts, &pcu_prim->u.txt_ind);
|
||||
break;
|
||||
default:
|
||||
LOGP(DPCU, LOGL_ERROR, "Received unknwon PCU msg type %d\n",
|
||||
LOGP(DPCU, LOGL_ERROR, "Received unknown PCU msg type %d\n",
|
||||
msg_type);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
@@ -713,13 +759,18 @@ static void pcu_sock_close(struct pcu_sock_state *state)
|
||||
bts = llist_entry(state->net->bts_list.next, struct gsm_bts, list);
|
||||
|
||||
LOGP(DPCU, LOGL_NOTICE, "PCU socket has LOST connection\n");
|
||||
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_PCU_VERS, NULL);
|
||||
oml_tx_failure_event_rep(&bts->gprs.cell.mo, NM_SEVER_MAJOR, OSMO_EVT_PCU_VERS,
|
||||
"PCU socket has LOST connection");
|
||||
|
||||
bts->pcu_version[0] = '\0';
|
||||
|
||||
close(bfd->fd);
|
||||
bfd->fd = -1;
|
||||
osmo_fd_unregister(bfd);
|
||||
|
||||
/* patch SI3 to remove GPRS indicator */
|
||||
regenerate_si3_restoctets(bts);
|
||||
|
||||
/* re-enable the generation of ACCEPT for new connections */
|
||||
state->listen_bfd.when |= BSC_FD_READ;
|
||||
|
||||
@@ -770,14 +821,17 @@ static int pcu_sock_read(struct osmo_fd *bfd)
|
||||
goto close;
|
||||
|
||||
if (rc < 0) {
|
||||
if (errno == EAGAIN)
|
||||
if (errno == EAGAIN) {
|
||||
msgb_free(msg);
|
||||
return 0;
|
||||
}
|
||||
goto close;
|
||||
}
|
||||
|
||||
if (rc < sizeof(*pcu_prim)) {
|
||||
LOGP(DPCU, LOGL_ERROR, "Received %d bytes on PCU Socket, but primitive size "
|
||||
"is %lu, discarding\n", rc, sizeof(*pcu_prim));
|
||||
"is %zu, discarding\n", rc, sizeof(*pcu_prim));
|
||||
msgb_free(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -858,7 +912,7 @@ static int pcu_sock_cb(struct osmo_fd *bfd, unsigned int flags)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* accept connection comming from PCU */
|
||||
/* accept connection coming from PCU */
|
||||
static int pcu_sock_accept(struct osmo_fd *bfd, unsigned int flags)
|
||||
{
|
||||
struct pcu_sock_state *state = (struct pcu_sock_state *)bfd->data;
|
||||
|
||||
@@ -81,6 +81,16 @@ void phy_link_state_set(struct phy_link *plink, enum phy_link_state state)
|
||||
plink->state = state;
|
||||
}
|
||||
|
||||
enum phy_link_state phy_link_state_get(struct phy_link *plink)
|
||||
{
|
||||
return plink->state;
|
||||
}
|
||||
|
||||
const char *phy_link_state_name(enum phy_link_state state)
|
||||
{
|
||||
return get_value_string(phy_link_state_vals, state);
|
||||
}
|
||||
|
||||
struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num)
|
||||
{
|
||||
struct phy_instance *pinst;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
@@ -29,61 +30,98 @@
|
||||
#include <osmo-bts/measurement.h>
|
||||
#include <osmo-bts/bts_model.h>
|
||||
#include <osmo-bts/l1sap.h>
|
||||
#include <osmo-bts/power_control.h>
|
||||
|
||||
/*
|
||||
* Check if manual power control is needed
|
||||
* Check if fixed power was selected
|
||||
* Check if the MS is already using our level if not
|
||||
* the value is bogus..
|
||||
* TODO: Add a timeout.. e.g. if the ms is not capable of reaching
|
||||
* the value we have set.
|
||||
*/
|
||||
/* how many dB do we raise/lower as maximum (1 ms power level = 2 dB) */
|
||||
#define MS_RAISE_MAX_DB 4
|
||||
#define MS_LOWER_MAX_DB 8
|
||||
|
||||
/*! compute the new MS POWER LEVEL communicated to the MS and store it in lchan.
|
||||
* \param lchan logical channel for which to compute (and in which to store) new power value.
|
||||
* \param[in] ms_power_lvl MS Power Level received from Uplink L1 SACCH Header in SACCH block.
|
||||
* \param[in] rxLevel Signal level of the received SACCH block, in dBm.
|
||||
*/
|
||||
int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
|
||||
const uint8_t ms_power, const int rxLevel)
|
||||
const uint8_t ms_power_lvl, const int rxLevel)
|
||||
{
|
||||
int rx;
|
||||
int cur_dBm, new_dBm, new_pwr;
|
||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
const enum gsm_band band = bts->band;
|
||||
int diff;
|
||||
struct gsm_bts_trx *trx = lchan->ts->trx;
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
enum gsm_band band = bts->band;
|
||||
int8_t new_power_lvl; /* TS 05.05 power level */
|
||||
int8_t ms_dbm, new_dbm, current_dbm, bsc_max_dbm;
|
||||
|
||||
if (!trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx))
|
||||
return 0;
|
||||
if (lchan->ms_power_ctrl.fixed)
|
||||
return 0;
|
||||
|
||||
/* The phone hasn't reached the power level yet */
|
||||
if (lchan->ms_power_ctrl.current != ms_power)
|
||||
ms_dbm = ms_pwr_dbm(band, ms_power_lvl);
|
||||
if (ms_dbm < 0) {
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE,
|
||||
"Failed to calculate dBm for power ctl level %" PRIu8 " on band %s\n",
|
||||
ms_power_lvl, gsm_band_name(band));
|
||||
return 0;
|
||||
}
|
||||
bsc_max_dbm = ms_pwr_dbm(band, lchan->ms_power_ctrl.max);
|
||||
if (bsc_max_dbm < 0) {
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE,
|
||||
"Failed to calculate dBm for power ctl level %" PRIu8 " on band %s\n",
|
||||
lchan->ms_power_ctrl.max, gsm_band_name(band));
|
||||
return 0;
|
||||
|
||||
/* What is the difference between what we want and received? */
|
||||
rx = bts->ul_power_target - rxLevel;
|
||||
|
||||
cur_dBm = ms_pwr_dbm(band, ms_power);
|
||||
new_dBm = cur_dBm + rx;
|
||||
|
||||
/* Clamp negative values and do it depending on the band */
|
||||
if (new_dBm < 0)
|
||||
new_dBm = 0;
|
||||
|
||||
switch (band) {
|
||||
case GSM_BAND_1800:
|
||||
/* If MS_TX_PWR_MAX_CCH is set the values 29,
|
||||
* 30, 31 are not used. Avoid specifying a dBm
|
||||
* that would lead to these power levels. The
|
||||
* phone might not be able to reach them. */
|
||||
if (new_dBm > 30)
|
||||
new_dBm = 30;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
new_pwr = ms_pwr_ctl_lvl(band, new_dBm);
|
||||
if (lchan->ms_power_ctrl.current != new_pwr) {
|
||||
lchan->ms_power_ctrl.current = new_pwr;
|
||||
bts_model_adjst_ms_pwr(lchan);
|
||||
return 1;
|
||||
/* How many dBs measured power should be increased (+) or decreased (-)
|
||||
to reach expected power. */
|
||||
diff = bts->ul_power_target - rxLevel;
|
||||
|
||||
/* don't ever change more than MS_{LOWER,RAISE}_MAX_DBM during one loop
|
||||
iteration, i.e. reduce the speed at which the MS transmit power can
|
||||
change. A higher value means a lower level (and vice versa) */
|
||||
if (diff > MS_RAISE_MAX_DB)
|
||||
diff = MS_RAISE_MAX_DB;
|
||||
else if (diff < -MS_LOWER_MAX_DB)
|
||||
diff = -MS_LOWER_MAX_DB;
|
||||
|
||||
new_dbm = ms_dbm + diff;
|
||||
|
||||
/* Make sure new_dbm is never negative. ms_pwr_ctl_lvl() can later on
|
||||
cope with any unsigned dbm value, regardless of band minimal value. */
|
||||
if (new_dbm < 0)
|
||||
new_dbm = 0;
|
||||
|
||||
/* Don't ask for smaller ms power level than the one set by BSC upon RSL CHAN ACT */
|
||||
if (new_dbm > bsc_max_dbm)
|
||||
new_dbm = bsc_max_dbm;
|
||||
|
||||
new_power_lvl = ms_pwr_ctl_lvl(band, new_dbm);
|
||||
if (new_power_lvl < 0) {
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE,
|
||||
"Failed to retrieve power level for %" PRId8 " dBm on band %d\n",
|
||||
new_dbm, band);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (lchan->ms_power_ctrl.current == new_power_lvl) {
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Keeping MS power at control level %d, %d dBm "
|
||||
"(rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", rx-current %d dBm, rx-target %d dBm)\n",
|
||||
new_power_lvl, new_dbm,
|
||||
ms_power_lvl, lchan->ms_power_ctrl.max,
|
||||
rxLevel, bts->ul_power_target);
|
||||
return 0;
|
||||
}
|
||||
|
||||
current_dbm = ms_pwr_dbm(band, lchan->ms_power_ctrl.current);
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "%s MS power from control level %d (%d dBm) to %d, %d dBm "
|
||||
"(rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", rx-current %d dBm, rx-target %d dBm)\n",
|
||||
(new_dbm > current_dbm) ? "Raising" : "Lowering",
|
||||
lchan->ms_power_ctrl.current, current_dbm, new_power_lvl, new_dbm,
|
||||
ms_power_lvl, lchan->ms_power_ctrl.max,
|
||||
rxLevel, bts->ul_power_target);
|
||||
|
||||
/* store the resulting new MS power level in the lchan */
|
||||
lchan->ms_power_ctrl.current = new_power_lvl;
|
||||
bts_model_adjst_ms_pwr(lchan);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
736
src/common/rsl.c
736
src/common/rsl.c
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,9 @@
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/bits.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_08_58.h>
|
||||
#include <osmocom/gsm/a5.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
@@ -111,95 +114,482 @@ const ubit_t _sched_sch_train[64] = {
|
||||
0,0,1,0,1,1,0,1,0,1,0,0,0,1,0,1,0,1,1,1,0,1,1,0,0,0,0,1,1,0,1,1,
|
||||
};
|
||||
|
||||
/*
|
||||
* subchannel description structure
|
||||
*/
|
||||
|
||||
/* Logical channel (TRXC_*) description */
|
||||
const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
/* is_pdch chan_type chan_nr link_id name rts_fn dl_fn ul_fn auto_active */
|
||||
{ 0, TRXC_IDLE, 0, LID_DEDIC, "IDLE", NULL, tx_idle_fn, NULL, 1 },
|
||||
{ 0, TRXC_FCCH, 0, LID_DEDIC, "FCCH", NULL, tx_fcch_fn, NULL, 1 },
|
||||
{ 0, TRXC_SCH, 0, LID_DEDIC, "SCH", NULL, tx_sch_fn, NULL, 1 },
|
||||
{ 0, TRXC_BCCH, 0x80, LID_DEDIC, "BCCH", rts_data_fn, tx_data_fn, NULL, 1 },
|
||||
{ 0, TRXC_RACH, 0x88, LID_DEDIC, "RACH", NULL, NULL, rx_rach_fn, 1 },
|
||||
{ 0, TRXC_CCCH, 0x90, LID_DEDIC, "CCCH", rts_data_fn, tx_data_fn, NULL, 1 },
|
||||
{ 0, TRXC_TCHF, 0x08, LID_DEDIC, "TCH/F", rts_tchf_fn, tx_tchf_fn, rx_tchf_fn, 0 },
|
||||
{ 0, TRXC_TCHH_0, 0x10, LID_DEDIC, "TCH/H(0)", rts_tchh_fn, tx_tchh_fn, rx_tchh_fn, 0 },
|
||||
{ 0, TRXC_TCHH_1, 0x18, LID_DEDIC, "TCH/H(1)", rts_tchh_fn, tx_tchh_fn, rx_tchh_fn, 0 },
|
||||
{ 0, TRXC_SDCCH4_0, 0x20, LID_DEDIC, "SDCCH/4(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH4_1, 0x28, LID_DEDIC, "SDCCH/4(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH4_2, 0x30, LID_DEDIC, "SDCCH/4(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH4_3, 0x38, LID_DEDIC, "SDCCH/4(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH8_0, 0x40, LID_DEDIC, "SDCCH/8(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH8_1, 0x48, LID_DEDIC, "SDCCH/8(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH8_2, 0x50, LID_DEDIC, "SDCCH/8(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH8_3, 0x58, LID_DEDIC, "SDCCH/8(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH8_4, 0x60, LID_DEDIC, "SDCCH/8(4)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH8_5, 0x68, LID_DEDIC, "SDCCH/8(5)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH8_6, 0x70, LID_DEDIC, "SDCCH/8(6)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SDCCH8_7, 0x78, LID_DEDIC, "SDCCH/8(7)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCHTF, 0x08, LID_SACCH, "SACCH/TF", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCHTH_0, 0x10, LID_SACCH, "SACCH/TH(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCHTH_1, 0x18, LID_SACCH, "SACCH/TH(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH4_0, 0x20, LID_SACCH, "SACCH/4(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH4_1, 0x28, LID_SACCH, "SACCH/4(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH4_2, 0x30, LID_SACCH, "SACCH/4(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH4_3, 0x38, LID_SACCH, "SACCH/4(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH8_0, 0x40, LID_SACCH, "SACCH/8(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH8_1, 0x48, LID_SACCH, "SACCH/8(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH8_2, 0x50, LID_SACCH, "SACCH/8(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH8_3, 0x58, LID_SACCH, "SACCH/8(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH8_4, 0x60, LID_SACCH, "SACCH/8(4)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH8_5, 0x68, LID_SACCH, "SACCH/8(5)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH8_6, 0x70, LID_SACCH, "SACCH/8(6)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_SACCH8_7, 0x78, LID_SACCH, "SACCH/8(7)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 1, TRXC_PDTCH, 0xc0, LID_DEDIC, "PDTCH", rts_data_fn, tx_pdtch_fn, rx_pdtch_fn, 0 },
|
||||
{ 1, TRXC_PTCCH, 0xc0, LID_DEDIC, "PTCCH", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
|
||||
{ 0, TRXC_CBCH, 0xc8, LID_DEDIC, "CBCH", rts_data_fn, tx_data_fn, NULL, 1 },
|
||||
};
|
||||
[TRXC_IDLE] = {
|
||||
.name = "IDLE",
|
||||
.desc = "Idle channel",
|
||||
|
||||
const struct value_string trx_chan_type_names[] = {
|
||||
OSMO_VALUE_STRING(TRXC_IDLE),
|
||||
OSMO_VALUE_STRING(TRXC_FCCH),
|
||||
OSMO_VALUE_STRING(TRXC_SCH),
|
||||
OSMO_VALUE_STRING(TRXC_BCCH),
|
||||
OSMO_VALUE_STRING(TRXC_RACH),
|
||||
OSMO_VALUE_STRING(TRXC_CCCH),
|
||||
OSMO_VALUE_STRING(TRXC_TCHF),
|
||||
OSMO_VALUE_STRING(TRXC_TCHH_0),
|
||||
OSMO_VALUE_STRING(TRXC_TCHH_1),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH4_0),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH4_1),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH4_2),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH4_3),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH8_0),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH8_1),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH8_2),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH8_3),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH8_4),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH8_5),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH8_6),
|
||||
OSMO_VALUE_STRING(TRXC_SDCCH8_7),
|
||||
OSMO_VALUE_STRING(TRXC_SACCHTF),
|
||||
OSMO_VALUE_STRING(TRXC_SACCHTH_0),
|
||||
OSMO_VALUE_STRING(TRXC_SACCHTH_1),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH4_0),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH4_1),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH4_2),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH4_3),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH8_0),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH8_1),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH8_2),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH8_3),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH8_4),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH8_5),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH8_6),
|
||||
OSMO_VALUE_STRING(TRXC_SACCH8_7),
|
||||
OSMO_VALUE_STRING(TRXC_PDTCH),
|
||||
OSMO_VALUE_STRING(TRXC_PTCCH),
|
||||
OSMO_VALUE_STRING(TRXC_CBCH),
|
||||
OSMO_VALUE_STRING(_TRX_CHAN_MAX),
|
||||
{ 0, NULL }
|
||||
/* On C0, BTS needs to ensure discontinuous burst transmission.
|
||||
* Therefore we need to send dummy bursts on IDLE slots. */
|
||||
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
|
||||
.dl_fn = tx_idle_fn,
|
||||
},
|
||||
[TRXC_FCCH] = {
|
||||
.name = "FCCH", /* 3GPP TS 05.02, section 3.3.2.1 */
|
||||
.desc = "Frequency correction channel",
|
||||
|
||||
/* Tx only, frequency correction bursts */
|
||||
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
|
||||
.dl_fn = tx_fcch_fn,
|
||||
},
|
||||
[TRXC_SCH] = {
|
||||
.name = "SCH", /* 3GPP TS 05.02, section 3.3.2.2 */
|
||||
.desc = "Synchronization channel",
|
||||
|
||||
/* Tx only, synchronization bursts */
|
||||
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
|
||||
.dl_fn = tx_sch_fn,
|
||||
},
|
||||
[TRXC_BCCH] = {
|
||||
.name = "BCCH", /* 3GPP TS 05.02, section 3.3.2.3 */
|
||||
.desc = "Broadcast control channel",
|
||||
.chan_nr = RSL_CHAN_BCCH,
|
||||
|
||||
/* Tx only, xCCH convolutional coding (3GPP TS 05.03, section 4.4),
|
||||
* regular interleaving (3GPP TS 05.02, clause 7, table 3):
|
||||
* a L2 frame is interleaved over 4 consecutive bursts. */
|
||||
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
},
|
||||
[TRXC_RACH] = {
|
||||
.name = "RACH", /* 3GPP TS 05.02, section 3.3.3.1 */
|
||||
.desc = "Random access channel",
|
||||
.chan_nr = RSL_CHAN_RACH,
|
||||
|
||||
/* Rx only, RACH convolutional coding (3GPP TS 05.03, section 4.6). */
|
||||
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
|
||||
.ul_fn = rx_rach_fn,
|
||||
},
|
||||
[TRXC_CCCH] = {
|
||||
.name = "CCCH", /* 3GPP TS 05.02, section 3.3.3.1 */
|
||||
.desc = "Common control channel",
|
||||
.chan_nr = RSL_CHAN_PCH_AGCH,
|
||||
|
||||
/* Tx only, xCCH convolutional coding (3GPP TS 05.03, section 4.4),
|
||||
* regular interleaving (3GPP TS 05.02, clause 7, table 3):
|
||||
* a L2 frame is interleaved over 4 consecutive bursts. */
|
||||
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
},
|
||||
[TRXC_TCHF] = {
|
||||
.name = "TCH/F", /* 3GPP TS 05.02, section 3.2 */
|
||||
.desc = "Full Rate traffic channel",
|
||||
.chan_nr = RSL_CHAN_Bm_ACCHs,
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Rx and Tx, multiple convolutional coding types (3GPP TS 05.03,
|
||||
* chapter 3), block diagonal interleaving (3GPP TS 05.02, clause 7):
|
||||
*
|
||||
* - a traffic frame is interleaved over 8 consecutive bursts
|
||||
* using the even numbered bits of the first 4 bursts
|
||||
* and odd numbered bits of the last 4 bursts;
|
||||
* - a FACCH/F frame 'steals' (replaces) one traffic frame,
|
||||
* interleaving is done in the same way. */
|
||||
.rts_fn = rts_tchf_fn,
|
||||
.dl_fn = tx_tchf_fn,
|
||||
.ul_fn = rx_tchf_fn,
|
||||
.nope_fn = rx_tchf_fn,
|
||||
},
|
||||
[TRXC_TCHH_0] = {
|
||||
.name = "TCH/H(0)", /* 3GPP TS 05.02, section 3.2 */
|
||||
.desc = "Half Rate traffic channel (sub-channel 0)",
|
||||
.chan_nr = RSL_CHAN_Lm_ACCHs + (0 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Rx and Tx, multiple convolutional coding types (3GPP TS 05.03,
|
||||
* chapter 3), block diagonal interleaving (3GPP TS 05.02, clause 7):
|
||||
*
|
||||
* - a traffic frame is interleaved over 6 consecutive bursts
|
||||
* using the even numbered bits of the first 2 bursts,
|
||||
* all bits of the middle two 2 bursts,
|
||||
* and odd numbered bits of the last 2 bursts;
|
||||
* - a FACCH/H frame 'steals' (replaces) two traffic frames,
|
||||
* interleaving is done over 4 consecutive bursts,
|
||||
* the same as given for a TCH/FS. */
|
||||
.rts_fn = rts_tchh_fn,
|
||||
.dl_fn = tx_tchh_fn,
|
||||
.ul_fn = rx_tchh_fn,
|
||||
.nope_fn = rx_tchh_fn,
|
||||
},
|
||||
[TRXC_TCHH_1] = {
|
||||
.name = "TCH/H(1)", /* 3GPP TS 05.02, section 3.2 */
|
||||
.desc = "Half Rate traffic channel (sub-channel 1)",
|
||||
.chan_nr = RSL_CHAN_Lm_ACCHs + (1 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_TCHH_0, see above. */
|
||||
.rts_fn = rts_tchh_fn,
|
||||
.dl_fn = tx_tchh_fn,
|
||||
.ul_fn = rx_tchh_fn,
|
||||
.nope_fn = rx_tchh_fn,
|
||||
},
|
||||
[TRXC_SDCCH4_0] = {
|
||||
.name = "SDCCH/4(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 0)",
|
||||
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (0 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH4_1] = {
|
||||
.name = "SDCCH/4(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 1)",
|
||||
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (1 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH4_2] = {
|
||||
.name = "SDCCH/4(2)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 2)",
|
||||
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (2 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH4_3] = {
|
||||
.name = "SDCCH/4(3)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 3)",
|
||||
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (3 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_0] = {
|
||||
.name = "SDCCH/8(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 0)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (0 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_1] = {
|
||||
.name = "SDCCH/8(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 1)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (1 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_2] = {
|
||||
.name = "SDCCH/8(2)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 2)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (2 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_3] = {
|
||||
.name = "SDCCH/8(3)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 3)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (3 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_4] = {
|
||||
.name = "SDCCH/8(4)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 4)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (4 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_5] = {
|
||||
.name = "SDCCH/8(5)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 5)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (5 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_6] = {
|
||||
.name = "SDCCH/8(6)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 6)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (6 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_7] = {
|
||||
.name = "SDCCH/8(7)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Stand-alone dedicated control channel (sub-channel 7)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (7 << 3),
|
||||
.link_id = LID_DEDIC,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCHTF] = {
|
||||
.name = "SACCH/TF", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow TCH/F associated control channel",
|
||||
.chan_nr = RSL_CHAN_Bm_ACCHs,
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCHTH_0] = {
|
||||
.name = "SACCH/TH(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow TCH/H associated control channel (sub-channel 0)",
|
||||
.chan_nr = RSL_CHAN_Lm_ACCHs + (0 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCHTH_1] = {
|
||||
.name = "SACCH/TH(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow TCH/H associated control channel (sub-channel 1)",
|
||||
.chan_nr = RSL_CHAN_Lm_ACCHs + (1 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH4_0] = {
|
||||
.name = "SACCH/4(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/4 associated control channel (sub-channel 0)",
|
||||
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (0 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH4_1] = {
|
||||
.name = "SACCH/4(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/4 associated control channel (sub-channel 1)",
|
||||
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (1 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH4_2] = {
|
||||
.name = "SACCH/4(2)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/4 associated control channel (sub-channel 2)",
|
||||
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (2 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH4_3] = {
|
||||
.name = "SACCH/4(3)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/4 associated control channel (sub-channel 3)",
|
||||
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (3 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH8_0] = {
|
||||
.name = "SACCH/8(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/8 associated control channel (sub-channel 0)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (0 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH8_1] = {
|
||||
.name = "SACCH/8(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/8 associated control channel (sub-channel 1)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (1 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH8_2] = {
|
||||
.name = "SACCH/8(2)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/8 associated control channel (sub-channel 2)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (2 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH8_3] = {
|
||||
.name = "SACCH/8(3)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/8 associated control channel (sub-channel 3)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (3 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH8_4] = {
|
||||
.name = "SACCH/8(4)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/8 associated control channel (sub-channel 4)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (4 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH8_5] = {
|
||||
.name = "SACCH/8(5)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/8 associated control channel (sub-channel 5)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (5 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH8_6] = {
|
||||
.name = "SACCH/8(6)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/8 associated control channel (sub-channel 6)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (6 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCH8_7] = {
|
||||
.name = "SACCH/8(7)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
.desc = "Slow SDCCH/8 associated control channel (sub-channel 7)",
|
||||
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (7 << 3),
|
||||
.link_id = LID_SACCH,
|
||||
|
||||
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_PDTCH] = {
|
||||
.name = "PDTCH", /* 3GPP TS 05.02, sections 3.2.4, 3.3.2.4 */
|
||||
.desc = "Packet data traffic & control channel",
|
||||
.chan_nr = RSL_CHAN_OSMO_PDCH,
|
||||
|
||||
/* Rx and Tx, multiple coding schemes: CS-2..4 and MCS-1..9 (3GPP TS
|
||||
* 05.03, chapter 5), regular interleaving as specified for xCCH.
|
||||
* NOTE: the burst buffer is three times bigger because the
|
||||
* payload of EDGE bursts is three times longer. */
|
||||
.flags = TRX_CHAN_FLAG_PDCH,
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_pdtch_fn,
|
||||
.ul_fn = rx_pdtch_fn,
|
||||
},
|
||||
[TRXC_PTCCH] = {
|
||||
.name = "PTCCH", /* 3GPP TS 05.02, section 3.3.4.2 */
|
||||
.desc = "Packet Timing advance control channel",
|
||||
.chan_nr = RSL_CHAN_OSMO_PDCH,
|
||||
|
||||
/* On the Uplink, mobile stations transmit random Access Bursts
|
||||
* to allow estimation of the timing advance for one MS in packet
|
||||
* transfer mode. On Downlink, the network sends timing advance
|
||||
* updates for several mobile stations. The coding scheme used
|
||||
* for PTCCH/D messages is the same as for PDTCH CS-1. */
|
||||
.flags = TRX_CHAN_FLAG_PDCH,
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_pdtch_fn,
|
||||
.ul_fn = rx_rach_fn,
|
||||
},
|
||||
[TRXC_CBCH] = {
|
||||
/* TODO: distinguish CBCH on SDCCH/4 and SDCCH/8 */
|
||||
.name = "CBCH", /* 3GPP TS 05.02, section 3.3.5 */
|
||||
.desc = "Cell Broadcast channel",
|
||||
.chan_nr = RSL_CHAN_OSMO_CBCH4,
|
||||
|
||||
/* Tx only, same as for TRXC_BCCH (xCCH), see above. */
|
||||
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -311,7 +701,7 @@ free_msg:
|
||||
"type %s is already disabled. If this happens in "
|
||||
"conjunction with PCU, increase 'rts-advance' by 5.\n",
|
||||
prim_fn, get_lchan_by_chan_nr(l1t->trx, chan_nr)->name,
|
||||
get_value_string(trx_chan_type_names, chan));
|
||||
trx_chan_desc[chan].name);
|
||||
/* unlink and free message */
|
||||
llist_del(&msg->list);
|
||||
msgb_free(msg);
|
||||
@@ -378,7 +768,8 @@ int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
}
|
||||
|
||||
int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len)
|
||||
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len,
|
||||
int16_t ta_offs_256bits, uint16_t ber10k, float rssi)
|
||||
{
|
||||
struct msgb *msg;
|
||||
struct osmo_phsap_prim *l1sap;
|
||||
@@ -394,6 +785,10 @@ int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
PRIM_OP_INDICATION, msg);
|
||||
l1sap->u.tch.chan_nr = chan_nr;
|
||||
l1sap->u.tch.fn = fn;
|
||||
l1sap->u.tch.rssi = (int8_t) (rssi);
|
||||
l1sap->u.tch.ber10k = ber10k;
|
||||
l1sap->u.tch.ta_offs_256bits = ta_offs_256bits;
|
||||
|
||||
msg->l2h = msgb_put(msg, tch_len);
|
||||
if (tch_len)
|
||||
memcpy(msg->l2h, tch, tch_len);
|
||||
@@ -421,12 +816,11 @@ int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap
|
||||
uint8_t tn = l1sap->u.data.chan_nr & 7;
|
||||
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
|
||||
|
||||
LOGL1S(DL1P, LOGL_INFO, l1t, tn, -1, l1sap->u.data.fn,
|
||||
LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, -1, l1sap->u.data.fn,
|
||||
"PH-DATA.req: chan_nr=0x%02x link_id=0x%02x\n",
|
||||
l1sap->u.data.chan_nr, l1sap->u.data.link_id);
|
||||
|
||||
if (!l1sap->oph.msg)
|
||||
abort();
|
||||
OSMO_ASSERT(l1sap->oph.msg);
|
||||
|
||||
/* ignore empty frame */
|
||||
if (!msgb_l2len(l1sap->oph.msg)) {
|
||||
@@ -444,11 +838,10 @@ int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap)
|
||||
uint8_t tn = l1sap->u.tch.chan_nr & 7;
|
||||
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
|
||||
|
||||
LOGL1S(DL1P, LOGL_INFO, l1t, tn, -1, l1sap->u.tch.fn, "TCH.req: chan_nr=0x%02x\n",
|
||||
LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, -1, l1sap->u.tch.fn, "TCH.req: chan_nr=0x%02x\n",
|
||||
l1sap->u.tch.chan_nr);
|
||||
|
||||
if (!l1sap->oph.msg)
|
||||
abort();
|
||||
OSMO_ASSERT(l1sap->oph.msg);
|
||||
|
||||
/* ignore empty frame */
|
||||
if (!msgb_l2len(l1sap->oph.msg)) {
|
||||
@@ -484,7 +877,7 @@ static int rts_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn,
|
||||
LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn,
|
||||
"PH-RTS.ind: chan_nr=0x%02x link_id=0x%02x\n", chan_nr, link_id);
|
||||
|
||||
/* generate prim */
|
||||
@@ -520,7 +913,7 @@ static int rts_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "TCH RTS.ind: chan_nr=0x%02x\n", chan_nr);
|
||||
LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "TCH RTS.ind: chan_nr=0x%02x\n", chan_nr);
|
||||
|
||||
/* only send, if FACCH is selected */
|
||||
if (facch) {
|
||||
@@ -538,7 +931,7 @@ static int rts_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
rc = l1sap_up(l1t->trx, l1sap);
|
||||
}
|
||||
|
||||
/* dont send, if TCH is in signalling only mode */
|
||||
/* don't send, if TCH is in signalling only mode */
|
||||
if (l1ts->chan_state[chan].rsl_cmode != RSL_CMOD_SPD_SIGN) {
|
||||
/* generate prim */
|
||||
msg = l1sap_msgb_alloc(200);
|
||||
@@ -608,10 +1001,10 @@ int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_i
|
||||
for (i = 0; i < _TRX_CHAN_MAX; i++) {
|
||||
struct l1sched_chan_state *chan_state;
|
||||
chan_state = &l1ts->chan_state[i];
|
||||
/* skip if pchan type does not match pdch flag */
|
||||
if ((trx_sched_multiframes[l1ts->mf_index].pchan
|
||||
== GSM_PCHAN_PDCH)
|
||||
!= trx_chan_desc[i].pdch)
|
||||
/* Skip if pchan type does not match pdch flag.
|
||||
* FIXME: Is it possible at all? Clarify if so. */
|
||||
if ((trx_sched_multiframes[l1ts->mf_index].pchan == GSM_PCHAN_PDCH)
|
||||
&& !(trx_chan_desc[i].flags & TRX_CHAN_FLAG_PDCH))
|
||||
continue;
|
||||
if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8)
|
||||
&& trx_chan_desc[i].link_id == link_id) {
|
||||
@@ -727,7 +1120,7 @@ int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink,
|
||||
/* look for all matching chan_nr */
|
||||
for (i = 0; i < _TRX_CHAN_MAX; i++) {
|
||||
/* skip if pchan type */
|
||||
if (trx_chan_desc[i].pdch)
|
||||
if (trx_chan_desc[i].flags & TRX_CHAN_FLAG_PDCH)
|
||||
continue;
|
||||
if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8)) {
|
||||
chan_state = &l1ts->chan_state[i];
|
||||
@@ -782,8 +1175,7 @@ int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn)
|
||||
return 0;
|
||||
|
||||
/* check if channel is active */
|
||||
if (!trx_chan_desc[chan].auto_active
|
||||
&& !l1ts->chan_state[chan].active)
|
||||
if (!TRX_CHAN_IS_ACTIVE(&l1ts->chan_state[chan], chan))
|
||||
return -EINVAL;
|
||||
|
||||
return func(l1t, tn, fn, frame->dl_chan);
|
||||
@@ -816,7 +1208,7 @@ const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
|
||||
l1cs = &l1ts->chan_state[chan];
|
||||
|
||||
/* check if channel is active */
|
||||
if (!trx_chan_desc[chan].auto_active && !l1cs->active) {
|
||||
if (!TRX_CHAN_IS_ACTIVE(l1cs, chan)) {
|
||||
if (nbits)
|
||||
*nbits = GSM_BURST_LEN;
|
||||
goto no_data;
|
||||
@@ -909,7 +1301,7 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t,
|
||||
* There are several TDMA frames between the last processed
|
||||
* frame and currently received one. Let's walk through this
|
||||
* path and count potentially lost frames, i.e. for which
|
||||
* we didn't receive the corresponsing UL bursts.
|
||||
* we didn't receive the corresponding UL bursts.
|
||||
*
|
||||
* Start counting from the last_fn + 1.
|
||||
*/
|
||||
@@ -933,9 +1325,19 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t,
|
||||
* Instead of doing this, it makes sense to use the
|
||||
* amount of lost frames in measurement calculations.
|
||||
*/
|
||||
static sbit_t zero_burst[GSM_BURST_LEN] = { 0 };
|
||||
trx_sched_ul_func *func;
|
||||
|
||||
/* Prepare dummy burst indication */
|
||||
struct trx_ul_burst_ind bi = {
|
||||
.flags = TRX_BI_F_NOPE_IND,
|
||||
.burst_len = GSM_BURST_LEN,
|
||||
.burst = { 0 },
|
||||
.rssi = -128,
|
||||
.toa256 = 0,
|
||||
/* TDMA FN is set below */
|
||||
.tn = tn,
|
||||
};
|
||||
|
||||
for (i = 1; i < elapsed_fs; i++) {
|
||||
fn_i = TDMA_FN_SUM(l1cs->last_tdma_fn, i);
|
||||
offset = fn_i % l1ts->mf_period;
|
||||
@@ -949,8 +1351,8 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t,
|
||||
"Substituting lost TDMA frame=%u by all-zero "
|
||||
"dummy burst\n", fn_i);
|
||||
|
||||
func(l1t, tn, fn_i, frame->ul_chan, frame->ul_bid,
|
||||
zero_burst, GSM_BURST_LEN, -128, 0);
|
||||
bi.fn = fn_i;
|
||||
func(l1t, frame->ul_chan, frame->ul_bid, &bi);
|
||||
|
||||
l1cs->lost_tdma_fs--;
|
||||
}
|
||||
@@ -959,11 +1361,10 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* process uplink burst */
|
||||
int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
sbit_t *bits, uint16_t nbits, int8_t rssi, int16_t toa256)
|
||||
/* Process an Uplink burst indication */
|
||||
int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi)
|
||||
{
|
||||
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
|
||||
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, bi->tn);
|
||||
struct l1sched_chan_state *l1cs;
|
||||
const struct trx_sched_frame *frame;
|
||||
uint8_t offset, period, bid;
|
||||
@@ -975,7 +1376,7 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
|
||||
/* get frame from multiframe */
|
||||
period = l1ts->mf_period;
|
||||
offset = fn % period;
|
||||
offset = bi->fn % period;
|
||||
frame = l1ts->mf_frames + offset;
|
||||
|
||||
chan = frame->ul_chan;
|
||||
@@ -983,8 +1384,15 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
l1cs = &l1ts->chan_state[chan];
|
||||
func = trx_chan_desc[chan].ul_fn;
|
||||
|
||||
/* TODO: handle noise measurements */
|
||||
if (chan == TRXC_IDLE && bi->flags & TRX_BI_F_NOPE_IND) {
|
||||
LOGL1S(DL1P, LOGL_DEBUG, l1t, bi->tn, chan, bi->fn,
|
||||
"Rx noise measurement (%d)\n", bi->rssi);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* check if channel is active */
|
||||
if (!trx_chan_desc[chan].auto_active && !l1cs->active)
|
||||
if (!TRX_CHAN_IS_ACTIVE(l1cs, chan))
|
||||
return -EINVAL;
|
||||
|
||||
/* omit bursts which have no handler, like IDLE bursts */
|
||||
@@ -992,28 +1400,36 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
return -EINVAL;
|
||||
|
||||
/* calculate how many TDMA frames were potentially lost */
|
||||
trx_sched_calc_frame_loss(l1t, l1cs, tn, fn);
|
||||
trx_sched_calc_frame_loss(l1t, l1cs, bi->tn, bi->fn);
|
||||
|
||||
/* update TDMA frame counters */
|
||||
l1cs->last_tdma_fn = fn;
|
||||
l1cs->last_tdma_fn = bi->fn;
|
||||
l1cs->proc_tdma_fs++;
|
||||
|
||||
/* handle NOPE indications (if the handler is present) */
|
||||
if (bi->flags & TRX_BI_F_NOPE_IND) {
|
||||
func = trx_chan_desc[chan].nope_fn;
|
||||
if (!func)
|
||||
return 0;
|
||||
return func(l1t, chan, bid, bi);
|
||||
}
|
||||
|
||||
/* decrypt */
|
||||
if (bits && l1cs->ul_encr_algo) {
|
||||
if (bi->burst_len && l1cs->ul_encr_algo) {
|
||||
ubit_t ks[114];
|
||||
int i;
|
||||
|
||||
osmo_a5(l1cs->ul_encr_algo, l1cs->ul_encr_key, fn, NULL, ks);
|
||||
osmo_a5(l1cs->ul_encr_algo, l1cs->ul_encr_key, bi->fn, NULL, ks);
|
||||
for (i = 0; i < 57; i++) {
|
||||
if (ks[i])
|
||||
bits[i + 3] = - bits[i + 3];
|
||||
bi->burst[i + 3] = - bi->burst[i + 3];
|
||||
if (ks[i + 57])
|
||||
bits[i + 88] = - bits[i + 88];
|
||||
bi->burst[i + 88] = - bi->burst[i + 88];
|
||||
}
|
||||
}
|
||||
|
||||
/* put burst to function */
|
||||
func(l1t, tn, fn, chan, bid, bits, nbits, rssi, toa256);
|
||||
/* Invoke the logical channel handler */
|
||||
func(l1t, chan, bid, bi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* (C) 2011 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2011-2019 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/pcu_if.h>
|
||||
|
||||
/* properly increment SI2q index and return SI2q data for scheduling */
|
||||
static inline uint8_t *get_si2q_inc_index(struct gsm_bts *bts)
|
||||
@@ -155,7 +156,7 @@ uint8_t num_agch(struct gsm_bts_trx *trx, const char * arg)
|
||||
si3 = GSM_BTS_SI(b, SYSINFO_TYPE_3);
|
||||
return si3->control_channel_desc.bs_ag_blks_res;
|
||||
}
|
||||
LOGP(DL1P, LOGL_ERROR, "%s: Unable to determine actual BS_AG_BLKS_RES "
|
||||
LOGP(DL1P, LOGL_NOTICE, "%s: Unable to determine actual BS_AG_BLKS_RES "
|
||||
"value as SI3 is not available yet, fallback to 1\n", arg);
|
||||
return 1;
|
||||
}
|
||||
@@ -172,6 +173,39 @@ uint8_t *lchan_sacch_get(struct gsm_lchan *lchan)
|
||||
lchan->si.last = tmp;
|
||||
return GSM_LCHAN_SI(lchan, tmp);
|
||||
}
|
||||
LOGP(DL1P, LOGL_NOTICE, "%s SACCH no SI available\n", gsm_lchan_name(lchan));
|
||||
LOGPLCHAN(lchan, DL1P, LOGL_NOTICE, "SACCH no SI available\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* re-generate SI3 restoctets with GPRS indicator depending on the PCU socket connection state */
|
||||
void regenerate_si3_restoctets(struct gsm_bts *bts)
|
||||
{
|
||||
uint8_t *si3_buf = GSM_BTS_SI(bts, SYSINFO_TYPE_3);
|
||||
size_t si3_size = offsetof(struct gsm48_system_information_type_3, rest_octets);
|
||||
struct osmo_gsm48_si_ro_info si3ro_tmp;
|
||||
|
||||
/* If BSC has never set SI3, there's nothing to patch */
|
||||
if (!GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_3))
|
||||
return;
|
||||
|
||||
/* If SI3 from BSC doesn't have a GPRS indicator, we won't have anything to patch */
|
||||
if (!bts->si3_ro_decoded.gprs_ind.present)
|
||||
return;
|
||||
|
||||
/* Create a temporary copy and patch that, if no PCU is around */
|
||||
si3ro_tmp = bts->si3_ro_decoded;
|
||||
if (!pcu_connected()) {
|
||||
if (!bts->si3_gprs_ind_disabled)
|
||||
LOGP(DPCU, LOGL_NOTICE, "Disabling GPRS Indicator in SI3 (No PCU connected)\n");
|
||||
bts->si3_gprs_ind_disabled = true;
|
||||
si3ro_tmp.gprs_ind.present = 0;
|
||||
} else {
|
||||
if (bts->si3_gprs_ind_disabled)
|
||||
LOGP(DPCU, LOGL_NOTICE, "Enabling GPRS Indicator in SI3 (PCU connected)\n");
|
||||
bts->si3_gprs_ind_disabled = false;
|
||||
si3ro_tmp.gprs_ind.present = 1; /* is a no-op as we copy from bts->si3_ro_decoded */
|
||||
}
|
||||
|
||||
/* re-generate the binary SI3 rest octets */
|
||||
osmo_gsm48_rest_octets_si3_encode(si3_buf + si3_size, &si3ro_tmp);
|
||||
}
|
||||
|
||||
55
src/common/ta_control.c
Normal file
55
src/common/ta_control.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/* Loop control for Timing Advance */
|
||||
|
||||
/* (C) 2013 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 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 <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
|
||||
/* 90% of one bit duration in 1/256 symbols: 256*0.9 */
|
||||
#define TOA256_9OPERCENT 230
|
||||
|
||||
/* rqd_ta value range */
|
||||
#define TOA_MIN 0
|
||||
#define TOA_MAX 63
|
||||
|
||||
void lchan_ms_ta_ctrl(struct gsm_lchan *lchan)
|
||||
{
|
||||
int16_t toa256 = lchan->meas.ms_toa256;
|
||||
|
||||
/* Do not perform any computation when the amount of measurement
|
||||
* results is too little. */
|
||||
if (lchan->meas.num_ul_meas < 4)
|
||||
return;
|
||||
|
||||
if (toa256 < -TOA256_9OPERCENT && lchan->rqd_ta > TOA_MIN) {
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_INFO,
|
||||
"TOA is too early (%d), now lowering TA from %d to %d\n",
|
||||
toa256, lchan->rqd_ta, lchan->rqd_ta - 1);
|
||||
lchan->rqd_ta--;
|
||||
} else if (toa256 > TOA256_9OPERCENT && lchan->rqd_ta < TOA_MAX) {
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_INFO,
|
||||
"TOA is too late (%d), now raising TA from %d to %d\n",
|
||||
toa256, lchan->rqd_ta, lchan->rqd_ta + 1);
|
||||
lchan->rqd_ta++;
|
||||
} else
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG,
|
||||
"TOA is correct (%d), keeping current TA of %d\n",
|
||||
toa256, lchan->rqd_ta);
|
||||
}
|
||||
239
src/common/vty.c
239
src/common/vty.c
@@ -26,11 +26,13 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/gsm/abis_nm.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/stats.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/logging.h>
|
||||
#include <osmocom/vty/misc.h>
|
||||
@@ -123,48 +125,6 @@ int bts_vty_is_config_node(struct vty *vty, int node)
|
||||
}
|
||||
}
|
||||
|
||||
gDEFUN(ournode_exit, ournode_exit_cmd, "exit",
|
||||
"Exit current node, go down to provious node")
|
||||
{
|
||||
switch (vty->node) {
|
||||
case PHY_INST_NODE:
|
||||
vty->node = PHY_NODE;
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
vty->index = pinst->phy_link;
|
||||
}
|
||||
break;
|
||||
case PHY_NODE:
|
||||
vty->node = CONFIG_NODE;
|
||||
vty->index = NULL;
|
||||
break;
|
||||
case TRX_NODE:
|
||||
vty->node = BTS_NODE;
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
vty->index = trx->bts;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
gDEFUN(ournode_end, ournode_end_cmd, "end",
|
||||
"End current mode and change to enable mode")
|
||||
{
|
||||
switch (vty->node) {
|
||||
default:
|
||||
vty_config_unlock(vty);
|
||||
vty->node = ENABLE_NODE;
|
||||
vty->index = NULL;
|
||||
vty->index_sub = NULL;
|
||||
break;
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static const char osmobts_copyright[] =
|
||||
"Copyright (C) 2010, 2011 by Harald Welte, Andreas Eversberg and On-Waves\r\n"
|
||||
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
|
||||
@@ -277,6 +237,8 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
vty_out(vty, " rtp port-range %u %u%s", bts->rtp_port_range_start,
|
||||
bts->rtp_port_range_end, VTY_NEWLINE);
|
||||
if (bts->rtp_ip_dscp != -1)
|
||||
vty_out(vty, " rtp ip-dscp %i%s", bts->rtp_ip_dscp, VTY_NEWLINE);
|
||||
vty_out(vty, " paging queue-size %u%s", paging_get_queue_max(bts->paging_state),
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " paging lifetime %u%s", paging_get_lifetime(bts->paging_state),
|
||||
@@ -290,7 +252,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
bts->agch_queue.high_level, VTY_NEWLINE);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (gsmtap_sapi_mask & (1 << i)) {
|
||||
if (gsmtap_sapi_mask & ((uint32_t) 1 << i)) {
|
||||
sapi_buf = osmo_str_tolower(get_value_string(gsmtap_sapi_names, i));
|
||||
vty_out(vty, " gsmtap-sapi %s%s", sapi_buf, VTY_NEWLINE);
|
||||
}
|
||||
@@ -299,9 +261,9 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
sapi_buf = osmo_str_tolower(get_value_string(gsmtap_sapi_names, GSMTAP_CHANNEL_ACCH));
|
||||
vty_out(vty, " gsmtap-sapi %s%s", sapi_buf, VTY_NEWLINE);
|
||||
}
|
||||
vty_out(vty, " min-qual-rach %.0f%s", bts->min_qual_rach * 10.0f,
|
||||
vty_out(vty, " min-qual-rach %d%s", bts->min_qual_rach,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " min-qual-norm %.0f%s", bts->min_qual_norm * 10.0f,
|
||||
vty_out(vty, " min-qual-norm %d%s", bts->min_qual_norm,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " max-ber10k-rach %u%s", bts->max_ber10k_rach,
|
||||
VTY_NEWLINE);
|
||||
@@ -309,6 +271,9 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
vty_out(vty, " pcu-socket %s%s", bts->pcu.sock_path, VTY_NEWLINE);
|
||||
if (bts->supp_meas_toa256)
|
||||
vty_out(vty, " supp-meas-info toa256%s", VTY_NEWLINE);
|
||||
vty_out(vty, " smscb queue-max-length %d%s", bts->smscb_queue_max_len, VTY_NEWLINE);
|
||||
vty_out(vty, " smscb queue-target-length %d%s", bts->smscb_queue_tgt_len, VTY_NEWLINE);
|
||||
vty_out(vty, " smscb queue-hysteresis %d%s", bts->smscb_queue_hyst, VTY_NEWLINE);
|
||||
|
||||
bts_model_config_write_bts(vty, bts);
|
||||
|
||||
@@ -327,7 +292,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
vty_out(vty, " power-ramp step-interval %d%s",
|
||||
tpp->ramp.step_interval_sec, VTY_NEWLINE);
|
||||
vty_out(vty, " ms-power-control %s%s",
|
||||
trx->ms_power_control == 0 ? "dsp" : "osmo",
|
||||
trx->ms_pwr_ctl_soft ? "osmo" : "dsp",
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " phy %u instance %u%s", pinst->phy_link->num,
|
||||
pinst->num, VTY_NEWLINE);
|
||||
@@ -538,6 +503,19 @@ DEFUN(cfg_bts_rtp_port_range,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_rtp_ip_dscp,
|
||||
cfg_bts_rtp_ip_dscp_cmd,
|
||||
"rtp ip-dscp <0-63>",
|
||||
RTP_STR "Specify DSCP for RTP/IP packets\n" "The DSCP value (upper 6 bits of TOS)\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
int dscp = atoi(argv[0]);
|
||||
|
||||
bts->rtp_ip_dscp = dscp;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define PAG_STR "Paging related parameters\n"
|
||||
|
||||
DEFUN(cfg_bts_paging_queue_size,
|
||||
@@ -614,24 +592,24 @@ DEFUN(cfg_bts_ul_power_target, cfg_bts_ul_power_target_cmd,
|
||||
|
||||
DEFUN(cfg_bts_min_qual_rach, cfg_bts_min_qual_rach_cmd,
|
||||
"min-qual-rach <-100-100>",
|
||||
"Set the minimum quality level of RACH burst to be accpeted\n"
|
||||
"C/I level in tenth of dB\n")
|
||||
"Set the minimum link quality level of Access Bursts to be accepted\n"
|
||||
"C/I (Carrier-to-Interference) ratio in centiBels (10e-2 B or 10e-1 dB)\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
bts->min_qual_rach = strtof(argv[0], NULL) / 10.0f;
|
||||
bts->min_qual_rach = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_min_qual_norm, cfg_bts_min_qual_norm_cmd,
|
||||
"min-qual-norm <-100-100>",
|
||||
"Set the minimum quality level of normal burst to be accpeted\n"
|
||||
"C/I level in tenth of dB\n")
|
||||
"Set the minimum link quality level of Normal Bursts to be accepted\n"
|
||||
"C/I (Carrier-to-Interference) ratio in centiBels (10e-2 B or 10e-1 dB)\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
bts->min_qual_norm = strtof(argv[0], NULL) / 10.0f;
|
||||
bts->min_qual_norm = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@@ -686,6 +664,33 @@ DEFUN(cfg_bts_no_supp_meas_toa256, cfg_bts_no_supp_meas_toa256_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_smscb_max_qlen, cfg_bts_smscb_max_qlen_cmd,
|
||||
"smscb queue-max-length <1-60>",
|
||||
"Maximum queue length for SMSCB (CBCH) queue. In count of messages/pages (Default: 15)")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
bts->smscb_queue_max_len = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_smscb_tgt_qlen, cfg_bts_smscb_tgt_qlen_cmd,
|
||||
"smscb queue-target-length <1-30>",
|
||||
"Target queue length for SMSCB (CBCH) queue. In count of messages/pages (Default: 2)")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
bts->smscb_queue_tgt_len = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_smscb_qhyst, cfg_bts_smscb_qhyst_cmd,
|
||||
"smscb queue-hysteresis <0-30>",
|
||||
"Hysteresis for SMSCB (CBCH) queue. In count of messages/pages (Default: 2)")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
bts->smscb_queue_hyst = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define DB_DBM_STR \
|
||||
"Unit is dB (decibels)\n" \
|
||||
@@ -757,8 +762,23 @@ DEFUN(cfg_trx_ms_power_control, cfg_trx_ms_power_control_cmd,
|
||||
"Handled by DSP\n" "Handled by OsmoBTS\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
bool soft = !strcmp(argv[0], "osmo");
|
||||
|
||||
trx->ms_power_control = argv[0][0] == 'd' ? 0 : 1;
|
||||
if (!soft && !gsm_bts_has_feature(trx->bts, BTS_FEAT_MS_PWR_CTRL_DSP)) {
|
||||
/* NOTE: osmo-bts-trx used to have its own (low-level) MS Power Control loop, which
|
||||
* has been ripped out in favour of the common implementation. Configuration files
|
||||
* may still contain 'dsp', so let's be tolerant and override 'dsp' by 'osmo'. */
|
||||
if (trx->bts->variant == BTS_OSMO_TRX && vty->type == VTY_FILE) {
|
||||
vty_out(vty, "BTS model 'osmo-bts-trx' has no DSP/HW MS Power Control support, "
|
||||
"consider updating your configuration file!%s", VTY_NEWLINE);
|
||||
soft = true; /* override */
|
||||
} else {
|
||||
vty_out(vty, "This BTS model has no DSP/HW MS Power Control support%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
trx->ms_pwr_ctl_soft = soft;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -802,17 +822,6 @@ static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms)
|
||||
abis_nm_avail_name(nms->availability), VTY_NEWLINE);
|
||||
}
|
||||
|
||||
static unsigned int llist_length(struct llist_head *list)
|
||||
{
|
||||
unsigned int len = 0;
|
||||
struct llist_head *pos;
|
||||
|
||||
llist_for_each(pos, list)
|
||||
len++;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void bts_dump_vty_features(struct vty *vty, struct gsm_bts *bts)
|
||||
{
|
||||
unsigned int i;
|
||||
@@ -864,13 +873,19 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
|
||||
bts->agch_queue.rejected_msgs, bts->agch_queue.agch_msgs,
|
||||
bts->agch_queue.pch_msgs,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " CBCH backlog queue length: %u%s",
|
||||
llist_length(&bts->smscb_state.queue), VTY_NEWLINE);
|
||||
vty_out(vty, " CBCH queue target: %d, hysteresis: %d, maximum: %d%s",
|
||||
bts->smscb_queue_tgt_len, bts->smscb_queue_max_len, bts->smscb_queue_hyst, VTY_NEWLINE);
|
||||
vty_out(vty, " CBCH backlog queue length (BASIC): %d%s",
|
||||
bts->smscb_basic.queue_len, VTY_NEWLINE);
|
||||
vty_out(vty, " CBCH backlog queue length (EXTENDED): %u%s",
|
||||
bts->smscb_extended.queue_len, VTY_NEWLINE);
|
||||
vty_out(vty, " Paging: queue length %d, buffer space %d%s",
|
||||
paging_queue_length(bts->paging_state), paging_buffer_space(bts->paging_state),
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " OML Link state: %s.%s",
|
||||
bts->oml_link ? "connected" : "disconnected", VTY_NEWLINE);
|
||||
vty_out(vty, " PH-RTS.ind FN advance average: %d, min: %d, max: %d%s",
|
||||
bts_get_avg_fn_advance(bts), bts->fn_stats.min, bts->fn_stats.max, VTY_NEWLINE);
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
@@ -913,6 +928,25 @@ DEFUN(show_bts, show_bts_cmd, "show bts <0-255>",
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(test_send_failure_event_report, test_send_failure_event_report_cmd, "test send-failure-event-report <0-255>",
|
||||
"Various testing commands\n"
|
||||
"Send a test OML failure event report to the BSC\n" BTS_NR_STR)
|
||||
{
|
||||
struct gsm_network *net = gsmnet_from_vty(vty);
|
||||
int bts_nr = atoi(argv[0]);
|
||||
struct gsm_bts *bts;
|
||||
|
||||
if (bts_nr >= net->num_bts) {
|
||||
vty_out(vty, "%% can't find BTS '%s'%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
bts = gsm_bts_num(net, bts_nr);
|
||||
oml_tx_failure_event_rep(&bts->mo, NM_SEVER_MINOR, OSMO_EVT_WARN_SW_WARN, "test message sent from VTY");
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void trx_dump_vty(struct vty *vty, struct gsm_bts_trx *trx)
|
||||
{
|
||||
vty_out(vty, "TRX %u of BTS %u is on ARFCN %u%s",
|
||||
@@ -1146,7 +1180,7 @@ static void lchan_dump_full_vty(struct vty *vty, struct gsm_lchan *lchan)
|
||||
vty_out(vty, " BS Power: %d dBm, MS Power: %u dBm%s",
|
||||
lchan->ts->trx->nominal_power - lchan->ts->trx->max_power_red
|
||||
- lchan->bs_power*2,
|
||||
ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power),
|
||||
ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power_ctrl.max),
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " Channel Mode / Codec: %s%s",
|
||||
get_value_string(gsm48_cmode_names, lchan->tch_mode),
|
||||
@@ -1463,8 +1497,8 @@ DEFUN(cfg_phy_inst, cfg_phy_inst_cmd,
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_no_inst, cfg_phy_no_inst_cmd,
|
||||
"no instance <0-255>"
|
||||
NO_STR "Select a PHY instance to remove\n", "PHY Instance number\n")
|
||||
"no instance <0-255>",
|
||||
NO_STR "Select a PHY instance to remove\n" "PHY Instance number\n")
|
||||
{
|
||||
int inst_nr = atoi(argv[0]);
|
||||
struct phy_link *plink = vty->index;
|
||||
@@ -1574,7 +1608,48 @@ DEFUN(no_bts_t_t_l_loopback,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
|
||||
DEFUN(logging_fltr_l1_sapi, logging_fltr_l1_sapi_cmd, "HIDDEN", "HIDDEN")
|
||||
{
|
||||
int sapi = get_string_value(l1sap_common_sapi_names, argv[0]);
|
||||
struct log_target *tgt = osmo_log_vty2tgt(vty);
|
||||
uint16_t **sapi_mask;
|
||||
|
||||
OSMO_ASSERT(sapi >= 0);
|
||||
if (!tgt)
|
||||
return CMD_WARNING;
|
||||
|
||||
sapi_mask = (uint16_t **)&tgt->filter_data[LOG_FLT_L1_SAPI];
|
||||
|
||||
if (!*sapi_mask)
|
||||
*sapi_mask = talloc(tgt, uint16_t);
|
||||
|
||||
OSMO_ASSERT(sapi <= 31);
|
||||
**sapi_mask |= (1 << sapi);
|
||||
tgt->filter_map |= (1 << LOG_FLT_L1_SAPI);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(no_logging_fltr_l1_sapi, no_logging_fltr_l1_sapi_cmd, "HIDDEN", "HIDDEN")
|
||||
{
|
||||
int sapi = get_string_value(l1sap_common_sapi_names, argv[0]);
|
||||
struct log_target *tgt = osmo_log_vty2tgt(vty);
|
||||
uint16_t *sapi_mask;
|
||||
|
||||
OSMO_ASSERT(sapi >= 0);
|
||||
if (!tgt)
|
||||
return CMD_WARNING;
|
||||
if (!tgt->filter_data[LOG_FLT_L1_SAPI])
|
||||
return CMD_SUCCESS;
|
||||
|
||||
OSMO_ASSERT(sapi <= 31);
|
||||
sapi_mask = (uint16_t *)tgt->filter_data[LOG_FLT_L1_SAPI];
|
||||
*sapi_mask &= ~(1 << sapi);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int bts_vty_init(struct gsm_bts *bts)
|
||||
{
|
||||
cfg_trx_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names,
|
||||
"gsmtap-sapi (",
|
||||
@@ -1590,14 +1665,31 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
|
||||
NO_STR "GSMTAP SAPI\n",
|
||||
"\n", "", 0);
|
||||
|
||||
logging_fltr_l1_sapi_cmd.string = vty_cmd_string_from_valstr(bts, l1sap_common_sapi_names,
|
||||
"logging filter l1-sapi (",
|
||||
"|", ")", VTY_DO_LOWER);
|
||||
logging_fltr_l1_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, l1sap_common_sapi_names,
|
||||
LOGGING_STR FILTER_STR "L1 SAPI\n",
|
||||
"\n", "", 0);
|
||||
|
||||
no_logging_fltr_l1_sapi_cmd.string = vty_cmd_string_from_valstr(bts, l1sap_common_sapi_names,
|
||||
"no logging filter l1-sapi (",
|
||||
"|", ")", VTY_DO_LOWER);
|
||||
no_logging_fltr_l1_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, l1sap_common_sapi_names,
|
||||
NO_STR LOGGING_STR FILTER_STR "L1 SAPI\n",
|
||||
"\n", "", 0);
|
||||
|
||||
install_element_ve(&show_bts_cmd);
|
||||
install_element_ve(&show_trx_cmd);
|
||||
install_element_ve(&show_ts_cmd);
|
||||
install_element_ve(&show_lchan_cmd);
|
||||
install_element_ve(&show_lchan_summary_cmd);
|
||||
install_element_ve(&logging_fltr_l1_sapi_cmd);
|
||||
install_element_ve(&no_logging_fltr_l1_sapi_cmd);
|
||||
|
||||
logging_vty_add_cmds(cat);
|
||||
logging_vty_add_cmds();
|
||||
osmo_talloc_vty_add_cmds();
|
||||
osmo_stats_vty_add_cmds();
|
||||
|
||||
install_node(&bts_node, config_write_bts);
|
||||
install_element(CONFIG_NODE, &cfg_bts_cmd);
|
||||
@@ -1607,6 +1699,7 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
|
||||
install_element(BTS_NODE, &cfg_bts_rtp_bind_ip_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rtp_jitbuf_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rtp_port_range_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rtp_ip_dscp_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_band_cmd);
|
||||
install_element(BTS_NODE, &cfg_description_cmd);
|
||||
install_element(BTS_NODE, &cfg_no_description_cmd);
|
||||
@@ -1621,6 +1714,9 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
|
||||
install_element(BTS_NODE, &cfg_bts_pcu_sock_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_supp_meas_toa256_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_no_supp_meas_toa256_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_smscb_max_qlen_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_smscb_tgt_qlen_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_smscb_qhyst_cmd);
|
||||
|
||||
install_element(BTS_NODE, &cfg_trx_gsmtap_sapi_cmd);
|
||||
install_element(BTS_NODE, &cfg_trx_no_gsmtap_sapi_cmd);
|
||||
@@ -1639,6 +1735,7 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
|
||||
install_element(ENABLE_NODE, &bts_t_t_l_jitter_buf_cmd);
|
||||
install_element(ENABLE_NODE, &bts_t_t_l_loopback_cmd);
|
||||
install_element(ENABLE_NODE, &no_bts_t_t_l_loopback_cmd);
|
||||
install_element(ENABLE_NODE, &test_send_failure_event_report_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &cfg_phy_cmd);
|
||||
install_node(&phy_node, config_write_phy);
|
||||
|
||||
@@ -317,7 +317,7 @@ static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *d
|
||||
fseek(st->fp, 0L, SEEK_END);
|
||||
sz = ftell(st->fp);
|
||||
|
||||
/* rewind read poiner */
|
||||
/* rewind read pointer */
|
||||
fseek(st->fp, 0L, SEEK_SET);
|
||||
|
||||
/* read file */
|
||||
|
||||
@@ -795,6 +795,45 @@ static uint8_t chan_nr_by_sapi(struct gsm_bts_trx_ts *ts,
|
||||
return (cbits << 3) | u8Tn;
|
||||
}
|
||||
|
||||
static const enum l1sap_common_sapi common_sapi_by_sapi_t[] = {
|
||||
[GsmL1_Sapi_Idle] = L1SAP_COMMON_SAPI_IDLE,
|
||||
[GsmL1_Sapi_Fcch] = L1SAP_COMMON_SAPI_FCCH,
|
||||
[GsmL1_Sapi_Sch] = L1SAP_COMMON_SAPI_SCH,
|
||||
[GsmL1_Sapi_Sacch] = L1SAP_COMMON_SAPI_SACCH,
|
||||
[GsmL1_Sapi_Sdcch] = L1SAP_COMMON_SAPI_SDCCH,
|
||||
[GsmL1_Sapi_Bcch] = L1SAP_COMMON_SAPI_BCCH,
|
||||
[GsmL1_Sapi_Pch] = L1SAP_COMMON_SAPI_PCH,
|
||||
[GsmL1_Sapi_Agch] = L1SAP_COMMON_SAPI_AGCH,
|
||||
[GsmL1_Sapi_Cbch] = L1SAP_COMMON_SAPI_CBCH,
|
||||
[GsmL1_Sapi_Rach] = L1SAP_COMMON_SAPI_RACH,
|
||||
[GsmL1_Sapi_TchF] = L1SAP_COMMON_SAPI_TCH_F,
|
||||
[GsmL1_Sapi_FacchF] = L1SAP_COMMON_SAPI_FACCH_F,
|
||||
[GsmL1_Sapi_TchH] = L1SAP_COMMON_SAPI_TCH_H,
|
||||
[GsmL1_Sapi_FacchH] = L1SAP_COMMON_SAPI_FACCH_H,
|
||||
[GsmL1_Sapi_Nch] = L1SAP_COMMON_SAPI_NCH,
|
||||
[GsmL1_Sapi_Pdtch] = L1SAP_COMMON_SAPI_PDTCH,
|
||||
[GsmL1_Sapi_Pacch] = L1SAP_COMMON_SAPI_PACCH,
|
||||
[GsmL1_Sapi_Pbcch] = L1SAP_COMMON_SAPI_PBCCH,
|
||||
[GsmL1_Sapi_Pagch] = L1SAP_COMMON_SAPI_PAGCH,
|
||||
[GsmL1_Sapi_Ppch] = L1SAP_COMMON_SAPI_PPCH,
|
||||
[GsmL1_Sapi_Pnch] = L1SAP_COMMON_SAPI_PNCH,
|
||||
[GsmL1_Sapi_Ptcch] = L1SAP_COMMON_SAPI_PTCCH,
|
||||
[GsmL1_Sapi_Prach] = L1SAP_COMMON_SAPI_PRACH,
|
||||
};
|
||||
|
||||
static enum l1sap_common_sapi get_common_sapi(GsmL1_Sapi_t sapi)
|
||||
{
|
||||
if (sapi >= GsmL1_Sapi_NUM)
|
||||
return L1SAP_COMMON_SAPI_UNKNOWN;
|
||||
return common_sapi_by_sapi_t[sapi];
|
||||
}
|
||||
|
||||
static void set_log_ctx_sapi(GsmL1_Sapi_t sapi)
|
||||
{
|
||||
l1sap_log_ctx_sapi = get_common_sapi(sapi);
|
||||
log_set_context(LOG_CTX_L1_SAPI, &l1sap_log_ctx_sapi);
|
||||
}
|
||||
|
||||
static int handle_ph_readytosend_ind(struct lc15l1_hdl *fl1,
|
||||
GsmL1_PhReadyToSendInd_t *rts_ind,
|
||||
struct msgb *l1p_msg)
|
||||
@@ -811,6 +850,8 @@ static int handle_ph_readytosend_ind(struct lc15l1_hdl *fl1,
|
||||
uint8_t chan_nr, link_id;
|
||||
uint32_t fn;
|
||||
|
||||
set_log_ctx_sapi(rts_ind->sapi);
|
||||
|
||||
/* check if primitive should be handled by common part */
|
||||
chan_nr = chan_nr_by_sapi(&trx->ts[rts_ind->u8Tn], rts_ind->sapi,
|
||||
rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn);
|
||||
@@ -895,12 +936,8 @@ empty_frame:
|
||||
goto tx;
|
||||
}
|
||||
|
||||
static void dump_meas_res(int ll, GsmL1_MeasParam_t *m)
|
||||
{
|
||||
LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, "
|
||||
"BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality,
|
||||
m->fBer, m->i16BurstTiming);
|
||||
}
|
||||
#define LOG_FMT_MEAS "Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, BER %-3.2f, Timing %d"
|
||||
#define LOG_PARAM_MEAS(meas_param) (meas_param)->fRssi, (meas_param)->fLinkQuality, (meas_param)->fBer, (meas_param)->i16BurstTiming
|
||||
|
||||
static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
GsmL1_MeasParam_t *m, uint32_t fn)
|
||||
@@ -933,6 +970,8 @@ static int handle_ph_data_ind(struct lc15l1_hdl *fl1, GsmL1_PhDataInd_t *data_in
|
||||
int rc = 0;
|
||||
int8_t rssi;
|
||||
|
||||
set_log_ctx_sapi(data_ind->sapi);
|
||||
|
||||
chan_nr = chan_nr_by_sapi(&trx->ts[data_ind->u8Tn], data_ind->sapi,
|
||||
data_ind->subCh, data_ind->u8Tn, data_ind->u32Fn);
|
||||
fn = data_ind->u32Fn;
|
||||
@@ -949,10 +988,10 @@ static int handle_ph_data_ind(struct lc15l1_hdl *fl1, GsmL1_PhDataInd_t *data_in
|
||||
process_meas_res(trx, chan_nr, &data_ind->measParam, fn);
|
||||
|
||||
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s\n",
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s, " LOG_FMT_MEAS "\n",
|
||||
get_value_string(lc15bts_l1sapi_names, data_ind->sapi), (uint32_t)data_ind->hLayer2,
|
||||
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size));
|
||||
dump_meas_res(LOGL_DEBUG, &data_ind->measParam);
|
||||
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size),
|
||||
LOG_PARAM_MEAS(&data_ind->measParam));
|
||||
|
||||
/* check for TCH */
|
||||
if (data_ind->sapi == GsmL1_Sapi_TchF
|
||||
@@ -985,11 +1024,10 @@ static int handle_ph_data_ind(struct lc15l1_hdl *fl1, GsmL1_PhDataInd_t *data_in
|
||||
l1sap->u.data.chan_nr = chan_nr;
|
||||
l1sap->u.data.fn = fn;
|
||||
l1sap->u.data.rssi = rssi;
|
||||
if (!pcu_direct) {
|
||||
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
|
||||
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64;
|
||||
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
|
||||
}
|
||||
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
|
||||
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64;
|
||||
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
|
||||
|
||||
return l1sap_up(trx, l1sap);
|
||||
}
|
||||
|
||||
@@ -997,19 +1035,14 @@ static int handle_ph_ra_ind(struct lc15l1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
|
||||
struct msgb *l1p_msg)
|
||||
{
|
||||
struct gsm_bts_trx *trx = lc15l1_hdl_trx(fl1);
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
struct gsm_lchan *lchan;
|
||||
struct osmo_phsap_prim *l1sap;
|
||||
int rc;
|
||||
struct ph_rach_ind_param rach_ind_param;
|
||||
|
||||
/* FIXME: this should be deprecated/obsoleted as it bypasses rach.busy counting */
|
||||
if (ra_ind->measParam.fLinkQuality < bts->min_qual_rach) {
|
||||
msgb_free(l1p_msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dump_meas_res(LOGL_DEBUG, &ra_ind->measParam);
|
||||
set_log_ctx_sapi(ra_ind->sapi);
|
||||
LOGPFN(DL1C, LOGL_DEBUG, ra_ind->u32Fn, "Rx PH-RA.ind, " LOG_FMT_MEAS "\n",
|
||||
LOG_PARAM_MEAS(&ra_ind->measParam));
|
||||
|
||||
if ((ra_ind->msgUnitParam.u8Size != 1) &&
|
||||
(ra_ind->msgUnitParam.u8Size != 2)) {
|
||||
@@ -1029,13 +1062,14 @@ static int handle_ph_ra_ind(struct lc15l1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
|
||||
.rssi = (int8_t) ra_ind->measParam.fRssi,
|
||||
.ber10k = (unsigned int) (ra_ind->measParam.fBer * 10000.0),
|
||||
.acc_delay_256bits = ra_ind->measParam.i16BurstTiming * 64,
|
||||
.lqual_cb = (int16_t) ra_ind->measParam.fLinkQuality * 10, /* centiBels */
|
||||
};
|
||||
|
||||
lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ra_ind->hLayer2);
|
||||
if (!lchan || lchan->ts->pchan == GSM_PCHAN_CCCH ||
|
||||
lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4 ||
|
||||
lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH)
|
||||
rach_ind_param.chan_nr = 0x88;
|
||||
rach_ind_param.chan_nr = RSL_CHAN_RACH;
|
||||
else
|
||||
rach_ind_param.chan_nr = gsm_lchan2chan_nr(lchan);
|
||||
|
||||
@@ -1229,8 +1263,10 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
LOGP(DL1C, LOGL_FATAL, "RF-ACT.conf with status %s\n",
|
||||
get_value_string(lc15bts_l1status_names, status));
|
||||
bts_shutdown(trx->bts, "RF-ACT failure");
|
||||
} else
|
||||
bts_update_status(BTS_STATUS_RF_ACTIVE, 1);
|
||||
} else {
|
||||
if(trx->bts->lc15.led_ctrl_mode == LC15_LED_CONTROL_BTS)
|
||||
bts_update_status(BTS_STATUS_RF_ACTIVE, 1);
|
||||
}
|
||||
|
||||
/* signal availability */
|
||||
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK);
|
||||
@@ -1241,7 +1277,8 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
|
||||
oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
|
||||
} else {
|
||||
bts_update_status(BTS_STATUS_RF_ACTIVE, 0);
|
||||
if(trx->bts->lc15.led_ctrl_mode == LC15_LED_CONTROL_BTS)
|
||||
bts_update_status(BTS_STATUS_RF_ACTIVE, 0);
|
||||
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
|
||||
oml_mo_state_chg(&trx->bb_transc.mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
|
||||
}
|
||||
@@ -1256,17 +1293,27 @@ int l1if_activate_rf(struct lc15l1_hdl *hdl, int on)
|
||||
{
|
||||
struct msgb *msg = sysp_msgb_alloc();
|
||||
Litecell15_Prim_t *sysp = msgb_sysprim(msg);
|
||||
struct phy_instance *pinst = hdl->phy_inst;
|
||||
|
||||
if (on) {
|
||||
sysp->id = Litecell15_PrimId_ActivateRfReq;
|
||||
sysp->u.activateRfReq.msgq.u8UseTchMsgq = 0;
|
||||
sysp->u.activateRfReq.msgq.u8UsePdtchMsgq = pcu_direct;
|
||||
|
||||
sysp->u.activateRfReq.u8UnusedTsMode = 0;
|
||||
sysp->u.activateRfReq.u8UnusedTsMode = pinst->u.lc15.pedestal_mode;
|
||||
sysp->u.activateRfReq.u8McCorrMode = 0;
|
||||
|
||||
/* diversity mode: 0: SISO-A, 1: SISO-B, 2: MRC */
|
||||
sysp->u.activateRfReq.u8DiversityMode = pinst->u.lc15.diversity_mode;
|
||||
|
||||
/* maximum cell size in quarter-bits, 90 == 12.456 km */
|
||||
sysp->u.activateRfReq.u8MaxCellSize = 90;
|
||||
sysp->u.activateRfReq.u8MaxCellSize = pinst->u.lc15.max_cell_size;
|
||||
|
||||
/* auto tx power adjustment mode 0:none, 1: automatic*/
|
||||
sysp->u.activateRfReq.autoPowerAdjust.u8EnAutoPowerAdjust = pinst->u.lc15.tx_pwr_adj_mode;
|
||||
|
||||
/* PSK modulation scheme maximum power level */
|
||||
sysp->u.activateRfReq.autoPowerAdjust.u8PowerReduction8Psk = pinst->u.lc15.tx_pwr_red_8psk;
|
||||
} else {
|
||||
sysp->id = Litecell15_PrimId_DeactivateRfReq;
|
||||
}
|
||||
@@ -1319,7 +1366,8 @@ static int mute_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "Rx RF-MUTE.conf with status=%s\n",
|
||||
get_value_string(lc15bts_l1status_names, status));
|
||||
bts_update_status(BTS_STATUS_RF_MUTE, fl1h->last_rf_mute[0]);
|
||||
if(trx->bts->lc15.led_ctrl_mode == LC15_LED_CONTROL_BTS)
|
||||
bts_update_status(BTS_STATUS_RF_MUTE, fl1h->last_rf_mute[0]);
|
||||
oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 1);
|
||||
|
||||
osmo_static_assert(
|
||||
@@ -1555,6 +1603,53 @@ int l1if_close(struct lc15l1_hdl *fl1h)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dsp_alive_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
{
|
||||
Litecell15_Prim_t *sysp = msgb_sysprim(resp);
|
||||
Litecell15_IsAliveCnf_t *sac = &sysp->u.IsAliveCnf;
|
||||
struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx);
|
||||
|
||||
fl1h->hw_alive.dsp_alive_cnt++;
|
||||
LOGP(DL1C, LOGL_NOTICE, "Rx SYS prim %s, status=%d (%d)\n",
|
||||
get_value_string(lc15bts_sysprim_names, sysp->id), sac->status, trx->nr);
|
||||
|
||||
msgb_free(resp);
|
||||
}
|
||||
|
||||
static int dsp_alive_timer_cb(void *data)
|
||||
{
|
||||
struct lc15l1_hdl *fl1h = data;
|
||||
struct gsm_bts_trx *trx = fl1h->phy_inst->trx;
|
||||
struct msgb *msg = sysp_msgb_alloc();
|
||||
int rc;
|
||||
|
||||
Litecell15_Prim_t *sys_prim = msgb_sysprim(msg);
|
||||
sys_prim->id = Litecell15_PrimId_IsAliveReq;
|
||||
|
||||
if (fl1h->hw_alive.dsp_alive_cnt == 0) {
|
||||
|
||||
LOGP(DL1C, LOGL_ERROR, "Timeout waiting for SYS prim %s primitive (%d)\n",
|
||||
get_value_string(lc15bts_sysprim_names, sys_prim->id + 1), trx->nr);
|
||||
|
||||
exit(23);
|
||||
}
|
||||
|
||||
LOGP(DL1C, LOGL_NOTICE, "Tx SYS prim %s (%d)\n",
|
||||
get_value_string(lc15bts_sysprim_names, sys_prim->id), trx->nr);
|
||||
|
||||
rc = l1if_req_compl(fl1h, msg, dsp_alive_compl_cb, NULL);
|
||||
if (rc < 0) {
|
||||
LOGP(DL1C, LOGL_FATAL, "Failed to send %s primitive\n", get_value_string(lc15bts_sysprim_names, sys_prim->id));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* restart timer */
|
||||
fl1h->hw_alive.dsp_alive_cnt = 0;
|
||||
osmo_timer_schedule(&fl1h->hw_alive.dsp_alive_timer, fl1h->hw_alive.dsp_alive_period, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bts_model_phy_link_open(struct phy_link *plink)
|
||||
{
|
||||
struct phy_instance *pinst = phy_instance_by_num(plink, 0);
|
||||
@@ -1574,6 +1669,24 @@ int bts_model_phy_link_open(struct phy_link *plink)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Set default PHY parameters */
|
||||
if (!pinst->u.lc15.max_cell_size)
|
||||
pinst->u.lc15.max_cell_size = LC15_BTS_MAX_CELL_SIZE_DEFAULT;
|
||||
|
||||
if (!pinst->u.lc15.diversity_mode)
|
||||
pinst->u.lc15.diversity_mode = LC15_BTS_DIVERSITY_MODE_DEFAULT;
|
||||
|
||||
if (!pinst->u.lc15.pedestal_mode)
|
||||
pinst->u.lc15.pedestal_mode = LC15_BTS_PEDESTAL_MODE_DEFAULT;
|
||||
|
||||
if (!pinst->u.lc15.dsp_alive_period)
|
||||
pinst->u.lc15.dsp_alive_period = LC15_BTS_DSP_ALIVE_TMR_DEFAULT;
|
||||
|
||||
if (!pinst->u.lc15.tx_pwr_adj_mode)
|
||||
pinst->u.lc15.tx_pwr_adj_mode = LC15_BTS_TX_PWR_ADJ_DEFAULT;
|
||||
|
||||
if (!pinst->u.lc15.tx_pwr_red_8psk)
|
||||
pinst->u.lc15.tx_pwr_red_8psk = LC15_BTS_TX_RED_PWR_8PSK_DEFAULT;
|
||||
|
||||
struct lc15l1_hdl *fl1h = pinst->u.lc15.hdl;
|
||||
fl1h->dsp_trace_f = dsp_trace;
|
||||
@@ -1582,5 +1695,24 @@ int bts_model_phy_link_open(struct phy_link *plink)
|
||||
|
||||
phy_link_state_set(plink, PHY_LINK_CONNECTED);
|
||||
|
||||
/* Send first IS_ALIVE primitive */
|
||||
struct msgb *msg = sysp_msgb_alloc();
|
||||
int rc;
|
||||
|
||||
Litecell15_Prim_t *sys_prim = msgb_sysprim(msg);
|
||||
sys_prim->id = Litecell15_PrimId_IsAliveReq;
|
||||
|
||||
rc = l1if_req_compl(fl1h, msg, dsp_alive_compl_cb, NULL);
|
||||
if (rc < 0) {
|
||||
LOGP(DL1C, LOGL_FATAL, "Failed to send %s primitive\n", get_value_string(lc15bts_sysprim_names, sys_prim->id));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* initialize DSP heart beat alive timer */
|
||||
fl1h->hw_alive.dsp_alive_timer.cb = dsp_alive_timer_cb;
|
||||
fl1h->hw_alive.dsp_alive_timer.data = fl1h;
|
||||
fl1h->hw_alive.dsp_alive_cnt = 0;
|
||||
fl1h->hw_alive.dsp_alive_period = pinst->u.lc15.dsp_alive_period;
|
||||
osmo_timer_schedule(&fl1h->hw_alive.dsp_alive_timer, fl1h->hw_alive.dsp_alive_period, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,12 @@ struct lc15l1_hdl {
|
||||
struct calib_send_state st;
|
||||
|
||||
uint8_t last_rf_mute[8];
|
||||
|
||||
struct {
|
||||
struct osmo_timer_list dsp_alive_timer;
|
||||
unsigned int dsp_alive_cnt;
|
||||
uint8_t dsp_alive_period;
|
||||
} hw_alive;
|
||||
};
|
||||
|
||||
#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h)
|
||||
|
||||
@@ -121,6 +121,8 @@ enum l1prim_type lc15bts_get_sysprim_type(Litecell15_PrimId_t id)
|
||||
case Litecell15_PrimId_MuteRfCnf: return L1P_T_CONF;
|
||||
case Litecell15_PrimId_SetRxAttenReq: return L1P_T_REQ;
|
||||
case Litecell15_PrimId_SetRxAttenCnf: return L1P_T_CONF;
|
||||
case Litecell15_PrimId_IsAliveReq: return L1P_T_REQ;
|
||||
case Litecell15_PrimId_IsAliveCnf: return L1P_T_CONF;
|
||||
default: return L1P_T_INVALID;
|
||||
}
|
||||
}
|
||||
@@ -142,6 +144,8 @@ const struct value_string lc15bts_sysprim_names[Litecell15_PrimId_NUM+1] = {
|
||||
{ Litecell15_PrimId_MuteRfCnf, "MUTE-RF.cnf" },
|
||||
{ Litecell15_PrimId_SetRxAttenReq, "SET-RX-ATTEN.req" },
|
||||
{ Litecell15_PrimId_SetRxAttenCnf, "SET-RX-ATTEN-CNF.cnf" },
|
||||
{ Litecell15_PrimId_IsAliveReq, "IS-ALIVE.req" },
|
||||
{ Litecell15_PrimId_IsAliveCnf, "IS-ALIVE-CNF.cnf" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
@@ -155,6 +159,7 @@ Litecell15_PrimId_t lc15bts_get_sysprim_conf(Litecell15_PrimId_t id)
|
||||
case Litecell15_PrimId_SetCalibTblReq: return Litecell15_PrimId_SetCalibTblCnf;
|
||||
case Litecell15_PrimId_MuteRfReq: return Litecell15_PrimId_MuteRfCnf;
|
||||
case Litecell15_PrimId_SetRxAttenReq: return Litecell15_PrimId_SetRxAttenCnf;
|
||||
case Litecell15_PrimId_IsAliveReq: return Litecell15_PrimId_IsAliveCnf;
|
||||
default: return -1; // Weak
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,27 @@ enum l1prim_type {
|
||||
L1P_T_IND,
|
||||
};
|
||||
|
||||
enum lc15_diversity_mode{
|
||||
LC15_DIVERSITY_SISO_A = 0,
|
||||
LC15_DIVERSITY_SISO_B,
|
||||
LC15_DIVERSITY_MRC,
|
||||
};
|
||||
|
||||
enum lc15_pedestal_mode{
|
||||
LC15_PEDESTAL_OFF = 0,
|
||||
LC15_PEDESTAL_ON,
|
||||
};
|
||||
|
||||
enum lc15_led_control_mode{
|
||||
LC15_LED_CONTROL_BTS = 0,
|
||||
LC15_LED_CONTROL_EXT,
|
||||
};
|
||||
|
||||
enum lc15_auto_pwr_adjust_mode{
|
||||
LC15_TX_PWR_ADJ_NONE = 0,
|
||||
LC15_TX_PWR_ADJ_AUTO,
|
||||
};
|
||||
|
||||
enum l1prim_type lc15bts_get_l1prim_type(GsmL1_PrimId_t id);
|
||||
const struct value_string lc15bts_l1prim_names[GsmL1_PrimId_NUM+1];
|
||||
GsmL1_PrimId_t lc15bts_get_l1prim_conf(GsmL1_PrimId_t id);
|
||||
@@ -61,4 +82,13 @@ enum pdch_cs {
|
||||
|
||||
const uint8_t pdch_msu_size[_NUM_PDCH_CS];
|
||||
|
||||
/* LC15 default parameters */
|
||||
#define LC15_BTS_MAX_CELL_SIZE_DEFAULT 166 /* 166 qbits is default value */
|
||||
#define LC15_BTS_DIVERSITY_MODE_DEFAULT 0 /* SISO-A is default mode */
|
||||
#define LC15_BTS_PEDESTAL_MODE_DEFAULT 0 /* Unused TS is off by default */
|
||||
#define LC15_BTS_LED_CTRL_MODE_DEFAULT 0 /* LED is controlled by BTS by default */
|
||||
#define LC15_BTS_DSP_ALIVE_TMR_DEFAULT 5 /* Default DSP alive timer is 5 seconds */
|
||||
#define LC15_BTS_TX_PWR_ADJ_DEFAULT 0 /* Default Tx power auto adjustment is none */
|
||||
#define LC15_BTS_TX_RED_PWR_8PSK_DEFAULT 0 /* Default 8-PSK maximum power level is 0 dB */
|
||||
|
||||
#endif /* LC15BTS_H */
|
||||
|
||||
@@ -65,6 +65,31 @@ extern int lchan_activate(struct gsm_lchan *lchan);
|
||||
|
||||
static struct gsm_bts *vty_bts;
|
||||
|
||||
static const struct value_string lc15_diversity_mode_strs[] = {
|
||||
{ LC15_DIVERSITY_SISO_A, "siso-a" },
|
||||
{ LC15_DIVERSITY_SISO_B, "siso-b" },
|
||||
{ LC15_DIVERSITY_MRC, "mrc" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct value_string lc15_pedestal_mode_strs[] = {
|
||||
{ LC15_PEDESTAL_OFF, "off" },
|
||||
{ LC15_PEDESTAL_ON, "on" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct value_string lc15_led_mode_strs[] = {
|
||||
{ LC15_LED_CONTROL_BTS, "bts" },
|
||||
{ LC15_LED_CONTROL_EXT, "external" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct value_string lc15_auto_adj_pwr_strs[] = {
|
||||
{ LC15_TX_PWR_ADJ_NONE, "none" },
|
||||
{ LC15_TX_PWR_ADJ_AUTO, "auto" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* configuration */
|
||||
|
||||
DEFUN(cfg_phy_cal_path, cfg_phy_cal_path_cmd,
|
||||
@@ -88,7 +113,7 @@ DEFUN(cfg_phy_dsp_trace_f, cfg_phy_dsp_trace_f_cmd,
|
||||
unsigned int flag;
|
||||
|
||||
flag = get_string_value(lc15bts_tracef_names, argv[1]);
|
||||
pinst->u.lc15.dsp_trace_f |= ~flag;
|
||||
pinst->u.lc15.dsp_trace_f |= flag;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@@ -321,8 +346,130 @@ DEFUN(cfg_trx_nominal_power, cfg_trx_nominal_power_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_max_cell_size, cfg_phy_max_cell_size_cmd,
|
||||
"max-cell-size <0-166>",
|
||||
"Set the maximum cell size in qbits\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
int cell_size = (uint8_t)atoi(argv[0]);
|
||||
|
||||
if (( cell_size > 166 ) || ( cell_size < 0 )) {
|
||||
vty_out(vty, "Max cell size must be between 0 and 166 qbits (%d) %s",
|
||||
cell_size, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.max_cell_size = (uint8_t)cell_size;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_diversity_mode, cfg_phy_diversity_mode_cmd,
|
||||
"diversity-mode (siso-a|siso-b|mrc)",
|
||||
"Set reception diversity mode \n"
|
||||
"Reception diversity mode can be (siso-a, siso-b, mrc)\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
int val = get_string_value(lc15_diversity_mode_strs, argv[0]);
|
||||
|
||||
if((val < LC15_DIVERSITY_SISO_A) || (val > LC15_DIVERSITY_MRC)) {
|
||||
vty_out(vty, "Invalid reception diversity mode %d%s", val, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.diversity_mode = (uint8_t)val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_pedestal_mode, cfg_phy_pedestal_mode_cmd,
|
||||
"pedestal-mode (on|off)",
|
||||
"Set unused time-slot transmission in pedestal mode\n"
|
||||
"Transmission pedestal mode can be (off, on)\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
int val = get_string_value(lc15_pedestal_mode_strs, argv[0]);
|
||||
|
||||
if((val < LC15_PEDESTAL_OFF) || (val > LC15_PEDESTAL_ON)) {
|
||||
vty_out(vty, "Invalid unused time-slot transmission mode %d%s", val, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.pedestal_mode = (uint8_t)val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_led_mode, cfg_bts_led_mode_cmd,
|
||||
"led-control-mode (bts|external)",
|
||||
"Set LED controlled by BTS or external software\n"
|
||||
"LED can be controlled by (bts, external)\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
int val = get_string_value(lc15_led_mode_strs, argv[0]);
|
||||
|
||||
if((val < LC15_LED_CONTROL_BTS) || (val > LC15_LED_CONTROL_EXT)) {
|
||||
vty_out(vty, "Invalid LED control mode %d%s", val, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
bts->lc15.led_ctrl_mode = (uint8_t)val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_dsp_alive_timer, cfg_phy_dsp_alive_timer_cmd,
|
||||
"dsp-alive-period <0-60>",
|
||||
"Set DSP alive timer period in second\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
uint8_t period = (uint8_t)atoi(argv[0]);
|
||||
|
||||
if (( period > 60 ) || ( period < 0 )) {
|
||||
vty_out(vty, "DSP heart beat alive timer period must be between 0 and 60 seconds (%d) %s",
|
||||
period, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.dsp_alive_period = period;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_auto_tx_pwr_adj, cfg_phy_auto_tx_pwr_adj_cmd,
|
||||
"pwr-adj-mode (none|auto)",
|
||||
"Set output power adjustment mode\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
int val = get_string_value(lc15_auto_adj_pwr_strs, argv[0]);
|
||||
|
||||
if((val < LC15_TX_PWR_ADJ_NONE) || (val > LC15_TX_PWR_ADJ_AUTO)) {
|
||||
vty_out(vty, "Invalid output power adjustment mode %d%s", val, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.tx_pwr_adj_mode = (uint8_t)val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_tx_red_pwr_8psk, cfg_phy_tx_red_pwr_8psk_cmd,
|
||||
"tx-red-pwr-8psk <0-40>",
|
||||
"Set reduction output power for 8-PSK scheme in dB unit\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
int val = atoi(argv[0]);
|
||||
|
||||
if ((val > 40) || (val < 0)) {
|
||||
vty_out(vty, "Reduction Tx power level must be between 0 and 40 dB (%d) %s",
|
||||
val, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.tx_pwr_red_8psk = (uint8_t)val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
|
||||
{
|
||||
|
||||
vty_out(vty, " led-control-mode %s%s",
|
||||
get_value_string(lc15_led_mode_strs, bts->lc15.led_ctrl_mode), VTY_NEWLINE);
|
||||
|
||||
}
|
||||
|
||||
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
|
||||
@@ -347,8 +494,27 @@ void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst
|
||||
}
|
||||
}
|
||||
if (pinst->u.lc15.calib_path)
|
||||
vty_out(vty, " trx-calibration-path %s%s",
|
||||
vty_out(vty, " trx-calibration-path %s%s",
|
||||
pinst->u.lc15.calib_path, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " max-cell-size %d%s",
|
||||
pinst->u.lc15.max_cell_size, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " diversity-mode %s%s",
|
||||
get_value_string(lc15_diversity_mode_strs, pinst->u.lc15.diversity_mode), VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " pedestal-mode %s%s",
|
||||
get_value_string(lc15_pedestal_mode_strs, pinst->u.lc15.pedestal_mode) , VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " dsp-alive-period %d%s",
|
||||
pinst->u.lc15.dsp_alive_period, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " pwr-adj-mode %s%s",
|
||||
get_value_string(lc15_auto_adj_pwr_strs, pinst->u.lc15.tx_pwr_adj_mode), VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " tx-red-pwr-8psk %d%s",
|
||||
pinst->u.lc15.tx_pwr_red_8psk, VTY_NEWLINE);
|
||||
|
||||
}
|
||||
|
||||
int bts_model_vty_init(struct gsm_bts *bts)
|
||||
@@ -401,12 +567,20 @@ int bts_model_vty_init(struct gsm_bts *bts)
|
||||
|
||||
install_element(BTS_NODE, &cfg_bts_auto_band_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_no_auto_band_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_led_mode_cmd);
|
||||
|
||||
install_element(TRX_NODE, &cfg_trx_nominal_power_cmd);
|
||||
|
||||
install_element(PHY_INST_NODE, &cfg_phy_dsp_trace_f_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_no_dsp_trace_f_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_cal_path_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_diversity_mode_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_pedestal_mode_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_max_cell_size_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_dsp_alive_timer_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_auto_tx_pwr_adj_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_tx_red_pwr_8psk_cmd);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com>
|
||||
* Copyright (C) 2016 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
*
|
||||
* Based on sysmoBTS:
|
||||
* (C) 2011-2013 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
@@ -51,6 +51,25 @@
|
||||
#include <osmo-bts/pcu_if.h>
|
||||
#include <osmo-bts/l1sap.h>
|
||||
|
||||
static int write_status_file(char *status_file, char *status_str)
|
||||
{
|
||||
FILE *outf;
|
||||
char tmp[PATH_MAX+1];
|
||||
|
||||
snprintf(tmp, sizeof(tmp)-1, "/var/run/osmo-bts/%s", status_file);
|
||||
tmp[PATH_MAX-1] = '\0';
|
||||
|
||||
outf = fopen(tmp, "w");
|
||||
if (!outf)
|
||||
return -1;
|
||||
|
||||
fprintf(outf, "%s\n", status_str);
|
||||
|
||||
fclose(outf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*NTQD: Change how rx_nr is handle in multi-trx*/
|
||||
#define LC15BTS_RF_LOCK_PATH "/var/lock/bts_rf_lock"
|
||||
|
||||
@@ -71,7 +90,8 @@ int bts_model_init(struct gsm_bts *bts)
|
||||
|
||||
bts->variant = BTS_OSMO_LITECELL15;
|
||||
bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
|
||||
|
||||
/* specific default values for LC15 platform */
|
||||
bts->lc15.led_ctrl_mode = LC15_BTS_LED_CTRL_MODE_DEFAULT;
|
||||
rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error creating the OML router: %s rc=%d\n",
|
||||
@@ -93,6 +113,7 @@ int bts_model_init(struct gsm_bts *bts)
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_EFR);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_MS_PWR_CTRL_DSP);
|
||||
|
||||
bts_model_vty_init(bts);
|
||||
|
||||
@@ -116,6 +137,9 @@ void bts_model_phy_instance_set_defaults(struct phy_instance *pinst)
|
||||
|
||||
int bts_model_oml_estab(struct gsm_bts *bts)
|
||||
{
|
||||
/* update status file */
|
||||
write_status_file("state", "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -123,24 +147,16 @@ void bts_update_status(enum bts_global_status which, int on)
|
||||
{
|
||||
static uint64_t states = 0;
|
||||
uint64_t old_states = states;
|
||||
int led_rf_active_on;
|
||||
|
||||
if (on)
|
||||
states |= (1ULL << which);
|
||||
else
|
||||
states &= ~(1ULL << which);
|
||||
|
||||
led_rf_active_on =
|
||||
(states & (1ULL << BTS_STATUS_RF_ACTIVE)) &&
|
||||
!(states & (1ULL << BTS_STATUS_RF_MUTE));
|
||||
|
||||
LOGP(DL1C, LOGL_INFO,
|
||||
"Set global status #%d to %d (%04llx -> %04llx), LEDs: ACT %d\n",
|
||||
"Set global status #%d to %d (%04llx -> %04llx)",
|
||||
which, on,
|
||||
(long long)old_states, (long long)states,
|
||||
led_rf_active_on);
|
||||
|
||||
lc15bts_led_set(led_rf_active_on ? LED_GREEN : LED_OFF);
|
||||
(long long)old_states, (long long)states);
|
||||
}
|
||||
|
||||
void bts_model_print_help()
|
||||
@@ -197,11 +213,17 @@ int bts_model_handle_options(int argc, char **argv)
|
||||
|
||||
void bts_model_abis_close(struct gsm_bts *bts)
|
||||
{
|
||||
/* write to status file */
|
||||
write_status_file("state", "ABIS DOWN");
|
||||
|
||||
/* for now, we simply terminate the program and re-spawn */
|
||||
bts_shutdown(bts, "Abis close");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* create status file with initial state */
|
||||
write_status_file("state", "ABIS DOWN");
|
||||
|
||||
return bts_main(argc, argv);
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ int main(int argc, char **argv)
|
||||
exit(2);
|
||||
|
||||
lc15bts_mgr_vty_init();
|
||||
logging_vty_add_cmds(&mgr_log_info);
|
||||
logging_vty_add_cmds();
|
||||
rc = lc15bts_mgr_parse_config(&manager);
|
||||
if (rc < 0) {
|
||||
LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n");
|
||||
|
||||
@@ -584,39 +584,39 @@ DEFUN(show_mgr, show_mgr_cmd, "show manager",
|
||||
lc15bts_mgr_sensor_get_state(s_mgr->state.state), VTY_NEWLINE);
|
||||
vty_out(vty, "Current Temperatures%s", VTY_NEWLINE);
|
||||
lc15bts_temp_get(LC15BTS_TEMP_SUPPLY, &temp);
|
||||
vty_out(vty, " Main Supply : %4.2f Celcius%s",
|
||||
vty_out(vty, " Main Supply : %4.2f Celsius%s",
|
||||
temp/ 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
lc15bts_temp_get(LC15BTS_TEMP_SOC, &temp);
|
||||
vty_out(vty, " SoC : %4.2f Celcius%s",
|
||||
vty_out(vty, " SoC : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
lc15bts_temp_get(LC15BTS_TEMP_FPGA, &temp);
|
||||
vty_out(vty, " FPGA : %4.2f Celcius%s",
|
||||
vty_out(vty, " FPGA : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
lc15bts_temp_get(LC15BTS_TEMP_RMSDET, &temp);
|
||||
vty_out(vty, " RMSDet : %4.2f Celcius%s",
|
||||
vty_out(vty, " RMSDet : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
lc15bts_temp_get(LC15BTS_TEMP_OCXO, &temp);
|
||||
vty_out(vty, " OCXO : %4.2f Celcius%s",
|
||||
vty_out(vty, " OCXO : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
lc15bts_temp_get(LC15BTS_TEMP_TX0, &temp);
|
||||
vty_out(vty, " TX 0 : %4.2f Celcius%s",
|
||||
vty_out(vty, " TX 0 : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
lc15bts_temp_get(LC15BTS_TEMP_TX1, &temp);
|
||||
vty_out(vty, " TX 1 : %4.2f Celcius%s",
|
||||
vty_out(vty, " TX 1 : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
lc15bts_temp_get(LC15BTS_TEMP_PA0, &temp);
|
||||
vty_out(vty, " Power Amp #0: %4.2f Celcius%s",
|
||||
vty_out(vty, " Power Amp #0: %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
lc15bts_temp_get(LC15BTS_TEMP_PA1, &temp);
|
||||
vty_out(vty, " Power Amp #1: %4.2f Celcius%s",
|
||||
vty_out(vty, " Power Amp #1: %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
|
||||
|
||||
@@ -363,7 +363,7 @@ int lc15bts_firmware_reload(enum lc15bts_firmware_type type)
|
||||
case LC15BTS_FW_DSP1:
|
||||
fd = open(fw_sysfs[type], O_WRONLY);
|
||||
if (fd < 0) {
|
||||
LOGP(DFW, LOGL_ERROR, "unable ot open firmware device %s: %s\n",
|
||||
LOGP(DFW, LOGL_ERROR, "unable to open firmware device %s: %s\n",
|
||||
fw_sysfs[type], strerror(errno));
|
||||
close(fd);
|
||||
return fd;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
#define FACTORY_ROM_PATH "/mnt/rom/factory"
|
||||
#define USER_ROM_PATH "/mnt/storage/var/run/lc15bts-mgr"
|
||||
|
||||
enum lc15bts_par {
|
||||
|
||||
@@ -161,7 +161,7 @@ int lc15bts_swd_init(struct lc15bts_mgr_instance *mgr, int swd_num_events)
|
||||
the value must be in the range of [0,'swd_num_events'[ (see lc15bts_swd_init).
|
||||
For example, if 'swd_num_events' was 64, 'swd_event' events are numbered 0 to 63.
|
||||
WARNING: if this function can be used from multiple threads at the same time,
|
||||
it must be protected with a kind of mutex to avoid loosing event notification.
|
||||
it must be protected with a kind of mutex to avoid losing event notification.
|
||||
*/
|
||||
int lc15bts_swd_event(struct lc15bts_mgr_instance *mgr, enum mgr_swd_events swd_event)
|
||||
{
|
||||
|
||||
@@ -1724,7 +1724,7 @@ int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg,
|
||||
power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0);
|
||||
}
|
||||
|
||||
/* FIXME: we actaully need to send a ACK or NACK for the OML message */
|
||||
/* FIXME: we actually need to send a ACK or NACK for the OML message */
|
||||
return oml_fom_ack_nack(msg, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -373,7 +373,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
|
||||
rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP");
|
||||
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
|
||||
data_ind->measParam.fBer * 10000,
|
||||
data_ind->measParam.fLinkQuality * 10);
|
||||
data_ind->measParam.fLinkQuality * 10, 0, 0, 0);
|
||||
}
|
||||
|
||||
payload_type = data_ind->msgUnitParam.u8Buffer[0];
|
||||
@@ -463,7 +463,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
|
||||
if (rmsg)
|
||||
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
|
||||
data_ind->measParam.fBer * 10000,
|
||||
data_ind->measParam.fLinkQuality * 10);
|
||||
data_ind->measParam.fLinkQuality * 10, 0, 0, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
|
||||
#include <nrw/oc2g/oc2g.h>
|
||||
#include <nrw/oc2g/gsml1const.h>
|
||||
@@ -132,17 +133,9 @@ static int calib_file_open(struct oc2gl1_hdl *fl1h,
|
||||
|
||||
st->fp = fopen(fname, "rb");
|
||||
if (!st->fp) {
|
||||
LOGP(DL1C, LOGL_NOTICE, "Failed to open '%s' for calibration data.\n", fname);
|
||||
|
||||
/* TODO (oramadan): Fix OML alarms
|
||||
if( fl1h->phy_inst->trx ){
|
||||
fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr;
|
||||
|
||||
alarm_sig_data.mo = &fl1h->phy_inst->trx->mo;
|
||||
alarm_sig_data.add_text = (char*)&fname[0];
|
||||
osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_FAIL_OPEN_CALIB_ALARM, &alarm_sig_data);
|
||||
}
|
||||
*/
|
||||
LOGP(DL1C, LOGL_FATAL, "Failed to open '%s' for calibration data.\n", fname);
|
||||
oml_tx_failure_event_rep(&fl1h->phy_inst->trx->mo, NM_SEVER_MAJOR, OSMO_EVT_WARN_SW_WARN,
|
||||
"Failed to open '%s' for calibration data", fname);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -227,18 +220,9 @@ static int calib_file_send(struct oc2gl1_hdl *fl1h,
|
||||
|
||||
rc = calib_verify(fl1h, desc);
|
||||
if (rc < 0) {
|
||||
LOGP(DL1C, LOGL_NOTICE,"Verify L1 calibration table %s -> failed (%d)\n", desc->fname, rc);
|
||||
|
||||
/* TODO (oramadan): Fix OML alarms
|
||||
if (fl1h->phy_inst->trx) {
|
||||
fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr;
|
||||
|
||||
alarm_sig_data.mo = &fl1h->phy_inst->trx->mo;
|
||||
alarm_sig_data.add_text = (char*)&desc->fname[0];
|
||||
memcpy(alarm_sig_data.spare, &rc, sizeof(int));
|
||||
osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_FAIL_VERIFY_CALIB_ALARM, &alarm_sig_data);
|
||||
}
|
||||
*/
|
||||
LOGP(DL1C, LOGL_FATAL, "Verify L1 calibration table %s -> failed (%d)\n", desc->fname, rc);
|
||||
oml_tx_failure_event_rep(&fl1h->phy_inst->trx->mo, NM_SEVER_MAJOR, OSMO_EVT_WARN_SW_WARN,
|
||||
"Verify L1 calibration table %s -> failed (%d)", desc->fname, rc);
|
||||
|
||||
st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx);
|
||||
|
||||
@@ -293,16 +277,9 @@ int calib_load(struct oc2gl1_hdl *fl1h)
|
||||
char *calib_path = fl1h->phy_inst->u.oc2g.calib_path;
|
||||
|
||||
if (!calib_path) {
|
||||
LOGP(DL1C, LOGL_NOTICE, "Calibration file path not specified\n");
|
||||
|
||||
/* TODO (oramadan): Fix OML alarms
|
||||
if( fl1h->phy_inst->trx ){
|
||||
fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr;
|
||||
|
||||
alarm_sig_data.mo = &fl1h->phy_inst->trx->mo;
|
||||
osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_NO_CALIB_PATH_ALARM, &alarm_sig_data);
|
||||
}
|
||||
*/
|
||||
LOGP(DL1C, LOGL_FATAL, "Calibration file path not specified\n");
|
||||
oml_tx_failure_event_rep(&fl1h->phy_inst->trx->mo, NM_SEVER_MAJOR, OSMO_EVT_WARN_SW_WARN,
|
||||
"Calibration file path not specified");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -330,7 +307,7 @@ static int calib_verify(struct oc2gl1_hdl *fl1h, const struct calib_file_desc *d
|
||||
fseek(st->fp, 0L, SEEK_END);
|
||||
sz = ftell(st->fp);
|
||||
|
||||
/* rewind read poiner */
|
||||
/* rewind read pointer */
|
||||
fseek(st->fp, 0L, SEEK_SET);
|
||||
|
||||
/* read file */
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include <osmo-bts/l1sap.h>
|
||||
#include <osmo-bts/msg_utils.h>
|
||||
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||
#include <osmo-bts/cbch.h>
|
||||
|
||||
#include <nrw/oc2g/oc2g.h>
|
||||
#include <nrw/oc2g/gsml1prim.h>
|
||||
@@ -846,6 +847,45 @@ static uint8_t chan_nr_by_sapi(struct gsm_bts_trx_ts *ts,
|
||||
return (cbits << 3) | u8Tn;
|
||||
}
|
||||
|
||||
static const enum l1sap_common_sapi common_sapi_by_sapi_t[] = {
|
||||
[GsmL1_Sapi_Idle] = L1SAP_COMMON_SAPI_IDLE,
|
||||
[GsmL1_Sapi_Fcch] = L1SAP_COMMON_SAPI_FCCH,
|
||||
[GsmL1_Sapi_Sch] = L1SAP_COMMON_SAPI_SCH,
|
||||
[GsmL1_Sapi_Sacch] = L1SAP_COMMON_SAPI_SACCH,
|
||||
[GsmL1_Sapi_Sdcch] = L1SAP_COMMON_SAPI_SDCCH,
|
||||
[GsmL1_Sapi_Bcch] = L1SAP_COMMON_SAPI_BCCH,
|
||||
[GsmL1_Sapi_Pch] = L1SAP_COMMON_SAPI_PCH,
|
||||
[GsmL1_Sapi_Agch] = L1SAP_COMMON_SAPI_AGCH,
|
||||
[GsmL1_Sapi_Cbch] = L1SAP_COMMON_SAPI_CBCH,
|
||||
[GsmL1_Sapi_Rach] = L1SAP_COMMON_SAPI_RACH,
|
||||
[GsmL1_Sapi_TchF] = L1SAP_COMMON_SAPI_TCH_F,
|
||||
[GsmL1_Sapi_FacchF] = L1SAP_COMMON_SAPI_FACCH_F,
|
||||
[GsmL1_Sapi_TchH] = L1SAP_COMMON_SAPI_TCH_H,
|
||||
[GsmL1_Sapi_FacchH] = L1SAP_COMMON_SAPI_FACCH_H,
|
||||
[GsmL1_Sapi_Nch] = L1SAP_COMMON_SAPI_NCH,
|
||||
[GsmL1_Sapi_Pdtch] = L1SAP_COMMON_SAPI_PDTCH,
|
||||
[GsmL1_Sapi_Pacch] = L1SAP_COMMON_SAPI_PACCH,
|
||||
[GsmL1_Sapi_Pbcch] = L1SAP_COMMON_SAPI_PBCCH,
|
||||
[GsmL1_Sapi_Pagch] = L1SAP_COMMON_SAPI_PAGCH,
|
||||
[GsmL1_Sapi_Ppch] = L1SAP_COMMON_SAPI_PPCH,
|
||||
[GsmL1_Sapi_Pnch] = L1SAP_COMMON_SAPI_PNCH,
|
||||
[GsmL1_Sapi_Ptcch] = L1SAP_COMMON_SAPI_PTCCH,
|
||||
[GsmL1_Sapi_Prach] = L1SAP_COMMON_SAPI_PRACH,
|
||||
};
|
||||
|
||||
static enum l1sap_common_sapi get_common_sapi(GsmL1_Sapi_t sapi)
|
||||
{
|
||||
if (sapi >= GsmL1_Sapi_NUM)
|
||||
return L1SAP_COMMON_SAPI_UNKNOWN;
|
||||
return common_sapi_by_sapi_t[sapi];
|
||||
}
|
||||
|
||||
static void set_log_ctx_sapi(GsmL1_Sapi_t sapi)
|
||||
{
|
||||
l1sap_log_ctx_sapi = get_common_sapi(sapi);
|
||||
log_set_context(LOG_CTX_L1_SAPI, &l1sap_log_ctx_sapi);
|
||||
}
|
||||
|
||||
static int handle_ph_readytosend_ind(struct oc2gl1_hdl *fl1,
|
||||
GsmL1_PhReadyToSendInd_t *rts_ind,
|
||||
struct msgb *l1p_msg)
|
||||
@@ -862,6 +902,8 @@ static int handle_ph_readytosend_ind(struct oc2gl1_hdl *fl1,
|
||||
uint8_t chan_nr, link_id;
|
||||
uint32_t fn;
|
||||
|
||||
set_log_ctx_sapi(rts_ind->sapi);
|
||||
|
||||
/* check if primitive should be handled by common part */
|
||||
chan_nr = chan_nr_by_sapi(&trx->ts[rts_ind->u8Tn], rts_ind->sapi,
|
||||
rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn);
|
||||
@@ -950,12 +992,9 @@ empty_frame:
|
||||
goto tx;
|
||||
}
|
||||
|
||||
static void dump_meas_res(int ll, GsmL1_MeasParam_t *m)
|
||||
{
|
||||
LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, "
|
||||
"BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality,
|
||||
m->fBer, m->i16BurstTiming);
|
||||
}
|
||||
|
||||
#define LOG_FMT_MEAS "Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, BER %-3.2f, Timing %d"
|
||||
#define LOG_PARAM_MEAS(meas_param) (meas_param)->fRssi, (meas_param)->fLinkQuality, (meas_param)->fBer, (meas_param)->i16BurstTiming
|
||||
|
||||
static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
GsmL1_MeasParam_t *m, uint32_t fn)
|
||||
@@ -988,6 +1027,8 @@ static int handle_ph_data_ind(struct oc2gl1_hdl *fl1, GsmL1_PhDataInd_t *data_in
|
||||
int rc = 0;
|
||||
int8_t rssi;
|
||||
|
||||
set_log_ctx_sapi(data_ind->sapi);
|
||||
|
||||
chan_nr = chan_nr_by_sapi(&trx->ts[data_ind->u8Tn], data_ind->sapi,
|
||||
data_ind->subCh, data_ind->u8Tn, data_ind->u32Fn);
|
||||
fn = data_ind->u32Fn;
|
||||
@@ -1004,10 +1045,10 @@ static int handle_ph_data_ind(struct oc2gl1_hdl *fl1, GsmL1_PhDataInd_t *data_in
|
||||
process_meas_res(trx, chan_nr, &data_ind->measParam, fn);
|
||||
|
||||
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s\n",
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s, " LOG_FMT_MEAS "\n",
|
||||
get_value_string(oc2gbts_l1sapi_names, data_ind->sapi), (uint32_t)data_ind->hLayer2,
|
||||
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size));
|
||||
dump_meas_res(LOGL_DEBUG, &data_ind->measParam);
|
||||
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size),
|
||||
LOG_PARAM_MEAS(&data_ind->measParam));
|
||||
|
||||
/* check for TCH */
|
||||
if (data_ind->sapi == GsmL1_Sapi_TchF
|
||||
@@ -1040,11 +1081,10 @@ static int handle_ph_data_ind(struct oc2gl1_hdl *fl1, GsmL1_PhDataInd_t *data_in
|
||||
l1sap->u.data.chan_nr = chan_nr;
|
||||
l1sap->u.data.fn = fn;
|
||||
l1sap->u.data.rssi = rssi;
|
||||
if (!pcu_direct) {
|
||||
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
|
||||
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64;
|
||||
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
|
||||
}
|
||||
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
|
||||
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64;
|
||||
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
|
||||
|
||||
return l1sap_up(trx, l1sap);
|
||||
}
|
||||
|
||||
@@ -1052,19 +1092,14 @@ static int handle_ph_ra_ind(struct oc2gl1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
|
||||
struct msgb *l1p_msg)
|
||||
{
|
||||
struct gsm_bts_trx *trx = oc2gl1_hdl_trx(fl1);
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
struct gsm_lchan *lchan;
|
||||
struct osmo_phsap_prim *l1sap;
|
||||
int rc;
|
||||
struct ph_rach_ind_param rach_ind_param;
|
||||
|
||||
/* FIXME: this should be deprecated/obsoleted as it bypasses rach.busy counting */
|
||||
if (ra_ind->measParam.fLinkQuality < bts->min_qual_rach) {
|
||||
msgb_free(l1p_msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dump_meas_res(LOGL_DEBUG, &ra_ind->measParam);
|
||||
set_log_ctx_sapi(ra_ind->sapi);
|
||||
LOGPFN(DL1C, LOGL_DEBUG, ra_ind->u32Fn, "Rx PH-RA.ind, " LOG_FMT_MEAS "\n",
|
||||
LOG_PARAM_MEAS(&ra_ind->measParam));
|
||||
|
||||
if ((ra_ind->msgUnitParam.u8Size != 1) &&
|
||||
(ra_ind->msgUnitParam.u8Size != 2)) {
|
||||
@@ -1084,13 +1119,14 @@ static int handle_ph_ra_ind(struct oc2gl1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
|
||||
.rssi = (int8_t) ra_ind->measParam.fRssi,
|
||||
.ber10k = (unsigned int) (ra_ind->measParam.fBer * 10000.0),
|
||||
.acc_delay_256bits = ra_ind->measParam.i16BurstTiming * 64,
|
||||
.lqual_cb = (int16_t) ra_ind->measParam.fLinkQuality * 10, /* centiBels */
|
||||
};
|
||||
|
||||
lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ra_ind->hLayer2);
|
||||
if (!lchan || lchan->ts->pchan == GSM_PCHAN_CCCH ||
|
||||
lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4 ||
|
||||
lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH)
|
||||
rach_ind_param.chan_nr = 0x88;
|
||||
rach_ind_param.chan_nr = RSL_CHAN_RACH;
|
||||
else
|
||||
rach_ind_param.chan_nr = gsm_lchan2chan_nr(lchan);
|
||||
|
||||
@@ -1266,7 +1302,6 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
GsmL1_Status_t status;
|
||||
int on = 0;
|
||||
unsigned int i;
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
|
||||
if (sysp->id == Oc2g_PrimId_ActivateRfCnf)
|
||||
on = 1;
|
||||
@@ -1495,13 +1530,25 @@ static int reset_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l1if_reset(struct oc2gl1_hdl *hdl)
|
||||
/* FIXME: This delays the TRX initialization by 5 sec in order to avoid the
|
||||
* occurrence of a race condition in the OML bringup. This a work around and
|
||||
* should be fixed properly. See also OS#3782, OS#2470 and OS#2469 */
|
||||
void l1if_reset_cb(void *arg)
|
||||
{
|
||||
struct oc2gl1_hdl *hdl = arg;
|
||||
struct msgb *msg = sysp_msgb_alloc();
|
||||
Oc2g_Prim_t *sysp = msgb_sysprim(msg);
|
||||
sysp->id = Oc2g_PrimId_Layer1ResetReq;
|
||||
|
||||
return l1if_req_compl(hdl, msg, reset_compl_cb, NULL);
|
||||
l1if_req_compl(hdl, msg, reset_compl_cb, NULL);
|
||||
}
|
||||
|
||||
int l1if_reset(struct oc2gl1_hdl *hdl)
|
||||
{
|
||||
static struct osmo_timer_list T_l1if_reset;
|
||||
osmo_timer_setup(&T_l1if_reset, l1if_reset_cb, hdl);
|
||||
osmo_timer_schedule(&T_l1if_reset, 5, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the trace flags within the DSP */
|
||||
@@ -1745,7 +1792,7 @@ int bts_model_phy_link_open(struct phy_link *plink)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* initialize DSP heart beat alive timer * /
|
||||
/ * initialize DSP heart beat alive timer * /
|
||||
fl1h->hw_alive.dsp_alive_timer.cb = dsp_alive_timer_cb;
|
||||
fl1h->hw_alive.dsp_alive_timer.data = fl1h;
|
||||
fl1h->hw_alive.dsp_alive_cnt = 0;
|
||||
|
||||
@@ -30,6 +30,13 @@ enum {
|
||||
_NUM_MQ_WRITE
|
||||
};
|
||||
|
||||
/* gsm_bts->model_priv, specific to Open Cellular 2G BTS */
|
||||
struct bts_oc2g_priv {
|
||||
uint8_t led_ctrl_mode; /* 0: control by BTS, 1: not control by BTS */
|
||||
struct llist_head ceased_alarm_list; /* ceased alarm list*/
|
||||
unsigned int rtp_drift_thres_ms; /* RTP timestamp drift detection threshold */
|
||||
};
|
||||
|
||||
struct calib_send_state {
|
||||
FILE *fp;
|
||||
const char *path;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com>
|
||||
* Copyright (C) 2016 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
*
|
||||
* Based on sysmoBTS:
|
||||
* (C) 2011-2013 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
@@ -83,20 +83,21 @@ unsigned int dsp_trace = 0x00000000;
|
||||
|
||||
int bts_model_init(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
struct stat st;
|
||||
static struct osmo_fd accept_fd, read_fd;
|
||||
int rc;
|
||||
|
||||
struct bts_oc2g_priv *bts_oc2g = talloc(bts, struct bts_oc2g_priv);
|
||||
bts->model_priv = bts_oc2g;
|
||||
bts->variant = BTS_OSMO_OC2G;
|
||||
bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
|
||||
/* specific default values for OC2G platform */
|
||||
|
||||
/* TODO(oramadan) MERGE
|
||||
bts->oc2g.led_ctrl_mode = OC2G_BTS_LED_CTRL_MODE_DEFAULT;
|
||||
/* RTP drift threshold default * /
|
||||
bts->oc2g.rtp_drift_thres_ms = OC2G_BTS_RTP_DRIFT_THRES_DEFAULT;
|
||||
bts_oc2g->led_ctrl_mode = OC2G_BTS_LED_CTRL_MODE_DEFAULT;
|
||||
*/
|
||||
/* RTP drift threshold default */
|
||||
/* bts_oc2g->rtp_drift_thres_ms = OC2G_BTS_RTP_DRIFT_THRES_DEFAULT; */
|
||||
|
||||
rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd);
|
||||
if (rc < 0) {
|
||||
@@ -119,6 +120,7 @@ int bts_model_init(struct gsm_bts *bts)
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_EFR);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_MS_PWR_CTRL_DSP);
|
||||
|
||||
bts_model_vty_init(bts);
|
||||
|
||||
@@ -127,7 +129,7 @@ int bts_model_init(struct gsm_bts *bts)
|
||||
|
||||
int bts_model_trx_init(struct gsm_bts_trx *trx)
|
||||
{
|
||||
trx->nominal_power = 40;
|
||||
trx->nominal_power = 25;
|
||||
trx->power_params.trx_p_max_out_mdBm = to_mdB(trx->bts->c0->nominal_power);
|
||||
return 0;
|
||||
}
|
||||
@@ -152,24 +154,16 @@ void bts_update_status(enum bts_global_status which, int on)
|
||||
{
|
||||
static uint64_t states = 0;
|
||||
uint64_t old_states = states;
|
||||
int led_rf_active_on;
|
||||
|
||||
if (on)
|
||||
states |= (1ULL << which);
|
||||
else
|
||||
states &= ~(1ULL << which);
|
||||
|
||||
led_rf_active_on =
|
||||
(states & (1ULL << BTS_STATUS_RF_ACTIVE)) &&
|
||||
!(states & (1ULL << BTS_STATUS_RF_MUTE));
|
||||
|
||||
LOGP(DL1C, LOGL_INFO,
|
||||
"Set global status #%d to %d (%04llx -> %04llx), LEDs: ACT %d\n",
|
||||
"Set global status #%d to %d (%04llx -> %04llx)\n",
|
||||
which, on,
|
||||
(long long)old_states, (long long)states,
|
||||
led_rf_active_on);
|
||||
|
||||
oc2gbts_led_set(led_rf_active_on ? LED_GREEN : LED_OFF);
|
||||
(long long)old_states, (long long)states);
|
||||
}
|
||||
|
||||
void bts_model_print_help()
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "oc2gbts_bid.h"
|
||||
|
||||
@@ -106,7 +107,6 @@ void oc2gbts_rev_get(char *rev_maj, char *rev_min)
|
||||
|
||||
const char* get_hwversion_desc()
|
||||
{
|
||||
int rev;
|
||||
int model;
|
||||
size_t len;
|
||||
static char model_name[64] = {0, };
|
||||
@@ -114,14 +114,9 @@ const char* get_hwversion_desc()
|
||||
|
||||
char rev_maj = 0, rev_min = 0;
|
||||
|
||||
int rc = 0;
|
||||
oc2gbts_rev_get(&rev_maj, &rev_min);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (rev >= 0) {
|
||||
len += snprintf(model_name + len, sizeof(model_name) - len,
|
||||
" Rev %d.%d", (uint8_t)rev_maj, (uint8_t)rev_min);
|
||||
}
|
||||
len += snprintf(model_name + len, sizeof(model_name) - len,
|
||||
" Rev %" PRIu8 ".%" PRIu8, (uint8_t)rev_maj, (uint8_t)rev_min);
|
||||
|
||||
model = oc2gbts_model_get();
|
||||
if (model >= 0) {
|
||||
|
||||
@@ -43,5 +43,6 @@ enum oc2gbts_gsm_band {
|
||||
void oc2gbts_rev_get(char *rev_maj, char *rev_min);
|
||||
int oc2gbts_model_get(void);
|
||||
int oc2gbts_option_get(enum oc2gbts_option_type type);
|
||||
const char* get_hwversion_desc();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -100,8 +100,6 @@ static int sysfs_write_str(int fd, const char *str)
|
||||
|
||||
int oc2gbts_clock_err_open(void)
|
||||
{
|
||||
int rc;
|
||||
int fault;
|
||||
|
||||
if (clkerr_fd_err < 0) {
|
||||
clkerr_fd_err = open(CLKERR_ERR_SYSFS, O_RDONLY);
|
||||
|
||||
@@ -150,7 +150,7 @@ static void led_sleep_cb(void *_data) {
|
||||
/* Delete current timer */
|
||||
osmo_timer_del(&led_list->led_timer.timer);
|
||||
/* Rotate the timer list */
|
||||
llist_move_tail(led_list, &mgr->oc2gbts_leds.list);
|
||||
llist_move_tail(&led_list->list, &mgr->oc2gbts_leds.list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,9 +261,9 @@ static const struct log_info mgr_log_info = {
|
||||
.num_cat = ARRAY_SIZE(mgr_log_info_cat),
|
||||
};
|
||||
|
||||
static int mgr_log_init(void)
|
||||
static int mgr_log_init(void *ctx)
|
||||
{
|
||||
osmo_init_logging(&mgr_log_info);
|
||||
osmo_init_logging2(ctx, &mgr_log_info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -271,13 +271,12 @@ int main(int argc, char **argv)
|
||||
{
|
||||
void *tall_msgb_ctx;
|
||||
int rc;
|
||||
pthread_t tid;
|
||||
|
||||
tall_mgr_ctx = talloc_named_const(NULL, 1, "bts manager");
|
||||
tall_msgb_ctx = talloc_named_const(tall_mgr_ctx, 1, "msgb");
|
||||
msgb_set_talloc_ctx(tall_msgb_ctx);
|
||||
msgb_talloc_ctx_init(tall_msgb_ctx, 0);
|
||||
|
||||
mgr_log_init();
|
||||
mgr_log_init(tall_mgr_ctx);
|
||||
|
||||
osmo_init_ignore_signals();
|
||||
signal(SIGINT, &signal_handler);
|
||||
@@ -289,7 +288,7 @@ int main(int argc, char **argv)
|
||||
exit(2);
|
||||
|
||||
oc2gbts_mgr_vty_init();
|
||||
logging_vty_add_cmds(&mgr_log_info);
|
||||
logging_vty_add_cmds();
|
||||
rc = oc2gbts_mgr_parse_config(&manager);
|
||||
if (rc < 0) {
|
||||
LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n");
|
||||
|
||||
@@ -87,7 +87,7 @@ static int oc2gbts_par_get_uptime(void *ctx, int *ret)
|
||||
|
||||
fpath = talloc_asprintf(ctx, "%s", UPTIME_TMP_PATH);
|
||||
if (!fpath)
|
||||
return NULL;
|
||||
return -EINVAL;
|
||||
|
||||
fp = fopen(fpath, "r");
|
||||
if (!fp)
|
||||
@@ -117,7 +117,7 @@ static int oc2gbts_par_set_uptime(void *ctx, int val)
|
||||
|
||||
fpath = talloc_asprintf(ctx, "%s", UPTIME_TMP_PATH);
|
||||
if (!fpath)
|
||||
return NULL;
|
||||
return -EINVAL;
|
||||
|
||||
fp = fopen(fpath, "w");
|
||||
if (!fp)
|
||||
@@ -134,7 +134,7 @@ static int oc2gbts_par_set_uptime(void *ctx, int val)
|
||||
fclose(fp);
|
||||
return -EIO;
|
||||
}
|
||||
fsync(fp);
|
||||
fsync(fileno(fp));
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
@@ -245,18 +245,6 @@ static void send_ctrl_cmd(struct oc2gbts_mgr_instance *mgr, struct msgb *msg)
|
||||
ipa_client_conn_send(mgr->oc2gbts_ctrl.bts_conn, msg);
|
||||
}
|
||||
|
||||
static void send_set_ctrl_cmd_int(struct oc2gbts_mgr_instance *mgr, const char *key, const int val)
|
||||
{
|
||||
struct msgb *msg;
|
||||
int ret;
|
||||
|
||||
msg = msgb_alloc_headroom(1024, 128, "CTRL SET");
|
||||
ret = snprintf((char *) msg->data, 4096, "SET %u %s %d",
|
||||
mgr->oc2gbts_ctrl.last_seqno++, key, val);
|
||||
msg->l2h = msgb_put(msg, ret);
|
||||
return send_ctrl_cmd(mgr, msg);
|
||||
}
|
||||
|
||||
static void send_set_ctrl_cmd(struct oc2gbts_mgr_instance *mgr, const char *key, const int val, const char *text)
|
||||
{
|
||||
struct msgb *msg;
|
||||
|
||||
@@ -512,35 +512,35 @@ DEFUN(show_mgr, show_mgr_cmd, "show manager",
|
||||
oc2gbts_mgr_sensor_get_state(s_mgr->state.state), VTY_NEWLINE);
|
||||
vty_out(vty, "Current Temperatures%s", VTY_NEWLINE);
|
||||
oc2gbts_temp_get(OC2GBTS_TEMP_SUPPLY, &temp);
|
||||
vty_out(vty, " Main Supply : %4.2f Celcius%s",
|
||||
vty_out(vty, " Main Supply : %4.2f Celsius%s",
|
||||
temp/ 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
oc2gbts_temp_get(OC2GBTS_TEMP_SOC, &temp);
|
||||
vty_out(vty, " SoC : %4.2f Celcius%s",
|
||||
vty_out(vty, " SoC : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
oc2gbts_temp_get(OC2GBTS_TEMP_FPGA, &temp);
|
||||
vty_out(vty, " FPGA : %4.2f Celcius%s",
|
||||
vty_out(vty, " FPGA : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
if (oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) ||
|
||||
oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) {
|
||||
oc2gbts_temp_get(OC2GBTS_TEMP_RMSDET, &temp);
|
||||
vty_out(vty, " RMSDet : %4.2f Celcius%s",
|
||||
vty_out(vty, " RMSDet : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
oc2gbts_temp_get(OC2GBTS_TEMP_OCXO, &temp);
|
||||
vty_out(vty, " OCXO : %4.2f Celcius%s",
|
||||
vty_out(vty, " OCXO : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
oc2gbts_temp_get(OC2GBTS_TEMP_TX, &temp);
|
||||
vty_out(vty, " TX : %4.2f Celcius%s",
|
||||
vty_out(vty, " TX : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
if (oc2gbts_option_get(OC2GBTS_OPTION_PA_TEMP)) {
|
||||
oc2gbts_temp_get(OC2GBTS_TEMP_PA, &temp);
|
||||
vty_out(vty, " Power Amp : %4.2f Celcius%s",
|
||||
vty_out(vty, " Power Amp : %4.2f Celsius%s",
|
||||
temp / 1000.0f,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
@@ -878,46 +878,37 @@ int oc2gbts_mgr_vty_init(void)
|
||||
|
||||
install_node(&mgr_node, config_write_mgr);
|
||||
install_element(CONFIG_NODE, &cfg_mgr_cmd);
|
||||
vty_install_default(MGR_NODE);
|
||||
|
||||
/* install the limit nodes */
|
||||
install_node(&limit_supply_temp_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_supply_temp_cmd);
|
||||
vty_install_default(LIMIT_SUPPLY_TEMP_NODE);
|
||||
|
||||
install_node(&limit_soc_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_soc_temp_cmd);
|
||||
vty_install_default(LIMIT_SOC_NODE);
|
||||
|
||||
install_node(&limit_fpga_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_fpga_temp_cmd);
|
||||
vty_install_default(LIMIT_FPGA_NODE);
|
||||
|
||||
if (oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) ||
|
||||
oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) {
|
||||
install_node(&limit_rmsdet_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_rmsdet_temp_cmd);
|
||||
vty_install_default(LIMIT_RMSDET_NODE);
|
||||
}
|
||||
|
||||
install_node(&limit_ocxo_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_ocxo_temp_cmd);
|
||||
vty_install_default(LIMIT_OCXO_NODE);
|
||||
|
||||
install_node(&limit_tx_temp_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_tx_temp_cmd);
|
||||
vty_install_default(LIMIT_TX_TEMP_NODE);
|
||||
|
||||
if (oc2gbts_option_get(OC2GBTS_OPTION_PA_TEMP)) {
|
||||
install_node(&limit_pa_temp_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_pa_temp_cmd);
|
||||
vty_install_default(LIMIT_PA_TEMP_NODE);
|
||||
}
|
||||
|
||||
install_node(&limit_supply_volt_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_supply_volt_cmd);
|
||||
register_limit(LIMIT_SUPPLY_VOLT_NODE, MGR_LIMIT_TYPE_VOLT);
|
||||
vty_install_default(LIMIT_SUPPLY_VOLT_NODE);
|
||||
|
||||
if (oc2gbts_option_get(OC2GBTS_OPTION_PA) &&
|
||||
oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) &&
|
||||
@@ -925,23 +916,19 @@ int oc2gbts_mgr_vty_init(void)
|
||||
install_node(&limit_vswr_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_vswr_cmd);
|
||||
register_limit(LIMIT_VSWR_NODE, MGR_LIMIT_TYPE_VSWR);
|
||||
vty_install_default(LIMIT_VSWR_NODE);
|
||||
}
|
||||
|
||||
install_node(&limit_supply_pwr_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_supply_pwr_cmd);
|
||||
register_limit(LIMIT_SUPPLY_PWR_NODE, MGR_LIMIT_TYPE_PWR);
|
||||
vty_install_default(LIMIT_SUPPLY_PWR_NODE);
|
||||
|
||||
if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) {
|
||||
install_node(&limit_pa_pwr_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_pa_pwr_cmd);
|
||||
vty_install_default(LIMIT_PA_PWR_NODE);
|
||||
}
|
||||
|
||||
install_node(&limit_gps_fix_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_limit_gps_fix_cmd);
|
||||
vty_install_default(LIMIT_GPS_FIX_NODE);
|
||||
|
||||
/* install the normal node */
|
||||
install_node(&act_norm_node, config_write_dummy);
|
||||
@@ -952,12 +939,10 @@ int oc2gbts_mgr_vty_init(void)
|
||||
install_node(&act_warn_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_action_warn_cmd);
|
||||
register_action(ACT_WARN_NODE);
|
||||
vty_install_default(ACT_WARN_NODE);
|
||||
|
||||
install_node(&act_crit_node, config_write_dummy);
|
||||
install_element(MGR_NODE, &cfg_action_critical_cmd);
|
||||
register_action(ACT_CRIT_NODE);
|
||||
vty_install_default(ACT_CRIT_NODE);
|
||||
|
||||
/* install LED pattern command for debugging purpose */
|
||||
install_element_ve(&set_led_pattern_cmd);
|
||||
|
||||
@@ -361,7 +361,7 @@ int oc2gbts_firmware_reload(enum oc2gbts_firmware_type type)
|
||||
case OC2GBTS_FW_DSP:
|
||||
fd = open(fw_sysfs[type], O_WRONLY);
|
||||
if (fd < 0) {
|
||||
LOGP(DFW, LOGL_ERROR, "unable ot open firmware device %s: %s\n",
|
||||
LOGP(DFW, LOGL_ERROR, "unable to open firmware device %s: %s\n",
|
||||
fw_sysfs[type], strerror(errno));
|
||||
close(fd);
|
||||
return fd;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user