mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-bts.git
synced 2025-11-11 01:15:57 +00:00
Compare commits
743 Commits
shared/31c
...
0.6.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1283e3d543 | ||
|
|
b026d38703 | ||
|
|
8876a507ff | ||
|
|
aa11997480 | ||
|
|
9a30b77813 | ||
|
|
01e84be54f | ||
|
|
2bbf98afa3 | ||
|
|
4d5df2ebd1 | ||
|
|
ed662e0799 | ||
|
|
b0578dda95 | ||
|
|
d4450051fc | ||
|
|
b78fc1eeee | ||
|
|
69ec4a419e | ||
|
|
506a7f98b2 | ||
|
|
fb78397cbd | ||
|
|
fe6c75d24a | ||
|
|
bd65b72f91 | ||
|
|
cd1b08b14f | ||
|
|
bc56094cac | ||
|
|
de99be4afb | ||
|
|
d1f8001cdf | ||
|
|
6fe823a7e1 | ||
|
|
d208132ab9 | ||
|
|
dc469994f3 | ||
|
|
82987f7a7d | ||
|
|
d6da809d2f | ||
|
|
69e0461674 | ||
|
|
bbd4d54e46 | ||
|
|
8edfe03595 | ||
|
|
cbb64cffa5 | ||
|
|
824764fa6b | ||
|
|
db4ab8e5ce | ||
|
|
69de62a573 | ||
|
|
9dccaa2064 | ||
|
|
0ebf985492 | ||
|
|
8785978c37 | ||
|
|
0e9dadc3d8 | ||
|
|
d7546ed090 | ||
|
|
f66d2fc1e6 | ||
|
|
2d2fca4342 | ||
|
|
b2bbc81921 | ||
|
|
91cecc051a | ||
|
|
173a4f1f79 | ||
|
|
f690e5d45c | ||
|
|
a59fb6220b | ||
|
|
df07f0a9cb | ||
|
|
3617fd1cb6 | ||
|
|
e0e2b9e303 | ||
|
|
576408b651 | ||
|
|
e3b8279f26 | ||
|
|
6feae225eb | ||
|
|
3cda4ff532 | ||
|
|
1f45db0ff5 | ||
|
|
81335edae3 | ||
|
|
5eb17e28ac | ||
|
|
152c2f489c | ||
|
|
9a2187e7b1 | ||
|
|
65db0f5c41 | ||
|
|
9a280eba48 | ||
|
|
7887ce7aea | ||
|
|
6a538a0921 | ||
|
|
390742b3ed | ||
|
|
f06ba300c4 | ||
|
|
ffdc05bc4e | ||
|
|
c2d3f14bfb | ||
|
|
f588b5f91d | ||
|
|
0bd7a19114 | ||
|
|
aa15504097 | ||
|
|
3ae0be0f12 | ||
|
|
523ae04e5e | ||
|
|
171d80a8d6 | ||
|
|
8baa45a8e3 | ||
|
|
3902e4d9c4 | ||
|
|
9b97d0f683 | ||
|
|
a38d34112f | ||
|
|
cc1602f592 | ||
|
|
f2eaba8869 | ||
|
|
cdf20fec7c | ||
|
|
bb71947829 | ||
|
|
c19ab9ed2f | ||
|
|
7738f5282f | ||
|
|
0ada527bc0 | ||
|
|
dd3c7815a5 | ||
|
|
b7425f3642 | ||
|
|
8d645dd0e5 | ||
|
|
250d77f8df | ||
|
|
53ce11ab95 | ||
|
|
59d0c2cca6 | ||
|
|
5047fbe3b8 | ||
|
|
521ab50dcc | ||
|
|
ae7ece1064 | ||
|
|
4962ed1811 | ||
|
|
d0846651a3 | ||
|
|
620bd83b12 | ||
|
|
2a4c5fa2b3 | ||
|
|
4699ebaa26 | ||
|
|
7a6b178fc0 | ||
|
|
53216b5d1f | ||
|
|
50f8165540 | ||
|
|
61f9158eaf | ||
|
|
1ba0cfe9c0 | ||
|
|
9d294c9cb1 | ||
|
|
5466ff9c1b | ||
|
|
94bdcfd803 | ||
|
|
114293a414 | ||
|
|
d4806db1e5 | ||
|
|
71ad40c647 | ||
|
|
5b87144f91 | ||
|
|
d5971d0681 | ||
|
|
aa5edff477 | ||
|
|
f4544573f8 | ||
|
|
186c6bac07 | ||
|
|
340cff51f4 | ||
|
|
0b7a3e9f62 | ||
|
|
0227e4d04c | ||
|
|
61d36212b1 | ||
|
|
de9357251c | ||
|
|
b7793ed8fd | ||
|
|
1dcbee3420 | ||
|
|
78a5073dfb | ||
|
|
16b8f51839 | ||
|
|
0e7886d379 | ||
|
|
3e2de526b0 | ||
|
|
88b2cc30a6 | ||
|
|
67d3b8b136 | ||
|
|
95d2505e57 | ||
|
|
d22b5b84c0 | ||
|
|
d5fdcfe6d9 | ||
|
|
e3a3906ee9 | ||
|
|
8a8d73a691 | ||
|
|
d36b3a8463 | ||
|
|
e91cd2b088 | ||
|
|
9eeb0b1a13 | ||
|
|
a8bf666a09 | ||
|
|
cb5a969a45 | ||
|
|
450714b19c | ||
|
|
43c763f5af | ||
|
|
440930be44 | ||
|
|
05ba5c2a10 | ||
|
|
3f97e4b1fc | ||
|
|
538475259c | ||
|
|
524e3e3170 | ||
|
|
ed9e022eb4 | ||
|
|
a493ce9e66 | ||
|
|
031e8fedac | ||
|
|
b4c9c8f35d | ||
|
|
ed51c3d145 | ||
|
|
72993079ed | ||
|
|
e0fb3ae52d | ||
|
|
27b022e0c4 | ||
|
|
3aeb9301f4 | ||
|
|
efbef50efc | ||
|
|
9c1d3f9606 | ||
|
|
2f028c4e2c | ||
|
|
67d8c72c2e | ||
|
|
b16eed22c7 | ||
|
|
2c841100a9 | ||
|
|
17a09507b8 | ||
|
|
e3de64cd67 | ||
|
|
22704a88e2 | ||
|
|
2d848a061e | ||
|
|
8913b29be2 | ||
|
|
028820510e | ||
|
|
9563039a2a | ||
|
|
9d5ec1af74 | ||
|
|
91685096f8 | ||
|
|
40dca8f991 | ||
|
|
d62a58dbfb | ||
|
|
322252d793 | ||
|
|
fce5b31b94 | ||
|
|
b4bf603c98 | ||
|
|
25742a5929 | ||
|
|
e4403464ed | ||
|
|
7a21dccec1 | ||
|
|
d040bf97de | ||
|
|
1fde15c8bd | ||
|
|
8e7a51d8c3 | ||
|
|
416ee3ec89 | ||
|
|
dafb363533 | ||
|
|
bbe90fd651 | ||
|
|
e16b593574 | ||
|
|
957843959d | ||
|
|
f4816fa577 | ||
|
|
a80c7024f8 | ||
|
|
b609ee879e | ||
|
|
f9eef0ce3e | ||
|
|
83c4fbc2dc | ||
|
|
f462c87581 | ||
|
|
339b9329ff | ||
|
|
9dfdf54d30 | ||
|
|
6f5e398ccb | ||
|
|
a1b891aab4 | ||
|
|
4acc98e68a | ||
|
|
758522947f | ||
|
|
64d16028eb | ||
|
|
70c68853c2 | ||
|
|
6b4c6aa375 | ||
|
|
c4ac69dcc2 | ||
|
|
b390dfb90d | ||
|
|
0418ef588c | ||
|
|
e2e0ed5a89 | ||
|
|
d5414cc30e | ||
|
|
ae50f7dac2 | ||
|
|
7a18906cfa | ||
|
|
d15dc832c9 | ||
|
|
1631266993 | ||
|
|
3c144069da | ||
|
|
69d297ce75 | ||
|
|
df5ac9aa11 | ||
|
|
13d0feb404 | ||
|
|
4ba7363286 | ||
|
|
eb4a3392e1 | ||
|
|
1beb9bcbe0 | ||
|
|
1965b0d880 | ||
|
|
67bc885c5d | ||
|
|
a760a043c4 | ||
|
|
16b4179fbe | ||
|
|
42ffb325f8 | ||
|
|
9344080109 | ||
|
|
8c45ae59f9 | ||
|
|
d81e5e963a | ||
|
|
c1d8f5a490 | ||
|
|
f65b57a707 | ||
|
|
871e0bec7e | ||
|
|
10b11325a7 | ||
|
|
8be9d7a6fe | ||
|
|
ea5ccfa481 | ||
|
|
2b763cc30c | ||
|
|
70b71507c2 | ||
|
|
c37fd88985 | ||
|
|
1e399f888e | ||
|
|
0e5b12f981 | ||
|
|
df75195666 | ||
|
|
b76043e6f4 | ||
|
|
de6d25e21d | ||
|
|
4723a19508 | ||
|
|
962b33ea9d | ||
|
|
563b744b38 | ||
|
|
792573dc97 | ||
|
|
ec11a85929 | ||
|
|
c038cb7903 | ||
|
|
94dd5060c8 | ||
|
|
2cf6b73a42 | ||
|
|
f3763590bd | ||
|
|
bfd42c2b0a | ||
|
|
f9778b2a26 | ||
|
|
c2ecca6b04 | ||
|
|
86d7843712 | ||
|
|
304420ca42 | ||
|
|
fbe655f320 | ||
|
|
fed8ce3c5a | ||
|
|
2c95ae6a09 | ||
|
|
a1fa955212 | ||
|
|
55a7b07417 | ||
|
|
960dd993cd | ||
|
|
20363d165e | ||
|
|
4a85828462 | ||
|
|
b58aa60d78 | ||
|
|
36153239bf | ||
|
|
aabeb2eae4 | ||
|
|
f4b238f91e | ||
|
|
103ddc7155 | ||
|
|
704fba5dc2 | ||
|
|
dd8a4a85e4 | ||
|
|
6f4ce14ed7 | ||
|
|
8ea93a8a7d | ||
|
|
ae5405e2a4 | ||
|
|
be671bc61f | ||
|
|
f7b559f960 | ||
|
|
b2fbdd023b | ||
|
|
66325aee71 | ||
|
|
bdf10eb705 | ||
|
|
c43352dbc4 | ||
|
|
c757272443 | ||
|
|
388a91cbd1 | ||
|
|
5ee3dba39f | ||
|
|
9f936344ea | ||
|
|
57b5fb8819 | ||
|
|
203ea2c209 | ||
|
|
38843fbf48 | ||
|
|
acfccb3f02 | ||
|
|
4008ebb925 | ||
|
|
9d102508a8 | ||
|
|
bce25a60f4 | ||
|
|
efb4a4baeb | ||
|
|
64a2bd72f5 | ||
|
|
ced9a5d0e2 | ||
|
|
5a4f4d12e1 | ||
|
|
c22da59342 | ||
|
|
068918f990 | ||
|
|
c88a10cece | ||
|
|
ebb483b69a | ||
|
|
b0c1d21581 | ||
|
|
21142f7898 | ||
|
|
b058778df1 | ||
|
|
de9dbe7958 | ||
|
|
babd05661d | ||
|
|
c09e5a44c3 | ||
|
|
93f3102da9 | ||
|
|
b8b939faa9 | ||
|
|
4ca5be766c | ||
|
|
9f9b96a67b | ||
|
|
c1b86d80d1 | ||
|
|
8b39ff8bcf | ||
|
|
f5494e84e8 | ||
|
|
3f192f2291 | ||
|
|
fac02d3d75 | ||
|
|
5f2e2de84f | ||
|
|
067ef3f1ce | ||
|
|
9959f45d90 | ||
|
|
7dffd553df | ||
|
|
94fa25295f | ||
|
|
1559678fa2 | ||
|
|
654175f33b | ||
|
|
eb08a87be5 | ||
|
|
a570e05ec8 | ||
|
|
e2069d968c | ||
|
|
c77b574d1f | ||
|
|
70460814ce | ||
|
|
527dd402c7 | ||
|
|
80473a113d | ||
|
|
0a05181603 | ||
|
|
b4969cc915 | ||
|
|
a91b2d9691 | ||
|
|
ac84afa409 | ||
|
|
d44f0772f9 | ||
|
|
3cc91746a3 | ||
|
|
c9a1f284ac | ||
|
|
ed6b48e4a5 | ||
|
|
8431bbb80f | ||
|
|
bf6bae2b23 | ||
|
|
8a148613b4 | ||
|
|
4dfc3da96b | ||
|
|
9faaf4ecf0 | ||
|
|
3b2e5de3ae | ||
|
|
988f634c97 | ||
|
|
e77bcaecb6 | ||
|
|
43d082e6f1 | ||
|
|
55c46022e1 | ||
|
|
37af36e85e | ||
|
|
63849ebf71 | ||
|
|
67a056c122 | ||
|
|
ef8e2ef681 | ||
|
|
b7cdd381d6 | ||
|
|
4b76a323b3 | ||
|
|
b0f8fa8143 | ||
|
|
44663c17e7 | ||
|
|
d6920df630 | ||
|
|
af3443385b | ||
|
|
0d4b37d641 | ||
|
|
45d3bbfb44 | ||
|
|
576071d6ca | ||
|
|
5069c1c518 | ||
|
|
108b60faba | ||
|
|
ba656fff91 | ||
|
|
2b34ae32cf | ||
|
|
53d792c3b0 | ||
|
|
dab54b9178 | ||
|
|
9407e644b0 | ||
|
|
e07ba54d62 | ||
|
|
a888e95efa | ||
|
|
dd34540ce4 | ||
|
|
7b186adb0a | ||
|
|
b0f77ce685 | ||
|
|
090a41f897 | ||
|
|
78458a3811 | ||
|
|
21ffe07894 | ||
|
|
6e656748b7 | ||
|
|
73cb583e51 | ||
|
|
c9582ac2d7 | ||
|
|
c57304b65e | ||
|
|
9ab51522da | ||
|
|
8e22ac3d1a | ||
|
|
ee2299c8fa | ||
|
|
95dec9ff4a | ||
|
|
334df9441a | ||
|
|
290c7d954f | ||
|
|
7f1365c05e | ||
|
|
2479ef4133 | ||
|
|
ae65ccd0b2 | ||
|
|
8a2f026cf0 | ||
|
|
4355021b8a | ||
|
|
2ed03cd640 | ||
|
|
cff0d44e53 | ||
|
|
b8f5f4e176 | ||
|
|
b151301c6c | ||
|
|
1c1b0e843d | ||
|
|
e3edc17426 | ||
|
|
7267a0d37e | ||
|
|
d5f95c308b | ||
|
|
bb1e3b089b | ||
|
|
c03d3ae7af | ||
|
|
5c0d88e69d | ||
|
|
4fa641d7b2 | ||
|
|
64e3813b06 | ||
|
|
9797a72cd7 | ||
|
|
99642656a0 | ||
|
|
c2874c4360 | ||
|
|
3f919171ef | ||
|
|
a4c6802315 | ||
|
|
0eaa27a6be | ||
|
|
037dcfe981 | ||
|
|
380a2e6d90 | ||
|
|
ccb1148717 | ||
|
|
724412a49a | ||
|
|
f0d6d6ba02 | ||
|
|
dd084e6e57 | ||
|
|
61372a20de | ||
|
|
c3fb0dcc8c | ||
|
|
274d29bedd | ||
|
|
7efc2f3c5b | ||
|
|
b231e0f6cd | ||
|
|
63b296bdd9 | ||
|
|
57fc1124e1 | ||
|
|
294fbe104b | ||
|
|
24a31cfe43 | ||
|
|
0d10f0e482 | ||
|
|
f8bf95fa6b | ||
|
|
e6cc04827a | ||
|
|
9375aa9a68 | ||
|
|
bfc9ff3118 | ||
|
|
6b60611a4d | ||
|
|
bc9c42663d | ||
|
|
8a75e60d0c | ||
|
|
ae2a8b75f9 | ||
|
|
3686005180 | ||
|
|
ea40bd60e7 | ||
|
|
a8168271eb | ||
|
|
e951042475 | ||
|
|
65efa691f8 | ||
|
|
6ab1ed580d | ||
|
|
213db32e30 | ||
|
|
703c2d6eb8 | ||
|
|
ecd5bc2aef | ||
|
|
7cc3c3156e | ||
|
|
58e4e18206 | ||
|
|
cbbce0be09 | ||
|
|
d0d2c9217a | ||
|
|
7158c2ed08 | ||
|
|
a55b166c6c | ||
|
|
3f3f34ba52 | ||
|
|
495fed9f43 | ||
|
|
a10ac248c6 | ||
|
|
60970056c8 | ||
|
|
8ecadc66ce | ||
|
|
9302abe054 | ||
|
|
45e97ac59a | ||
|
|
3a1f1b8e91 | ||
|
|
4582222757 | ||
|
|
c1586388dc | ||
|
|
51bfebec39 | ||
|
|
ef30f50d5d | ||
|
|
201b424b73 | ||
|
|
0778cd488a | ||
|
|
ed494443cc | ||
|
|
b61850248a | ||
|
|
c8da1ac9a6 | ||
|
|
227015e52e | ||
|
|
460e1b7387 | ||
|
|
21fc6e45fb | ||
|
|
925fcf48ed | ||
|
|
0fe3b215b9 | ||
|
|
06968beab9 | ||
|
|
ae5a737c18 | ||
|
|
c4fc00d851 | ||
|
|
3044a26d71 | ||
|
|
b857f27704 | ||
|
|
9591b6c253 | ||
|
|
bb0cc685f1 | ||
|
|
6044785a22 | ||
|
|
b2b1112a6e | ||
|
|
f3ee66207d | ||
|
|
0be80aa2d1 | ||
|
|
710e99c2e3 | ||
|
|
40e8365854 | ||
|
|
d5c658b22e | ||
|
|
91565b2d51 | ||
|
|
2278fdc580 | ||
|
|
cb20c83323 | ||
|
|
94bb3769f3 | ||
|
|
e81cc6a158 | ||
|
|
69b959e557 | ||
|
|
ad7f7a7117 | ||
|
|
81cc8cdba5 | ||
|
|
e634fd256b | ||
|
|
433863e4c9 | ||
|
|
634c3e4648 | ||
|
|
a9a7120c82 | ||
|
|
5dfb115eaf | ||
|
|
c6723c8206 | ||
|
|
3b4d9e7c07 | ||
|
|
53e0291df6 | ||
|
|
e9a17292e8 | ||
|
|
9b5cff87ec | ||
|
|
9684099ae9 | ||
|
|
38933afdd9 | ||
|
|
6a0f0f9e21 | ||
|
|
4dd8bd84a4 | ||
|
|
8f0266b885 | ||
|
|
234309878e | ||
|
|
1dcb97eaa3 | ||
|
|
29a0197ead | ||
|
|
ccc7a1bf46 | ||
|
|
b936bd7162 | ||
|
|
6e1aed4b23 | ||
|
|
2a711887b7 | ||
|
|
5a945dad0c | ||
|
|
b1d2dd316f | ||
|
|
f5b42c3421 | ||
|
|
a02bf125ac | ||
|
|
fcef6b2b52 | ||
|
|
d784e50747 | ||
|
|
f58542899a | ||
|
|
1a5b00ebe2 | ||
|
|
48726242ad | ||
|
|
67311cc1f2 | ||
|
|
b6b42d150d | ||
|
|
11db925f15 | ||
|
|
2b0e209029 | ||
|
|
5538f5cff8 | ||
|
|
5f17720fcd | ||
|
|
5d212055b7 | ||
|
|
6f9beedc48 | ||
|
|
131ab36e3a | ||
|
|
2ed116efec | ||
|
|
5f8c85bf9c | ||
|
|
3ca59512d2 | ||
|
|
111a02f214 | ||
|
|
0d19e48487 | ||
|
|
728448a7f1 | ||
|
|
0db18d030d | ||
|
|
0048a788dd | ||
|
|
611ef23700 | ||
|
|
a0192b859b | ||
|
|
ec3be11ec6 | ||
|
|
69fc57b028 | ||
|
|
32d681ab98 | ||
|
|
e60b9d1de6 | ||
|
|
3d431bb4eb | ||
|
|
5e8d8a1e75 | ||
|
|
f9de18ea15 | ||
|
|
97cb71971a | ||
|
|
dd562d84ba | ||
|
|
773ab8b2c5 | ||
|
|
69ace680dd | ||
|
|
1bdd08d07d | ||
|
|
519a639cf3 | ||
|
|
6323d2e617 | ||
|
|
601781f463 | ||
|
|
695d8eb277 | ||
|
|
5b500f5d8f | ||
|
|
2bf00d7729 | ||
|
|
12992d86dc | ||
|
|
d93bd21185 | ||
|
|
8250800d3b | ||
|
|
6d101a79a8 | ||
|
|
20e8770df0 | ||
|
|
866f9b979d | ||
|
|
3e98f942e5 | ||
|
|
7bd2251dcb | ||
|
|
0c017618cd | ||
|
|
8d198f3598 | ||
|
|
bca8d3b8f8 | ||
|
|
a9003acb1c | ||
|
|
dad89e50a2 | ||
|
|
b92100ad36 | ||
|
|
e9f12acbeb | ||
|
|
7d6860b114 | ||
|
|
056c267b89 | ||
|
|
2b7728cd9d | ||
|
|
65b4a7ba2b | ||
|
|
74269054a6 | ||
|
|
a62e3221b6 | ||
|
|
085569df55 | ||
|
|
21b020b336 | ||
|
|
e28a20a2d9 | ||
|
|
2da932c7a0 | ||
|
|
2ecbf87130 | ||
|
|
62d7502b82 | ||
|
|
2d5481da27 | ||
|
|
44bc9408b1 | ||
|
|
02337e1d1d | ||
|
|
437deb5f3a | ||
|
|
48e99fd05a | ||
|
|
3c161bb7df | ||
|
|
bbcf703be8 | ||
|
|
94da045be5 | ||
|
|
33f234f278 | ||
|
|
55d89d17b2 | ||
|
|
94a05abb98 | ||
|
|
45e597cc16 | ||
|
|
9a9ddc1203 | ||
|
|
13947b3408 | ||
|
|
1009a87f3c | ||
|
|
f1fb0fa3af | ||
|
|
caa648d92e | ||
|
|
88a31e2a99 | ||
|
|
307bfc81c1 | ||
|
|
5becc4613a | ||
|
|
b812839dfa | ||
|
|
ae525a8761 | ||
|
|
29ea40f538 | ||
|
|
e9abc5a4f3 | ||
|
|
17be7fa73b | ||
|
|
68e8b2b1d5 | ||
|
|
391ff14977 | ||
|
|
cf18dcd5fd | ||
|
|
6fceaca584 | ||
|
|
ddc0bf14d5 | ||
|
|
deb01a2652 | ||
|
|
3cfc9d5fa3 | ||
|
|
a7d0c5ef5a | ||
|
|
f39c739bd6 | ||
|
|
f66f5b3ddc | ||
|
|
c241afa87c | ||
|
|
178d618d5a | ||
|
|
c9ddb2ba22 | ||
|
|
73d3f46994 | ||
|
|
b2482a8574 | ||
|
|
812fdd92c7 | ||
|
|
ec6225e3e0 | ||
|
|
ef6eb5442c | ||
|
|
f0072a8de8 | ||
|
|
3cf28aa924 | ||
|
|
578340c7a7 | ||
|
|
3caf3b7c45 | ||
|
|
ee47913389 | ||
|
|
f5aaf523c5 | ||
|
|
8c8998e551 | ||
|
|
da0c44a9db | ||
|
|
798c1bba9d | ||
|
|
db0b93ac39 | ||
|
|
86c936cbb1 | ||
|
|
b9a917a138 | ||
|
|
6527dffc94 | ||
|
|
fb04746bce | ||
|
|
05597a7ddb | ||
|
|
82676c13ee | ||
|
|
c2ee307fd4 | ||
|
|
2e4a26a0e9 | ||
|
|
6508f21130 | ||
|
|
c5241c3aa4 | ||
|
|
c910a332b2 | ||
|
|
f62a64e440 | ||
|
|
a7f5e07712 | ||
|
|
5e2341411f | ||
|
|
917cf7018b | ||
|
|
84b9a44535 | ||
|
|
7ff22823ca | ||
|
|
9855e8bd48 | ||
|
|
219ece83a3 | ||
|
|
889890da43 | ||
|
|
23a5183767 | ||
|
|
ce0f20b597 | ||
|
|
7bd6e8b89b | ||
|
|
d692b6e054 | ||
|
|
89e36c0e64 | ||
|
|
801c182c02 | ||
|
|
7451ce29a7 | ||
|
|
450d32919a | ||
|
|
78b2080027 | ||
|
|
9de67ca962 | ||
|
|
b9880bc812 | ||
|
|
d10eaee4cc | ||
|
|
b104aed5ec | ||
|
|
cd463dd72a | ||
|
|
7d684d6866 | ||
|
|
e0959e7929 | ||
|
|
2ea68e2b7b | ||
|
|
2c8787224f | ||
|
|
74d63b7212 | ||
|
|
d0603d96e9 | ||
|
|
414faaca19 | ||
|
|
7a0d11dd68 | ||
|
|
cd0581d815 | ||
|
|
1de7085d31 | ||
|
|
acc71ffb4b | ||
|
|
c64fa4f888 | ||
|
|
79bc80102c | ||
|
|
5fa388c366 | ||
|
|
75f105bbb5 | ||
|
|
2340b88ede | ||
|
|
329085a8ff | ||
|
|
819b50e1a7 | ||
|
|
f449842053 | ||
|
|
9cfbf27d4c | ||
|
|
a450ef73ed | ||
|
|
04b5d65575 | ||
|
|
90e543bd83 | ||
|
|
75caaf2949 | ||
|
|
5027e122a8 | ||
|
|
a313bb0a47 | ||
|
|
923e324abc | ||
|
|
bac087c207 | ||
|
|
80f039973e | ||
|
|
3a381367a6 | ||
|
|
12472df8f0 | ||
|
|
7cc199ea95 | ||
|
|
793e713c4b | ||
|
|
faba84b9b7 | ||
|
|
7cf313c75b | ||
|
|
21b5e6318e | ||
|
|
4fe00da9f8 | ||
|
|
75be092b99 | ||
|
|
c9441b3c0b | ||
|
|
ace9a8742f | ||
|
|
54eceac257 | ||
|
|
d410eb9787 | ||
|
|
9ae5b50d78 | ||
|
|
52476fc1d4 | ||
|
|
e969f08892 | ||
|
|
7b1b832618 | ||
|
|
e0146997a6 | ||
|
|
a391d3691a | ||
|
|
5e90f2a809 | ||
|
|
1eaa3d72ea | ||
|
|
668f8df3be | ||
|
|
cc4a08bdc7 | ||
|
|
862807504b | ||
|
|
a7c276b72b | ||
|
|
f869a95f3b | ||
|
|
0ddd4b6c25 | ||
|
|
24839068f5 | ||
|
|
b631bd21d2 | ||
|
|
579651bf30 | ||
|
|
0d6946741c | ||
|
|
7e10bd6401 | ||
|
|
84e4dd92d4 | ||
|
|
55da9874c0 | ||
|
|
d8d5f5904f | ||
|
|
9acc82ce4a | ||
|
|
c017e309c4 | ||
|
|
2e59b20204 | ||
|
|
fd425b1484 | ||
|
|
50131c125e | ||
|
|
5a03e129a6 | ||
|
|
b7ebf545e6 | ||
|
|
8fc2630dd4 | ||
|
|
bd988f6ad3 | ||
|
|
1e245336ec | ||
|
|
4457c0d9ba | ||
|
|
660116fb9d | ||
|
|
b15d2c9d2f |
29
.gitignore
vendored
29
.gitignore
vendored
@@ -25,10 +25,21 @@ core.*
|
|||||||
contrib/sysmobts-calib/sysmobts-calib
|
contrib/sysmobts-calib/sysmobts-calib
|
||||||
|
|
||||||
src/osmo-bts-sysmo/l1fwd-proxy
|
src/osmo-bts-sysmo/l1fwd-proxy
|
||||||
src/osmo-bts-sysmo/sysmobts
|
src/osmo-bts-sysmo/osmo-bts-sysmo
|
||||||
src/osmo-bts-sysmo/sysmobts-remote
|
src/osmo-bts-sysmo/osmo-bts-sysmo-remote
|
||||||
src/osmo-bts-sysmo/sysmobts-mgr
|
src/osmo-bts-sysmo/sysmobts-mgr
|
||||||
|
src/osmo-bts-sysmo/sysmobts-util
|
||||||
|
|
||||||
|
src/osmo-bts-litecell15/lc15bts-mgr
|
||||||
|
src/osmo-bts-litecell15/lc15bts-util
|
||||||
|
src/osmo-bts-litecell15/misc/.dirstamp
|
||||||
|
src/osmo-bts-litecell15/osmo-bts-lc15
|
||||||
|
|
||||||
|
src/osmo-bts-trx/osmo-bts-trx
|
||||||
|
|
||||||
|
src/osmo-bts-octphy/osmo-bts-octphy
|
||||||
|
|
||||||
|
src/osmo-bts-virtual/osmo-bts-virtual
|
||||||
|
|
||||||
tests/atconfig
|
tests/atconfig
|
||||||
tests/package.m4
|
tests/package.m4
|
||||||
@@ -37,6 +48,8 @@ tests/paging/paging_test
|
|||||||
tests/cipher/cipher_test
|
tests/cipher/cipher_test
|
||||||
tests/sysmobts/sysmobts_test
|
tests/sysmobts/sysmobts_test
|
||||||
tests/misc/misc_test
|
tests/misc/misc_test
|
||||||
|
tests/handover/handover_test
|
||||||
|
tests/tx_power/tx_power_test
|
||||||
tests/testsuite
|
tests/testsuite
|
||||||
tests/testsuite.log
|
tests/testsuite.log
|
||||||
|
|
||||||
@@ -44,6 +57,18 @@ tests/testsuite.log
|
|||||||
doc/vty_reference.xml
|
doc/vty_reference.xml
|
||||||
|
|
||||||
# Backups, vi, merges
|
# Backups, vi, merges
|
||||||
|
*~
|
||||||
*.sw?
|
*.sw?
|
||||||
*.orig
|
*.orig
|
||||||
*.sav
|
*.sav
|
||||||
|
|
||||||
|
# debian
|
||||||
|
.tarball-version
|
||||||
|
debian/autoreconf.after
|
||||||
|
debian/autoreconf.before
|
||||||
|
debian/files
|
||||||
|
debian/*.debhelper.log
|
||||||
|
debian/*.substvars
|
||||||
|
debian/osmo-bts-trx-dbg/
|
||||||
|
debian/osmo-bts-trx/
|
||||||
|
debian/tmp/
|
||||||
|
|||||||
3
.gitreview
Normal file
3
.gitreview
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[gerrit]
|
||||||
|
host=gerrit.osmocom.org
|
||||||
|
project=osmo-bts
|
||||||
12
.mailmap
Normal file
12
.mailmap
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Harald Welte <laforge@gnumonks.org>
|
||||||
|
Harald Welte <laforge@gnumonks.org> <laflocal@hanuman.gnumonks.org>
|
||||||
|
Harald Welte <laforge@gnumonks.org> <laflocal@goeller.de.gnumonks.org>
|
||||||
|
Holger Hans Peter Freyther <holger@moiji-mobile.com> <zecke@selfish.org>
|
||||||
|
Holger Hans Peter Freyther <holger@moiji-mobile.com> <ich@tamarin.(none)>
|
||||||
|
Holger Hans Peter Freyther <holgre@moiji-mobile.com> <holger@freyther.de>
|
||||||
|
Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
Andreas Eversberg <jolly@eversberg.eu> <Andreas.Eversberg@versatel.de>
|
||||||
|
Andreas Eversberg <jolly@eversberg.eu> <root@nuedel.(none)>
|
||||||
|
Pablo Neira Ayuso <pablo@soleta.eu> <pablo@gnumonks.org>
|
||||||
|
Max Suraev <msuraev@sysmocom.de>
|
||||||
|
Tom Tsou <tom.tsou@ettus.com> <tom@tsou.cc>
|
||||||
19
Makefile.am
19
Makefile.am
@@ -5,11 +5,24 @@ SUBDIRS = include src tests
|
|||||||
|
|
||||||
# package the contrib and doc
|
# package the contrib and doc
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
contrib/dump_docs.py contrib/screenrc-l1fwd contrib/sysmobts.service \
|
contrib/dump_docs.py contrib/screenrc-l1fwd contrib/osmo-bts-sysmo.service \
|
||||||
contrib/l1fwd.init contrib/screenrc-sysmobts contrib/respawn.sh \
|
contrib/l1fwd.init contrib/screenrc-sysmobts contrib/respawn.sh \
|
||||||
contrib/sysmobts.init contrib/sysmobts-calib/Makefile \
|
contrib/sysmobts.init contrib/sysmobts-calib/Makefile \
|
||||||
contrib/sysmobts-calib/sysmobts-calib.c \
|
contrib/sysmobts-calib/sysmobts-calib.c \
|
||||||
contrib/sysmobts-calib/sysmobts-layer1.c \
|
contrib/sysmobts-calib/sysmobts-layer1.c \
|
||||||
contrib/sysmobts-calib/sysmobts-layer1.h \
|
contrib/sysmobts-calib/sysmobts-layer1.h \
|
||||||
doc/examples/osmo-bts.cfg \
|
doc/examples/sysmo/osmo-bts.cfg \
|
||||||
doc/examples/sysmobts-mgr.cfg
|
doc/examples/sysmo/sysmobts-mgr.cfg \
|
||||||
|
doc/examples/virtual/openbsc-virtual.cfg \
|
||||||
|
doc/examples/virtual/osmobts-virtual.cfg \
|
||||||
|
git-version-gen .version \
|
||||||
|
README.md
|
||||||
|
|
||||||
|
@RELMAKE@
|
||||||
|
|
||||||
|
BUILT_SOURCES = $(top_srcdir)/.version
|
||||||
|
|
||||||
|
$(top_srcdir)/.version:
|
||||||
|
echo $(VERSION) > $@-t && mv $@-t $@
|
||||||
|
dist-hook:
|
||||||
|
echo $(VERSION) > $(distdir)/.tarball-version
|
||||||
|
|||||||
59
README
59
README
@@ -1,59 +0,0 @@
|
|||||||
Repository for new the Osmocom BTS implementation.
|
|
||||||
|
|
||||||
This code implementes the Layer 2 and higher of a more or less
|
|
||||||
conventional GSM BTS (Base Transceiver Station) - however, using an
|
|
||||||
Abis/IP interface, rather than the old-fashioned E1/T1.
|
|
||||||
|
|
||||||
Specificallt, this includes
|
|
||||||
* BTS-Side implementation of TS 08.58 (RSL) and TS 12.21 (OML)
|
|
||||||
* BTS-Side implementation of LAPDm (using libosmocore/libosmogsm)
|
|
||||||
* A somewhat separated interface between those higher layer parts
|
|
||||||
and the Layer1 interface.
|
|
||||||
|
|
||||||
Right now, only one hardware and Layer1 are supported: The sysmocom
|
|
||||||
sysmoBTS.
|
|
||||||
|
|
||||||
There is some experimental and way incomplete code to use a couple of
|
|
||||||
OsmocomBB phones and run them in the BTS. However, the required code
|
|
||||||
for the Calypso DSP code have not been written yet. This would still
|
|
||||||
require a lot of work.
|
|
||||||
|
|
||||||
Some additional work is being done in using some parts of the OpenBTS
|
|
||||||
L1FEC and glue it against omso-bts. However, this is also still in an
|
|
||||||
early, experimental stage.
|
|
||||||
|
|
||||||
== Known Limitations ==
|
|
||||||
|
|
||||||
As of June 3, 2012, the following known limitations exist in this
|
|
||||||
implementation:
|
|
||||||
|
|
||||||
=== Common Core ===
|
|
||||||
* No Extended BCCH support
|
|
||||||
* System Information limited to 1,2,2bis,2ter,2quater,3,4,5,6,9,13
|
|
||||||
* No RATSCCH in AMR
|
|
||||||
* No OML (TS 12.21) alarms yet (temperature, ...)
|
|
||||||
* Only single-TRX BTS at this point
|
|
||||||
* Will reject TS 12.21 STARTING TIME in SET BTS ATTR / SET CHAN ATTR
|
|
||||||
* No support for frequency hopping
|
|
||||||
* No reporting of interference levels as part of TS 08.58 RF RES IND
|
|
||||||
* No error reporting in case PAGING COMMAND fails due to queue overflow
|
|
||||||
* No hand-over support (planned)
|
|
||||||
* No use of TS 08.58 BS Power and MS Power parameters
|
|
||||||
* No support of TS 08.58 MultiRate Control
|
|
||||||
* No support of TS 08.58 Supported Codec Types
|
|
||||||
* No support of Bter frame / ENHANCED MEASUREMENT REPORT
|
|
||||||
|
|
||||||
=== osmo-bts-sysmo ===
|
|
||||||
* No CSD / ECSD support (not planned)
|
|
||||||
* No GPRS/EDGE support (planned)
|
|
||||||
* GSM-R frequency band supported, but no NCH/ASCI/SoLSA
|
|
||||||
* All timeslots on one TRX have to use same training sequence (TSC)
|
|
||||||
* No multi-TRX support yet, though hardware+L1 support stacking
|
|
||||||
* Makes no use of 12.21 Intave Parameters and Interference
|
|
||||||
Level Boundaries
|
|
||||||
* Makes no use of TS 12.21 T3105
|
|
||||||
* Doesn't yet include MAC address in Abis/IP Identity message
|
|
||||||
* MphConfig.CNF can be returned to the wrong callback. E.g. with Tx Power
|
|
||||||
and ciphering. The dispatch should take a look at the hLayer3.
|
|
||||||
|
|
||||||
|
|
||||||
127
README.md
Normal file
127
README.md
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
osmo-bts - Osmocom BTS Implementation
|
||||||
|
====================================
|
||||||
|
|
||||||
|
This repository contains a C-language implementation of a GSM Base
|
||||||
|
Transceiver Station (BTS). It is part of the
|
||||||
|
[Osmocom](https://osmocom.org/) Open Source Mobile Communications
|
||||||
|
project.
|
||||||
|
|
||||||
|
This code implements Layer 2 and higher of a more or less conventional GSM BTS
|
||||||
|
(Base Transceiver Station) - however, using an Abis/IP interface, rather than
|
||||||
|
the old-fashioned E1/T1.
|
||||||
|
|
||||||
|
Specifically, this includes
|
||||||
|
* BTS-side implementation of TS 08.58 (RSL) and TS 12.21 (OML)
|
||||||
|
* BTS-side implementation of LAPDm (using libosmocore/libosmogsm)
|
||||||
|
* A somewhat separated interface between those higher layer parts and the
|
||||||
|
Layer1 interface.
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
Homepage
|
||||||
|
--------
|
||||||
|
|
||||||
|
The official homepage of the project is
|
||||||
|
https://osmocom.org/projects/osmobts/wiki
|
||||||
|
|
||||||
|
GIT Repository
|
||||||
|
--------------
|
||||||
|
|
||||||
|
You can clone from the official osmo-bts.git repository using
|
||||||
|
|
||||||
|
git clone git://git.osmocom.org/osmo-bts.git
|
||||||
|
|
||||||
|
There is a cgit interface at http://git.osmocom.org/osmo-bts/
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
We provide a
|
||||||
|
[User Manual](http://ftp.osmocom.org/docs/latest/osmobts-usermanual.pdf)
|
||||||
|
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)
|
||||||
|
describing the OsmoBTS specific A-bis dialect.
|
||||||
|
|
||||||
|
Mailing List
|
||||||
|
------------
|
||||||
|
|
||||||
|
Discussions related to osmo-bts are happening on the
|
||||||
|
openbsc@lists.osmocom.org mailing list, please see
|
||||||
|
https://lists.osmocom.org/mailman/listinfo/openbsc for subscription
|
||||||
|
options and the list archive.
|
||||||
|
|
||||||
|
Please observe the [Osmocom Mailing List
|
||||||
|
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
|
||||||
|
when posting.
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
------------
|
||||||
|
|
||||||
|
Our coding standards are described at
|
||||||
|
https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards
|
||||||
|
|
||||||
|
We us a gerrit based patch submission/review process for managing
|
||||||
|
contributions. Please see
|
||||||
|
https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit for
|
||||||
|
more details
|
||||||
|
|
||||||
|
The current patch queue for osmo-bts can be seen at
|
||||||
|
https://gerrit.osmocom.org/#/q/project:osmo-bts+status:open
|
||||||
|
|
||||||
|
Known Limitations
|
||||||
|
=================
|
||||||
|
|
||||||
|
As of March 17, 2017, the following known limitations exist in this
|
||||||
|
implementation:
|
||||||
|
|
||||||
|
Common Core
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* No Extended BCCH support
|
||||||
|
* System Information limited to 1,2,2bis,2ter,2quater,3,4,5,6,9,13
|
||||||
|
* No RATSCCH in AMR
|
||||||
|
* Will reject TS 12.21 STARTING TIME in SET BTS ATTR / SET CHAN ATTR
|
||||||
|
* No support for frequency hopping
|
||||||
|
* No reporting of interference levels as part of TS 08.58 RF RES IND
|
||||||
|
* No error reporting in case PAGING COMMAND fails due to queue overflow
|
||||||
|
* No use of TS 08.58 BS Power and MS Power parameters
|
||||||
|
* No support of TS 08.58 MultiRate Control
|
||||||
|
* No support of TS 08.58 Supported Codec Types
|
||||||
|
* No support of Bter frame / ENHANCED MEASUREMENT REPORT
|
||||||
|
|
||||||
|
osmo-bts-sysmo
|
||||||
|
--------------
|
||||||
|
|
||||||
|
* No CSD / ECSD support (not planned)
|
||||||
|
* GSM-R frequency band supported, but no NCH/ASCI/SoLSA
|
||||||
|
* All timeslots on one TRX have to use same training sequence (TSC)
|
||||||
|
* No multi-TRX support yet, though hardware+L1 support stacking
|
||||||
|
* Makes no use of 12.21 Intave Parameters and Interference
|
||||||
|
Level Boundaries
|
||||||
|
* MphConfig.CNF can be returned to the wrong callback. E.g. with Tx Power
|
||||||
|
and ciphering. The dispatch should take a look at the hLayer3.
|
||||||
|
|
||||||
|
osmo-bts-octphy
|
||||||
|
---------------
|
||||||
|
|
||||||
|
* No support of EFR, HR voice codec (lack of PHY support?)
|
||||||
|
* No re-transmission of PHY primitives in case of time-out
|
||||||
|
* Link Quality / Measurement processing incomplete
|
||||||
|
* impossible to modify encryption parameters using RSL MODE MODIFY
|
||||||
|
* 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)
|
||||||
|
* No CBCH support (https://osmocom.org/issues/1617)
|
||||||
124
configure.ac
124
configure.ac
@@ -3,18 +3,32 @@ AC_INIT([osmo-bts],
|
|||||||
m4_esyscmd([./git-version-gen .tarball-version]),
|
m4_esyscmd([./git-version-gen .tarball-version]),
|
||||||
[openbsc-devel@lists.openbsc.org])
|
[openbsc-devel@lists.openbsc.org])
|
||||||
|
|
||||||
|
dnl *This* is the root dir, even if an install-sh exists in ../ or ../../
|
||||||
|
AC_CONFIG_AUX_DIR([.])
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([dist-bzip2])
|
AM_INIT_AUTOMAKE([dist-bzip2])
|
||||||
AC_CONFIG_TESTDIR(tests)
|
AC_CONFIG_TESTDIR(tests)
|
||||||
|
|
||||||
dnl kernel style compile messages
|
dnl kernel style compile messages
|
||||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
|
dnl include release helper
|
||||||
|
RELMAKE='-include osmo-release.mk'
|
||||||
|
AC_SUBST([RELMAKE])
|
||||||
|
|
||||||
dnl checks for programs
|
dnl checks for programs
|
||||||
AC_PROG_MAKE_SET
|
AC_PROG_MAKE_SET
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
AC_PROG_RANLIB
|
AC_PROG_RANLIB
|
||||||
|
|
||||||
|
dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
|
||||||
|
AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
|
||||||
|
if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
|
||||||
|
AC_MSG_WARN([You need to install pkg-config])
|
||||||
|
fi
|
||||||
|
PKG_PROG_PKG_CONFIG([0.20])
|
||||||
|
|
||||||
dnl checks for header files
|
dnl checks for header files
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
|
|
||||||
@@ -23,18 +37,115 @@ dnl Checks for typedefs, structures and compiler characteristics
|
|||||||
dnl checks for libraries
|
dnl checks for libraries
|
||||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.3.9)
|
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.3.9)
|
||||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty)
|
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty)
|
||||||
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.0.7)
|
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.3.2)
|
||||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.3.3)
|
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.3.3)
|
||||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl)
|
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl)
|
||||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis)
|
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding)
|
||||||
|
PKG_CHECK_MODULES(ORTP, ortp)
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether to enable sysmocom-bts hardware support])
|
AC_MSG_CHECKING([whether to enable support for sysmoBTS L1/PHY support])
|
||||||
AC_ARG_ENABLE(sysmocom-bts,
|
AC_ARG_ENABLE(sysmocom-bts,
|
||||||
AC_HELP_STRING([--enable-sysmocom-bts],
|
AC_HELP_STRING([--enable-sysmocom-bts],
|
||||||
[enable code for sysmocom femto-bts [default=no]]),
|
[enable code for sysmoBTS L1/PHY [default=no]]),
|
||||||
[enable_sysmocom_bts="yes"],[enable_sysmocom_bts="no"])
|
[enable_sysmocom_bts="yes"],[enable_sysmocom_bts="no"])
|
||||||
AC_MSG_RESULT([$enable_sysmocom_bts])
|
AC_MSG_RESULT([$enable_sysmocom_bts])
|
||||||
AM_CONDITIONAL(ENABLE_SYSMOBTS, test "x$enable_sysmocom_bts" = "xyes")
|
AM_CONDITIONAL(ENABLE_SYSMOBTS, test "x$enable_sysmocom_bts" = "xyes")
|
||||||
|
if test "$enable_sysmocom_bts" = "yes"; then
|
||||||
|
PKG_CHECK_MODULES(LIBGPS, libgps)
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to enable support for osmo-trx based L1/PHY support])
|
||||||
|
AC_ARG_ENABLE(trx,
|
||||||
|
AC_HELP_STRING([--enable-trx],
|
||||||
|
[enable code for osmo-trx L1/PHY [default=no]]),
|
||||||
|
[enable_trx="yes"],[enable_trx="no"])
|
||||||
|
AC_MSG_RESULT([$enable_trx])
|
||||||
|
AM_CONDITIONAL(ENABLE_TRX, test "x$enable_trx" = "xyes")
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to enable support for Octasic OCTPHY-2G])
|
||||||
|
AC_ARG_ENABLE(octphy,
|
||||||
|
AC_HELP_STRING([--enable-octphy],
|
||||||
|
[enable code for Octasic OCTPHY-2G [default=no]]),
|
||||||
|
[enable_octphy="yes"],[enable_octphy="no"])
|
||||||
|
AC_ARG_WITH([octsdr-2g], [AS_HELP_STRING([--with-octsdr-2g], [Location of the OCTSDR-2G API header files])],
|
||||||
|
[octsdr2g_incdir="$withval"],[octsdr2g_incdir="`cd $srcdir; pwd`/src/osmo-bts-octphy/"])
|
||||||
|
AC_SUBST([OCTSDR2G_INCDIR], $octsdr2g_incdir)
|
||||||
|
AC_MSG_RESULT([$enable_octphy])
|
||||||
|
AM_CONDITIONAL(ENABLE_OCTPHY, test "x$enable_octphy" = "xyes")
|
||||||
|
if test "$enable_octphy" = "yes" ; then
|
||||||
|
oldCPPFLAGS=$CPPFLAGS
|
||||||
|
CPPFLAGS="$CPPFLAGS -I$OCTSDR2G_INCDIR -I$srcdir/include $LIBOSMOCORE_CFLAGS"
|
||||||
|
|
||||||
|
AC_CHECK_HEADER([octphy/octvc1/gsm/octvc1_gsm_default.h],[],
|
||||||
|
[AC_MSG_ERROR([octphy/octvc1/gsm/octvc1_gsm_default.h can not be found in $octsdr2g_incdir])],
|
||||||
|
[#include <octphy/octvc1/gsm/octvc1_gsm_default.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_GSM_TRX_CONFIG.usCentreArfcn],
|
||||||
|
AC_DEFINE([OCTPHY_MULTI_TRX],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files support multi-trx]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/gsm/octvc1_gsm_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_RF_PORT_RX_STATS.Frequency],
|
||||||
|
AC_DEFINE([OCTPHY_USE_FREQUENCY],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files support tOCTVC1_RADIO_FREQUENCY_VALUE type]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulSyncLossCnt],
|
||||||
|
AC_DEFINE([OCTPHY_USE_SYNC_LOSS_CNT],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files renamed ulSyncLosseCnt to ulSyncLossCnt]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_RSP.TxConfig],
|
||||||
|
AC_DEFINE([OCTPHY_USE_TX_CONFIG],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files support tOCTVC1_HW_RF_PORT_ANTENNA_TX_CONFIG type]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_RSP.RxConfig],
|
||||||
|
AC_DEFINE([OCTPHY_USE_RX_CONFIG],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files support tOCTVC1_HW_RF_PORT_ANTENNA_RX_CONFIG type]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_GSM_RF_CONFIG.ulTxAntennaId],
|
||||||
|
AC_DEFINE([OCTPHY_USE_ANTENNA_ID],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files support antenna ids in tOCTVC1_GSM_RF_CONFIG]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/gsm/octvc1_gsm_api.h>])
|
||||||
|
|
||||||
|
CPPFLAGS=$oldCPPFLAGS
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to enable NuRAN Wireless Litecell 1.5 hardware support])
|
||||||
|
AC_ARG_ENABLE(litecell15,
|
||||||
|
AC_HELP_STRING([--enable-litecell15],
|
||||||
|
[enable code for NuRAN Wireless Litecell15 bts [default=no]]),
|
||||||
|
[enable_litecell15="yes"],[enable_litecell15="no"])
|
||||||
|
AC_ARG_WITH([litecell15], [AS_HELP_STRING([--with-litecell15=INCLUDE_DIR], [Location of the litecell 1.5 API header files])],
|
||||||
|
[litecell15_incdir="$withval"],[litecell15_incdir="$incdir"])
|
||||||
|
AC_SUBST([LITECELL15_INCDIR], $litecell15_incdir)
|
||||||
|
AC_MSG_RESULT([$enable_litecell15])
|
||||||
|
AM_CONDITIONAL(ENABLE_LC15BTS, test "x$enable_litecell15" = "xyes")
|
||||||
|
if test "$enable_litecell15" = "yes"; then
|
||||||
|
oldCPPFLAGS=$CPPFLAGS
|
||||||
|
CPPFLAGS="$CPPFLAGS -I$LITECELL15_INCDIR -I$srcdir/include $LIBOSMOCORE_CFLAGS"
|
||||||
|
AC_CHECK_HEADER([nrw/litecell15/litecell15.h],[],
|
||||||
|
[AC_MSG_ERROR([nrw/litecell15/litecell15.h can not be found in $litecell15_incdir])],
|
||||||
|
[#include <nrw/litecell15/litecell15.h>])
|
||||||
|
PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd)
|
||||||
|
CPPFLAGS=$oldCPPFLAGS
|
||||||
|
fi
|
||||||
|
|
||||||
# We share gsm_data.h with OpenBSC and need to be pointed to the source
|
# We share gsm_data.h with OpenBSC and need to be pointed to the source
|
||||||
# directory of OpenBSC for now.
|
# directory of OpenBSC for now.
|
||||||
@@ -68,7 +179,11 @@ AM_CONFIG_HEADER(btsconfig.h)
|
|||||||
AC_OUTPUT(
|
AC_OUTPUT(
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/common/Makefile
|
src/common/Makefile
|
||||||
|
src/osmo-bts-virtual/Makefile
|
||||||
src/osmo-bts-sysmo/Makefile
|
src/osmo-bts-sysmo/Makefile
|
||||||
|
src/osmo-bts-litecell15/Makefile
|
||||||
|
src/osmo-bts-trx/Makefile
|
||||||
|
src/osmo-bts-octphy/Makefile
|
||||||
include/Makefile
|
include/Makefile
|
||||||
include/osmo-bts/Makefile
|
include/osmo-bts/Makefile
|
||||||
tests/Makefile
|
tests/Makefile
|
||||||
@@ -77,4 +192,7 @@ AC_OUTPUT(
|
|||||||
tests/cipher/Makefile
|
tests/cipher/Makefile
|
||||||
tests/sysmobts/Makefile
|
tests/sysmobts/Makefile
|
||||||
tests/misc/Makefile
|
tests/misc/Makefile
|
||||||
|
tests/handover/Makefile
|
||||||
|
tests/tx_power/Makefile
|
||||||
|
tests/meas/Makefile
|
||||||
Makefile)
|
Makefile)
|
||||||
|
|||||||
89
contrib/dtx_check.gawk
Executable file
89
contrib/dtx_check.gawk
Executable file
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/gawk -f
|
||||||
|
|
||||||
|
# Expected input format: FN TYPE
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
DELTA = 0
|
||||||
|
ERR = 0
|
||||||
|
FORCE = 0
|
||||||
|
FN = 0
|
||||||
|
SILENCE = 0
|
||||||
|
TYPE = ""
|
||||||
|
CHK = ""
|
||||||
|
U_MAX = 8 * 20 + 120 / 26
|
||||||
|
U_MIN = 8 * 20 - 120 / 26
|
||||||
|
F_MAX = 3 * 20 + 120 / 26
|
||||||
|
F_MIN = 3 * 20 - 120 / 26
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
if (NR > 2) { # we have data from previous record to compare to
|
||||||
|
DELTA = ($1 - FN) * 120 / 26
|
||||||
|
CHK = "OK"
|
||||||
|
if ("FACCH" == $2 && "ONSET" == TYPE) { # ONSET due to FACCH is NOT a talkspurt
|
||||||
|
SILENCE = 1
|
||||||
|
}
|
||||||
|
if (("UPDATE" == TYPE || "FIRST" == TYPE) && ("FACCH" == $2 || "SPEECH" == $2)) { # check for missing ONSET:
|
||||||
|
CHK = "FAIL: missing ONSET (" $2 ") after " TYPE "."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("SID_P1" == $2) {
|
||||||
|
CHK = "FAIL: regular AMR payload with FT SID and STI=0 (should be either pyaload Update or STI=1)."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("FORCED_FIRST" == $2 || "FORCED_NODATA" == $2 || "FORCED_F_P2" == $2 || "FORCED_F_INH" == $2 || "FORCED_U_INH" == $2) {
|
||||||
|
CHK = "FAIL: event " $2 " inserted by DSP."
|
||||||
|
FORCE++
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("FIRST_P2" != $2 && "FIRST_P1" == TYPE) {
|
||||||
|
CHK = "FAIL: " TYPE " followed by " $2 " instead of P2."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("FIRST" == $2 && "FIRST" == TYPE) {
|
||||||
|
CHK = "FAIL: multiple SID FIRST in a row."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("OK" == CHK && "ONSET" != $2) { # check inter-SID distances:
|
||||||
|
if ("UPDATE" == TYPE) {
|
||||||
|
if (DELTA > U_MAX) {
|
||||||
|
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID UPDATE (@" FN ") too big " DELTA "ms > " U_MAX "ms."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("UPDATE" == $2 && DELTA < U_MIN) {
|
||||||
|
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID UPDATE (@" FN ") too small " DELTA "ms < " U_MIN "ms."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("FIRST" == TYPE) {
|
||||||
|
if (DELTA > F_MAX) {
|
||||||
|
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID FIRST (@" FN ") too big " DELTA "ms > " F_MAX "ms."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("UPDATE" == $2 && DELTA < F_MIN) {
|
||||||
|
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID UPDATE (@" FN ") too small " DELTA "ms < " F_MIN "ms."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("FACCH" == TYPE && "FIRST" != $2 && "FACCH" != $2 && 1 == SILENCE) { # check FACCH handling
|
||||||
|
CHK = "FAIL: incorrect silence resume with " $2 " after FACCH."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("SPEECH" == $2 || "ONSET" == $2) { # talkspurt
|
||||||
|
SILENCE = 0
|
||||||
|
}
|
||||||
|
if ("UPDATE" == $2 || "FIRST" == $2) { # silence
|
||||||
|
SILENCE = 1
|
||||||
|
}
|
||||||
|
print $1, $2, CHK
|
||||||
|
if ($2 != "EMPTY") { # skip over EMPTY records
|
||||||
|
TYPE = $2
|
||||||
|
FN = $1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
print "Check completed: found " ERR " errors (" FORCE " events inserted by DSP) in " NR " records."
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ env = os.environ
|
|||||||
env['L1FWD_BTS_HOST'] = '127.0.0.1'
|
env['L1FWD_BTS_HOST'] = '127.0.0.1'
|
||||||
|
|
||||||
bts_proc = subprocess.Popen(["./src/osmo-bts-sysmo/sysmobts-remote",
|
bts_proc = subprocess.Popen(["./src/osmo-bts-sysmo/sysmobts-remote",
|
||||||
"-c", "./doc/examples/osmo-bts.cfg"], env = env,
|
"-c", "./doc/examples/sysmo/osmo-bts.cfg"], env = env,
|
||||||
stdin=None, stdout=None)
|
stdin=None, stdout=None)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|||||||
91
contrib/eeprom_reader.c
Normal file
91
contrib/eeprom_reader.c
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/* GPLv3+ to read sysmobts-v2 revD or later EEPROM from userspace */
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Can read a 16bit at24 eeprom with 8192 byte in storage (24c64) */
|
||||||
|
static int dump_eeprom(int fd, int out)
|
||||||
|
{
|
||||||
|
#define STEP 8192
|
||||||
|
#define SIZE 8192
|
||||||
|
uint8_t buf[STEP + 2];
|
||||||
|
int rc = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < SIZE; i += STEP) {
|
||||||
|
/* write the address */
|
||||||
|
buf[0] = i >> 8;
|
||||||
|
buf[1] = i;
|
||||||
|
rc = write(fd, buf, 2);
|
||||||
|
if (rc != 2) {
|
||||||
|
fprintf(stderr, "writing address failed: %d/%d/%s\n", rc, errno, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* execute step amount of reads */
|
||||||
|
rc = read(fd, buf, STEP);
|
||||||
|
if (rc != STEP) {
|
||||||
|
fprintf(stderr, "Failed to read: %d/%d/%s\n", rc, errno, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(out, buf, STEP);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i2c_fd, out_fd;
|
||||||
|
char *filename = "/dev/i2c-1";
|
||||||
|
char *out_file = "eeprom.out";
|
||||||
|
int addr = 0x50;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
i2c_fd = open(filename, O_RDWR);
|
||||||
|
if (i2c_fd < 0) {
|
||||||
|
fprintf(stderr, "Failed to open i2c device %d/%d/%s\n",
|
||||||
|
i2c_fd, errno, strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* force using that address it is already bound with a driver */
|
||||||
|
rc = ioctl(i2c_fd, I2C_SLAVE_FORCE, addr);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "Failed to claim i2c device %d/%d/%s\n",
|
||||||
|
rc, errno, strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc >= 2)
|
||||||
|
out_file = argv[1];
|
||||||
|
out_fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
|
if (out_fd < 0) {
|
||||||
|
fprintf(stderr, "Failed to open out device %s %d/%d/%s\n",
|
||||||
|
out_file, rc, errno, strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dump_eeprom(i2c_fd, out_fd) != 0) {
|
||||||
|
unlink(out_file);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
45
contrib/jenkins_bts_model.sh
Executable file
45
contrib/jenkins_bts_model.sh
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# this is a dispatcher script which will call the bts-model-specific
|
||||||
|
# script based on the bts model specified as command line argument
|
||||||
|
|
||||||
|
bts_model="$1"
|
||||||
|
|
||||||
|
if [ "x$bts_model" == "x" ]; then
|
||||||
|
echo "Error: You have to specify the BTS model as first argument, e.g. $0 sysmo"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "./contrib" ]; then
|
||||||
|
echo "Run ./contrib/jenkins_bts_model.sh from the root of the osmo-bts tree"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -x -e
|
||||||
|
|
||||||
|
case "$bts_model" in
|
||||||
|
|
||||||
|
sysmo)
|
||||||
|
./contrib/jenkins_sysmobts.sh
|
||||||
|
;;
|
||||||
|
|
||||||
|
oct)
|
||||||
|
./contrib/jenkins_oct.sh
|
||||||
|
;;
|
||||||
|
|
||||||
|
lc15)
|
||||||
|
./contrib/jenkins_lc15.sh
|
||||||
|
;;
|
||||||
|
|
||||||
|
trx)
|
||||||
|
./contrib/jenkins_bts_trx.sh
|
||||||
|
;;
|
||||||
|
|
||||||
|
oct+trx)
|
||||||
|
./contrib/jenkins_oct_and_bts_trx.sh
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
set +x
|
||||||
|
echo "Unknown BTS model '$bts_model'"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
24
contrib/jenkins_bts_trx.sh
Executable file
24
contrib/jenkins_bts_trx.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# jenkins build helper script for osmo-bts-trx
|
||||||
|
|
||||||
|
# shellcheck source=contrib/jenkins_common.sh
|
||||||
|
. $(dirname "$0")/jenkins_common.sh
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmo-abis
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
|
||||||
|
# Get osmo-pcu for pcuif_proto.h
|
||||||
|
osmo-deps.sh osmo-pcu
|
||||||
|
|
||||||
|
configure_flags="\
|
||||||
|
--with-osmo-pcu=$deps/osmo-pcu/include \
|
||||||
|
--enable-trx \
|
||||||
|
"
|
||||||
|
|
||||||
|
build_bts "osmo-bts-trx" "$configure_flags"
|
||||||
54
contrib/jenkins_common.sh
Normal file
54
contrib/jenkins_common.sh
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# this is a common helper script that is shared among all BTS model
|
||||||
|
# specific helper scripts like jenkins_sysmobts.sh. You shouldn't call
|
||||||
|
# this directly, but rather indirectly via the bts-specific scripts
|
||||||
|
|
||||||
|
if ! [ -x "$(command -v osmo-deps.sh)" ]; then
|
||||||
|
echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
base="$PWD"
|
||||||
|
deps="$base/deps"
|
||||||
|
inst="$deps/install"
|
||||||
|
|
||||||
|
export deps inst
|
||||||
|
|
||||||
|
mkdir -p "$deps"
|
||||||
|
rm -rf "$inst"
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
|
||||||
|
# Get libosmocore for verify_value_string_arrays_are_terminated.py
|
||||||
|
osmo-deps.sh libosmocore
|
||||||
|
|
||||||
|
cd "$base"
|
||||||
|
|
||||||
|
"$deps"/libosmocore/contrib/verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
|
||||||
|
|
||||||
|
# generic project build function, usage:
|
||||||
|
# build "PROJECT-NAME" "CONFIGURE OPTIONS"
|
||||||
|
build_bts() {
|
||||||
|
set +x
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo " =============================== $1 ==============================="
|
||||||
|
echo
|
||||||
|
set -x
|
||||||
|
|
||||||
|
cd $deps
|
||||||
|
osmo-deps.sh openbsc
|
||||||
|
conf_flags="--with-openbsc=$deps/openbsc/openbsc/include"
|
||||||
|
cd $base
|
||||||
|
shift
|
||||||
|
conf_flags="$conf_flags $*"
|
||||||
|
autoreconf --install --force
|
||||||
|
./configure $conf_flags
|
||||||
|
$MAKE $PARALLEL_MAKE
|
||||||
|
$MAKE check || cat-testlogs.sh
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS=$conf_flags $MAKE distcheck || cat-testlogs.sh
|
||||||
|
}
|
||||||
19
contrib/jenkins_lc15.sh
Executable file
19
contrib/jenkins_lc15.sh
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# jenkins build helper script for osmo-bts-lc15
|
||||||
|
|
||||||
|
# shellcheck source=contrib/jenkins_common.sh
|
||||||
|
. $(dirname "$0")/jenkins_common.sh
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmo-abis
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
osmo-layer1-headers.sh lc15 "$FIRMWARE_VERSION"
|
||||||
|
|
||||||
|
configure_flags="--with-litecell15=$deps/layer1-headers/inc/ --enable-litecell15"
|
||||||
|
|
||||||
|
build_bts "osmo-bts-lc15" "$configure_flags"
|
||||||
19
contrib/jenkins_oct.sh
Executable file
19
contrib/jenkins_oct.sh
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# jenkins build helper script for osmo-bts-octphy
|
||||||
|
|
||||||
|
# shellcheck source=contrib/jenkins_common.sh
|
||||||
|
. $(dirname "$0")/jenkins_common.sh
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmo-abis
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
osmo-layer1-headers.sh oct "$FIRMWARE_VERSION"
|
||||||
|
|
||||||
|
configure_flags="--with-octsdr-2g=$deps/layer1-headers/ --enable-octphy"
|
||||||
|
|
||||||
|
build_bts "osmo-bts-octphy" "$configure_flags"
|
||||||
28
contrib/jenkins_oct_and_bts_trx.sh
Executable file
28
contrib/jenkins_oct_and_bts_trx.sh
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# jenkins build helper script for osmo-bts-octphy + osmo-bts-trx
|
||||||
|
|
||||||
|
# shellcheck source=contrib/jenkins_common.sh
|
||||||
|
. $(dirname "$0")/jenkins_common.sh
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmo-abis
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
|
||||||
|
# Get osmo-pcu for pcuif_proto.h
|
||||||
|
osmo-deps.sh osmo-pcu
|
||||||
|
|
||||||
|
osmo-layer1-headers.sh oct "$FIRMWARE_VERSION"
|
||||||
|
|
||||||
|
configure_flags="\
|
||||||
|
--with-osmo-pcu=$deps/osmo-pcu/include \
|
||||||
|
--with-octsdr-2g=$deps/layer1-headers/ \
|
||||||
|
--enable-octphy \
|
||||||
|
--enable-trx \
|
||||||
|
"
|
||||||
|
|
||||||
|
build_bts "osmo-bts-octphy+trx" "$configure_flags"
|
||||||
26
contrib/jenkins_sysmobts.sh
Executable file
26
contrib/jenkins_sysmobts.sh
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# jenkins build helper script for osmo-bts-sysmo
|
||||||
|
|
||||||
|
# shellcheck source=contrib/jenkins_common.sh
|
||||||
|
. $(dirname "$0")/jenkins_common.sh
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmo-abis
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
osmo-layer1-headers.sh sysmo "$FIRMWARE_VERSION"
|
||||||
|
mkdir -p "$inst/include/sysmocom/femtobts"
|
||||||
|
ln -s $deps/layer1-headers/include/* "$inst/include/sysmocom/femtobts/"
|
||||||
|
|
||||||
|
configure_flags="--enable-sysmocom-bts"
|
||||||
|
|
||||||
|
build_bts "osmo-bts-sysmo" "$configure_flags"
|
||||||
|
|
||||||
|
# This will not work for the femtobts
|
||||||
|
if [ $FIRMWARE_VERSION != "femtobts_v2.7" ]; then
|
||||||
|
$MAKE -C contrib/sysmobts-calib
|
||||||
|
fi
|
||||||
29
contrib/lc15bts-mgr.service
Normal file
29
contrib/lc15bts-mgr.service
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=osmo-bts manager for LC15 / sysmoBTS 2100
|
||||||
|
After=lc15-sysdev-remap.service
|
||||||
|
Wants=lc15-sysdev-remap.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
NotifyAccess=all
|
||||||
|
WatchdogSec=21780s
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
|
||||||
|
# Make sure directories and symbolic link exist
|
||||||
|
ExecStartPre=/bin/sh -c 'test -d /mnt/storage/var/run/lc15bts-mgr || mkdir -p /mnt/storage/var/run/lc15bts-mgr ; test -d /var/run/lc15bts-mgr || ln -sf /mnt/storage/var/run/lc15bts-mgr/ /var/run'
|
||||||
|
# Make sure BTS operation hour exist
|
||||||
|
ExecStartPre=/bin/sh -c 'test -f /mnt/storage/var/run/lc15bts-mgr/hours-running || echo 0 > /mnt/storage/var/run/lc15bts-mgr/hours-running'
|
||||||
|
# Shutdown all PA correctly
|
||||||
|
ExecStartPre=/bin/sh -c 'echo disabled > /var/lc15/pa-state/pa0/state; echo disabled > /var/lc15/pa-state/pa1/state'
|
||||||
|
ExecStartPre=/bin/sh -c 'echo 0 > /var/lc15/pa-supply/max_microvolts; echo 0 > /var/lc15/pa-supply/min_microvolts'
|
||||||
|
|
||||||
|
ExecStart=/usr/bin/lc15bts-mgr -s -c /etc/osmocom/lc15bts-mgr.cfg
|
||||||
|
|
||||||
|
# Shutdown all PA correctly
|
||||||
|
ExecStopPost=/bin/sh -c 'echo disabled > /var/lc15/pa-state/pa0/state; echo disabled > /var/lc15/pa-state/pa1/state'
|
||||||
|
ExecStopPost=/bin/sh -c 'echo 0 > /var/lc15/pa-supply/max_microvolts; echo 0 > /var/lc15/pa-supply/min_microvolts'
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
Alias=osmo-bts-mgr.service
|
||||||
21
contrib/osmo-bts-lc15.service
Normal file
21
contrib/osmo-bts-lc15.service
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
[Unit]
|
||||||
|
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.cfg -M
|
||||||
|
ExecStopPost=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
|
||||||
|
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/usr1/brightness'
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
RestartPreventExitStatus=1
|
||||||
|
|
||||||
|
# The msg queues must be read fast enough
|
||||||
|
CPUSchedulingPolicy=rr
|
||||||
|
CPUSchedulingPriority=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
Alias=osmo-bts.service
|
||||||
21
contrib/osmo-bts-sysmo.service
Normal file
21
contrib/osmo-bts-sysmo.service
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=osmo-bts for sysmocom sysmoBTS
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||||
|
ExecStart=/usr/bin/osmo-bts-sysmo -s -c /etc/osmocom/osmo-bts.cfg -M
|
||||||
|
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||||
|
ExecStopPost=/bin/sh -c 'cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0 ; sleep 3s; cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0; sleep 1s'
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
RestartPreventExitStatus=1
|
||||||
|
|
||||||
|
# The msg queues must be read fast enough
|
||||||
|
CPUSchedulingPolicy=rr
|
||||||
|
CPUSchedulingPriority=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
Alias=sysmobts.service
|
||||||
|
Alias=osmo-bts.service
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
chdir /tmp
|
chdir /tmp
|
||||||
screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/sysmobts -c /etc/osmocom/osmo-bts.cfg -r 1 -M
|
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 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
|
screen -t MGR 2 /etc/osmocom/respawn-only.sh /usr/bin/sysmobts-mgr -n -c /etc/osmocom/sysmobts-mgr.cfg
|
||||||
detach
|
detach
|
||||||
|
|||||||
91
contrib/si_check.gawk
Executable file
91
contrib/si_check.gawk
Executable file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/gawk -f
|
||||||
|
|
||||||
|
# Usage example:
|
||||||
|
# tshark -2 -t r -E 'header=n' -E 'separator=,' -E 'quote=n' -T fields -e gsmtap.frame_nr -e gsmtap.ts -e gsmtap.arfcn -e _ws.col.Info -Y 'gsmtap' -r test.pcapng.gz | grep Information | env ARFCN=878 ./si_check.gawk
|
||||||
|
# read summary on number of bis/ter messages and adjust BT_BOTH and BT_NONE environment variables accordingly
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
FS = ","
|
||||||
|
FAILED = 0
|
||||||
|
IGNORE = 0
|
||||||
|
BIS = 0
|
||||||
|
TER = 0
|
||||||
|
QUA = 0
|
||||||
|
BT_BOTH = ENVIRON["BOTH"]
|
||||||
|
BT_NONE = ENVIRON["NONE"]
|
||||||
|
TC_INDEX = 0
|
||||||
|
TC4[4] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
{ # expected .csv input as follows: gsmtap.frame_nr,gsmtap.ts,gsmtap.arfcn,_ws.col.Info
|
||||||
|
if ("ARFCN" in ENVIRON) { # ARFCN filtering is enabled
|
||||||
|
if (ENVIRON["ARFCN"] != $3) { # ignore other ARFCNs
|
||||||
|
IGNORE++
|
||||||
|
next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type = get_si_type($4)
|
||||||
|
tc = get_tc($1)
|
||||||
|
result = "FAIL"
|
||||||
|
|
||||||
|
if (1 == check_si_tc(tc, type)) { result = "OK" }
|
||||||
|
else { FAILED++ }
|
||||||
|
|
||||||
|
if (4 == tc) {
|
||||||
|
TC4[TC_INDEX] = type
|
||||||
|
TC_INDEX = int((TC_INDEX + 1) % 4)
|
||||||
|
if (0 == check_tc4c(type) && "OK" == result) {
|
||||||
|
result = "FAIL"
|
||||||
|
FAILED++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == "2bis") { BIS++ }
|
||||||
|
if (type == "2ter") { TER++ }
|
||||||
|
if (type == "2quater") { QUA++ }
|
||||||
|
# for (i in TC4) print TC4[i] # debugging
|
||||||
|
printf "ARFCN=%d FN=%d TS=%d TC=%d TYPE=%s %s\n", $3, $1, $2, tc, type, result
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
printf "check completed: total %d, failed %d, ignored %d, ok %d\nSI2bis = %d, SI2ter = %d, SI2quater = %d\n", NR, FAILED, IGNORE, NR - FAILED - IGNORE, BIS, TER, QUA
|
||||||
|
if ((BIS > 0 || TER > 0) && BT_NONE) { printf "please re-run with correct environment: unset 'NONE' variable\n" }
|
||||||
|
if ((BIS > 0 && TER > 0) && !BT_BOTH) { printf "please re-run with correct environment: set 'BOTH' variable\n" }
|
||||||
|
}
|
||||||
|
|
||||||
|
func get_si_type(s, x) { # we rely on format of Info column in wireshark output - if it's changed we're screwed
|
||||||
|
return x[split(s, x, " ")]
|
||||||
|
}
|
||||||
|
|
||||||
|
func get_tc(f) { # N. B: all numbers in awk are float
|
||||||
|
return int(int(f / 51) % 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func check_tc4c(si, count) { # check for "once in 4 consecutive occurrences" rule
|
||||||
|
count = 0
|
||||||
|
if ("2quater" != si || "2ter" != si) { return 1 } # rules is not applicable to other types
|
||||||
|
if (BT_NONE && "2quater" == si) { return 0 } # should be on TC=5 instead
|
||||||
|
if (!BT_BOTH && "2ter" == si) { return 0 } # should be on TC=5 instead
|
||||||
|
if (0 in TC4 && 1 in TC4 && 2 in TC4 && 3 in TC4) { # only check if we have 4 consecutive occurrences already
|
||||||
|
if (si == TC4[0]) { count++ }
|
||||||
|
if (si == TC4[1]) { count++ }
|
||||||
|
if (si == TC4[2]) { count++ }
|
||||||
|
if (si == TC4[3]) { count++ }
|
||||||
|
if (0 == count) { return 0 }
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func check_si_tc(tc, si) { # check that SI scheduling on BCCH Norm is matching rules from 3GPP TS 05.02 § 6.3.1.3
|
||||||
|
switch (si) {
|
||||||
|
case "1": return (0 == tc) ? 1 : 0
|
||||||
|
case "2": return (1 == tc) ? 1 : 0
|
||||||
|
case "2bis": return (5 == tc) ? 1 : 0
|
||||||
|
case "13": return (4 == tc) ? 1 : 0
|
||||||
|
case "9": return (4 == tc) ? 1 : 0
|
||||||
|
case "2ter": if (BT_BOTH) { return (4 == tc) ? 1 : 0 } else { return (5 == tc) ? 1 : 0 }
|
||||||
|
case "2quater": if (BT_NONE) { return (5 == tc) ? 1 : 0 } else { return (4 == tc) ? 1 : 0 }
|
||||||
|
case "3": return (2 == tc || 6 == tc) ? 1 : 0
|
||||||
|
case "4": return (3 == tc || 7 == tc) ? 1 : 0
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
110
contrib/superfemto.sh
Executable file
110
contrib/superfemto.sh
Executable file
@@ -0,0 +1,110 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Split common DSP call log file (produced by superfemto-compatible firmware) into 4 separate call leg files (MO/MT & DL/UL) with events in format "FN EVENT_TYPE":
|
||||||
|
# MO Mobile Originated
|
||||||
|
# MT Mobile Terminated
|
||||||
|
# DL DownLink (BTS -> L1)
|
||||||
|
# UL UpLink (L1 -> BTS)
|
||||||
|
|
||||||
|
if [ -z $1 ]; then
|
||||||
|
echo "expecting DSP log file name as parameter"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# MO handle appear 1st in the logs
|
||||||
|
MO=$(grep 'h=' $1 | head -n 1 | cut -f2 -d',' | cut -f2 -d= | cut -f1 -d']')
|
||||||
|
|
||||||
|
# direction markers:
|
||||||
|
DLST="_CodeBurst"
|
||||||
|
ULST="_DecodeAndIdentify"
|
||||||
|
|
||||||
|
# DL sed filters:
|
||||||
|
D_EMP='s/ Empty frame request!/EMPTY/i'
|
||||||
|
D_FAC='s/ Coding a FACCH\/. frame !!/FACCH/i'
|
||||||
|
D_FST='s/ Coding a RTP SID First frame !!/FIRST/i'
|
||||||
|
D_FS1='s/ Coding a SID First P1 frame !!/FIRST_P1/i'
|
||||||
|
D_FS2='s/ Coding a SID First P2 frame !!/FIRST_P2/i'
|
||||||
|
D_RP1='s/ Coding a RTP SID P1 frame !!/SID_P1/i'
|
||||||
|
D_UPD='s/ Coding a RTP SID Update frame !!/UPDATE/i'
|
||||||
|
D_SPE='s/ Coding a RTP Speech frame !!/SPEECH/i'
|
||||||
|
D_ONS='s/ Coding a Onset frame !!/ONSET/i'
|
||||||
|
D_FO1='s/ A speech frame is following a NoData or SID First without an Onset./FORCED_FIRST/i'
|
||||||
|
D_FO2='s/ A speech frame is following a NoData without an Onset./FORCED_NODATA/i'
|
||||||
|
D_FP2='s/ A speech frame is following a NoData or SID_FIRST_P2 without an Onset./FORCED_F_P2/i'
|
||||||
|
D_FIN='s/ A speech frame is following a SID_FIRST without inhibit. A SID_FIRST_INH will be inserted./FORCED_F_INH/i'
|
||||||
|
D_UIN='s/ A speech frame is following a SID_UPDATE without inhibit. A SID_UPDATE_INH will be inserted./FORCED_U_INH/i'
|
||||||
|
|
||||||
|
# UL sed filters:
|
||||||
|
U_NOD='s/ It is a No Data frame !!/NODATA/i'
|
||||||
|
U_ONS='s/ It is an ONSET frame !!/ONSET/i'
|
||||||
|
U_UPD='s/ It is a SID UPDATE frame !!/UPDATE/i'
|
||||||
|
U_FST='s/ It is a SID FIRST frame !!/FIRST/i'
|
||||||
|
U_FP1='s/ It is a SID-First P1 frame !!/FIRST_P1/i'
|
||||||
|
U_FP2='s/ It is a SID-First P2 frame !!/FIRST_P2/i'
|
||||||
|
U_SPE='s/ It is a SPEECH frame *!!/SPEECH/i'
|
||||||
|
U_UIN='s/ It is a SID update InH frame !!/UPD_INH/i'
|
||||||
|
U_FIN='s/ It is a SID-First InH frame !!/FST_INH/i'
|
||||||
|
U_RAT='s/ It is a RATSCCH data frame !!/RATSCCH/i'
|
||||||
|
|
||||||
|
DL () { # filter downlink-related entries
|
||||||
|
grep $DLST $1 > $1.DL.tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
UL () { # uplink does not require special fix
|
||||||
|
grep $ULST $1 > $1.UL.tmp.fix
|
||||||
|
}
|
||||||
|
|
||||||
|
DL $1
|
||||||
|
UL $1
|
||||||
|
|
||||||
|
FIX() { # add MO/MT marker from preceding line to inserted ONSETs so filtering works as expected
|
||||||
|
cat $1.DL.tmp | awk 'BEGIN{ FS=" h="; H="" } { if (NF > 1) { H = $2; print $1 "h=" $2 } else { print $1 ", h=" H } }' > $1.DL.tmp.fix
|
||||||
|
}
|
||||||
|
|
||||||
|
FIX $1
|
||||||
|
|
||||||
|
MO() { # filter MO call DL or UL logs
|
||||||
|
grep "h=$MO" $1.tmp.fix > $1.MO.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
MT() { # filter MT call DL or UL logs
|
||||||
|
grep -v "h=$MO" $1.tmp.fix > $1.MT.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
MO $1.DL
|
||||||
|
MT $1.DL
|
||||||
|
MO $1.UL
|
||||||
|
MT $1.UL
|
||||||
|
|
||||||
|
PREP() { # prepare logs for reformatting
|
||||||
|
cat $1.raw | cut -f2 -d')' | cut -f1 -d',' | cut -f2 -d'>' | sed 's/\[u32Fn/fn/' | sed 's/\[ u32Fn/fn/' | sed 's/fn = /fn=/' | sed 's/fn=//' | sed 's/\[Fn=//' | sed 's/ An Onset will be inserted.//' > $1.tmp1
|
||||||
|
}
|
||||||
|
|
||||||
|
PREP "$1.DL.MT"
|
||||||
|
PREP "$1.DL.MO"
|
||||||
|
PREP "$1.UL.MT"
|
||||||
|
PREP "$1.UL.MO"
|
||||||
|
|
||||||
|
RD() { # reformat DL logs for consistency checks
|
||||||
|
cat $1.tmp1 | sed "$D_FST" | sed "$D_SPE" | sed "$D_FS1" | sed "$D_FS2" | sed "$D_UIN" | sed "$D_FIN" | sed "$D_UPD" | sed "$D_INH" | sed "$D_RP1" | sed "$D_ONS" | sed "$D_EMP" | sed "$D_FAC" | sed "$D_FO1" | sed "$D_FO2" | sed "$D_FP2" > $1.tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
RU() { # reformat UL logs for consistency checks
|
||||||
|
cat $1.tmp1 | sed "$U_FST" | sed "$U_SPE" | sed "$U_FP1" | sed "$U_FP2" | sed "$U_UPD" | sed "$U_ONS" | sed "$U_NOD" | sed "$U_UIN" | sed "$U_FIN" | sed "$U_RAT" > $1.tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
RD "$1.DL.MT"
|
||||||
|
RD "$1.DL.MO"
|
||||||
|
RU "$1.UL.MT"
|
||||||
|
RU "$1.UL.MO"
|
||||||
|
|
||||||
|
SW() { # swap fields
|
||||||
|
cat $1.tmp2 | awk '{ print $2, $1 }' > $1
|
||||||
|
}
|
||||||
|
|
||||||
|
SW "$1.DL.MT"
|
||||||
|
SW "$1.DL.MO"
|
||||||
|
SW "$1.UL.MT"
|
||||||
|
SW "$1.UL.MO"
|
||||||
|
|
||||||
|
rm $1.*.tmp*
|
||||||
@@ -310,19 +310,36 @@ int print_system_info()
|
|||||||
#ifdef FEMTOBTS_NO_BOARD_VERSION
|
#ifdef FEMTOBTS_NO_BOARD_VERSION
|
||||||
#define BOARD_REV(x) -1
|
#define BOARD_REV(x) -1
|
||||||
#define BOARD_OPT(x) -1
|
#define BOARD_OPT(x) -1
|
||||||
|
#define COMPILED_MAJOR (FEMTOBTS_API_VERSION >> 16)
|
||||||
|
#define COMPILED_MINOR ((FEMTOBTS_API_VERSION >> 8) & 0xff)
|
||||||
|
#define COMPILED_BUILD (FEMTOBTS_API_VERSION & 0xff)
|
||||||
#else
|
#else
|
||||||
#define BOARD_REV(x) x.u.systemInfoCnf.boardVersion.rev
|
#define BOARD_REV(x) x.u.systemInfoCnf.boardVersion.rev
|
||||||
#define BOARD_OPT(x) x.u.systemInfoCnf.boardVersion.option
|
#define BOARD_OPT(x) x.u.systemInfoCnf.boardVersion.option
|
||||||
|
#define COMPILED_MAJOR (SUPERFEMTO_API_VERSION >> 16)
|
||||||
|
#define COMPILED_MINOR ((SUPERFEMTO_API_VERSION >> 8) & 0xff)
|
||||||
|
#define COMPILED_BUILD (SUPERFEMTO_API_VERSION & 0xff)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
printf("DSP v%d.%d.%d FPGA v%d.%d.%d Rev: %d Option: %d\n",
|
printf("Compiled against: v%u.%u.%u\n",
|
||||||
|
COMPILED_MAJOR, COMPILED_MINOR, COMPILED_BUILD);
|
||||||
|
printf("Running DSP v%d.%d.%d FPGA v%d.%d.%d Rev: %d Option: %d\n",
|
||||||
INFO_DSP(prim).major, INFO_DSP(prim).minor, INFO_DSP(prim).build,
|
INFO_DSP(prim).major, INFO_DSP(prim).minor, INFO_DSP(prim).build,
|
||||||
INFO_FPGA(prim).major, INFO_FPGA(prim).minor, INFO_FPGA(prim).build,
|
INFO_FPGA(prim).major, INFO_FPGA(prim).minor, INFO_FPGA(prim).build,
|
||||||
BOARD_REV(prim), BOARD_OPT(prim));
|
BOARD_REV(prim), BOARD_OPT(prim));
|
||||||
|
|
||||||
|
if (COMPILED_MAJOR != INFO_DSP(prim).major || COMPILED_MINOR != INFO_DSP(prim).minor) {
|
||||||
|
printf("WARNING! WARNING! WARNING! WARNING! WARNING\n");
|
||||||
|
printf("You might run this against an incompatible firmware.\n");
|
||||||
|
printf("Continuing anyway but the result might be broken\n");
|
||||||
|
}
|
||||||
#undef INFO_DSP
|
#undef INFO_DSP
|
||||||
#undef INFO_FPGA
|
#undef INFO_FPGA
|
||||||
#undef BOARD_REV
|
#undef BOARD_REV
|
||||||
#undef BOARD_OPT
|
#undef BOARD_OPT
|
||||||
|
#undef COMPILED_MAJOR
|
||||||
|
#undef COMPILED_MINOR
|
||||||
|
#undef COMPILED_BUILD
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=sysmocom sysmoBTS manager
|
Description=osmo-bts manager for sysmoBTS
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
@@ -9,4 +9,4 @@ RestartSec=2
|
|||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
Alias=osmo-bts-mgr.service
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Description=sysmocom sysmoBTS
|
|||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||||
ExecStart=/usr/bin/sysmobts -s -c /etc/osmocom/osmo-bts.cfg -M
|
ExecStart=/usr/bin/osmo-bts-sysmo -s -c /etc/osmocom/osmo-bts.cfg -M
|
||||||
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||||
ExecStopPost=/bin/sh -c 'cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0 ; sleep 3s; cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0; sleep 1s'
|
ExecStopPost=/bin/sh -c 'cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0 ; sleep 3s; cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0; sleep 1s'
|
||||||
Restart=always
|
Restart=always
|
||||||
@@ -17,3 +17,4 @@ CPUSchedulingPriority=1
|
|||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
Alias=osmo-bts-sysmo.service
|
||||||
|
|||||||
486
debian/changelog
vendored
Normal file
486
debian/changelog
vendored
Normal file
@@ -0,0 +1,486 @@
|
|||||||
|
osmo-bts (0.6.0) unstable; urgency=medium
|
||||||
|
|
||||||
|
[ Holger Hans Peter Freyther ]
|
||||||
|
* Initial release.
|
||||||
|
* misc: Ignore files generated by a debian packaging build
|
||||||
|
* jenkins: Add the build script from jenkins here
|
||||||
|
* jenkins: Add the build script from jenkins here
|
||||||
|
* sysmobts: Add the barebox boot state reservation
|
||||||
|
* sysmobts: Fix eeprom padding before gpg key
|
||||||
|
* ci/spatch: Remove the "static" analysis handling
|
||||||
|
* oct: Attempt to enable the Octphy for the osmo-bts-oct build
|
||||||
|
* debian: Use the header files installed by openbsc-dev
|
||||||
|
* build: Do not require more headers from OpenBSC
|
||||||
|
* sysmobts: Make reservation for mode/netmask/ip and suc
|
||||||
|
* sysmobts: Store a simple network config in the EEPROM as well
|
||||||
|
|
||||||
|
[ Max ]
|
||||||
|
* Ensure TRX invariant
|
||||||
|
* Use libosmocore function for uplink measurements
|
||||||
|
* Fix debug output
|
||||||
|
* Fix RTP timestamps in case of DTX
|
||||||
|
* Add DTXd support for sysmoBTS and LC15
|
||||||
|
* Use libosmocodec for AMR RTP
|
||||||
|
* octphy: Use the app. info. defaults as base
|
||||||
|
* Fix debug output
|
||||||
|
* DTXd: store/repeat last SID
|
||||||
|
* DTXd: store/repeat last SID
|
||||||
|
* DTXu: mark beginning of speech burst in RTP
|
||||||
|
* Fix OML activation
|
||||||
|
* TRX: Add vty command to power on/off transceiver
|
||||||
|
* TRX: add configuration example
|
||||||
|
* Add .gitreview
|
||||||
|
* DTX: add support for AMR/HR
|
||||||
|
* Move copy-pasted code into common part
|
||||||
|
* Use libosmocodec functions for AMR
|
||||||
|
* Use error values instead of number for RSL error
|
||||||
|
* Clarify logging message
|
||||||
|
* Make get_lchan_by_chan_nr globally available
|
||||||
|
* DTXu: move copy-pasted code to common part
|
||||||
|
* Remove duplicated nibble shift code
|
||||||
|
* TRX: add Uplink DTX support for FR/HR
|
||||||
|
* Mark array as static const
|
||||||
|
* sysmobts: dump PRACH and PTCCH parameters
|
||||||
|
* Activate PTCCH UL
|
||||||
|
* Fix dsp tracing at phy config
|
||||||
|
* octphy: fix build
|
||||||
|
* Fill measurements data for L1SAP
|
||||||
|
* sysmo: ts_connect: log channel combination name instead of number
|
||||||
|
* DTX: fix last SID saving
|
||||||
|
* DTX: fix SID repeat scheduling
|
||||||
|
* DTX: fix SID logic
|
||||||
|
* lc15, sysmo: Use SID_FIRST_P1 to initiate DTX
|
||||||
|
* DTX: check Marker bit to send ONSET to L1
|
||||||
|
* DTX: remove misleading comment
|
||||||
|
* LC15: Clarify msgb ownership / fix memory leaks
|
||||||
|
* DTX: move scheduling check inside repeat_last_sid
|
||||||
|
* DTX: further AMR SID cache fixes (lc15, sysmo)
|
||||||
|
* DTX: move ONSET detection into separate function
|
||||||
|
* DTX: send AMR voice alongside with ONSET
|
||||||
|
* DTX: fix conversion from fn to ms
|
||||||
|
* Move copy-pasted array into shared header
|
||||||
|
* DTX DL: use FSM for AMR
|
||||||
|
* TRX: fix building with latest DTX changes
|
||||||
|
* DTX: fix array size calculation
|
||||||
|
* DTX AMR - fix buffer length check
|
||||||
|
* Replace magic number with define
|
||||||
|
* Fix lc15 build
|
||||||
|
* Extend RTP RX callback parameters
|
||||||
|
* DTX HR - fix array size calculation
|
||||||
|
* Fix DTX DL AMR SIDscheduling logic
|
||||||
|
* Add tools to check DTX operation
|
||||||
|
* DTX DL: split ONSET state handling
|
||||||
|
* Remove obsolete define
|
||||||
|
* DTX DL: add AMR HR support to scheduling check
|
||||||
|
* DTX fix ONSET handling
|
||||||
|
* dtx_check.gawk: Fix false-positives in DTX check
|
||||||
|
* Fix tests linking with libosmocodec
|
||||||
|
* DTX DL: tighten check for enabled operation
|
||||||
|
* DTX: wrap FSM signal dispatching
|
||||||
|
* Add libosmocodec for octphy build
|
||||||
|
* dtx_check.gawk: add check for repetitive SID FIRST
|
||||||
|
* Remove duplicated code
|
||||||
|
* Replace link_id constant with define
|
||||||
|
* DTX DL AMR: rewrite FSM recursion
|
||||||
|
* Remove duplicated code
|
||||||
|
* Fix AGCH/PCH proportional allocation
|
||||||
|
* TRX: prevent segfault upon phy init
|
||||||
|
* DTX: add explicit check if DTX enabled
|
||||||
|
* Save RTP metadata in Control Buffer
|
||||||
|
* osmo-bts-trx: fix lchan deactivation
|
||||||
|
* DTX: fix TS adjustment for ONSET
|
||||||
|
* Optionally use adaptive RTP jitter buffering
|
||||||
|
* Integrate Debian packaging changes
|
||||||
|
* DTX AMR HR: fix inhibition
|
||||||
|
* Add copyright for .deb packages
|
||||||
|
* Move code to libosmocore
|
||||||
|
* Log socket path on error
|
||||||
|
* Add Abis OML failure event reporting
|
||||||
|
* Alarm on various errors
|
||||||
|
* Remove obsolete define TLVP_PRES_LEN
|
||||||
|
* scheduler: log lchan on which prim error occured
|
||||||
|
* deb: use gsm_data_shared.* from openbsc-dev
|
||||||
|
* OML: internalize failure reporting
|
||||||
|
* Add ctrl command to send OML alert
|
||||||
|
* Fix typo in TCH/H interleaving table
|
||||||
|
* Use oml-alert CTRL command for temp report
|
||||||
|
* Remove code duplication
|
||||||
|
* Handle ctrl cmd allocation failures
|
||||||
|
* Check for suitable lchan type when detecting HO
|
||||||
|
* osmo-bts-trx: fix scheduling of broken frames
|
||||||
|
* Sync protocol with OsmoPCU
|
||||||
|
* vty: reduce code duplication
|
||||||
|
* Handle TXT indication from OsmoPCU
|
||||||
|
* Add MS TO to RSL measurements
|
||||||
|
* Signal to BSC when PCU disconnects
|
||||||
|
* Prepare for extended SI2quater support
|
||||||
|
* Set BTS variant while initializing BTS model
|
||||||
|
* Prepare for BTS attribute reporting via OML
|
||||||
|
* osmo-bts-trx: use libosmocoding
|
||||||
|
* Remove redundant test
|
||||||
|
* Implement basic Get Attribute responder
|
||||||
|
* Add version to phy_instance
|
||||||
|
* OML: fix Coverity-reported issues
|
||||||
|
* Re-add version to phy_instance
|
||||||
|
* Use systemd template specifiers
|
||||||
|
* Place *-mgr config examples according to BTS model
|
||||||
|
* lc15: add example systemd service file
|
||||||
|
* Extend Get Attribute responder
|
||||||
|
* Set and report BTS features
|
||||||
|
* Cleanup SI scheduling
|
||||||
|
* RSL: receive and send multiple SI2q messages
|
||||||
|
* RSL: check for abnormal SI2q values
|
||||||
|
* lc15bts-mgr: use extended config file example
|
||||||
|
* Move parameter file opening into separate function
|
||||||
|
* Move common steps into common jenkins helper
|
||||||
|
* lc15: add jenkins helper
|
||||||
|
* Use generic L1 headers helper
|
||||||
|
* Copy sysmobts.service to osmo-bts-sysmo
|
||||||
|
* OML: move BTS number check into separate function
|
||||||
|
* lc15: make jenkins helper executable
|
||||||
|
* lc15: fix jenkins build
|
||||||
|
* Add missing include for abis.h header file
|
||||||
|
* RSL: receive and send multiple SI2q messages
|
||||||
|
* Use release helper from libosmocore
|
||||||
|
* si2q: do not consider count update as error
|
||||||
|
* Cleanup example config files
|
||||||
|
* Fix .deb build
|
||||||
|
* Unify *.service files
|
||||||
|
* lc15: cleanup board parameters reading
|
||||||
|
* lc15-mgr: update parameter read/write
|
||||||
|
* lc15: fix BTS revision and hw options
|
||||||
|
* lc15: make default config usable
|
||||||
|
* lc15: port lc15bts-mgr changes
|
||||||
|
* lc15bts-mgr: separate service file
|
||||||
|
* lc15: port lc15bts-mgr dependency changes
|
||||||
|
* Simplify jenkins build scripts
|
||||||
|
* OML: use fom_hdr while handling attr. request
|
||||||
|
* osmo-bts-trx: fix 'osmotrx legacy-setbsic'
|
||||||
|
* osmo-bts-trx: remove global variables from loops
|
||||||
|
|
||||||
|
[ Daniel Laszlo Sitzer ]
|
||||||
|
* octphy: Update outdated config param name in error message.
|
||||||
|
|
||||||
|
[ Jason DSouza ]
|
||||||
|
* Close TRX session before opening new one
|
||||||
|
|
||||||
|
[ Minh-Quang Nguyen ]
|
||||||
|
* l1sap.h: fix wrong L1SAP_FN2PTCCHBLOCK calculation according to TS 45.002 Table 6
|
||||||
|
* common/abis.c: fix 100% CPU usage after disconnecting OML/RSL link (Bug #1703)
|
||||||
|
* LC15: Bring back DSP trace argument
|
||||||
|
* LC15: Hardware changes
|
||||||
|
* LC15: TRX nominal TX power can be used from EEPROM or from BTS configuration
|
||||||
|
* rsl: Fix dropping of LAPDm UA message.
|
||||||
|
* LC15: properly handle BS-AG-BLKS-RES as received from BSC
|
||||||
|
|
||||||
|
[ Neels Hofmeyr ]
|
||||||
|
* sysmo: add L3 handle to l1prim messages
|
||||||
|
* pcu_sock: add pcu_connected() to query PCU availability
|
||||||
|
* tests/stubs.c: remove unused stubs
|
||||||
|
* fix typo in error message ('at lEast')
|
||||||
|
* oml, Set Chan Attr: treat unknown PCHAN types as error
|
||||||
|
* dyn PDCH: rsl rx dchan: also log ip.access message names
|
||||||
|
* doc: add ladder diagram on dynamic PDCH, add msc-README
|
||||||
|
* add missing DSUM entry to bts_log_info_cat
|
||||||
|
* fix compiler warning: printf format for sizeof()
|
||||||
|
* fix compiler warning: add missing case (PHY_LINK_CONNECTING)
|
||||||
|
* fix two compiler warnings: add two opaque struct declarations
|
||||||
|
* dyn PDCH: add bts_model_ts_connect() and _disconnect() stubs
|
||||||
|
* dyn PDCH: conf_lchans_for_pchan(): handle TCH/F_PDCH
|
||||||
|
* dyn PDCH: pcu_tx_info_ind(): handle TCH/F_PDCH in PDCH mode
|
||||||
|
* dyn PDCH: chan_nr_by_sapi(): handle TCH/F_PDCH according to ts->flags
|
||||||
|
* dyn PDCH: implement main dyn PDCH logic in common/
|
||||||
|
* dyn PDCH: sysmo-bts/oml.c: add ts_connect_as(), absorbing ts_connect() guts
|
||||||
|
* dyn PDCH: sysmo: handle TCH/F_PDCH init like TCH/F
|
||||||
|
* dyn PDCH: complete for sysmo-bts: implement bts_model_ts_*()
|
||||||
|
* error log: two minor clarifications
|
||||||
|
* debug log: log lchan state transitions
|
||||||
|
* debug log: log TS pchan type on connect
|
||||||
|
* fix lc15 build: put src/common/libbts.a left of -losmogsm
|
||||||
|
* lc15: add L3 handle to l1prim messages
|
||||||
|
* dyn PDCH: lc15: chan_nr_by_sapi(): handle TCH/F_PDCH according to ts->flags
|
||||||
|
* dyn PDCH: lc15: add ts_connect_as(), absorbing ts_connect() guts
|
||||||
|
* dyn PDCH: lc15: handle TCH/F_PDCH init like TCH/F
|
||||||
|
* dyn PDCH: lc15: complete for litecell15-bts: implement bts_model_ts_*()
|
||||||
|
* dyn PDCH: safeguard: exit if nothing pending in dyn_pdch_ts_disconnected()
|
||||||
|
* vty: install orphaned trx nominal power command
|
||||||
|
* fix compiler warnings: include bts_model.h in phy_link.c
|
||||||
|
* fix compiler warning: remove useless 'static' storage class for struct decl
|
||||||
|
* fix compiler warning: remove unused variable 'i' in calib_verify()
|
||||||
|
* log: osmo-bts-trx: change access burst logs to DEBUG level
|
||||||
|
* log: osmo-bts-trx: change PDTCH block logs to DEBUG level
|
||||||
|
* osmo-bts-trx: init OML only once by sending AVSTATE_OK with OPSTATE_ENABLED
|
||||||
|
* doc: move dyn_pdch.msc to osmo-gsm-manuals.git
|
||||||
|
* error log: rsl.c: typo x2
|
||||||
|
* info log: l1sap.c: add '0x' to hex output
|
||||||
|
* fix compiler warning: msg_utils.c: fn_chk() constify arg
|
||||||
|
* fix compiler warning: msg_utils.c: fn_chk() constify arg
|
||||||
|
* info log: l1sap.c: add '0x' to hex output
|
||||||
|
* error log: rsl.c: typo x2
|
||||||
|
* dyn PDCH: code dup: use conf_lchans_as_pchan()
|
||||||
|
* prepare dyn TS: split/replace conf_lchans_for_pchan()
|
||||||
|
* code dup: join [rsl_]lchan_lookup() from libbsc and osmo-bts
|
||||||
|
* dyn TS: common TCH/F_TCH/H_PDCH implementation
|
||||||
|
* sysmo/oml.c: rename ts_connect() to ts_opstart()
|
||||||
|
* dyn TS: implement SysmoBTS specifics
|
||||||
|
* lc15/oml.c: rename ts_connect() to ts_opstart()
|
||||||
|
* dyn TS: implement litecell15 specifics
|
||||||
|
* comment typo: common/l1sap.c
|
||||||
|
* log typo: trx_sched_set_pchan()
|
||||||
|
* dyn TS: sysmo,lc15: chan_nr_by_sapi(): add missing assertion
|
||||||
|
* fix comment in common/l1sap.c, function name changed
|
||||||
|
* dyn TS, dyn PDCH: common/l1sap.c: properly notice PDCH
|
||||||
|
* dyn PDCH: trx l1_if.c: factor out trx_set_ts_as_pchan() from trx_set_ts()
|
||||||
|
* dyn PDCH: complete for trx: implement bts_model_ts_[dis]connect()
|
||||||
|
* dyn PDCH: trx l1_if.c: drop fixme, add comment
|
||||||
|
* dyn TS: complete for TRX
|
||||||
|
* dyn TS: measurement.c: replace fixme with comment
|
||||||
|
* sysmo,lc15: ts_connect_as(): log error also for pchan_as == TCH/F_PDCH
|
||||||
|
* sysmo: fix dyn TS: Revert "Activate PTCCH UL" [in sysmobts]
|
||||||
|
* log: l1sap: add 0x to hex output of chan_nr, 5 times
|
||||||
|
* dyn TS: measurement: use correct nr of subslots, rm code dup
|
||||||
|
* dyn TS: sysmo,lc15: ph_data_req: fix PDCH mode detection
|
||||||
|
* Fix ip.access style dyn PDCH, broken in 37af36e85eca546595081246aec010fa7f6fd0be
|
||||||
|
* common/rsl: move decision whether to chan act ack/nack to common function
|
||||||
|
* octphy: fix build: Revert "octphy: fix for multiple trx with more than 1 dsp"
|
||||||
|
* octphy: fix build: Revert "octphy: add support for multiple trx ids"
|
||||||
|
* octphy: fix build with OCTSDR-OPENBSC-02.07.00-B708: name changed
|
||||||
|
* dyn TS: if PCU is not connected, allow operation as TCH
|
||||||
|
* log: sysmo,lc15: tweak log about sapi_cmds queue
|
||||||
|
* log causing rx event for lchan_lookup errors
|
||||||
|
* heed VTY 'line vty'/'bind' command
|
||||||
|
* sysmobts_mgr, lc15bts_mgr: fix tall context for telnet vty
|
||||||
|
* build: be robust against install-sh files above the root dir
|
||||||
|
* configure: check for pkg-config presence
|
||||||
|
* jenkins.sh: use osmo-build-dep.sh, log test failures
|
||||||
|
* msgb ctx: use new msgb_talloc_ctx_init() in various main()s
|
||||||
|
* jenkins-oct.sh: fix build: typo in deps path
|
||||||
|
* fix 'osmo-bts-* --version' segfault
|
||||||
|
* osmo-bts-trx: remove obsolete include of netif/rtp.h
|
||||||
|
* add jenkins_bts_trx.sh
|
||||||
|
* add jenkins_oct_and_bts_trx.sh
|
||||||
|
* jenkins: add jenkins_bts_model.sh
|
||||||
|
* bursts test: test_pdtch: pre-init result mem
|
||||||
|
* fix: dyn ts: uplink measurement report
|
||||||
|
* fix missing ~ in bit logic for lchan->si.valid in rsl_rx_sacch_inf_mod()
|
||||||
|
* SACCH: fix sending of SI with an enum value > 7
|
||||||
|
* SACCH SI: assert that SI enum vals fit in bit mask
|
||||||
|
* all models: fix vty write: bts_model_config_write_phy
|
||||||
|
* jenkins: add value_string termination check
|
||||||
|
* Revert "Add version to phy_instance"
|
||||||
|
* Revert "RSL: check for abnormal SI2q values"
|
||||||
|
* Revert "RSL: receive and send multiple SI2q messages"
|
||||||
|
|
||||||
|
[ Harald Welte ]
|
||||||
|
* sysmobts: screnrc/systemd-service: Use osmo-bts-sysmo instead of sysmobts
|
||||||
|
* Add .mailmap for mapping mail addresses in shortlog
|
||||||
|
* vty: Ensure to not use negative (error) sapi value
|
||||||
|
* sysmobts: Add correct nominal transmit power for sysmoBTS 1020
|
||||||
|
* sysmobts_eeprom.h: Fix/extend model number definitions
|
||||||
|
* Revert "sysmobts: Add correct nominal transmit power for sysmoBTS 1020"
|
||||||
|
* tx_power: Change PA calibration tables to use delta vales
|
||||||
|
* Add new unit-test for transmit power computation code
|
||||||
|
* sysmobts: fully support trx_power_params
|
||||||
|
* README: Add general project information and convert to markdown
|
||||||
|
* README: update some of the limitations
|
||||||
|
* sysmobts: Don't start with 0dBm TRX output power before ramping
|
||||||
|
* Remove unusued left-over gsm0503_conv.c
|
||||||
|
* scheduler_trx.c: Avoid code duplication for BER10k computation
|
||||||
|
* scheduler_trx: Avoid copy+pasting determining CMR from FN
|
||||||
|
* rx_tchh_fn(): Avoid copy+pasting formula to determine odd-ness of fn
|
||||||
|
* Consistently check for minimum attribute/TLV length in RSL and OML
|
||||||
|
* l1sap.c: Add spec reference to link timeout implementation
|
||||||
|
* osmo-bts-trx: Remove duplicate parsing of NM_ATT_CONN_FAIL_CRIT
|
||||||
|
* vty: Remove command for manual channel activation/deactivation
|
||||||
|
* l1_if: Add inline functions to check dsp/fgpa version at runtime
|
||||||
|
* sysmobts: Re-order the bit-endianness of every HR codec parameter
|
||||||
|
* OML Add osmocom-specific way to deactivate radio link timeout
|
||||||
|
* measurement: Remove dead code
|
||||||
|
* l1sap.c: Factor out function to limit message queue
|
||||||
|
* osmo-bts-sysmo/l1_if.c: PH-DATA.ind belongs to L1P, not L1C
|
||||||
|
* l1sap: if lchan is in loopback, don't accept incoming RTP
|
||||||
|
* TRX: Use timerfd and CLOCK_MONOTONIC for GSM frame timer (Closes: #2325)
|
||||||
|
* Add loopback support for PDTCH
|
||||||
|
* TRX: trx_if: Improve code description / comments
|
||||||
|
* trx_if: Improve error handling
|
||||||
|
* TRX: Rename trx_if_data() -> trx_if_send_burst()
|
||||||
|
* TRX: merge/simplify l1_if and trx_if code
|
||||||
|
* TRX: don't free l1h in trx_phy_inst_close()
|
||||||
|
* l1sap: Don't enqueue PTCCH blocks for loopback
|
||||||
|
* TRX: permit transmission of all-zero loopback frames
|
||||||
|
* jenkins helpers: some minimal documentation/comments + print errors
|
||||||
|
* VIRT-PHY: Initial check-in of a new virtual BTS
|
||||||
|
* VIRT-PHY: Fix handling of default values for vty configuration
|
||||||
|
* VIRT-PHY: Use IPv4 multicast groups for private / local scope
|
||||||
|
* VIRT-PHY: cause BTS to terminate in case of recv()/send() on udp socket returns 0
|
||||||
|
* Ensure we don't send dummy UI frames on BCCH for TC=5
|
||||||
|
* virt: Don't print NOTICE log message if ARFCN doesn't match
|
||||||
|
* VIRT-PHY: Report virtual RACH bursts with plausible burst type
|
||||||
|
* scheduler: Fix wrong log subsystem: L1C is L1 *control* not user data
|
||||||
|
* VIRT-PHY: Print NOTICE log message from unimplemented stubs
|
||||||
|
* TRX / VIRT-PHY: Make check for BCCH/CCCH more specific
|
||||||
|
* L1SAP: Print chan_nr and link_id always as hex
|
||||||
|
* VIRT-BTS: Support for GPRS
|
||||||
|
* L1SAP: Use RSL_CHAN_OSMO_PDCH across L1SAP
|
||||||
|
* GSMTAP: Don't log fill frames via GSMTAP
|
||||||
|
* TRX: Remove bogus extern global variable declarations
|
||||||
|
* l1sap/osmo-bts-sysmo: Improve logging
|
||||||
|
* TRX: Remove global variables, move SETBSIC/SETTSC handling into phy_link
|
||||||
|
* Fix build after recent gsm_bts_alloc() change
|
||||||
|
* Treat SIGTERM just like SIGINT in our programs
|
||||||
|
|
||||||
|
[ Tom Tsou ]
|
||||||
|
* trx: Add EGPRS tables, sequences, and mappings
|
||||||
|
* trx: Add EGPRS coding and decoding procedures
|
||||||
|
* trx: Enable EGPRS handling through burst lengths
|
||||||
|
* trx: Fix coverity BER calculation NULL dereference
|
||||||
|
|
||||||
|
[ Vadim Yanitskiy ]
|
||||||
|
* pcu_sock: use osmo_sock_unix_init() from libosmocore
|
||||||
|
* osmo-bts-trx/l1_if.c: use channel combination III for TCH/H
|
||||||
|
* scheduler_trx.c: strip unused variable
|
||||||
|
|
||||||
|
[ Mike McTernan ]
|
||||||
|
* osmo-bts-trx: Fix PCS1900 operation
|
||||||
|
* osmo-bts-trx: log decoder bit errors as DEBUG, not NOTICE
|
||||||
|
|
||||||
|
[ bhargava ]
|
||||||
|
* Change interface in osmo-bts for 11 bit RACH
|
||||||
|
* Update parameters in osmo-bts-sysmo for 11bit RACH
|
||||||
|
* 11bit RACH support for osmo-bts-litecell15
|
||||||
|
* Initialize parameters in osmo-trx for 11bit RACH
|
||||||
|
|
||||||
|
[ Philipp ]
|
||||||
|
* octphy: Fixing missing payload type in ph. chan. activation
|
||||||
|
* octphy: Fixing band selection for ARFCN 0
|
||||||
|
* octphy: reintroducing multi-trx support
|
||||||
|
* octopy: fixing renamed constant
|
||||||
|
* octphy: prevent mismatch between dsp-firmware and octphy headers
|
||||||
|
* rsl: improving the log output
|
||||||
|
* octphy: multi-trx support: fix AC_CHECK order
|
||||||
|
* RSL: drop obsolete NULL check
|
||||||
|
* RSL: add assertions to check args of public API
|
||||||
|
* OML: fix possible segfault: add NULL check in oml_ipa_set_attr()
|
||||||
|
* CTRL: make the CTRL-Interface IP address configurable
|
||||||
|
* l1sap: Fix expired rach slot counting
|
||||||
|
* l1sap: fix missing 'else's causing wrong rach frame expiry counts
|
||||||
|
* octphy: set tx attenuation via VTY
|
||||||
|
* octphy: Improve OML ADM state handling
|
||||||
|
|
||||||
|
[ Yves Godin ]
|
||||||
|
* DTX: fix 1st RTP packet drop
|
||||||
|
|
||||||
|
[ Alexander Chemeris ]
|
||||||
|
* l1sap: Fix use-after-free in loopback mode.
|
||||||
|
* vty: Add commands to manually activate/deactivate a channel.
|
||||||
|
* trx: Add "maxdlynb" VTY command to control max TA for Normal Bursts.
|
||||||
|
* rsl: Output RTP stats before closing the socket.
|
||||||
|
* osmo-bts-trx: Fix MS power control loop.
|
||||||
|
* osmo-bts-trx: Remove an unused variable. Resolves a compiler warning.
|
||||||
|
* osmo-bts-trx: Increase a maximum allowed MS power reduction step from 2dB to 4dB.
|
||||||
|
* Fix static build of osmo-bts-trx and osmo-bts-virtual.
|
||||||
|
|
||||||
|
[ Jean-Francois Dionne ]
|
||||||
|
* DTX: don't always perform AMR HR specific check
|
||||||
|
* DTX: fix SID-FIRST detection
|
||||||
|
* lc15,sysmobts l1_if: fix memleak in handle_mph_time_ind()
|
||||||
|
* sysmo,lc15: fix memory leak at each call placed
|
||||||
|
* DTX: fix "unexpected burst" error
|
||||||
|
* Fix AMR HR DTX FSM logic.
|
||||||
|
* Fix SACCH channel release indication not sent to BSC after location update.
|
||||||
|
* Fix RTP duration adjustment not done when speech resumes in DTX mode.
|
||||||
|
|
||||||
|
[ Ruben Undheim ]
|
||||||
|
* Fix some spelling errors
|
||||||
|
|
||||||
|
[ Holger Freyther ]
|
||||||
|
* Revert "deb: use gsm_data_shared.* from openbsc-dev"
|
||||||
|
|
||||||
|
[ Philipp Maier ]
|
||||||
|
* octphy VTY: fix vty write output for octphy's phy section
|
||||||
|
* octphy: Fix VTY commands
|
||||||
|
* l1sap: fix rach reason (ra) parsing
|
||||||
|
* l1sap: fix PTCCH detection
|
||||||
|
* octphy: fix usage of wrong define constant
|
||||||
|
* octphy: add CBCH support
|
||||||
|
* l1sap: improve log output
|
||||||
|
* octphy: print log message for multi-trx support
|
||||||
|
* octphy: display hint in case of wrongly configured transceiver number
|
||||||
|
* octphy: add conditional compilation to support latest octasic header release
|
||||||
|
* octphy: set tx/rx antenne IDs via VTY
|
||||||
|
* bts: revert trx shutdown order
|
||||||
|
* octphy: activate CBCH after all physical channels are activated
|
||||||
|
* octphy: align frame number for new firmware versions
|
||||||
|
* octphy: ensure that 11 bit rach flag is not set
|
||||||
|
* measurement: fix measurement reporting period
|
||||||
|
* measurement: make lchan_meas_check_compute() available to l1sap.c
|
||||||
|
* measurement: Compute measurement results on measurement idication
|
||||||
|
* measurement: exclude idle channels from uplink measurement
|
||||||
|
* octphy: integrate channel measurement handling
|
||||||
|
* octphy: remove old event control code
|
||||||
|
* osmo-bts-sysmo: Include frame number in MEAS IND
|
||||||
|
* measurement: fix measurement computation
|
||||||
|
* octphy: fix segfault
|
||||||
|
* Revert "measurement: exclude idle channels from uplink measurement"
|
||||||
|
* sysmobts: normalize frame number in measurement indication
|
||||||
|
* measurement: Improve log output
|
||||||
|
* measurement: improve log output
|
||||||
|
* octphy: improve log output
|
||||||
|
* octphy: initalize l1msg and only when needed
|
||||||
|
* octphy: initalize nmsg only when needed
|
||||||
|
* octphy: remove log output
|
||||||
|
* Revert "sysmobts: normalize frame number in measurement indication"
|
||||||
|
* osmo-bts-trx: fix missing frame number in MEAS IND
|
||||||
|
* osmo-bts-litecell15: Fix missing frame number in MEAS IND
|
||||||
|
* Revert "osmo-bts-sysmo: Include frame number in MEAS IND"
|
||||||
|
* octphy: complete value strings (octphy_cid_vals)
|
||||||
|
* octphy: do not send empty frames to phy
|
||||||
|
* osmo-bts-sysmo: Include frame number in MEAS IND
|
||||||
|
* measurement: fix measurment report
|
||||||
|
* octphy: remap frame number in MEAS_IND
|
||||||
|
* octphy: implement support for dynamic timeslots
|
||||||
|
|
||||||
|
[ Ivan Klyuchnikov ]
|
||||||
|
* osmo-trx-bts: Fix incorrect setting of RXGAIN and POWER parameters on second channel (TRX1) of osmo-trx
|
||||||
|
* osmo-trx-bts: Fix osmo-bts-trx crash on startup during reading phy instance parameters from config file
|
||||||
|
* osmo-trx-bts: Fix incorrect bts shutdown procedure in case of abis connection closure
|
||||||
|
* osmo-trx-bts: Fix incorrect bts shutdown procedure in case of clock loss from osmo-trx
|
||||||
|
|
||||||
|
[ Ivan Kluchnikov ]
|
||||||
|
* oml: Fix incorrect usage of const variable abis_nm_att_tlvdef_ipa
|
||||||
|
|
||||||
|
[ Pau Espin Pedrol ]
|
||||||
|
* phy_link: Fix typo in state being printed
|
||||||
|
* trx: Allow BTS and TRX to be on different IPs
|
||||||
|
* trx: Save osmotrx base-port vty properties
|
||||||
|
* sysmo/tch.c: Clean up use of empty buffer
|
||||||
|
* litecell15/tch.c: Clean up use of empty buffer
|
||||||
|
* Use L1P instead of L1C for TCH logging and allocation
|
||||||
|
* Fix annoying trailing whitespace
|
||||||
|
* sysmo, litecell15: Make sure all TCH events are triggered
|
||||||
|
* sysmo: Remove non longer valid -p option from help
|
||||||
|
* Allow passing low link quality buffers to upper layers
|
||||||
|
* l1sap.c: Avoid sending RTP frame with empty payload
|
||||||
|
* l1sap.c: fn_ms_adj: Add err logging and always return GSM_RTP_DURATION
|
||||||
|
* Move dump_gsmtime to libosmocore as osmo_dump_gsmtime
|
||||||
|
* Use osmo_dump_gsmtime to log fn across different layers
|
||||||
|
* lc15bts-mgr.cfg: Set default vswr to a value inside valid range
|
||||||
|
* litecell15: Register in vty limits for paX_pwr
|
||||||
|
* lc15: Tweak led colors used in service file
|
||||||
|
* lc-15, sysmo: l1_if: print name on PH-DATA.ind unknwon sapi
|
||||||
|
* lc15bts-mgr.service: Prepare dirs and sysctls for the process
|
||||||
|
* osmo-bts-trx: Enable osmotrx tx-attenuation oml by default
|
||||||
|
* osmo-bts-trx: Relax validation to allow TRX data bursts without padding
|
||||||
|
|
||||||
|
[ Sebastian Stumpf ]
|
||||||
|
* VIRT-PHY: Added example configurations for openbsc and osmobts.
|
||||||
|
* VIRT-PHY: Fixed timeslot in gsmtap-msg on downlink which was always 0.
|
||||||
|
* VIRT-PHY: Added test option for fast hyperframe repeat.
|
||||||
|
|
||||||
|
-- Max <msuraev@sysmocom.de> Fri, 25 Aug 2017 15:16:56 +0200
|
||||||
|
|
||||||
|
osmo-bts (0.5.0) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Initial release.
|
||||||
|
|
||||||
|
-- Holger Hans Peter Freyther <holger@moiji-mobile.com> Fri, 01 Apr 2016 16:13:40 +0200
|
||||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
9
|
||||||
36
debian/control
vendored
Normal file
36
debian/control
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
Source: osmo-bts
|
||||||
|
Maintainer: Holger Hans Peter Freyther <holger@moiji-mobile.com>
|
||||||
|
Section: net
|
||||||
|
Priority: optional
|
||||||
|
Build-Depends: debhelper (>= 9),
|
||||||
|
pkg-config,
|
||||||
|
dh-autoreconf,
|
||||||
|
dh-systemd (>= 1.5),
|
||||||
|
autotools-dev,
|
||||||
|
pkg-config,
|
||||||
|
libosmocore-dev,
|
||||||
|
openbsc-dev,
|
||||||
|
libosmo-abis-dev,
|
||||||
|
libosmo-netif-dev,
|
||||||
|
libgps-dev,
|
||||||
|
libortp-dev,
|
||||||
|
txt2man
|
||||||
|
Standards-Version: 3.9.8
|
||||||
|
Vcs-Browser: http://git.osmocom.org/osmo-bts/
|
||||||
|
Vcs-Git: git://git.osmocom.org/osmo-bts
|
||||||
|
Homepage: https://projects.osmocom.org/projects/osmobts
|
||||||
|
|
||||||
|
Package: osmo-bts-trx
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||||
|
Description: osmo-bts-trx GSM BTS with osmo-trx
|
||||||
|
osmo-bts-trx to be used with the osmo-trx application
|
||||||
|
|
||||||
|
Package: osmo-bts-trx-dbg
|
||||||
|
Architecture: any
|
||||||
|
Section: debug
|
||||||
|
Priority: extra
|
||||||
|
Depends: osmo-bts-trx (= ${binary:Version}), ${misc:Depends}
|
||||||
|
Description: Debug symbols for the osmo-bts-trx
|
||||||
|
Make debugging possible
|
||||||
|
|
||||||
81
debian/copyright
vendored
Normal file
81
debian/copyright
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: osmo-bts
|
||||||
|
Source: http://cgit.osmocom.org/osmo-bts/
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2008-2014 Harald Welte <laforge@gnumonks.org>
|
||||||
|
2009,2011,2013 Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
2010,2011 On-Waves
|
||||||
|
2012-2015 Holger Hans Peter Freyther
|
||||||
|
2014 sysmocom s.f.m.c. Gmbh
|
||||||
|
2015 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||||
|
License: AGPL-3+
|
||||||
|
|
||||||
|
Files: src/osmo-bts-sysmo/eeprom.c
|
||||||
|
src/osmo-bts-sysmo/eeprom.h
|
||||||
|
Copyright: 2012 Nutaq
|
||||||
|
License: MIT
|
||||||
|
Comment: Yves Godin is the author
|
||||||
|
|
||||||
|
Files: src/common/pcu_sock.c
|
||||||
|
Copyright: 2008-2010 Harald Welte <laforge@gnumonks.org>
|
||||||
|
2009-2012 Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
2012 Holger Hans Peter Freyther
|
||||||
|
License: GPL-2+
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2015-2016 Ruben Undheim <ruben.undheim@gmail.com>
|
||||||
|
License: AGPL-3+
|
||||||
|
|
||||||
|
|
||||||
|
License: AGPL-3+
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
|
||||||
|
License: GPL-2+
|
||||||
|
This package is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
.
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General
|
||||||
|
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||||
|
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
.
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
2
debian/osmo-bts-trx.install
vendored
Normal file
2
debian/osmo-bts-trx.install
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
usr/bin/osmo-bts-trx
|
||||||
|
usr/bin/osmo-bts-virtual
|
||||||
15
debian/osmo-bts-trx.service
vendored
Normal file
15
debian/osmo-bts-trx.service
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Osmocom osmo-bts for osmo-trx
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/osmo-bts-trx -s -c /etc/osmocom/osmo-bts.cfg
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
|
||||||
|
# Let it process messages quickly enough
|
||||||
|
CPUSchedulingPolicy=rr
|
||||||
|
CPUSchedulingPriority=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
32
debian/rules
vendored
Executable file
32
debian/rules
vendored
Executable file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
DEBIAN := $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2)
|
||||||
|
DEBVERS := $(shell echo '$(DEBIAN)' | cut -d- -f1)
|
||||||
|
VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/[+-].*//' -e 's/~//g')
|
||||||
|
|
||||||
|
#export DH_VERBOSE=1
|
||||||
|
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
|
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@ --with=systemd --with autoreconf --fail-missing
|
||||||
|
|
||||||
|
override_dh_strip:
|
||||||
|
dh_strip --dbg-package=osmo-bts-trx-dbg
|
||||||
|
|
||||||
|
override_dh_autoreconf:
|
||||||
|
echo $(VERSION) > .tarball-version
|
||||||
|
dh_autoreconf
|
||||||
|
|
||||||
|
override_dh_auto_configure:
|
||||||
|
dh_auto_configure -- --enable-trx --with-openbsc=/usr/src/osmocom/openbsc/openbsc/include/
|
||||||
|
|
||||||
|
override_dh_clean:
|
||||||
|
dh_clean
|
||||||
|
$(RM) tests/package.m4
|
||||||
|
$(RM) tests/testsuite
|
||||||
|
|
||||||
|
# Print test results in case of a failure
|
||||||
|
override_dh_auto_test:
|
||||||
|
dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
|
||||||
|
|
||||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.0 (native)
|
||||||
43
doc/examples/litecell15/lc15bts-mgr.cfg
Normal file
43
doc/examples/litecell15/lc15bts-mgr.cfg
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
!
|
||||||
|
! lc15bts-mgr (0.3.0.284-a7c2-dirty) configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 1
|
||||||
|
logging print category 0
|
||||||
|
logging timestamp 0
|
||||||
|
logging level temp info
|
||||||
|
logging level fw info
|
||||||
|
logging level find info
|
||||||
|
logging level calib info
|
||||||
|
logging level lglobal notice
|
||||||
|
logging level llapd notice
|
||||||
|
logging level linp notice
|
||||||
|
logging level lmux notice
|
||||||
|
logging level lmi notice
|
||||||
|
logging level lmib notice
|
||||||
|
logging level lsms notice
|
||||||
|
logging level lctrl notice
|
||||||
|
logging level lgtp notice
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
lc15bts-mgr
|
||||||
|
limits supply_volt
|
||||||
|
threshold warning min 17500
|
||||||
|
threshold critical min 19000
|
||||||
|
limits tx0_vswr
|
||||||
|
threshold warning max 1000
|
||||||
|
limits tx1_vswr
|
||||||
|
threshold warning max 1000
|
||||||
|
limits supply_pwr
|
||||||
|
threshold warning max 110
|
||||||
|
threshold critical max 120
|
||||||
|
limits pa0_pwr
|
||||||
|
threshold warning max 50
|
||||||
|
threshold critical max 60
|
||||||
|
limits pa1_pwr
|
||||||
|
threshold warning max 50
|
||||||
|
threshold critical max 60
|
||||||
43
doc/examples/litecell15/osmo-bts.cfg
Normal file
43
doc/examples/litecell15/osmo-bts.cfg
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS (0.0.1.100-0455-dirty) configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl info
|
||||||
|
logging level oml info
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level pag info
|
||||||
|
logging level l1c info
|
||||||
|
logging level l1p info
|
||||||
|
logging level dsp debug
|
||||||
|
logging level abis notice
|
||||||
|
logging level rtp notice
|
||||||
|
logging level lglobal notice
|
||||||
|
logging level llapd notice
|
||||||
|
logging level linp notice
|
||||||
|
logging level lmux notice
|
||||||
|
logging level lmi notice
|
||||||
|
logging level lmib notice
|
||||||
|
logging level lsms notice
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
phy 0
|
||||||
|
instance 0
|
||||||
|
trx-calibration-path /mnt/rom/factory/calib
|
||||||
|
phy 1
|
||||||
|
instance 0
|
||||||
|
trx-calibration-path /mnt/rom/factory/calib
|
||||||
|
bts 0
|
||||||
|
band 900
|
||||||
|
ipa unit-id 1500 0
|
||||||
|
oml remote-ip 192.168.234.185
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
|
trx 1
|
||||||
|
phy 1 instance 0
|
||||||
34
doc/examples/octphy/osmo-bts-trx2dsp1.cfg
Normal file
34
doc/examples/octphy/osmo-bts-trx2dsp1.cfg
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS () configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl info
|
||||||
|
logging level oml info
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level pag info
|
||||||
|
logging level l1c info
|
||||||
|
logging level l1p info
|
||||||
|
logging level dsp info
|
||||||
|
logging level abis notice
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
phy 0
|
||||||
|
octphy hw-addr 00:0c:de:ad:fa:ce
|
||||||
|
octphy net-device eth2
|
||||||
|
instance 0
|
||||||
|
instance 1
|
||||||
|
bts 0
|
||||||
|
band 1800
|
||||||
|
ipa unit-id 1234 0
|
||||||
|
oml remote-ip 127.0.0.1
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
|
trx 1
|
||||||
|
phy 0 instance 1
|
||||||
31
doc/examples/octphy/osmo-bts.cfg
Normal file
31
doc/examples/octphy/osmo-bts.cfg
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS () configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl info
|
||||||
|
logging level oml info
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level pag info
|
||||||
|
logging level l1c info
|
||||||
|
logging level l1p info
|
||||||
|
logging level dsp info
|
||||||
|
logging level abis notice
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
phy 0
|
||||||
|
octphy hw-addr 00:0C:90:2e:80:1e
|
||||||
|
octphy net-device eth0.2342
|
||||||
|
instance 0
|
||||||
|
bts 0
|
||||||
|
band 1800
|
||||||
|
ipa unit-id 1234 0
|
||||||
|
oml remote-ip 127.0.0.1
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
@@ -3,9 +3,8 @@
|
|||||||
!!
|
!!
|
||||||
!
|
!
|
||||||
log stderr
|
log stderr
|
||||||
logging color 0
|
logging color 1
|
||||||
logging timestamp 0
|
logging timestamp 0
|
||||||
logging level all everything
|
|
||||||
logging level rsl info
|
logging level rsl info
|
||||||
logging level oml info
|
logging level oml info
|
||||||
logging level rll notice
|
logging level rll notice
|
||||||
@@ -14,13 +13,17 @@ log stderr
|
|||||||
logging level pag info
|
logging level pag info
|
||||||
logging level l1c info
|
logging level l1c info
|
||||||
logging level l1p info
|
logging level l1p info
|
||||||
logging level dsp debug
|
logging level dsp info
|
||||||
logging level abis notice
|
logging level abis notice
|
||||||
!
|
!
|
||||||
line vty
|
line vty
|
||||||
no login
|
no login
|
||||||
!
|
!
|
||||||
|
phy 0
|
||||||
|
instance 0
|
||||||
bts 0
|
bts 0
|
||||||
band 1800
|
band 1800
|
||||||
ipa unit-id 1234 0
|
ipa unit-id 666 0
|
||||||
oml remote-ip 192.168.100.11
|
oml remote-ip 10.1.2.3
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
@@ -6,7 +6,6 @@ log stderr
|
|||||||
logging filter all 1
|
logging filter all 1
|
||||||
logging color 1
|
logging color 1
|
||||||
logging timestamp 0
|
logging timestamp 0
|
||||||
logging level all everything
|
|
||||||
logging level temp info
|
logging level temp info
|
||||||
logging level fw info
|
logging level fw info
|
||||||
logging level find info
|
logging level find info
|
||||||
35
doc/examples/trx/osmo-bts.cfg
Normal file
35
doc/examples/trx/osmo-bts.cfg
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS () configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl notice
|
||||||
|
logging level oml notice
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas error
|
||||||
|
logging level pag error
|
||||||
|
logging level l1c error
|
||||||
|
logging level l1p error
|
||||||
|
logging level dsp error
|
||||||
|
logging level abis error
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
phy 0
|
||||||
|
instance 0
|
||||||
|
osmotrx rx-gain 1
|
||||||
|
osmotrx ip local 127.0.0.1
|
||||||
|
osmotrx ip remote 127.0.0.1
|
||||||
|
bts 0
|
||||||
|
band 1800
|
||||||
|
ipa unit-id 6969 0
|
||||||
|
oml remote-ip 192.168.122.1
|
||||||
|
settsc
|
||||||
|
gsmtap-sapi ccch
|
||||||
|
gsmtap-sapi pdtch
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
151
doc/examples/virtual/openbsc-virtual.cfg
Normal file
151
doc/examples/virtual/openbsc-virtual.cfg
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
!
|
||||||
|
! OpenBSC (0.15.0.629-34f0-dirty) configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 0
|
||||||
|
logging print category 1
|
||||||
|
logging timestamp 1
|
||||||
|
logging level all info
|
||||||
|
logging level rll notice
|
||||||
|
logging level cc notice
|
||||||
|
logging level mm debug
|
||||||
|
logging level rr notice
|
||||||
|
logging level rsl notice
|
||||||
|
logging level nm info
|
||||||
|
logging level mncc notice
|
||||||
|
logging level pag notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level sccp notice
|
||||||
|
logging level msc notice
|
||||||
|
logging level mgcp notice
|
||||||
|
logging level ho notice
|
||||||
|
logging level db notice
|
||||||
|
logging level ref notice
|
||||||
|
logging level gprs debug
|
||||||
|
logging level ns info
|
||||||
|
logging level bssgp debug
|
||||||
|
logging level llc debug
|
||||||
|
logging level sndcp debug
|
||||||
|
logging level nat notice
|
||||||
|
logging level ctrl notice
|
||||||
|
logging level smpp debug
|
||||||
|
logging level filter debug
|
||||||
|
logging level ranap debug
|
||||||
|
logging level sua debug
|
||||||
|
logging level lglobal notice
|
||||||
|
logging level llapd notice
|
||||||
|
logging level linp notice
|
||||||
|
logging level lmux notice
|
||||||
|
logging level lmi notice
|
||||||
|
logging level lmib notice
|
||||||
|
logging level lsms notice
|
||||||
|
logging level lctrl notice
|
||||||
|
logging level lgtp notice
|
||||||
|
logging level lstats notice
|
||||||
|
logging level lgsup notice
|
||||||
|
logging level loap notice
|
||||||
|
!
|
||||||
|
stats interval 5
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
e1_input
|
||||||
|
e1_line 0 driver ipa
|
||||||
|
e1_line 0 port 0
|
||||||
|
no e1_line 0 keepalive
|
||||||
|
network
|
||||||
|
network country code 262
|
||||||
|
mobile network code 42
|
||||||
|
short name OpenBSC
|
||||||
|
long name OpenBSC
|
||||||
|
auth policy accept-all
|
||||||
|
authorized-regexp .*
|
||||||
|
location updating reject cause 13
|
||||||
|
encryption a5 0
|
||||||
|
neci 1
|
||||||
|
paging any use tch 0
|
||||||
|
rrlp mode ms-based
|
||||||
|
mm info 1
|
||||||
|
handover 0
|
||||||
|
handover window rxlev averaging 10
|
||||||
|
handover window rxqual averaging 1
|
||||||
|
handover window rxlev neighbor averaging 10
|
||||||
|
handover power budget interval 6
|
||||||
|
handover power budget hysteresis 3
|
||||||
|
handover maximum distance 9999
|
||||||
|
timer t3101 10
|
||||||
|
timer t3103 0
|
||||||
|
timer t3105 0
|
||||||
|
timer t3107 0
|
||||||
|
timer t3109 4
|
||||||
|
timer t3111 0
|
||||||
|
timer t3113 60
|
||||||
|
timer t3115 0
|
||||||
|
timer t3117 0
|
||||||
|
timer t3119 0
|
||||||
|
timer t3122 10
|
||||||
|
timer t3141 0
|
||||||
|
subscriber-keep-in-ram 0
|
||||||
|
bts 0
|
||||||
|
type sysmobts
|
||||||
|
band DCS1800
|
||||||
|
cell_identity 6969
|
||||||
|
location_area_code 1
|
||||||
|
base_station_id_code 63
|
||||||
|
ms max power 0
|
||||||
|
cell reselection hysteresis 4
|
||||||
|
rxlev access min 0
|
||||||
|
periodic location update 30
|
||||||
|
radio-link-timeout 32
|
||||||
|
channel allocator descending
|
||||||
|
rach tx integer 9
|
||||||
|
rach max transmission 7
|
||||||
|
channel-descrption attach 1
|
||||||
|
channel-descrption bs-pa-mfrms 5
|
||||||
|
channel-descrption bs-ag-blks-res 1
|
||||||
|
ip.access unit_id 6969 0
|
||||||
|
oml ip.access stream_id 255 line 0
|
||||||
|
neighbor-list mode automatic
|
||||||
|
codec-support fr
|
||||||
|
gprs mode none
|
||||||
|
no force-combined-si
|
||||||
|
trx 0
|
||||||
|
rf_locked 0
|
||||||
|
arfcn 666
|
||||||
|
nominal power 0
|
||||||
|
max_power_red 0
|
||||||
|
rsl e1 tei 0
|
||||||
|
timeslot 0
|
||||||
|
phys_chan_config CCCH+SDCCH4
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 1
|
||||||
|
phys_chan_config SDCCH8
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 2
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 3
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 4
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 5
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 6
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 7
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
mncc-int
|
||||||
|
default-codec tch-f fr
|
||||||
|
default-codec tch-h hr
|
||||||
|
nitb
|
||||||
|
subscriber-create-on-demand
|
||||||
|
subscriber-create-on-demand random 1 24
|
||||||
|
assign-tmsi
|
||||||
61
doc/examples/virtual/osmobts-virtual.cfg
Normal file
61
doc/examples/virtual/osmobts-virtual.cfg
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS (0.4.0.216-bc49-dirty) configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 0
|
||||||
|
logging color 0
|
||||||
|
logging print category 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl info
|
||||||
|
logging level oml info
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level pag info
|
||||||
|
logging level l1c info
|
||||||
|
logging level l1p info
|
||||||
|
logging level dsp error
|
||||||
|
logging level pcu notice
|
||||||
|
logging level ho debug
|
||||||
|
logging level trx notice
|
||||||
|
logging level loop notice
|
||||||
|
logging level abis debug
|
||||||
|
logging level rtp notice
|
||||||
|
logging level sum error
|
||||||
|
logging level lglobal notice
|
||||||
|
logging level llapd notice
|
||||||
|
logging level linp notice
|
||||||
|
logging level lmux notice
|
||||||
|
logging level lmi notice
|
||||||
|
logging level lmib notice
|
||||||
|
logging level lsms notice
|
||||||
|
logging level lctrl notice
|
||||||
|
logging level lgtp notice
|
||||||
|
logging level lstats error
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
e1_input
|
||||||
|
e1_line 0 driver ipa
|
||||||
|
e1_line 0 port 0
|
||||||
|
no e1_line 0 keepalive
|
||||||
|
phy 0
|
||||||
|
instance 0
|
||||||
|
bts 0
|
||||||
|
band DCS1800
|
||||||
|
ipa unit-id 6969 0
|
||||||
|
oml remote-ip 127.0.0.1
|
||||||
|
rtp jitter-buffer 100
|
||||||
|
paging queue-size 200
|
||||||
|
paging lifetime 0
|
||||||
|
uplink-power-target -75
|
||||||
|
min-qual-rach 50
|
||||||
|
min-qual-norm -5
|
||||||
|
trx 0
|
||||||
|
power-ramp max-initial 23000 mdBm
|
||||||
|
power-ramp step-size 2000 mdB
|
||||||
|
power-ramp step-interval 1
|
||||||
|
ms-power-control dsp
|
||||||
|
phy 0 instance 0
|
||||||
57
doc/phy_link.txt
Normal file
57
doc/phy_link.txt
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
== OsmoBTS PHY interface abstraction
|
||||||
|
|
||||||
|
The OsmoBTS PHY interface serves as an abstraction layer between given
|
||||||
|
PHY hardware and the actual logical transceivers (TRXs) of a BTS inside
|
||||||
|
the OsmoBTS code base.
|
||||||
|
|
||||||
|
|
||||||
|
=== PHY link
|
||||||
|
|
||||||
|
A PHY link is a physical connection / link towards a given PHY. This
|
||||||
|
might be, for example,
|
||||||
|
|
||||||
|
* a set of file descriptors to device nodes in the /dev/ directory
|
||||||
|
(sysmobts, litecell15)
|
||||||
|
* a packet socket for sending raw Ethernet frames to an OCTPHY
|
||||||
|
* a set of UDP sockets for interacting with OsmoTRX
|
||||||
|
|
||||||
|
Each PHY interface has a set of attribute/parameters and a list of 1 to
|
||||||
|
n PHY instances.
|
||||||
|
|
||||||
|
PHY links are numbered 0..n globally inside OsmoBTS.
|
||||||
|
|
||||||
|
Each PHY link is configured via the VTY using its individual top-level
|
||||||
|
vty node. Given the different bts-model / phy specific properties, the
|
||||||
|
VTY configuration options (if any) of the PHY instance differ between
|
||||||
|
BTS models.
|
||||||
|
|
||||||
|
The PHY links and instances must be configured above the BTS/TRX nodes
|
||||||
|
in the configuration file. If the file is saved via the VTY, the code
|
||||||
|
automatically ensures this.
|
||||||
|
|
||||||
|
|
||||||
|
=== PHY instance
|
||||||
|
|
||||||
|
A PHY instance is an instance of a PHY, accessed via a PHY link.
|
||||||
|
|
||||||
|
In the case of osmo-bts-sysmo and osmo-bts-trx, there is only one
|
||||||
|
instance in every PHY link. This is due to the fact that the API inside
|
||||||
|
that PHY link does not permit for distinguishing multiple different
|
||||||
|
logical TRXs.
|
||||||
|
|
||||||
|
Other PHY implementations like the OCTPHY however do support addressing
|
||||||
|
multiple PHY instances via a single PHY link.
|
||||||
|
|
||||||
|
PHY instances are numbered 0..n inside each PHY link.
|
||||||
|
|
||||||
|
Each PHY instance is configured via the VTY as a separate node beneath each
|
||||||
|
PHY link. Given the different bts-model / phy specific properties, the
|
||||||
|
VTY configuration options (if any) of the PHY instance differ between
|
||||||
|
BTS models.
|
||||||
|
|
||||||
|
|
||||||
|
=== Mapping PHY instances to TRXs
|
||||||
|
|
||||||
|
Each TRX node in the VTY must use the 'phy N instance M' command in
|
||||||
|
order to specify which PHY instance is allocated to this specific TRX.
|
||||||
42
doc/startup.txt
Normal file
42
doc/startup.txt
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
== start-up / sequencing during OsmoBTS start
|
||||||
|
|
||||||
|
The start-up procedure of OsmoBTS can be described as follows:
|
||||||
|
|
||||||
|
|===
|
||||||
|
| bts-specific | main() |
|
||||||
|
| common | bts_main() | initialization of talloc contexts
|
||||||
|
| common | bts_log_init() | initialization of logging
|
||||||
|
| common | handle_options() | common option parsing
|
||||||
|
| bts-specific | bts_model_handle_options() | model-specific option parsing
|
||||||
|
| common | gsm_bts_alloc() | allocation of BTS/TRX/TS data structures
|
||||||
|
| common | vty_init() | Initialziation of VTY core, libosmo-abis and osmo-bts VTY
|
||||||
|
| common | main() | Setting of scheduler RR priority (if configured)
|
||||||
|
| common | main() | Initialization of GSMTAP (if configured)
|
||||||
|
| common | bts_init() | configuration of defaults in bts/trx/s object
|
||||||
|
| bts-specific | bts_model_init | ?
|
||||||
|
| common | abis_init() | Initialization of libosmo-abis
|
||||||
|
| common | vty_read_config_file() | Reading of configuration file
|
||||||
|
| bts-specific | bts_model_phy_link_set_defaults() | Called for every PHY link created
|
||||||
|
| bts-specific | bts_model_phy_instance_set_defaults() | Called for every PHY Instance created
|
||||||
|
| 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 | 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
|
||||||
|
| bts-specific | bts_model_phy_link_open() | Open each of the configured PHY links
|
||||||
|
| common | write_pid_file() | Generate the pid file
|
||||||
|
| common | osmo_daemonize() | Fork as daemon in background (if configured)
|
||||||
|
| common | bts_main() | Run main loop until global variable quit >= 2
|
||||||
|
| bts-specific | bts_model_oml_estab() | Called by core once OML link is established
|
||||||
|
| bts-specific | bts_model_check_oml() | called each time OML sets some attributes on a MO, checks if attributes are valid
|
||||||
|
| bts-specific | bts_model_apply_oml() | called each time OML sets some attributes on a MO, stores attribute contents in data structures
|
||||||
|
| bts-specific | bts_model_opstart() | for NM_OC_BTS, NM_OC_SITE_MANAGER, NM_OC_GPRS_NSE, NM_OC_GPRS_CELL, NMO_OC_GPRS_NSVC
|
||||||
|
| bts-specific | bts_model_opstart() | for NM_OC_RADIO_CARRIER for each trx
|
||||||
|
| bts-specific | bts_model_opstart() | for NM_OC_BASEB_TRANSC for each trx
|
||||||
|
| bts-specific | bts_model_opstart() | for NM_OC_CHANNEL for each timeslot on each trx
|
||||||
|
| bts-specific | bts_model_change_power() | change transmit power for each trx (power ramp-up/ramp-down
|
||||||
|
|
||||||
|
| bts-specific | bts_model_abis_close() | called when either one of the RSL links or the OML link are down
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h logging.h measurement.h \
|
noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h logging.h measurement.h \
|
||||||
oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.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
|
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
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ void amr_log_mr_conf(int ss, int logl, const char *pfx,
|
|||||||
|
|
||||||
int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
|
int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
|
||||||
const uint8_t *mr_conf, unsigned int len);
|
const uint8_t *mr_conf, unsigned int len);
|
||||||
|
void amr_set_mode_pref(uint8_t *data, const struct amr_multirate_conf *amr_mrc,
|
||||||
|
uint8_t cmi, uint8_t cmr);
|
||||||
unsigned int amr_get_initial_mode(struct gsm_lchan *lchan);
|
unsigned int amr_get_initial_mode(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
#endif /* _OSMO_BTS_AMR_H */
|
#endif /* _OSMO_BTS_AMR_H */
|
||||||
|
|||||||
@@ -21,23 +21,29 @@ void destroy_bts(struct gsm_bts *bts);
|
|||||||
int work_bts(struct gsm_bts *bts);
|
int work_bts(struct gsm_bts *bts);
|
||||||
int bts_link_estab(struct gsm_bts *bts);
|
int bts_link_estab(struct gsm_bts *bts);
|
||||||
int trx_link_estab(struct gsm_bts_trx *trx);
|
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_new_si(void *arg);
|
||||||
void bts_setup_slot(struct gsm_bts_trx_ts *slot, uint8_t comb);
|
void bts_setup_slot(struct gsm_bts_trx_ts *slot, uint8_t comb);
|
||||||
|
|
||||||
int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg);
|
int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg);
|
||||||
struct msgb *bts_agch_dequeue(struct gsm_bts *bts);
|
struct msgb *bts_agch_dequeue(struct gsm_bts *bts);
|
||||||
void bts_update_agch_max_queue_length(struct gsm_bts *bts);
|
|
||||||
int bts_agch_max_queue_length(int T, int bcch_conf);
|
int bts_agch_max_queue_length(int T, int bcch_conf);
|
||||||
int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt,
|
int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt,
|
||||||
int is_ag_res);
|
int is_ag_res);
|
||||||
|
|
||||||
uint8_t *bts_sysinfo_get(struct gsm_bts *bts, struct gsm_time *g_time);
|
uint8_t *bts_sysinfo_get(struct gsm_bts *bts, const struct gsm_time *g_time);
|
||||||
uint8_t *lchan_sacch_get(struct gsm_lchan *lchan);
|
uint8_t *lchan_sacch_get(struct gsm_lchan *lchan);
|
||||||
int lchan_init_lapdm(struct gsm_lchan *lchan);
|
int lchan_init_lapdm(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
void load_timer_start(struct gsm_bts *bts);
|
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);
|
void bts_update_status(enum bts_global_status which, int on);
|
||||||
|
|
||||||
|
int trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx);
|
||||||
|
|
||||||
|
struct gsm_time *get_time(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
int bts_main(int argc, char **argv);
|
||||||
|
|
||||||
#endif /* _BTS_H */
|
#endif /* _BTS_H */
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,13 @@
|
|||||||
|
|
||||||
#include <osmo-bts/gsm_data.h>
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
struct phy_link;
|
||||||
|
struct phy_instance;
|
||||||
|
|
||||||
/* BTS model specific functions needed by the common code */
|
/* BTS model specific functions needed by the common code */
|
||||||
|
|
||||||
int bts_model_init(struct gsm_bts *bts);
|
int bts_model_init(struct gsm_bts *bts);
|
||||||
|
|
||||||
struct gsm_time *bts_model_get_time(struct gsm_bts *bts);
|
|
||||||
|
|
||||||
int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type,
|
int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type,
|
||||||
struct tlv_parsed *old_attr, struct tlv_parsed *new_attr,
|
struct tlv_parsed *old_attr, struct tlv_parsed *new_attr,
|
||||||
void *obj);
|
void *obj);
|
||||||
@@ -27,25 +28,37 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
|
|||||||
int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo,
|
int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo,
|
||||||
void *obj, uint8_t adm_state);
|
void *obj, uint8_t adm_state);
|
||||||
|
|
||||||
int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp);
|
|
||||||
int bts_model_rsl_chan_rel(struct gsm_lchan *lchan);
|
|
||||||
int bts_model_rsl_chan_mod(struct gsm_lchan *lchan);
|
|
||||||
int bts_model_rsl_deact_sacch(struct gsm_lchan *lchan);
|
|
||||||
int bts_model_rsl_mode_modify(struct gsm_lchan *lchan);
|
|
||||||
|
|
||||||
int bts_model_trx_deact_rf(struct gsm_bts_trx *trx);
|
int bts_model_trx_deact_rf(struct gsm_bts_trx *trx);
|
||||||
int bts_model_trx_close(struct gsm_bts_trx *trx);
|
int bts_model_trx_close(struct gsm_bts_trx *trx);
|
||||||
|
|
||||||
void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
|
|
||||||
unsigned int rtp_pl_len);
|
|
||||||
|
|
||||||
int bts_model_vty_init(struct gsm_bts *bts);
|
int bts_model_vty_init(struct gsm_bts *bts);
|
||||||
|
|
||||||
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts);
|
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts);
|
||||||
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx);
|
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx);
|
||||||
|
void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink);
|
||||||
|
void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst);
|
||||||
|
|
||||||
int bts_model_oml_estab(struct gsm_bts *bts);
|
int bts_model_oml_estab(struct gsm_bts *bts);
|
||||||
|
|
||||||
int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm);
|
int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm);
|
||||||
|
int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
|
int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap);
|
||||||
|
|
||||||
|
int bts_model_lchan_deactivate(struct gsm_lchan *lchan);
|
||||||
|
int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
|
void bts_model_abis_close(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
int bts_model_ctrl_cmds_install(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
int bts_model_handle_options(int argc, char **argv);
|
||||||
|
void bts_model_print_help();
|
||||||
|
|
||||||
|
void bts_model_phy_link_set_defaults(struct phy_link *plink);
|
||||||
|
void bts_model_phy_instance_set_defaults(struct phy_instance *pinst);
|
||||||
|
|
||||||
|
int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts);
|
||||||
|
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
16
include/osmo-bts/cbch.h
Normal file
16
include/osmo-bts/cbch.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <osmocom/gsm/gsm_utils.h>
|
||||||
|
#include <osmocom/gsm/protocol/gsm_08_58.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time);
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
int bts_ctrl_cmds_install(struct gsm_bts *bts);
|
int bts_ctrl_cmds_install(struct gsm_bts *bts);
|
||||||
struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts);
|
struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts,
|
||||||
|
const char *bind_addr, uint16_t port);
|
||||||
|
|||||||
44
include/osmo-bts/dtx_dl_amr_fsm.h
Normal file
44
include/osmo-bts/dtx_dl_amr_fsm.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <osmocom/core/fsm.h>
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
#include <osmocom/core/logging.h>
|
||||||
|
|
||||||
|
/* DTX DL AMR FSM */
|
||||||
|
|
||||||
|
#define X(s) (1 << (s))
|
||||||
|
|
||||||
|
enum dtx_dl_amr_fsm_states {
|
||||||
|
ST_VOICE,
|
||||||
|
ST_SID_F1,
|
||||||
|
ST_SID_F2,
|
||||||
|
ST_F1_INH_V,
|
||||||
|
ST_F1_INH_F,
|
||||||
|
ST_U_INH_V,
|
||||||
|
ST_U_INH_F,
|
||||||
|
ST_U_NOINH,
|
||||||
|
ST_F1_INH_V_REC,
|
||||||
|
ST_F1_INH_F_REC,
|
||||||
|
ST_U_INH_V_REC,
|
||||||
|
ST_U_INH_F_REC,
|
||||||
|
ST_SID_U,
|
||||||
|
ST_ONSET_V,
|
||||||
|
ST_ONSET_F,
|
||||||
|
ST_ONSET_V_REC,
|
||||||
|
ST_ONSET_F_REC,
|
||||||
|
ST_FACCH,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dtx_dl_amr_fsm_events {
|
||||||
|
E_VOICE,
|
||||||
|
E_ONSET,
|
||||||
|
E_FACCH,
|
||||||
|
E_COMPL,
|
||||||
|
E_FIRST,
|
||||||
|
E_INHIB,
|
||||||
|
E_SID_F,
|
||||||
|
E_SID_U,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct value_string dtx_dl_amr_fsm_event_names[];
|
||||||
|
extern struct osmo_fsm dtx_dl_amr_fsm;
|
||||||
@@ -8,12 +8,23 @@
|
|||||||
#include <osmo-bts/paging.h>
|
#include <osmo-bts/paging.h>
|
||||||
#include <osmo-bts/tx_power.h>
|
#include <osmo-bts/tx_power.h>
|
||||||
|
|
||||||
|
#define GSM_FR_BITS 260
|
||||||
|
#define GSM_EFR_BITS 244
|
||||||
|
|
||||||
|
#define GSM_FR_BYTES 33 /* TS 101318 Chapter 5.1: 260 bits + 4bit sig */
|
||||||
|
#define GSM_HR_BYTES 14 /* TS 101318 Chapter 5.2: 112 bits, no sig */
|
||||||
|
#define GSM_EFR_BYTES 31 /* TS 101318 Chapter 5.3: 244 bits + 4bit sig */
|
||||||
|
|
||||||
|
#define GSM_SUPERFRAME (26*51) /* 1326 TDMA frames */
|
||||||
|
#define GSM_HYPERFRAME (2048*GSM_SUPERFRAME) /* GSM_HYPERFRAME frames */
|
||||||
|
|
||||||
#define GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT 41
|
#define GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT 41
|
||||||
#define GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DISABLE 999999
|
#define GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DISABLE 999999
|
||||||
#define GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT 41
|
#define GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT 41
|
||||||
#define GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT 91
|
#define GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT 91
|
||||||
|
|
||||||
struct pcu_sock_state;
|
struct pcu_sock_state;
|
||||||
|
struct smscb_msg;
|
||||||
|
|
||||||
struct gsm_network {
|
struct gsm_network {
|
||||||
struct llist_head bts_list;
|
struct llist_head bts_list;
|
||||||
@@ -73,45 +84,66 @@ struct gsm_bts_role_bts {
|
|||||||
|
|
||||||
struct paging_state *paging_state;
|
struct paging_state *paging_state;
|
||||||
char *bsc_oml_host;
|
char *bsc_oml_host;
|
||||||
|
struct llist_head oml_queue;
|
||||||
unsigned int rtp_jitter_buf_ms;
|
unsigned int rtp_jitter_buf_ms;
|
||||||
|
bool rtp_jitter_adaptive;
|
||||||
struct {
|
struct {
|
||||||
uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */
|
uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */
|
||||||
} support;
|
} support;
|
||||||
struct {
|
struct {
|
||||||
uint8_t tc4_ctr;
|
uint8_t tc4_ctr;
|
||||||
} si;
|
} si;
|
||||||
uint8_t radio_link_timeout;
|
struct gsm_time gsm_time;
|
||||||
|
/* Radio Link Timeout counter. -1 disables timeout for
|
||||||
|
* lab/measurement purpose */
|
||||||
|
int radio_link_timeout;
|
||||||
|
|
||||||
|
int ul_power_target; /* Uplink Rx power target */
|
||||||
|
|
||||||
/* used by the sysmoBTS to adjust band */
|
/* used by the sysmoBTS to adjust band */
|
||||||
uint8_t auto_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;
|
||||||
|
|
||||||
|
float min_qual_rach; /* minimum quality for RACH bursts */
|
||||||
|
float min_qual_norm; /* minimum quality for normal daata */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *sock_path;
|
||||||
|
} pcu;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t last_fn;
|
||||||
|
struct timeval tv_clock;
|
||||||
|
struct osmo_timer_list fn_timer;
|
||||||
|
} vbts;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum lchan_ciph_state {
|
enum lchan_ciph_state {
|
||||||
LCHAN_CIPH_NONE,
|
LCHAN_CIPH_NONE,
|
||||||
LCHAN_CIPH_RX_REQ,
|
LCHAN_CIPH_RX_REQ,
|
||||||
LCHAN_CIPH_RX_CONF,
|
LCHAN_CIPH_RX_CONF,
|
||||||
LCHAN_CIPH_TXRX_REQ,
|
LCHAN_CIPH_RXTX_REQ,
|
||||||
LCHAN_CIPH_TXRX_CONF,
|
LCHAN_CIPH_RX_CONF_TX_REQ,
|
||||||
|
LCHAN_CIPH_RXTX_CONF,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define bts_role_bts(x) ((struct gsm_bts_role_bts *)(x)->role)
|
#define bts_role_bts(x) ((struct gsm_bts_role_bts *)(x)->role)
|
||||||
|
|
||||||
#include "openbsc/gsm_data_shared.h"
|
#include "openbsc/gsm_data_shared.h"
|
||||||
|
|
||||||
struct femtol1_hdl;
|
|
||||||
|
|
||||||
static inline struct femtol1_hdl *trx_femtol1_hdl(struct gsm_bts_trx *trx)
|
|
||||||
{
|
|
||||||
return trx->role_bts.l1h;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state);
|
void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state);
|
||||||
|
int conf_lchans_as_pchan(struct gsm_bts_trx_ts *ts,
|
||||||
|
enum gsm_phys_chan_config pchan);
|
||||||
|
|
||||||
/* cipher code */
|
/* cipher code */
|
||||||
#define CIPHER_A5(x) (1 << (x-1))
|
#define CIPHER_A5(x) (1 << (x-1))
|
||||||
|
|
||||||
int bts_supports_cipher(struct gsm_bts_role_bts *bts, int rsl_cipher);
|
int bts_supports_cipher(struct gsm_bts_role_bts *bts, int rsl_cipher);
|
||||||
|
|
||||||
|
bool ts_is_pdch(const struct gsm_bts_trx_ts *ts);
|
||||||
|
|
||||||
#endif /* _GSM_DATA_H */
|
#endif /* _GSM_DATA_H */
|
||||||
|
|||||||
96
include/osmo-bts/l1sap.h
Normal file
96
include/osmo-bts/l1sap.h
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#ifndef L1SAP_H
|
||||||
|
#define L1SAP_H
|
||||||
|
|
||||||
|
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||||
|
|
||||||
|
/* lchan link ID */
|
||||||
|
#define LID_SACCH 0x40
|
||||||
|
#define LID_DEDIC 0x00
|
||||||
|
|
||||||
|
/* timeslot and subslot from chan_nr */
|
||||||
|
#define L1SAP_CHAN2TS(chan_nr) (chan_nr & 7)
|
||||||
|
#define L1SAP_CHAN2SS_TCHH(chan_nr) ((chan_nr >> 3) & 1)
|
||||||
|
#define L1SAP_CHAN2SS_SDCCH4(chan_nr) ((chan_nr >> 3) & 3)
|
||||||
|
#define L1SAP_CHAN2SS_SDCCH8(chan_nr) ((chan_nr >> 3) & 7)
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
|
||||||
|
/* rach type from ra */
|
||||||
|
#define L1SAP_IS_PACKET_RACH(ra) ((ra & 0xf0) == 0x70 && (ra & 0x0f) != 0x0f)
|
||||||
|
|
||||||
|
/* CCCH block from frame number */
|
||||||
|
#define L1SAP_FN2CCCHBLOCK(fn) ((fn % 51) / 5 - 1)
|
||||||
|
|
||||||
|
/* PTCH layout from frame number */
|
||||||
|
#define L1SAP_FN2MACBLOCK(fn) ((fn % 52) / 4)
|
||||||
|
#define L1SAP_FN2PTCCHBLOCK(fn) ((fn / 104) & 3)
|
||||||
|
|
||||||
|
/* Calculate PTCCH occurrence, See also 3GPP TS 05.02, Clause 7, Table 6 of 9 */
|
||||||
|
#define L1SAP_IS_PTCCH(fn) (((fn % 52) == 12) || ((fn % 52) == 38))
|
||||||
|
|
||||||
|
|
||||||
|
static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = {
|
||||||
|
0x03, 0x03, 0x01, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
|
||||||
|
0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
|
||||||
|
0x2B, 0x2B, 0x2B
|
||||||
|
};
|
||||||
|
|
||||||
|
/* subslot from any chan_nr */
|
||||||
|
static inline uint8_t l1sap_chan2ss(uint8_t chan_nr)
|
||||||
|
{
|
||||||
|
if (L1SAP_IS_CHAN_SDCCH8(chan_nr))
|
||||||
|
return L1SAP_CHAN2SS_SDCCH8(chan_nr);
|
||||||
|
if (L1SAP_IS_CHAN_SDCCH4(chan_nr))
|
||||||
|
return L1SAP_CHAN2SS_SDCCH4(chan_nr);
|
||||||
|
if (L1SAP_IS_CHAN_TCHH(chan_nr))
|
||||||
|
return L1SAP_CHAN2SS_TCHH(chan_nr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsm_lchan *get_lchan_by_chan_nr(struct gsm_bts_trx *trx,
|
||||||
|
unsigned int chan_nr);
|
||||||
|
|
||||||
|
/* allocate a msgb containing a osmo_phsap_prim + optional l2 data */
|
||||||
|
struct msgb *l1sap_msgb_alloc(unsigned int l2_len);
|
||||||
|
|
||||||
|
/* any L1 prim received from bts model */
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* call-back function for incoming RTP */
|
||||||
|
void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
|
||||||
|
unsigned int rtp_pl_len, uint16_t seq_number,
|
||||||
|
uint32_t timestamp, bool marker);
|
||||||
|
|
||||||
|
/* channel control */
|
||||||
|
int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *tp);
|
||||||
|
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);
|
||||||
|
|
||||||
|
extern const struct value_string gsmtap_sapi_names[];
|
||||||
|
extern struct gsmtap_inst *gsmtap;
|
||||||
|
extern uint32_t gsmtap_sapi_mask;
|
||||||
|
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);
|
||||||
|
|
||||||
|
#define msgb_l1sap_prim(msg) ((struct osmo_phsap_prim *)(msg)->l1h)
|
||||||
|
|
||||||
|
int bts_check_for_first_ciphrd(struct gsm_lchan *lchan,
|
||||||
|
uint8_t *data, int len);
|
||||||
|
#endif /* L1SAP_H */
|
||||||
@@ -16,6 +16,8 @@ enum {
|
|||||||
DDSP,
|
DDSP,
|
||||||
DPCU,
|
DPCU,
|
||||||
DHO,
|
DHO,
|
||||||
|
DTRX,
|
||||||
|
DLOOP,
|
||||||
DABIS,
|
DABIS,
|
||||||
DRTP,
|
DRTP,
|
||||||
DSUM,
|
DSUM,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#ifndef OSMO_BTS_MEAS_H
|
#ifndef OSMO_BTS_MEAS_H
|
||||||
#define OSMO_BTS_MEAS_H
|
#define OSMO_BTS_MEAS_H
|
||||||
|
|
||||||
|
#define MEAS_MAX_TIMING_ADVANCE 63
|
||||||
|
#define MEAS_MIN_TIMING_ADVANCE 0
|
||||||
|
|
||||||
int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm);
|
int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm);
|
||||||
|
|
||||||
int trx_meas_check_compute(struct gsm_bts_trx *trx, uint32_t fn);
|
int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn);
|
||||||
|
|
||||||
/* build the 3 byte RSL uplinke measurement IE content */
|
|
||||||
int lchan_build_rsl_ul_meas(struct gsm_lchan *, uint8_t *buf);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,8 +4,24 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||||
|
|
||||||
|
#include <osmocom/codec/codec.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
struct msgb;
|
struct msgb;
|
||||||
|
|
||||||
|
/* Access 1st part of msgb control buffer */
|
||||||
|
#define rtpmsg_marker_bit(x) ((x)->cb[0])
|
||||||
|
|
||||||
|
/* Access 2nd part of msgb control buffer */
|
||||||
|
#define rtpmsg_seq(x) ((x)->cb[1])
|
||||||
|
|
||||||
|
/* Access 3rd part of msgb control buffer */
|
||||||
|
#define rtpmsg_ts(x) ((x)->cb[2])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Classification of OML message. ETSI for plain GSM 12.21
|
* Classification of OML message. ETSI for plain GSM 12.21
|
||||||
* messages and IPA/Osmo for manufacturer messages.
|
* messages and IPA/Osmo for manufacturer messages.
|
||||||
@@ -16,5 +32,17 @@ enum {
|
|||||||
OML_MSG_TYPE_OSMO,
|
OML_MSG_TYPE_OSMO,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void lchan_set_marker(bool t, struct gsm_lchan *lchan);
|
||||||
|
bool dtx_dl_amr_enabled(const struct gsm_lchan *lchan);
|
||||||
|
void dtx_dispatch(struct gsm_lchan *lchan, enum dtx_dl_amr_fsm_events e);
|
||||||
|
bool dtx_recursion(const struct gsm_lchan *lchan);
|
||||||
|
void dtx_int_signal(struct gsm_lchan *lchan);
|
||||||
|
bool dtx_is_first_p1(const struct gsm_lchan *lchan);
|
||||||
|
void dtx_cache_payload(struct gsm_lchan *lchan, const uint8_t *l1_payload,
|
||||||
|
size_t length, uint32_t fn, int update);
|
||||||
|
int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl,
|
||||||
|
size_t rtp_pl_len, uint32_t fn, uint8_t *l1_payload,
|
||||||
|
bool marker, uint8_t *len, uint8_t *ft_out);
|
||||||
|
uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn);
|
||||||
int msg_verify_ipa_structure(struct msgb *msg);
|
int msg_verify_ipa_structure(struct msgb *msg);
|
||||||
int msg_verify_oml_structure(struct msgb *msg);
|
int msg_verify_oml_structure(struct msgb *msg);
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
#ifndef _OML_H
|
#ifndef _OML_H
|
||||||
#define _OML_H
|
#define _OML_H
|
||||||
|
|
||||||
|
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||||
|
|
||||||
struct gsm_bts;
|
struct gsm_bts;
|
||||||
struct gsm_abis_mo;
|
struct gsm_abis_mo;
|
||||||
struct msgb;
|
struct msgb;
|
||||||
|
struct gsm_lchan;
|
||||||
|
|
||||||
|
|
||||||
int oml_init(void);
|
int oml_init(struct gsm_abis_mo *mo);
|
||||||
int down_oml(struct gsm_bts *bts, struct msgb *msg);
|
int down_oml(struct gsm_bts *bts, struct msgb *msg);
|
||||||
|
|
||||||
struct msgb *oml_msgb_alloc(void);
|
struct msgb *oml_msgb_alloc(void);
|
||||||
@@ -37,4 +40,11 @@ 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(struct gsm_abis_mo *mo, uint8_t orig_msg_type,
|
||||||
uint8_t cause);
|
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, ...);
|
||||||
|
|
||||||
#endif // _OML_H */
|
#endif // _OML_H */
|
||||||
|
|||||||
@@ -1,18 +1,25 @@
|
|||||||
#ifndef _PCU_IF_H
|
#ifndef _PCU_IF_H
|
||||||
#define _PCU_IF_H
|
#define _PCU_IF_H
|
||||||
|
|
||||||
|
#define PCU_SOCK_DEFAULT "/tmp/pcu_bts"
|
||||||
|
|
||||||
|
extern int pcu_direct;
|
||||||
|
|
||||||
int pcu_tx_info_ind(void);
|
int pcu_tx_info_ind(void);
|
||||||
int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
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);
|
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,
|
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,
|
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len,
|
||||||
int8_t rssi);
|
int8_t rssi, uint16_t ber10k, int16_t bto, int16_t lqual);
|
||||||
int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint8_t ra, uint32_t fn);
|
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_time_ind(uint32_t fn);
|
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_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_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len);
|
||||||
|
|
||||||
int pcu_sock_init(void);
|
int pcu_sock_init(const char *path);
|
||||||
void pcu_sock_exit(void);
|
void pcu_sock_exit(void);
|
||||||
|
|
||||||
|
bool pcu_connected(void);
|
||||||
|
|
||||||
#endif /* _PCU_IF_H */
|
#endif /* _PCU_IF_H */
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#ifndef _PCUIF_PROTO_H
|
#ifndef _PCUIF_PROTO_H
|
||||||
#define _PCUIF_PROTO_H
|
#define _PCUIF_PROTO_H
|
||||||
|
|
||||||
#define PCU_IF_VERSION 0x05
|
#include <osmocom/gsm/l1sap.h>
|
||||||
|
|
||||||
|
#define PCU_IF_VERSION 0x07
|
||||||
|
#define TXT_MAX_LEN 128
|
||||||
|
|
||||||
/* msg_type */
|
/* msg_type */
|
||||||
#define PCU_IF_MSG_DATA_REQ 0x00 /* send data to given channel */
|
#define PCU_IF_MSG_DATA_REQ 0x00 /* send data to given channel */
|
||||||
@@ -13,6 +16,7 @@
|
|||||||
#define PCU_IF_MSG_ACT_REQ 0x40 /* activate/deactivate PDCH */
|
#define PCU_IF_MSG_ACT_REQ 0x40 /* activate/deactivate PDCH */
|
||||||
#define PCU_IF_MSG_TIME_IND 0x52 /* GSM time indication */
|
#define PCU_IF_MSG_TIME_IND 0x52 /* GSM time indication */
|
||||||
#define PCU_IF_MSG_PAG_REQ 0x60 /* paging request */
|
#define PCU_IF_MSG_PAG_REQ 0x60 /* paging request */
|
||||||
|
#define PCU_IF_MSG_TXT_IND 0x70 /* Text indication for BTS */
|
||||||
|
|
||||||
/* sapi */
|
/* sapi */
|
||||||
#define PCU_IF_SAPI_RACH 0x01 /* channel request on CCCH */
|
#define PCU_IF_SAPI_RACH 0x01 /* channel request on CCCH */
|
||||||
@@ -40,6 +44,16 @@
|
|||||||
#define PCU_IF_FLAG_MCS8 (1 << 27)
|
#define PCU_IF_FLAG_MCS8 (1 << 27)
|
||||||
#define PCU_IF_FLAG_MCS9 (1 << 28)
|
#define PCU_IF_FLAG_MCS9 (1 << 28)
|
||||||
|
|
||||||
|
enum gsm_pcu_if_text_type {
|
||||||
|
PCU_VERSION,
|
||||||
|
PCU_OML_ALERT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gsm_pcu_if_txt_ind {
|
||||||
|
uint8_t type; /* gsm_pcu_if_text_type */
|
||||||
|
char text[TXT_MAX_LEN]; /* Text to be transmitted to BTS */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct gsm_pcu_if_data {
|
struct gsm_pcu_if_data {
|
||||||
uint8_t sapi;
|
uint8_t sapi;
|
||||||
uint8_t len;
|
uint8_t len;
|
||||||
@@ -50,6 +64,9 @@ struct gsm_pcu_if_data {
|
|||||||
uint8_t ts_nr;
|
uint8_t ts_nr;
|
||||||
uint8_t block_nr;
|
uint8_t block_nr;
|
||||||
int8_t rssi;
|
int8_t rssi;
|
||||||
|
uint16_t ber10k; /*!< \brief BER in units of 0.01% */
|
||||||
|
int16_t ta_offs_qbits; /* !< \brief Burst TA Offset in quarter bits */
|
||||||
|
int16_t lqual_cb; /* !< \brief Link quality in centiBel */
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct gsm_pcu_if_rts_req {
|
struct gsm_pcu_if_rts_req {
|
||||||
@@ -64,10 +81,12 @@ struct gsm_pcu_if_rts_req {
|
|||||||
|
|
||||||
struct gsm_pcu_if_rach_ind {
|
struct gsm_pcu_if_rach_ind {
|
||||||
uint8_t sapi;
|
uint8_t sapi;
|
||||||
uint8_t ra;
|
uint16_t ra;
|
||||||
int16_t qta;
|
int16_t qta;
|
||||||
uint32_t fn;
|
uint32_t fn;
|
||||||
uint16_t arfcn;
|
uint16_t arfcn;
|
||||||
|
uint8_t is_11bit;
|
||||||
|
uint8_t burst_type;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct gsm_pcu_if_info_trx {
|
struct gsm_pcu_if_info_trx {
|
||||||
@@ -143,6 +162,7 @@ struct gsm_pcu_if {
|
|||||||
struct gsm_pcu_if_data data_ind;
|
struct gsm_pcu_if_data data_ind;
|
||||||
struct gsm_pcu_if_rts_req rts_req;
|
struct gsm_pcu_if_rts_req rts_req;
|
||||||
struct gsm_pcu_if_rach_ind rach_ind;
|
struct gsm_pcu_if_rach_ind rach_ind;
|
||||||
|
struct gsm_pcu_if_txt_ind txt_ind;
|
||||||
struct gsm_pcu_if_info_ind info_ind;
|
struct gsm_pcu_if_info_ind info_ind;
|
||||||
struct gsm_pcu_if_act_req act_req;
|
struct gsm_pcu_if_act_req act_req;
|
||||||
struct gsm_pcu_if_time_ind time_ind;
|
struct gsm_pcu_if_time_ind time_ind;
|
||||||
|
|||||||
160
include/osmo-bts/phy_link.h
Normal file
160
include/osmo-bts/phy_link.h
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/scheduler.h>
|
||||||
|
|
||||||
|
#include <linux/if_packet.h>
|
||||||
|
#include "btsconfig.h"
|
||||||
|
|
||||||
|
struct gsm_bts_trx;
|
||||||
|
struct virt_um_inst;
|
||||||
|
|
||||||
|
enum phy_link_type {
|
||||||
|
PHY_LINK_T_NONE,
|
||||||
|
PHY_LINK_T_SYSMOBTS,
|
||||||
|
PHY_LINK_T_OSMOTRX,
|
||||||
|
PHY_LINK_T_VIRTUAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum phy_link_state {
|
||||||
|
PHY_LINK_SHUTDOWN,
|
||||||
|
PHY_LINK_CONNECTING,
|
||||||
|
PHY_LINK_CONNECTED,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A PHY link represents the connection to a given PHYsical layer
|
||||||
|
* implementation. That PHY link contains 1...N PHY instances, one for
|
||||||
|
* each TRX */
|
||||||
|
struct phy_link {
|
||||||
|
struct llist_head list;
|
||||||
|
int num;
|
||||||
|
enum phy_link_type type;
|
||||||
|
enum phy_link_state state;
|
||||||
|
struct llist_head instances;
|
||||||
|
char *description;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
} sysmobts;
|
||||||
|
struct {
|
||||||
|
char *local_ip;
|
||||||
|
char *remote_ip;
|
||||||
|
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;
|
||||||
|
} osmotrx;
|
||||||
|
struct {
|
||||||
|
char *mcast_dev; /* Network device for 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 */
|
||||||
|
uint16_t ms_mcast_port;
|
||||||
|
struct virt_um_inst *virt_um;
|
||||||
|
} virt;
|
||||||
|
struct {
|
||||||
|
/* MAC address of the PHY */
|
||||||
|
struct sockaddr_ll phy_addr;
|
||||||
|
/* Network device name */
|
||||||
|
char *netdev_name;
|
||||||
|
|
||||||
|
/* configuration */
|
||||||
|
uint32_t rf_port_index;
|
||||||
|
#if OCTPHY_USE_ANTENNA_ID == 1
|
||||||
|
uint32_t rx_ant_id;
|
||||||
|
uint32_t tx_ant_id;
|
||||||
|
#endif
|
||||||
|
uint32_t rx_gain_db;
|
||||||
|
bool tx_atten_flag;
|
||||||
|
uint32_t tx_atten_db;
|
||||||
|
#if OCTPHY_MULTI_TRX == 1
|
||||||
|
/* arfcn used by TRX with id 0 */
|
||||||
|
uint16_t center_arfcn;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct octphy_hdl *hdl;
|
||||||
|
} octphy;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct phy_instance {
|
||||||
|
/* liked inside phy_link.linstances */
|
||||||
|
struct llist_head list;
|
||||||
|
int num;
|
||||||
|
char *description;
|
||||||
|
char version[MAX_VERSION_LENGTH];
|
||||||
|
/* pointer to the PHY link to which we belong */
|
||||||
|
struct phy_link *phy_link;
|
||||||
|
|
||||||
|
/* back-pointer to the TRX to which we're associated */
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
/* configuration */
|
||||||
|
uint8_t clk_use_eeprom;
|
||||||
|
uint32_t dsp_trace_f;
|
||||||
|
int clk_cal;
|
||||||
|
uint8_t clk_src;
|
||||||
|
char *calib_path;
|
||||||
|
|
||||||
|
struct femtol1_hdl *hdl;
|
||||||
|
} sysmobts;
|
||||||
|
struct {
|
||||||
|
struct trx_l1h *hdl;
|
||||||
|
bool sw_act_reported;
|
||||||
|
} osmotrx;
|
||||||
|
struct {
|
||||||
|
struct l1sched_trx sched;
|
||||||
|
} virt;
|
||||||
|
struct {
|
||||||
|
/* logical transceiver number within one PHY */
|
||||||
|
uint32_t trx_id;
|
||||||
|
/* trx lock state variable */
|
||||||
|
int trx_locked;
|
||||||
|
} octphy;
|
||||||
|
struct {
|
||||||
|
/* configuration */
|
||||||
|
uint32_t dsp_trace_f;
|
||||||
|
char *calib_path;
|
||||||
|
int minTxPower;
|
||||||
|
int maxTxPower;
|
||||||
|
struct lc15l1_hdl *hdl;
|
||||||
|
uint8_t max_cell_size; /* 0:166 qbits*/
|
||||||
|
uint8_t diversity_mode; /* 0: SISO A, 1: SISO B, 2: MRC */
|
||||||
|
uint8_t pedestal_mode; /* 0: unused TS is OFF, 1: unused TS is in minimum Tx power */
|
||||||
|
uint8_t dsp_alive_period; /* DSP alive timer period */
|
||||||
|
uint8_t tx_pwr_adj_mode; /* 0: no auto adjust power, 1: auto adjust power using RMS detector */
|
||||||
|
uint8_t tx_pwr_red_8psk; /* 8-PSK maximum Tx power reduction level in dB */
|
||||||
|
} lc15;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
int phy_links_open(void);
|
||||||
|
|
||||||
|
struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num);
|
||||||
|
struct phy_instance *phy_instance_create(struct phy_link *plink, int num);
|
||||||
|
void phy_instance_link_to_trx(struct phy_instance *pinst, struct gsm_bts_trx *trx);
|
||||||
|
void phy_instance_destroy(struct phy_instance *pinst);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
OSMO_ASSERT(trx);
|
||||||
|
return trx->role_bts.l1h;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_model_phy_link_open(struct phy_link *plink);
|
||||||
7
include/osmo-bts/power_control.h
Normal file
7
include/osmo-bts/power_control.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
|
||||||
|
const uint8_t ms_power, const int rxLevel);
|
||||||
@@ -9,20 +9,27 @@ enum {
|
|||||||
LCHAN_REL_ACT_RSL,
|
LCHAN_REL_ACT_RSL,
|
||||||
LCHAN_REL_ACT_PCU,
|
LCHAN_REL_ACT_PCU,
|
||||||
LCHAN_REL_ACT_OML,
|
LCHAN_REL_ACT_OML,
|
||||||
|
LCHAN_REL_ACT_REACT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define LCHAN_FN_DUMMY 0xFFFFFFFF
|
||||||
|
#define LCHAN_FN_WAIT 0xFFFFFFFE
|
||||||
|
|
||||||
|
int msgb_queue_flush(struct llist_head *list);
|
||||||
|
|
||||||
int down_rsl(struct gsm_bts_trx *trx, struct msgb *msg);
|
int down_rsl(struct gsm_bts_trx *trx, struct msgb *msg);
|
||||||
int rsl_tx_rf_res(struct gsm_bts_trx *trx);
|
int rsl_tx_rf_res(struct gsm_bts_trx *trx);
|
||||||
int rsl_tx_chan_rqd(struct gsm_bts_trx *trx, struct gsm_time *gtime,
|
int rsl_tx_chan_rqd(struct gsm_bts_trx *trx, struct gsm_time *gtime,
|
||||||
uint8_t ra, uint8_t acc_delay);
|
uint8_t ra, uint8_t acc_delay);
|
||||||
int rsl_tx_est_ind(struct gsm_lchan *lchan, uint8_t link_id, uint8_t *data, int len);
|
int rsl_tx_est_ind(struct gsm_lchan *lchan, uint8_t link_id, uint8_t *data, int len);
|
||||||
|
|
||||||
int rsl_tx_chan_act_ack(struct gsm_lchan *lchan, struct gsm_time *gtime);
|
int rsl_tx_chan_act_acknack(struct gsm_lchan *lchan, uint8_t cause);
|
||||||
int rsl_tx_chan_act_nack(struct gsm_lchan *lchan, uint8_t cause);
|
|
||||||
int rsl_tx_conn_fail(struct gsm_lchan *lchan, uint8_t cause);
|
int rsl_tx_conn_fail(struct gsm_lchan *lchan, uint8_t cause);
|
||||||
int rsl_tx_rf_rel_ack(struct gsm_lchan *lchan);
|
int rsl_tx_rf_rel_ack(struct gsm_lchan *lchan);
|
||||||
int rsl_tx_hando_det(struct gsm_lchan *lchan, uint8_t *ho_delay);
|
int rsl_tx_hando_det(struct gsm_lchan *lchan, uint8_t *ho_delay);
|
||||||
|
|
||||||
|
int lchan_deactivate(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
/* call-back for LAPDm code, called when it wants to send msgs UP */
|
/* call-back for LAPDm code, called when it wants to send msgs UP */
|
||||||
int lapdm_rll_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx);
|
int lapdm_rll_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx);
|
||||||
|
|
||||||
@@ -31,7 +38,9 @@ int rsl_tx_ccch_load_ind_pch(struct gsm_bts *bts, uint16_t paging_avail);
|
|||||||
int rsl_tx_ccch_load_ind_rach(struct gsm_bts *bts, uint16_t total,
|
int rsl_tx_ccch_load_ind_rach(struct gsm_bts *bts, uint16_t total,
|
||||||
uint16_t busy, uint16_t access);
|
uint16_t busy, uint16_t access);
|
||||||
|
|
||||||
struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr);
|
void cb_ts_disconnected(struct gsm_bts_trx_ts *ts);
|
||||||
|
void cb_ts_connected(struct gsm_bts_trx_ts *ts);
|
||||||
|
void ipacc_dyn_pdch_complete(struct gsm_bts_trx_ts *ts, int rc);
|
||||||
|
|
||||||
#endif // _RSL_H */
|
#endif // _RSL_H */
|
||||||
|
|
||||||
|
|||||||
191
include/osmo-bts/scheduler.h
Normal file
191
include/osmo-bts/scheduler.h
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
#ifndef TRX_SCHEDULER_H
|
||||||
|
#define TRX_SCHEDULER_H
|
||||||
|
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
/* These types define the different channels on a multiframe.
|
||||||
|
* Each channel has queues and can be activated individually.
|
||||||
|
*/
|
||||||
|
enum trx_chan_type {
|
||||||
|
TRXC_IDLE = 0,
|
||||||
|
TRXC_FCCH,
|
||||||
|
TRXC_SCH,
|
||||||
|
TRXC_BCCH,
|
||||||
|
TRXC_RACH,
|
||||||
|
TRXC_CCCH,
|
||||||
|
TRXC_TCHF,
|
||||||
|
TRXC_TCHH_0,
|
||||||
|
TRXC_TCHH_1,
|
||||||
|
TRXC_SDCCH4_0,
|
||||||
|
TRXC_SDCCH4_1,
|
||||||
|
TRXC_SDCCH4_2,
|
||||||
|
TRXC_SDCCH4_3,
|
||||||
|
TRXC_SDCCH8_0,
|
||||||
|
TRXC_SDCCH8_1,
|
||||||
|
TRXC_SDCCH8_2,
|
||||||
|
TRXC_SDCCH8_3,
|
||||||
|
TRXC_SDCCH8_4,
|
||||||
|
TRXC_SDCCH8_5,
|
||||||
|
TRXC_SDCCH8_6,
|
||||||
|
TRXC_SDCCH8_7,
|
||||||
|
TRXC_SACCHTF,
|
||||||
|
TRXC_SACCHTH_0,
|
||||||
|
TRXC_SACCHTH_1,
|
||||||
|
TRXC_SACCH4_0,
|
||||||
|
TRXC_SACCH4_1,
|
||||||
|
TRXC_SACCH4_2,
|
||||||
|
TRXC_SACCH4_3,
|
||||||
|
TRXC_SACCH8_0,
|
||||||
|
TRXC_SACCH8_1,
|
||||||
|
TRXC_SACCH8_2,
|
||||||
|
TRXC_SACCH8_3,
|
||||||
|
TRXC_SACCH8_4,
|
||||||
|
TRXC_SACCH8_5,
|
||||||
|
TRXC_SACCH8_6,
|
||||||
|
TRXC_SACCH8_7,
|
||||||
|
TRXC_PDTCH,
|
||||||
|
TRXC_PTCCH,
|
||||||
|
_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
|
||||||
|
|
||||||
|
enum trx_burst_type {
|
||||||
|
TRX_BURST_GMSK,
|
||||||
|
TRX_BURST_8PSK,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* States each channel on a multiframe */
|
||||||
|
struct l1sched_chan_state {
|
||||||
|
/* scheduler */
|
||||||
|
uint8_t active; /* Channel is active */
|
||||||
|
ubit_t *dl_bursts; /* burst buffer for TX */
|
||||||
|
enum trx_burst_type dl_burst_type; /* GMSK or 8PSK burst type */
|
||||||
|
sbit_t *ul_bursts; /* burst buffer for RX */
|
||||||
|
uint32_t ul_first_fn; /* fn of first burst */
|
||||||
|
uint8_t ul_mask; /* mask of received bursts */
|
||||||
|
|
||||||
|
/* RSSI / TOA */
|
||||||
|
uint8_t rssi_num; /* number of RSSI values */
|
||||||
|
float rssi_sum; /* sum of RSSI values */
|
||||||
|
uint8_t toa_num; /* number of TOA values */
|
||||||
|
float toa_sum; /* sum of TOA values */
|
||||||
|
|
||||||
|
/* loss detection */
|
||||||
|
uint8_t lost; /* (SACCH) loss detection */
|
||||||
|
|
||||||
|
/* mode */
|
||||||
|
uint8_t rsl_cmode, tch_mode; /* mode for TCH channels */
|
||||||
|
|
||||||
|
/* AMR */
|
||||||
|
uint8_t codec[4]; /* 4 possible codecs for amr */
|
||||||
|
int codecs; /* number of possible codecs */
|
||||||
|
float ber_sum; /* sum of bit error rates */
|
||||||
|
int ber_num; /* number of bit error rates */
|
||||||
|
uint8_t ul_ft; /* current uplink FT index */
|
||||||
|
uint8_t dl_ft; /* current downlink FT index */
|
||||||
|
uint8_t ul_cmr; /* current uplink CMR index */
|
||||||
|
uint8_t dl_cmr; /* current downlink CMR index */
|
||||||
|
uint8_t amr_loop; /* if AMR loop is enabled */
|
||||||
|
|
||||||
|
/* TCH/H */
|
||||||
|
uint8_t dl_ongoing_facch; /* FACCH/H on downlink */
|
||||||
|
uint8_t ul_ongoing_facch; /* FACCH/H on uplink */
|
||||||
|
|
||||||
|
/* encryption */
|
||||||
|
int ul_encr_algo; /* A5/x encry algo downlink */
|
||||||
|
int dl_encr_algo; /* A5/x encry algo uplink */
|
||||||
|
int ul_encr_key_len;
|
||||||
|
int dl_encr_key_len;
|
||||||
|
uint8_t ul_encr_key[MAX_A5_KEY_LEN];
|
||||||
|
uint8_t dl_encr_key[MAX_A5_KEY_LEN];
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
float toa_sum; /* sum of TOA values */
|
||||||
|
int toa_num; /* number of TOA value */
|
||||||
|
} meas;
|
||||||
|
|
||||||
|
/* handover */
|
||||||
|
uint8_t ho_rach_detect; /* if rach detection is on */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct l1sched_ts {
|
||||||
|
uint8_t mf_index; /* selected multiframe index */
|
||||||
|
uint32_t mf_last_fn; /* last received frame number */
|
||||||
|
uint8_t mf_period; /* period of multiframe */
|
||||||
|
const struct trx_sched_frame *mf_frames; /* pointer to frame layout */
|
||||||
|
|
||||||
|
struct llist_head dl_prims; /* Queue primitives for TX */
|
||||||
|
|
||||||
|
/* Channel states for all logical channels */
|
||||||
|
struct l1sched_chan_state chan_state[_TRX_CHAN_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct l1sched_trx {
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
struct l1sched_ts ts[TRX_NR_TS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn);
|
||||||
|
|
||||||
|
/*! \brief how many frame numbers in advance we should send bursts to PHY */
|
||||||
|
extern uint32_t trx_clock_advance;
|
||||||
|
/*! \brief advance RTS.ind to L2 by that many clocks */
|
||||||
|
extern uint32_t trx_rts_advance;
|
||||||
|
/*! \brief last frame number as received from PHY */
|
||||||
|
extern uint32_t transceiver_last_fn;
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Initialize the scheduler data structures */
|
||||||
|
int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx);
|
||||||
|
|
||||||
|
/*! \brief De-initialize the scheduler data structures */
|
||||||
|
void trx_sched_exit(struct l1sched_trx *l1t);
|
||||||
|
|
||||||
|
/*! \brief Handle a PH-DATA.req from L2 down to L1 */
|
||||||
|
int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
|
||||||
|
|
||||||
|
/*! \brief Handle a PH-TCH.req from L2 down to L1 */
|
||||||
|
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, float toa);
|
||||||
|
|
||||||
|
/*! \brief set multiframe scheduler to given physical channel config */
|
||||||
|
int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn,
|
||||||
|
enum gsm_phys_chan_config pchan);
|
||||||
|
|
||||||
|
/*! \brief set all matching logical channels active/inactive */
|
||||||
|
int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_id,
|
||||||
|
int active);
|
||||||
|
|
||||||
|
/*! \brief set mode of all matching logical channels to given mode(s) */
|
||||||
|
int trx_sched_set_mode(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t rsl_cmode,
|
||||||
|
uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1,
|
||||||
|
uint8_t codec2, uint8_t codec3, uint8_t initial_codec,
|
||||||
|
uint8_t handover);
|
||||||
|
|
||||||
|
/*! \brief set ciphering on given logical channels */
|
||||||
|
int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink,
|
||||||
|
int algo, uint8_t *key, int key_len);
|
||||||
|
|
||||||
|
/* \brief close all logical channels and reset timeslots */
|
||||||
|
void trx_sched_reset(struct l1sched_trx *l1t);
|
||||||
|
|
||||||
|
#endif /* TRX_SCHEDULER_H */
|
||||||
88
include/osmo-bts/scheduler_backend.h
Normal file
88
include/osmo-bts/scheduler_backend.h
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef int trx_sched_rts_func(struct l1sched_trx *l1t, uint8_t tn,
|
||||||
|
uint32_t fn, enum trx_chan_type chan);
|
||||||
|
|
||||||
|
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, float toa);
|
||||||
|
|
||||||
|
struct trx_chan_desc {
|
||||||
|
/*! \brief Is this on a PDCH (PS) ? */
|
||||||
|
int pdch;
|
||||||
|
/*! \brief TRX Channel Type */
|
||||||
|
enum trx_chan_type chan;
|
||||||
|
/*! \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;
|
||||||
|
};
|
||||||
|
extern const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX];
|
||||||
|
|
||||||
|
extern const ubit_t _sched_tsc[8][26];
|
||||||
|
extern const ubit_t _sched_egprs_tsc[8][78];
|
||||||
|
const ubit_t _sched_fcch_burst[148];
|
||||||
|
const ubit_t _sched_sch_train[64];
|
||||||
|
|
||||||
|
struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, int8_t tn, uint32_t fn,
|
||||||
|
enum trx_chan_type chan);
|
||||||
|
|
||||||
|
int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||||
|
enum trx_chan_type chan, uint8_t *l2,
|
||||||
|
uint8_t l2_len, float rssi,
|
||||||
|
int16_t ta_offs_qbits, int16_t link_qual_cb,
|
||||||
|
uint16_t ber10k,
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
ubit_t *tx_fcch_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_sch_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_data_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_pdtch_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_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, float toa);
|
||||||
|
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, float toa);
|
||||||
|
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, float toa);
|
||||||
|
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, float toa);
|
||||||
|
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, float toa);
|
||||||
|
|
||||||
|
const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
|
||||||
|
uint32_t fn, uint16_t *nbits);
|
||||||
|
int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn);
|
||||||
|
void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate);
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
enum sig_subsys {
|
enum sig_subsys {
|
||||||
SS_GLOBAL,
|
SS_GLOBAL,
|
||||||
|
SS_FAIL,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum signals_global {
|
enum signals_global {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
/* PA calibration table */
|
/* PA calibration table */
|
||||||
struct pa_calibration {
|
struct pa_calibration {
|
||||||
int gain_mdB[1024]; /* gain provided at given ARFCN */
|
int delta_mdB[1024]; /* gain delta at given ARFCN */
|
||||||
/* FIXME: thermal calibration */
|
/* FIXME: thermal calibration */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,3 +74,5 @@ int get_p_trxout_actual_mdBm_lchan(struct gsm_lchan *lchan);
|
|||||||
int power_ramp_start(struct gsm_bts_trx *trx, int p_total_tgt_mdBm, int bypass);
|
int power_ramp_start(struct gsm_bts_trx *trx, int p_total_tgt_mdBm, int bypass);
|
||||||
|
|
||||||
void power_trx_change_compl(struct gsm_bts_trx *trx, int p_trxout_cur_mdBm);
|
void power_trx_change_compl(struct gsm_bts_trx *trx, int p_trxout_cur_mdBm);
|
||||||
|
|
||||||
|
int power_ramp_initial_power_mdBm(struct gsm_bts_trx *trx);
|
||||||
|
|||||||
@@ -5,17 +5,27 @@
|
|||||||
#include <osmocom/vty/command.h>
|
#include <osmocom/vty/command.h>
|
||||||
|
|
||||||
enum bts_vty_node {
|
enum bts_vty_node {
|
||||||
BTS_NODE = _LAST_OSMOVTY_NODE + 1,
|
/* PHY_NODE must come before BTS node to ensure the phy
|
||||||
|
* instances are created at the time the TRX nodes want to refer
|
||||||
|
* to them */
|
||||||
|
PHY_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||||
|
PHY_INST_NODE,
|
||||||
|
BTS_NODE,
|
||||||
TRX_NODE,
|
TRX_NODE,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct cmd_element ournode_exit_cmd;
|
extern struct cmd_element ournode_exit_cmd;
|
||||||
extern struct cmd_element ournode_end_cmd;
|
extern struct cmd_element ournode_end_cmd;
|
||||||
|
|
||||||
enum node_type bts_vty_go_parent(struct vty *vty);
|
extern struct cmd_element cfg_bts_auto_band_cmd;
|
||||||
|
extern struct cmd_element cfg_bts_no_auto_band_cmd;
|
||||||
|
|
||||||
|
struct phy_instance *vty_get_phy_instance(struct vty *vty, int phy_nr, int inst_nr);
|
||||||
|
|
||||||
|
int bts_vty_go_parent(struct vty *vty);
|
||||||
int bts_vty_is_config_node(struct vty *vty, int node);
|
int bts_vty_is_config_node(struct vty *vty, int node);
|
||||||
|
|
||||||
int bts_vty_init(const struct log_info *cat);
|
int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat);
|
||||||
|
|
||||||
extern struct vty_app_info bts_vty_info;
|
extern struct vty_app_info bts_vty_info;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
SUBDIRS = common
|
SUBDIRS = common osmo-bts-virtual
|
||||||
|
|
||||||
if ENABLE_SYSMOBTS
|
if ENABLE_SYSMOBTS
|
||||||
SUBDIRS += osmo-bts-sysmo
|
SUBDIRS += osmo-bts-sysmo
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if ENABLE_TRX
|
||||||
|
SUBDIRS += osmo-bts-trx
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_OCTPHY
|
||||||
|
SUBDIRS += osmo-bts-octphy
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_LC15BTS
|
||||||
|
SUBDIRS += osmo-bts-litecell15
|
||||||
|
endif
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(OPENBSC_INCDIR)
|
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(OPENBSC_INCDIR)
|
||||||
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOTRAU_CFLAGS)
|
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOCODEC_CFLAGS)
|
||||||
LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS)
|
LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOCODEC_LIBS)
|
||||||
|
|
||||||
noinst_LIBRARIES = libbts.a
|
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 \
|
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 \
|
rsl.c vty.c paging.c measurement.c amr.c lchan.c \
|
||||||
load_indication.c pcu_sock.c handover.c msg_utils.c \
|
load_indication.c pcu_sock.c handover.c msg_utils.c \
|
||||||
load_indication.c pcu_sock.c handover.c msg_utils.c \
|
tx_power.c bts_ctrl_commands.c bts_ctrl_lookup.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
|
||||||
|
|
||||||
|
libl1sched_a_SOURCES = scheduler.c
|
||||||
|
|||||||
@@ -47,17 +47,38 @@
|
|||||||
#include <osmo-bts/bts.h>
|
#include <osmo-bts/bts.h>
|
||||||
#include <osmo-bts/rsl.h>
|
#include <osmo-bts/rsl.h>
|
||||||
#include <osmo-bts/oml.h>
|
#include <osmo-bts/oml.h>
|
||||||
|
#include <osmo-bts/bts_model.h>
|
||||||
|
|
||||||
static struct gsm_bts *g_bts;
|
static struct gsm_bts *g_bts;
|
||||||
|
|
||||||
int abis_oml_sendmsg(struct msgb *msg)
|
int abis_oml_sendmsg(struct msgb *msg)
|
||||||
{
|
{
|
||||||
struct gsm_bts *bts = msg->trx->bts;
|
struct gsm_bts *bts = msg->trx->bts;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
|
if (!bts->oml_link) {
|
||||||
|
llist_add_tail(&msg->list, &btsb->oml_queue);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
/* osmo-bts uses msg->trx internally, but libosmo-abis uses
|
/* osmo-bts uses msg->trx internally, but libosmo-abis uses
|
||||||
* the signalling link at msg->dst */
|
* the signalling link at msg->dst */
|
||||||
msg->dst = bts->oml_link;
|
msg->dst = bts->oml_link;
|
||||||
return abis_sendmsg(msg);
|
return abis_sendmsg(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drain_oml_queue(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
struct msgb *msg, *msg2;
|
||||||
|
|
||||||
|
llist_for_each_entry_safe(msg, msg2, &btsb->oml_queue, list) {
|
||||||
|
/* osmo-bts uses msg->trx internally, but libosmo-abis uses
|
||||||
|
* the signalling link at msg->dst */
|
||||||
|
llist_del(&msg->list);
|
||||||
|
msg->dst = bts->oml_link;
|
||||||
|
abis_sendmsg(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int abis_bts_rsl_sendmsg(struct msgb *msg)
|
int abis_bts_rsl_sendmsg(struct msgb *msg)
|
||||||
@@ -72,6 +93,8 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
|
|||||||
enum e1inp_sign_type type)
|
enum e1inp_sign_type type)
|
||||||
{
|
{
|
||||||
struct e1inp_sign_link *sign_link = NULL;
|
struct e1inp_sign_link *sign_link = NULL;
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
int trx_nr;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case E1INP_SIGN_OML:
|
case E1INP_SIGN_OML:
|
||||||
@@ -80,20 +103,26 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
|
|||||||
sign_link = g_bts->oml_link =
|
sign_link = g_bts->oml_link =
|
||||||
e1inp_sign_link_create(&line->ts[E1INP_SIGN_OML-1],
|
e1inp_sign_link_create(&line->ts[E1INP_SIGN_OML-1],
|
||||||
E1INP_SIGN_OML, NULL, 255, 0);
|
E1INP_SIGN_OML, NULL, 255, 0);
|
||||||
|
drain_oml_queue(g_bts);
|
||||||
sign_link->trx = g_bts->c0;
|
sign_link->trx = g_bts->c0;
|
||||||
bts_link_estab(g_bts);
|
bts_link_estab(g_bts);
|
||||||
break;
|
break;
|
||||||
case E1INP_SIGN_RSL:
|
|
||||||
LOGP(DABIS, LOGL_INFO, "RSL Signalling link up\n");
|
|
||||||
e1inp_ts_config_sign(&line->ts[E1INP_SIGN_RSL-1], line);
|
|
||||||
sign_link = g_bts->c0->rsl_link =
|
|
||||||
e1inp_sign_link_create(&line->ts[E1INP_SIGN_RSL-1],
|
|
||||||
E1INP_SIGN_RSL, NULL, 0, 0);
|
|
||||||
/* FIXME: This assumes there is only one TRX! */
|
|
||||||
sign_link->trx = g_bts->c0;
|
|
||||||
trx_link_estab(sign_link->trx);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
|
trx_nr = type - E1INP_SIGN_RSL;
|
||||||
|
LOGP(DABIS, LOGL_INFO, "RSL Signalling link for TRX%d up\n",
|
||||||
|
trx_nr);
|
||||||
|
trx = gsm_bts_trx_num(g_bts, trx_nr);
|
||||||
|
if (!trx) {
|
||||||
|
LOGP(DABIS, LOGL_ERROR, "TRX%d does not exixt!\n",
|
||||||
|
trx_nr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
trx_link_estab(trx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,19 +131,23 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
|
|||||||
|
|
||||||
static void sign_link_down(struct e1inp_line *line)
|
static void sign_link_down(struct e1inp_line *line)
|
||||||
{
|
{
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
LOGP(DABIS, LOGL_ERROR, "Signalling link down\n");
|
LOGP(DABIS, LOGL_ERROR, "Signalling link down\n");
|
||||||
|
|
||||||
if (g_bts->c0->rsl_link) {
|
/* First remove the OML signalling link */
|
||||||
e1inp_sign_link_destroy(g_bts->c0->rsl_link);
|
|
||||||
g_bts->c0->rsl_link = NULL;
|
|
||||||
trx_link_estab(g_bts->c0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_bts->oml_link)
|
if (g_bts->oml_link)
|
||||||
e1inp_sign_link_destroy(g_bts->oml_link);
|
e1inp_sign_link_destroy(g_bts->oml_link);
|
||||||
g_bts->oml_link = NULL;
|
g_bts->oml_link = NULL;
|
||||||
|
|
||||||
bts_shutdown(g_bts, "Abis close");
|
/* Then iterate over the RSL signalling links */
|
||||||
|
llist_for_each_entry(trx, &g_bts->trx_list, list) {
|
||||||
|
if (trx->rsl_link) {
|
||||||
|
e1inp_sign_link_destroy(trx->rsl_link);
|
||||||
|
trx->rsl_link = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bts_model_abis_close(g_bts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -202,8 +235,7 @@ void abis_init(struct gsm_bts *bts)
|
|||||||
{
|
{
|
||||||
g_bts = bts;
|
g_bts = bts;
|
||||||
|
|
||||||
oml_init();
|
oml_init(&bts->mo);
|
||||||
e1inp_vty_init();
|
|
||||||
libosmo_abis_init(NULL);
|
libosmo_abis_init(NULL);
|
||||||
|
|
||||||
osmo_signal_register_handler(SS_L_INPUT, &inp_s_cbfn, bts);
|
osmo_signal_register_handler(SS_L_INPUT, &inp_s_cbfn, bts);
|
||||||
|
|||||||
@@ -16,11 +16,62 @@ void amr_log_mr_conf(int ss, int logl, const char *pfx,
|
|||||||
|
|
||||||
for (i = 0; i < amr_mrc->num_modes; i++)
|
for (i = 0; i < amr_mrc->num_modes; i++)
|
||||||
LOGPC(ss, logl, ", mode[%u] = %u/%u/%u",
|
LOGPC(ss, logl, ", mode[%u] = %u/%u/%u",
|
||||||
i, amr_mrc->mode[i].mode, amr_mrc->mode[i].threshold,
|
i, amr_mrc->bts_mode[i].mode,
|
||||||
amr_mrc->mode[i].hysteresis);
|
amr_mrc->bts_mode[i].threshold,
|
||||||
|
amr_mrc->bts_mode[i].hysteresis);
|
||||||
LOGPC(ss, logl, "\n");
|
LOGPC(ss, logl, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int get_amr_mode_idx(const struct amr_multirate_conf *amr_mrc,
|
||||||
|
uint8_t cmi)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < amr_mrc->num_modes; i++) {
|
||||||
|
if (amr_mrc->bts_mode[i].mode == cmi)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t set_cmr_mode_idx(const struct amr_multirate_conf *amr_mrc,
|
||||||
|
uint8_t cmr)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Codec Mode Request is in upper 4 bits of RTP payload header,
|
||||||
|
* and we simply copy the CMR into the CMC */
|
||||||
|
if (cmr == 0xF) {
|
||||||
|
/* FIXME: we need some state about the last codec mode */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = get_amr_mode_idx(amr_mrc, cmr);
|
||||||
|
if (rc < 0) {
|
||||||
|
/* FIXME: we need some state about the last codec mode */
|
||||||
|
LOGP(DRTP, LOGL_INFO, "RTP->L1: overriding CMR %u\n", cmr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t set_cmi_mode_idx(const struct amr_multirate_conf *amr_mrc,
|
||||||
|
uint8_t cmi)
|
||||||
|
{
|
||||||
|
int rc = get_amr_mode_idx(amr_mrc, cmi);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOGP(DRTP, LOGL_ERROR, "AMR CMI %u not part of AMR MR set\n",
|
||||||
|
cmi);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amr_set_mode_pref(uint8_t *data, const struct amr_multirate_conf *amr_mrc,
|
||||||
|
uint8_t cmi, uint8_t cmr)
|
||||||
|
{
|
||||||
|
data[0] = set_cmi_mode_idx(amr_mrc, cmi);
|
||||||
|
data[1] = set_cmr_mode_idx(amr_mrc, cmr);
|
||||||
|
}
|
||||||
|
|
||||||
/* parse a GSM 04.08 MultiRate Config IE (10.5.2.21aa) in a more
|
/* parse a GSM 04.08 MultiRate Config IE (10.5.2.21aa) in a more
|
||||||
* comfortable internal data structure */
|
* comfortable internal data structure */
|
||||||
@@ -32,7 +83,7 @@ int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
|
|||||||
int i, j = 0;
|
int i, j = 0;
|
||||||
|
|
||||||
if (mr_version != 1) {
|
if (mr_version != 1) {
|
||||||
LOGP(DRSL, LOGL_ERROR, "AMR Multirate Version %u unknonw\n",
|
LOGP(DRSL, LOGL_ERROR, "AMR Multirate Version %u unknown\n",
|
||||||
mr_version);
|
mr_version);
|
||||||
goto ret_einval;
|
goto ret_einval;
|
||||||
}
|
}
|
||||||
@@ -63,23 +114,23 @@ int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
|
|||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
if (mr_conf[1] & (1 << i)) {
|
if (mr_conf[1] & (1 << i)) {
|
||||||
amr_mrc->mode[j++].mode = i;
|
amr_mrc->bts_mode[j++].mode = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_codecs >= 2) {
|
if (num_codecs >= 2) {
|
||||||
amr_mrc->mode[0].threshold = mr_conf[1] & 0x3F;
|
amr_mrc->bts_mode[0].threshold = mr_conf[1] & 0x3F;
|
||||||
amr_mrc->mode[0].hysteresis = mr_conf[2] >> 4;
|
amr_mrc->bts_mode[0].hysteresis = mr_conf[2] >> 4;
|
||||||
}
|
}
|
||||||
if (num_codecs >= 3) {
|
if (num_codecs >= 3) {
|
||||||
amr_mrc->mode[1].threshold =
|
amr_mrc->bts_mode[1].threshold =
|
||||||
((mr_conf[2] & 0xF) << 2) | (mr_conf[3] >> 6);
|
((mr_conf[2] & 0xF) << 2) | (mr_conf[3] >> 6);
|
||||||
amr_mrc->mode[1].hysteresis = (mr_conf[3] >> 2) & 0x7;
|
amr_mrc->bts_mode[1].hysteresis = (mr_conf[3] >> 2) & 0xF;
|
||||||
}
|
}
|
||||||
if (num_codecs >= 4) {
|
if (num_codecs >= 4) {
|
||||||
amr_mrc->mode[3].threshold =
|
amr_mrc->bts_mode[2].threshold =
|
||||||
((mr_conf[3] & 0x3) << 4) | (mr_conf[4] >> 4);
|
((mr_conf[3] & 0x3) << 4) | (mr_conf[4] >> 4);
|
||||||
amr_mrc->mode[3].hysteresis = mr_conf[4] & 0xF;
|
amr_mrc->bts_mode[2].hysteresis = mr_conf[4] & 0xF;
|
||||||
}
|
}
|
||||||
|
|
||||||
return num_codecs;
|
return num_codecs;
|
||||||
@@ -94,10 +145,12 @@ ret_einval:
|
|||||||
unsigned int amr_get_initial_mode(struct gsm_lchan *lchan)
|
unsigned int amr_get_initial_mode(struct gsm_lchan *lchan)
|
||||||
{
|
{
|
||||||
struct amr_multirate_conf *amr_mrc = &lchan->tch.amr_mr;
|
struct amr_multirate_conf *amr_mrc = &lchan->tch.amr_mr;
|
||||||
|
struct gsm48_multi_rate_conf *mr_conf =
|
||||||
|
(struct gsm48_multi_rate_conf *) amr_mrc->gsm48_ie;
|
||||||
|
|
||||||
if (lchan->mr_conf.icmi) {
|
if (mr_conf->icmi) {
|
||||||
/* initial mode given, coding in TS 05.09 3.4.1 */
|
/* initial mode given, coding in TS 05.09 3.4.1 */
|
||||||
return lchan->mr_conf.smod;
|
return mr_conf->smod;
|
||||||
} else {
|
} else {
|
||||||
/* implicit rule according to TS 05.09 Chapter 3.4.3 */
|
/* implicit rule according to TS 05.09 Chapter 3.4.3 */
|
||||||
switch (amr_mrc->num_modes) {
|
switch (amr_mrc->num_modes) {
|
||||||
|
|||||||
@@ -40,10 +40,17 @@
|
|||||||
#include <osmo-bts/abis.h>
|
#include <osmo-bts/abis.h>
|
||||||
#include <osmo-bts/bts.h>
|
#include <osmo-bts/bts.h>
|
||||||
#include <osmo-bts/bts_model.h>
|
#include <osmo-bts/bts_model.h>
|
||||||
|
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||||
|
#include <osmo-bts/pcu_if.h>
|
||||||
#include <osmo-bts/rsl.h>
|
#include <osmo-bts/rsl.h>
|
||||||
#include <osmo-bts/oml.h>
|
#include <osmo-bts/oml.h>
|
||||||
#include <osmo-bts/signal.h>
|
#include <osmo-bts/signal.h>
|
||||||
|
#include <osmo-bts/dtx_dl_amr_fsm.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 */
|
||||||
|
|
||||||
|
static void bts_update_agch_max_queue_length(struct gsm_bts *bts);
|
||||||
|
|
||||||
struct gsm_network bts_gsmnet = {
|
struct gsm_network bts_gsmnet = {
|
||||||
.bts_list = { &bts_gsmnet.bts_list, &bts_gsmnet.bts_list },
|
.bts_list = { &bts_gsmnet.bts_list, &bts_gsmnet.bts_list },
|
||||||
@@ -72,12 +79,15 @@ static int bts_signal_cbfn(unsigned int subsys, unsigned int signal,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize the BTS (and TRX) data structures, called before config
|
||||||
|
* file reading */
|
||||||
int bts_init(struct gsm_bts *bts)
|
int bts_init(struct gsm_bts *bts)
|
||||||
{
|
{
|
||||||
struct gsm_bts_role_bts *btsb;
|
struct gsm_bts_role_bts *btsb;
|
||||||
struct gsm_bts_trx *trx;
|
struct gsm_bts_trx *trx;
|
||||||
int rc;
|
int rc, i;
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
|
void *tall_rtp_ctx;
|
||||||
|
|
||||||
/* add to list of BTSs */
|
/* add to list of BTSs */
|
||||||
llist_add_tail(&bts->list, &bts_gsmnet.bts_list);
|
llist_add_tail(&bts->list, &bts_gsmnet.bts_list);
|
||||||
@@ -99,6 +109,8 @@ int bts_init(struct gsm_bts *bts)
|
|||||||
|
|
||||||
/* configurable via VTY */
|
/* configurable via VTY */
|
||||||
btsb->paging_state = paging_init(btsb, 200, 0);
|
btsb->paging_state = paging_init(btsb, 200, 0);
|
||||||
|
btsb->ul_power_target = -75; /* dBm default */
|
||||||
|
btsb->rtp_jitter_adaptive = false;
|
||||||
|
|
||||||
/* configurable via OML */
|
/* configurable via OML */
|
||||||
btsb->load.ccch.load_ind_period = 112;
|
btsb->load.ccch.load_ind_period = 112;
|
||||||
@@ -107,6 +119,11 @@ int bts_init(struct gsm_bts *bts)
|
|||||||
btsb->max_ta = 63;
|
btsb->max_ta = 63;
|
||||||
btsb->ny1 = 4;
|
btsb->ny1 = 4;
|
||||||
btsb->t3105_ms = 300;
|
btsb->t3105_ms = 300;
|
||||||
|
btsb->min_qual_rach = MIN_QUAL_RACH;
|
||||||
|
btsb->min_qual_norm = MIN_QUAL_NORM;
|
||||||
|
btsb->pcu.sock_path = talloc_strdup(btsb, PCU_SOCK_DEFAULT);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(btsb->t200_ms); i++)
|
||||||
|
btsb->t200_ms[i] = oml_default_t200_ms[i];
|
||||||
|
|
||||||
/* default RADIO_LINK_TIMEOUT */
|
/* default RADIO_LINK_TIMEOUT */
|
||||||
btsb->radio_link_timeout = 32;
|
btsb->radio_link_timeout = 32;
|
||||||
@@ -136,12 +153,15 @@ int bts_init(struct gsm_bts *bts)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Default values for the power adjustments */
|
/* Default values for the power adjustments */
|
||||||
tpp->ramp.max_initial_pout_mdBm = to_mdB(23);
|
tpp->ramp.max_initial_pout_mdBm = to_mdB(0);
|
||||||
tpp->ramp.step_size_mdB = to_mdB(2);
|
tpp->ramp.step_size_mdB = to_mdB(2);
|
||||||
tpp->ramp.step_interval_sec = 1;
|
tpp->ramp.step_interval_sec = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
osmo_rtp_init(tall_bts_ctx);
|
/* allocate a talloc pool for ORTP to ensure it doesn't have to go back
|
||||||
|
* to the libc malloc all the time */
|
||||||
|
tall_rtp_ctx = talloc_pool(tall_bts_ctx, 262144);
|
||||||
|
osmo_rtp_init(tall_rtp_ctx);
|
||||||
|
|
||||||
rc = bts_model_init(bts);
|
rc = bts_model_init(bts);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
@@ -156,6 +176,11 @@ int bts_init(struct gsm_bts *bts)
|
|||||||
initialized = 1;
|
initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INIT_LLIST_HEAD(&btsb->smscb_state.queue);
|
||||||
|
INIT_LLIST_HEAD(&btsb->oml_queue);
|
||||||
|
|
||||||
|
/* register DTX DL FSM */
|
||||||
|
osmo_fsm_register(&dtx_dl_amr_fsm);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +207,7 @@ void bts_shutdown(struct gsm_bts *bts, const char *reason)
|
|||||||
LOGP(DOML, LOGL_NOTICE, "Shutting down BTS %u, Reason %s\n",
|
LOGP(DOML, LOGL_NOTICE, "Shutting down BTS %u, Reason %s\n",
|
||||||
bts->nr, reason);
|
bts->nr, reason);
|
||||||
|
|
||||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
llist_for_each_entry_reverse(trx, &bts->trx_list, list) {
|
||||||
bts_model_trx_deact_rf(trx);
|
bts_model_trx_deact_rf(trx);
|
||||||
bts_model_trx_close(trx);
|
bts_model_trx_close(trx);
|
||||||
}
|
}
|
||||||
@@ -231,6 +256,7 @@ int trx_link_estab(struct gsm_bts_trx *trx)
|
|||||||
{
|
{
|
||||||
struct e1inp_sign_link *link = trx->rsl_link;
|
struct e1inp_sign_link *link = trx->rsl_link;
|
||||||
uint8_t radio_state = link ? NM_OPSTATE_ENABLED : NM_OPSTATE_DISABLED;
|
uint8_t radio_state = link ? NM_OPSTATE_ENABLED : NM_OPSTATE_DISABLED;
|
||||||
|
int rc;
|
||||||
|
|
||||||
LOGP(DSUM, LOGL_INFO, "RSL link (TRX %02x) state changed to %s, sending Status'.\n",
|
LOGP(DSUM, LOGL_INFO, "RSL link (TRX %02x) state changed to %s, sending Status'.\n",
|
||||||
trx->nr, link ? "up" : "down");
|
trx->nr, link ? "up" : "down");
|
||||||
@@ -238,8 +264,38 @@ int trx_link_estab(struct gsm_bts_trx *trx)
|
|||||||
oml_mo_state_chg(&trx->mo, radio_state, NM_AVSTATE_OK);
|
oml_mo_state_chg(&trx->mo, radio_state, NM_AVSTATE_OK);
|
||||||
|
|
||||||
if (link)
|
if (link)
|
||||||
rsl_tx_rf_res(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);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the availability of the TRX (used by PHY driver) */
|
||||||
|
int trx_set_available(struct gsm_bts_trx *trx, int avail)
|
||||||
|
{
|
||||||
|
int tn;
|
||||||
|
|
||||||
|
LOGP(DSUM, LOGL_INFO, "TRX(%d): Setting available = %d\n",
|
||||||
|
trx->nr, avail);
|
||||||
|
if (avail) {
|
||||||
|
/* FIXME: This needs to be sorted out */
|
||||||
|
#if 0
|
||||||
|
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
|
||||||
|
oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OFF_LINE);
|
||||||
|
for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
|
||||||
|
oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED);
|
||||||
|
oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_NOT_INSTALLED);
|
||||||
|
|
||||||
|
for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
|
||||||
|
oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,6 +307,7 @@ int lchan_init_lapdm(struct gsm_lchan *lchan)
|
|||||||
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
|
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
|
||||||
lapdm_channel_set_l1(lc, NULL, lchan);
|
lapdm_channel_set_l1(lc, NULL, lchan);
|
||||||
lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
|
lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
|
||||||
|
oml_set_lchan_t200(lchan);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -297,7 +354,7 @@ int bts_agch_max_queue_length(int T, int bcch_conf)
|
|||||||
return (T + 2 * S) * ccch_rach_ratio256 / 256;
|
return (T + 2 * S) * ccch_rach_ratio256 / 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bts_update_agch_max_queue_length(struct gsm_bts *bts)
|
static void bts_update_agch_max_queue_length(struct gsm_bts *bts)
|
||||||
{
|
{
|
||||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
struct gsm48_system_information_type_3 *si3;
|
struct gsm48_system_information_type_3 *si3;
|
||||||
@@ -604,3 +661,15 @@ int bts_supports_cipher(struct gsm_bts_role_bts *bts, int rsl_cipher)
|
|||||||
sup = (1 << (rsl_cipher - 2)) & bts->support.ciphers;
|
sup = (1 << (rsl_cipher - 2)) & bts->support.ciphers;
|
||||||
return sup > 0;
|
return sup > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx)
|
||||||
|
{
|
||||||
|
return trx->ms_power_control == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsm_time *get_time(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct gsm_bts_role_bts *btsb = bts->role;
|
||||||
|
|
||||||
|
return &btsb->gsm_time;
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,11 +24,15 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||||
#include <osmocom/ctrl/control_cmd.h>
|
#include <osmocom/ctrl/control_cmd.h>
|
||||||
|
|
||||||
#include <osmo-bts/logging.h>
|
#include <osmo-bts/logging.h>
|
||||||
#include <osmo-bts/gsm_data.h>
|
#include <osmo-bts/gsm_data.h>
|
||||||
#include <osmo-bts/tx_power.h>
|
#include <osmo-bts/tx_power.h>
|
||||||
|
#include <osmo-bts/signal.h>
|
||||||
|
#include <osmo-bts/oml.h>
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
|
||||||
CTRL_CMD_DEFINE(therm_att, "thermal-attenuation");
|
CTRL_CMD_DEFINE(therm_att, "thermal-attenuation");
|
||||||
static int get_therm_att(struct ctrl_cmd *cmd, void *data)
|
static int get_therm_att(struct ctrl_cmd *cmd, void *data)
|
||||||
@@ -67,12 +71,23 @@ static int verify_therm_att(struct ctrl_cmd *cmd, const char *value, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
cmd->reply = "OK";
|
||||||
|
|
||||||
|
return CTRL_CMD_REPLY;
|
||||||
|
}
|
||||||
|
|
||||||
int bts_ctrl_cmds_install(struct gsm_bts *bts)
|
int bts_ctrl_cmds_install(struct gsm_bts *bts)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_therm_att);
|
rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_therm_att);
|
||||||
|
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_oml_alert);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,10 @@
|
|||||||
#include <osmocom/vty/command.h>
|
#include <osmocom/vty/command.h>
|
||||||
#include <osmocom/ctrl/control_if.h>
|
#include <osmocom/ctrl/control_if.h>
|
||||||
#include <osmocom/ctrl/ports.h>
|
#include <osmocom/ctrl/ports.h>
|
||||||
|
#include <osmo-bts/bts_model.h>
|
||||||
#include <osmo-bts/logging.h>
|
#include <osmo-bts/logging.h>
|
||||||
#include <osmo-bts/gsm_data.h>
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/control_if.h>
|
||||||
|
|
||||||
extern vector ctrl_node_vec;
|
extern vector ctrl_node_vec;
|
||||||
|
|
||||||
@@ -85,12 +87,14 @@ err_index:
|
|||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts)
|
struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts,
|
||||||
|
const char *bind_addr, uint16_t port)
|
||||||
{
|
{
|
||||||
struct ctrl_handle *hdl;
|
struct ctrl_handle *hdl;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
hdl = ctrl_interface_setup(bts, OSMO_CTRL_PORT_BTS, bts_ctrl_node_lookup);
|
hdl = ctrl_interface_setup_dynip(bts, bind_addr, port,
|
||||||
|
bts_ctrl_node_lookup);
|
||||||
if (!hdl)
|
if (!hdl)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -100,5 +104,12 @@ struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = bts_model_ctrl_cmds_install(bts);
|
||||||
|
if (rc) {
|
||||||
|
/* FIXME: cleanup generic control commands */
|
||||||
|
/* FIXME: close control interface */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return hdl;
|
return hdl;
|
||||||
}
|
}
|
||||||
|
|||||||
196
src/common/cbch.c
Normal file
196
src/common/cbch.c
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
/* Cell Broadcast routines */
|
||||||
|
|
||||||
|
/* (C) 2014 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 <errno.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
#include <osmocom/gsm/protocol/gsm_04_12.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
#include <osmo-bts/cbch.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
|
||||||
|
struct smscb_msg {
|
||||||
|
struct llist_head list; /* list in smscb_state.queue */
|
||||||
|
|
||||||
|
uint8_t msg[GSM412_MSG_LEN]; /* message buffer */
|
||||||
|
uint8_t next_seg; /* next segment number */
|
||||||
|
uint8_t num_segs; /* total number of segments */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_smscb_null_block(uint8_t *out)
|
||||||
|
{
|
||||||
|
struct gsm412_block_type *block_type = (struct gsm412_block_type *) out;
|
||||||
|
|
||||||
|
block_type->spare = 0;
|
||||||
|
block_type->lpd = 1;
|
||||||
|
block_type->seq_nr = GSM412_SEQ_NULL_MSG;
|
||||||
|
block_type->lb = 0;
|
||||||
|
memset(out+1, GSM_MACBLOCK_PADDING, GSM412_BLOCK_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the next block of the current CB message */
|
||||||
|
static int get_smscb_block(struct gsm_bts *bts, uint8_t *out)
|
||||||
|
{
|
||||||
|
int to_copy;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
struct gsm412_block_type *block_type;
|
||||||
|
struct smscb_msg *msg = btsb->smscb_state.cur_msg;
|
||||||
|
|
||||||
|
if (!msg) {
|
||||||
|
/* No message: Send NULL mesage */
|
||||||
|
return get_smscb_null_block(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
block_type = (struct gsm412_block_type *) out++;
|
||||||
|
|
||||||
|
/* LPD is always 01 */
|
||||||
|
block_type->spare = 0;
|
||||||
|
block_type->lpd = 1;
|
||||||
|
|
||||||
|
/* determine how much data to copy */
|
||||||
|
to_copy = GSM412_MSG_LEN - (msg->next_seg * GSM412_BLOCK_LEN);
|
||||||
|
if (to_copy > GSM412_BLOCK_LEN)
|
||||||
|
to_copy = GSM412_BLOCK_LEN;
|
||||||
|
|
||||||
|
/* copy data and increment index */
|
||||||
|
memcpy(out, &msg->msg[msg->next_seg * GSM412_BLOCK_LEN], to_copy);
|
||||||
|
|
||||||
|
/* set + increment sequence number */
|
||||||
|
block_type->seq_nr = msg->next_seg++;
|
||||||
|
|
||||||
|
/* determine if this is the last block */
|
||||||
|
if (block_type->seq_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(btsb->smscb_state.cur_msg);
|
||||||
|
btsb->smscb_state.cur_msg = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return block_type->lb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t last_block_rsl2um[4] = {
|
||||||
|
[RSL_CB_CMD_LASTBLOCK_4] = 4,
|
||||||
|
[RSL_CB_CMD_LASTBLOCK_1] = 1,
|
||||||
|
[RSL_CB_CMD_LASTBLOCK_2] = 2,
|
||||||
|
[RSL_CB_CMD_LASTBLOCK_3] = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
struct smscb_msg *scm;
|
||||||
|
|
||||||
|
if (msg_len > sizeof(scm->msg)) {
|
||||||
|
LOGP(DLSMS, LOGL_ERROR,
|
||||||
|
"Cannot process SMSCB of %u bytes (max %zu)\n",
|
||||||
|
msg_len, sizeof(scm->msg));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
scm = talloc_zero_size(bts, sizeof(*scm));
|
||||||
|
|
||||||
|
/* initialize entire message with default padding */
|
||||||
|
memset(scm->msg, GSM_MACBLOCK_PADDING, sizeof(scm->msg));
|
||||||
|
/* next segment is first segment */
|
||||||
|
scm->next_seg = 0;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
break;
|
||||||
|
case RSL_CB_CMD_TYPE_DEFAULT:
|
||||||
|
/* use def_bcast, ignore command */
|
||||||
|
/* def_bcast == 0: normal mess */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
llist_add_tail(&scm->list, &btsb->smscb_state.queue);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct smscb_msg *select_next_smscb(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct smscb_msg *msg;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
|
if (llist_empty(&btsb->smscb_state.queue))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
msg = llist_entry(btsb->smscb_state.queue.next,
|
||||||
|
struct smscb_msg, list);
|
||||||
|
|
||||||
|
llist_del(&msg->list);
|
||||||
|
|
||||||
|
return 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. */
|
||||||
|
int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time)
|
||||||
|
{
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
uint32_t fn = gsm_gsmtime2fn(g_time);
|
||||||
|
/* According to 05.02 Section 6.5.4 */
|
||||||
|
uint32_t tb = (fn / 51) % 8;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* in which TB = 4, 5, 6 and 7 */
|
||||||
|
|
||||||
|
/* The SMSCB header shall be sent in the multiframe in which TB
|
||||||
|
* = 0 for the basic, and TB = 4 for the extended cell
|
||||||
|
* broadcast channel. */
|
||||||
|
|
||||||
|
switch (tb) {
|
||||||
|
case 0:
|
||||||
|
/* select a new SMSCB message */
|
||||||
|
btsb->smscb_state.cur_msg = select_next_smscb(bts);
|
||||||
|
rc = get_smscb_block(bts, outbuf);
|
||||||
|
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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
477
src/common/dtx_dl_amr_fsm.c
Normal file
477
src/common/dtx_dl_amr_fsm.c
Normal file
@@ -0,0 +1,477 @@
|
|||||||
|
/* DTX DL AMR FSM */
|
||||||
|
|
||||||
|
/* (C) 2016 by sysmocom s.f.m.c. GmbH
|
||||||
|
*
|
||||||
|
* 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/dtx_dl_amr_fsm.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
|
||||||
|
void dtx_fsm_voice(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_VOICE:
|
||||||
|
case E_FACCH:
|
||||||
|
break;
|
||||||
|
case E_SID_F:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_SID_F1, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_SID_U:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_INHIB:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_F1_INH_V, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Inexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_sid_f1(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_SID_F:
|
||||||
|
/* FIXME: what shall we do if we get SID-FIRST _again_ (twice in a row)?
|
||||||
|
Was observed during testing, let's just ignore it for now */
|
||||||
|
break;
|
||||||
|
case E_SID_U:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_FACCH:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_F1_INH_F, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_FIRST:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_SID_F2, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_ONSET:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_sid_f2(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_FACCH:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_ONSET:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_f1_inh_v(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_F1_INH_V_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_f1_inh_f(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_F1_INH_F_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_u_inh_v(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_INH_V_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_u_inh_f(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_INH_F_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_f1_inh_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_VOICE:
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_f1_inh_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_FACCH:
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_u_inh_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_VOICE:
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_u_inh_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_FACCH:
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_u_noinh(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_FACCH:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_VOICE:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_SID_U, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_SID_U:
|
||||||
|
case E_SID_F:
|
||||||
|
/* FIXME: what shall we do if we get SID-FIRST _after_ sending SID-UPDATE?
|
||||||
|
Was observed during testing, let's just ignore it for now */
|
||||||
|
break;
|
||||||
|
case E_ONSET:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_sid_upd(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_FACCH:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_INH_F, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_VOICE:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_INHIB:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_INH_V, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_SID_U:
|
||||||
|
case E_SID_F:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_onset_v(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_V_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_onset_f(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_F_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_onset_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_onset_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_facch(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_SID_U:
|
||||||
|
case E_SID_F:
|
||||||
|
case E_FACCH:
|
||||||
|
break;
|
||||||
|
case E_VOICE:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_SID_F1, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct osmo_fsm_state dtx_dl_amr_fsm_states[] = {
|
||||||
|
/* default state for non-DTX and DTX when SPEECH is in progress */
|
||||||
|
[ST_VOICE] = {
|
||||||
|
.in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_VOICE) | X(E_FACCH) | X(E_INHIB),
|
||||||
|
.out_state_mask = X(ST_SID_F1) | X(ST_U_NOINH) | X(ST_F1_INH_V),
|
||||||
|
.name = "Voice",
|
||||||
|
.action = dtx_fsm_voice,
|
||||||
|
},
|
||||||
|
/* SID-FIRST or SID-FIRST-P1 in case of AMR HR:
|
||||||
|
start of silence period (might be interrupted in case of AMR HR) */
|
||||||
|
[ST_SID_F1]= {
|
||||||
|
.in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_FACCH) | X(E_FIRST) | X(E_ONSET),
|
||||||
|
.out_state_mask = X(ST_U_NOINH) | X(ST_ONSET_F) | X(ST_SID_F2) | X(ST_ONSET_V),
|
||||||
|
.name = "SID-FIRST (P1)",
|
||||||
|
.action = dtx_fsm_sid_f1,
|
||||||
|
},
|
||||||
|
/* SID-FIRST P2 (only for AMR HR):
|
||||||
|
actual start of silence period in case of AMR HR */
|
||||||
|
[ST_SID_F2]= {
|
||||||
|
.in_event_mask = X(E_COMPL) | X(E_FACCH) | X(E_ONSET),
|
||||||
|
.out_state_mask = X(ST_U_NOINH) | X(ST_ONSET_F) | X(ST_ONSET_V),
|
||||||
|
.name = "SID-FIRST (P2)",
|
||||||
|
.action = dtx_fsm_sid_f2,
|
||||||
|
},
|
||||||
|
/* SID-FIRST Inhibited: incoming SPEECH (only for AMR HR) */
|
||||||
|
[ST_F1_INH_V]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_F1_INH_V_REC),
|
||||||
|
.name = "SID-FIRST (Inh, SPEECH)",
|
||||||
|
.action = dtx_fsm_f1_inh_v,
|
||||||
|
},
|
||||||
|
/* SID-FIRST Inhibited: incoming FACCH frame (only for AMR HR) */
|
||||||
|
[ST_F1_INH_F]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_F1_INH_F_REC),
|
||||||
|
.name = "SID-FIRST (Inh, FACCH)",
|
||||||
|
.action = dtx_fsm_f1_inh_f,
|
||||||
|
},
|
||||||
|
/* SID-UPDATE Inhibited: incoming SPEECH (only for AMR HR) */
|
||||||
|
[ST_U_INH_V]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_U_INH_V_REC),
|
||||||
|
.name = "SID-UPDATE (Inh, SPEECH)",
|
||||||
|
.action = dtx_fsm_u_inh_v,
|
||||||
|
},
|
||||||
|
/* SID-UPDATE Inhibited: incoming FACCH frame (only for AMR HR) */
|
||||||
|
[ST_U_INH_F]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_U_INH_F_REC),
|
||||||
|
.name = "SID-UPDATE (Inh, FACCH)",
|
||||||
|
.action = dtx_fsm_u_inh_f,
|
||||||
|
},
|
||||||
|
/* SID-UPDATE: Inhibited not allowed (only for AMR HR) */
|
||||||
|
[ST_U_NOINH]= {
|
||||||
|
.in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_COMPL) | X(E_SID_U) | X(E_SID_F) | X(E_ONSET),
|
||||||
|
.out_state_mask = X(ST_ONSET_F) | X(ST_VOICE) | X(ST_SID_U) | X(ST_ONSET_V),
|
||||||
|
.name = "SID-UPDATE (NoInh)",
|
||||||
|
.action = dtx_fsm_u_noinh,
|
||||||
|
},
|
||||||
|
/* SID-FIRST Inhibition recursion in progress:
|
||||||
|
Inhibit itself was already sent, now have to send the voice that caused it */
|
||||||
|
[ST_F1_INH_V_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL) | X(E_VOICE),
|
||||||
|
.out_state_mask = X(ST_VOICE),
|
||||||
|
.name = "SID-FIRST (Inh, SPEECH, Rec)",
|
||||||
|
.action = dtx_fsm_f1_inh_v_rec,
|
||||||
|
},
|
||||||
|
/* SID-FIRST Inhibition recursion in progress:
|
||||||
|
Inhibit itself was already sent, now have to send the data that caused it */
|
||||||
|
[ST_F1_INH_F_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL) | X(E_FACCH),
|
||||||
|
.out_state_mask = X(ST_FACCH),
|
||||||
|
.name = "SID-FIRST (Inh, FACCH, Rec)",
|
||||||
|
.action = dtx_fsm_f1_inh_f_rec,
|
||||||
|
},
|
||||||
|
/* SID-UPDATE Inhibition recursion in progress:
|
||||||
|
Inhibit itself was already sent, now have to send the voice that caused it */
|
||||||
|
[ST_U_INH_V_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL) | X(E_VOICE),
|
||||||
|
.out_state_mask = X(ST_VOICE),
|
||||||
|
.name = "SID-UPDATE (Inh, SPEECH, Rec)",
|
||||||
|
.action = dtx_fsm_u_inh_v_rec,
|
||||||
|
},
|
||||||
|
/* SID-UPDATE Inhibition recursion in progress:
|
||||||
|
Inhibit itself was already sent, now have to send the data that caused it */
|
||||||
|
[ST_U_INH_F_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL) | X(E_FACCH),
|
||||||
|
.out_state_mask = X(ST_FACCH),
|
||||||
|
.name = "SID-UPDATE (Inh, FACCH, Rec)",
|
||||||
|
.action = dtx_fsm_u_inh_f_rec,
|
||||||
|
},
|
||||||
|
/* Silence period with periodic comfort noise data updates */
|
||||||
|
[ST_SID_U]= {
|
||||||
|
.in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_INHIB) | X(E_SID_U) | X(E_SID_F),
|
||||||
|
.out_state_mask = X(ST_ONSET_F) | X(ST_VOICE) | X(ST_U_INH_V) | X(ST_U_INH_F) | X(ST_U_NOINH),
|
||||||
|
.name = "SID-UPDATE (AMR/HR)",
|
||||||
|
.action = dtx_fsm_sid_upd,
|
||||||
|
},
|
||||||
|
/* ONSET - end of silent period due to incoming SPEECH frame */
|
||||||
|
[ST_ONSET_V]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_ONSET_V_REC),
|
||||||
|
.name = "ONSET (SPEECH)",
|
||||||
|
.action = dtx_fsm_onset_v,
|
||||||
|
},
|
||||||
|
/* ONSET - end of silent period due to incoming FACCH frame */
|
||||||
|
[ST_ONSET_F]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_ONSET_F_REC),
|
||||||
|
.name = "ONSET (FACCH)",
|
||||||
|
.action = dtx_fsm_onset_f,
|
||||||
|
},
|
||||||
|
/* ONSET recursion in progress:
|
||||||
|
ONSET itself was already sent, now have to send the voice that caused it */
|
||||||
|
[ST_ONSET_V_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_VOICE),
|
||||||
|
.name = "ONSET (SPEECH, Rec)",
|
||||||
|
.action = dtx_fsm_onset_v_rec,
|
||||||
|
},
|
||||||
|
/* ONSET recursion in progress:
|
||||||
|
ONSET itself was already sent, now have to send the data that caused it */
|
||||||
|
[ST_ONSET_F_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_FACCH),
|
||||||
|
.name = "ONSET (FACCH, Rec)",
|
||||||
|
.action = dtx_fsm_onset_f_rec,
|
||||||
|
},
|
||||||
|
/* FACCH sending state */
|
||||||
|
[ST_FACCH]= {
|
||||||
|
.in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_COMPL) | X(E_SID_U) | X(E_SID_F),
|
||||||
|
.out_state_mask = X(ST_VOICE) | X(ST_SID_F1),
|
||||||
|
.name = "FACCH",
|
||||||
|
.action = dtx_fsm_facch,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct value_string dtx_dl_amr_fsm_event_names[] = {
|
||||||
|
{ E_VOICE, "Voice" },
|
||||||
|
{ E_ONSET, "ONSET" },
|
||||||
|
{ E_FACCH, "FACCH" },
|
||||||
|
{ E_COMPL, "Complete" },
|
||||||
|
{ E_FIRST, "FIRST P1->P2" },
|
||||||
|
{ E_INHIB, "Inhibit" },
|
||||||
|
{ E_SID_F, "SID-FIRST" },
|
||||||
|
{ E_SID_U, "SID-UPDATE" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct osmo_fsm dtx_dl_amr_fsm = {
|
||||||
|
.name = "DTX DL AMR FSM",
|
||||||
|
.states = dtx_dl_amr_fsm_states,
|
||||||
|
.num_states = ARRAY_SIZE(dtx_dl_amr_fsm_states),
|
||||||
|
.event_names = dtx_dl_amr_fsm_event_names,
|
||||||
|
.log_subsys = DL1C,
|
||||||
|
};
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <osmo-bts/rsl.h>
|
#include <osmo-bts/rsl.h>
|
||||||
#include <osmo-bts/logging.h>
|
#include <osmo-bts/logging.h>
|
||||||
#include <osmo-bts/handover.h>
|
#include <osmo-bts/handover.h>
|
||||||
|
#include <osmo-bts/l1sap.h>
|
||||||
|
|
||||||
/* Transmit a handover related PHYS INFO on given lchan */
|
/* Transmit a handover related PHYS INFO on given lchan */
|
||||||
static int ho_tx_phys_info(struct gsm_lchan *lchan)
|
static int ho_tx_phys_info(struct gsm_lchan *lchan)
|
||||||
@@ -105,16 +106,24 @@ void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
|
|||||||
return;
|
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));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LOGP(DHO, LOGL_NOTICE,
|
LOGP(DHO, LOGL_NOTICE,
|
||||||
"%s RACH on dedicated channel received with TA=%u\n",
|
"%s RACH on dedicated channel type %s received with TA=%u, ref=%u\n",
|
||||||
gsm_lchan_name(lchan), acc_delay);
|
gsm_lchan_name(lchan), gsm_lchant_name(lchan->type), acc_delay, ra);
|
||||||
|
|
||||||
/* Set timing advance */
|
/* Set timing advance */
|
||||||
lchan->rqd_ta = acc_delay;
|
lchan->rqd_ta = acc_delay;
|
||||||
|
|
||||||
/* Stop handover detection, wait for valid frame */
|
/* Stop handover detection, wait for valid frame */
|
||||||
lchan->ho.active = HANDOVER_WAIT_FRAME;
|
lchan->ho.active = HANDOVER_WAIT_FRAME;
|
||||||
if (bts_model_rsl_chan_mod(lchan) != 0) {
|
if (l1sap_chan_modify(lchan->ts->trx, gsm_lchan2chan_nr(lchan)) != 0) {
|
||||||
LOGP(DHO, LOGL_ERROR,
|
LOGP(DHO, LOGL_ERROR,
|
||||||
"%s failed to modify channel after handover\n",
|
"%s failed to modify channel after handover\n",
|
||||||
gsm_lchan_name(lchan));
|
gsm_lchan_name(lchan));
|
||||||
|
|||||||
1396
src/common/l1sap.c
Normal file
1396
src/common/l1sap.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -19,9 +19,31 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <osmocom/core/logging.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
#include <osmo-bts/gsm_data.h>
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state)
|
void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state)
|
||||||
{
|
{
|
||||||
|
DEBUGP(DL1C, "%s state %s -> %s\n",
|
||||||
|
gsm_lchan_name(lchan),
|
||||||
|
gsm_lchans_name(lchan->state),
|
||||||
|
gsm_lchans_name(state));
|
||||||
lchan->state = state;
|
lchan->state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ts_is_pdch(const struct gsm_bts_trx_ts *ts)
|
||||||
|
{
|
||||||
|
switch (ts->pchan) {
|
||||||
|
case GSM_PCHAN_PDCH:
|
||||||
|
return true;
|
||||||
|
case GSM_PCHAN_TCH_F_PDCH:
|
||||||
|
return (ts->flags & TS_F_PDCH_ACTIVE)
|
||||||
|
&& !(ts->flags & TS_F_PDCH_PENDING_MASK);
|
||||||
|
case GSM_PCHAN_TCH_F_TCH_H_PDCH:
|
||||||
|
return ts->dyn.pchan_is == GSM_PCHAN_PDCH
|
||||||
|
&& ts->dyn.pchan_want == ts->dyn.pchan_is;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -107,6 +107,18 @@ static struct log_info_cat bts_log_info_cat[] = {
|
|||||||
.color = "\033[0;37m",
|
.color = "\033[0;37m",
|
||||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
},
|
},
|
||||||
|
[DTRX] = {
|
||||||
|
.name = "DTRX",
|
||||||
|
.description = "TRX interface",
|
||||||
|
.color = "\033[1;33m",
|
||||||
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
|
},
|
||||||
|
[DLOOP] = {
|
||||||
|
.name = "DLOOP",
|
||||||
|
.description = "Control loops",
|
||||||
|
.color = "\033[0;34m",
|
||||||
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
|
},
|
||||||
#if 0
|
#if 0
|
||||||
[DNS] = {
|
[DNS] = {
|
||||||
.name = "DNS",
|
.name = "DNS",
|
||||||
@@ -124,6 +136,12 @@ static struct log_info_cat bts_log_info_cat[] = {
|
|||||||
.enabled = 1, .loglevel = LOGL_DEBUG,
|
.enabled = 1, .loglevel = LOGL_DEBUG,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
[DSUM] = {
|
||||||
|
.name = "DSUM",
|
||||||
|
.description = "DSUM",
|
||||||
|
.loglevel = LOGL_NOTICE,
|
||||||
|
.enabled = 1,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct log_info bts_log_info = {
|
const struct log_info bts_log_info = {
|
||||||
|
|||||||
365
src/common/main.c
Normal file
365
src/common/main.c
Normal file
@@ -0,0 +1,365 @@
|
|||||||
|
/* Main program for Osmocom BTS */
|
||||||
|
|
||||||
|
/* (C) 2011-2016 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sched.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/talloc.h>
|
||||||
|
#include <osmocom/core/application.h>
|
||||||
|
#include <osmocom/vty/telnet_interface.h>
|
||||||
|
#include <osmocom/vty/logging.h>
|
||||||
|
#include <osmocom/core/gsmtap_util.h>
|
||||||
|
#include <osmocom/core/gsmtap.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/phy_link.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/abis.h>
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
#include <osmo-bts/vty.h>
|
||||||
|
#include <osmo-bts/l1sap.h>
|
||||||
|
#include <osmo-bts/bts_model.h>
|
||||||
|
#include <osmo-bts/pcu_if.h>
|
||||||
|
#include <osmo-bts/control_if.h>
|
||||||
|
#include <osmocom/ctrl/control_if.h>
|
||||||
|
#include <osmocom/ctrl/ports.h>
|
||||||
|
#include <osmocom/ctrl/control_vty.h>
|
||||||
|
#include <osmo-bts/oml.h>
|
||||||
|
|
||||||
|
int quit = 0;
|
||||||
|
static const char *config_file = "osmo-bts.cfg";
|
||||||
|
static int daemonize = 0;
|
||||||
|
static int rt_prio = -1;
|
||||||
|
static int trx_num = 1;
|
||||||
|
static char *gsmtap_ip = 0;
|
||||||
|
extern int g_vty_port_num;
|
||||||
|
|
||||||
|
static void print_help()
|
||||||
|
{
|
||||||
|
printf( "Some useful options:\n"
|
||||||
|
" -h --help this text\n"
|
||||||
|
" -d --debug MASK Enable debugging (e.g. -d DRSL:DOML:DLAPDM)\n"
|
||||||
|
" -D --daemonize For the process into a background daemon\n"
|
||||||
|
" -c --config-file Specify the filename of the config file\n"
|
||||||
|
" -s --disable-color Don't use colors in stderr log output\n"
|
||||||
|
" -T --timestamp Prefix every log line with a timestamp\n"
|
||||||
|
" -V --version Print version information and exit\n"
|
||||||
|
" -e --log-level Set a global log-level\n"
|
||||||
|
" -r --realtime PRIO Use SCHED_RR with the specified priority\n"
|
||||||
|
" -i --gsmtap-ip The destination IP used for GSMTAP.\n"
|
||||||
|
" -t --trx-num Set number of TRX (default=%d)\n",
|
||||||
|
trx_num
|
||||||
|
);
|
||||||
|
bts_model_print_help();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: finally get some option parsing code into libosmocore */
|
||||||
|
static void handle_options(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *argv_out[argc];
|
||||||
|
int argc_out = 0;
|
||||||
|
|
||||||
|
argv_out[argc_out++] = argv[0];
|
||||||
|
|
||||||
|
/* disable generation of error messages on encountering unknown
|
||||||
|
* options */
|
||||||
|
opterr = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int option_idx = 0, c;
|
||||||
|
static const struct option long_options[] = {
|
||||||
|
/* FIXME: all those are generic Osmocom app options */
|
||||||
|
{ "help", 0, 0, 'h' },
|
||||||
|
{ "debug", 1, 0, 'd' },
|
||||||
|
{ "daemonize", 0, 0, 'D' },
|
||||||
|
{ "config-file", 1, 0, 'c' },
|
||||||
|
{ "disable-color", 0, 0, 's' },
|
||||||
|
{ "timestamp", 0, 0, 'T' },
|
||||||
|
{ "version", 0, 0, 'V' },
|
||||||
|
{ "log-level", 1, 0, 'e' },
|
||||||
|
/* FIXME: generic BTS app options */
|
||||||
|
{ "gsmtap-ip", 1, 0, 'i' },
|
||||||
|
{ "trx-num", 1, 0, 't' },
|
||||||
|
{ "realtime", 1, 0, 'r' },
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
c = getopt_long(argc, argv, "-hc:d:Dc:sTVe:i:t:r:",
|
||||||
|
long_options, &option_idx);
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
print_help();
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
log_set_use_color(osmo_stderr_target, 0);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
log_parse_category_mask(osmo_stderr_target, optarg);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
daemonize = 1;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
config_file = optarg;
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
log_set_print_timestamp(osmo_stderr_target, 1);
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
print_version(1);
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
log_set_log_level(osmo_stderr_target, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
rt_prio = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
gsmtap_ip = optarg;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
trx_num = atoi(optarg);
|
||||||
|
if (trx_num < 1)
|
||||||
|
trx_num = 1;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
case 1:
|
||||||
|
/* prepare argv[] for bts_model */
|
||||||
|
argv_out[argc_out++] = argv[optind-1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* re-set opt-ind for new parsig round */
|
||||||
|
optind = 1;
|
||||||
|
/* enable error-checking for the following getopt call */
|
||||||
|
opterr = 1;
|
||||||
|
if (bts_model_handle_options(argc_out, argv_out)) {
|
||||||
|
print_help();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct gsm_bts *bts;
|
||||||
|
|
||||||
|
static void signal_handler(int signal)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "signal %u received\n", signal);
|
||||||
|
|
||||||
|
switch (signal) {
|
||||||
|
case SIGINT:
|
||||||
|
case SIGTERM:
|
||||||
|
if (!quit) {
|
||||||
|
oml_fail_rep(OSMO_EVT_CRIT_PROC_STOP,
|
||||||
|
"BTS: SIGINT received -> shutdown");
|
||||||
|
bts_shutdown(bts, "SIGINT");
|
||||||
|
}
|
||||||
|
quit++;
|
||||||
|
break;
|
||||||
|
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:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_pid_file(char *procname)
|
||||||
|
{
|
||||||
|
FILE *outf;
|
||||||
|
char tmp[PATH_MAX+1];
|
||||||
|
|
||||||
|
snprintf(tmp, sizeof(tmp)-1, "/var/run/%s.pid", procname);
|
||||||
|
tmp[PATH_MAX-1] = '\0';
|
||||||
|
|
||||||
|
outf = fopen(tmp, "w");
|
||||||
|
if (!outf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fprintf(outf, "%d\n", getpid());
|
||||||
|
|
||||||
|
fclose(outf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct gsm_bts_role_bts *btsb;
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
struct e1inp_line *line;
|
||||||
|
int rc, i;
|
||||||
|
|
||||||
|
printf("((*))\n |\n / \\ OsmoBTS\n");
|
||||||
|
|
||||||
|
tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context");
|
||||||
|
msgb_talloc_ctx_init(tall_bts_ctx, 100*1024);
|
||||||
|
|
||||||
|
bts_log_init(NULL);
|
||||||
|
vty_init(&bts_vty_info);
|
||||||
|
ctrl_vty_init(tall_bts_ctx);
|
||||||
|
|
||||||
|
handle_options(argc, argv);
|
||||||
|
|
||||||
|
bts = gsm_bts_alloc(tall_bts_ctx, 0);
|
||||||
|
if (!bts) {
|
||||||
|
fprintf(stderr, "Failed to create BTS structure\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
for (i = 1; i < trx_num; i++) {
|
||||||
|
trx = gsm_bts_trx_alloc(bts);
|
||||||
|
if (!trx) {
|
||||||
|
fprintf(stderr, "Failed to create TRX structure\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e1inp_vty_init();
|
||||||
|
bts_vty_init(bts, &bts_log_info);
|
||||||
|
|
||||||
|
/* enable realtime priority for us */
|
||||||
|
if (rt_prio != -1) {
|
||||||
|
struct sched_param param;
|
||||||
|
|
||||||
|
memset(¶m, 0, sizeof(param));
|
||||||
|
param.sched_priority = rt_prio;
|
||||||
|
rc = sched_setscheduler(getpid(), SCHED_RR, ¶m);
|
||||||
|
if (rc != 0) {
|
||||||
|
fprintf(stderr, "Setting SCHED_RR priority(%d) failed: %s\n",
|
||||||
|
param.sched_priority, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gsmtap_ip) {
|
||||||
|
gsmtap = gsmtap_source_init(gsmtap_ip, GSMTAP_UDP_PORT, 1);
|
||||||
|
if (!gsmtap) {
|
||||||
|
fprintf(stderr, "Failed during gsmtap_init()\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
gsmtap_source_add_sink(gsmtap);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bts_init(bts) < 0) {
|
||||||
|
fprintf(stderr, "unable to open bts\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
|
abis_init(bts);
|
||||||
|
|
||||||
|
rc = vty_read_config_file(config_file, NULL);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "Failed to parse the config file: '%s'\n",
|
||||||
|
config_file);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!phy_link_by_num(0)) {
|
||||||
|
fprintf(stderr, "You need to configure at least phy0\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||||
|
if (!trx->role_bts.l1h) {
|
||||||
|
fprintf(stderr, "TRX %u has no associated PHY instance\n",
|
||||||
|
trx->nr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_pid_file("osmo-bts");
|
||||||
|
|
||||||
|
bts_controlif_setup(bts, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_BTS);
|
||||||
|
|
||||||
|
rc = telnet_init_dynif(tall_bts_ctx, NULL, vty_get_bind_addr(),
|
||||||
|
g_vty_port_num);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "Error initializing telnet\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcu_sock_init(btsb->pcu.sock_path)) {
|
||||||
|
fprintf(stderr, "PCU L1 socket failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
signal(SIGINT, &signal_handler);
|
||||||
|
signal(SIGTERM, &signal_handler);
|
||||||
|
//signal(SIGABRT, &signal_handler);
|
||||||
|
signal(SIGUSR1, &signal_handler);
|
||||||
|
signal(SIGUSR2, &signal_handler);
|
||||||
|
osmo_init_ignore_signals();
|
||||||
|
|
||||||
|
if (!btsb->bsc_oml_host) {
|
||||||
|
fprintf(stderr, "Cannot start BTS without knowing BSC OML IP\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
line = abis_open(bts, btsb->bsc_oml_host, "sysmoBTS");
|
||||||
|
if (!line) {
|
||||||
|
fprintf(stderr, "unable to connect to BSC\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = phy_links_open();
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "unable ot open PHY link(s)\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daemonize) {
|
||||||
|
rc = osmo_daemonize();
|
||||||
|
if (rc < 0) {
|
||||||
|
perror("Error during daemonize");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (quit < 2) {
|
||||||
|
log_reset_context();
|
||||||
|
osmo_select_main(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
@@ -8,19 +8,42 @@
|
|||||||
#include <osmo-bts/logging.h>
|
#include <osmo-bts/logging.h>
|
||||||
#include <osmo-bts/measurement.h>
|
#include <osmo-bts/measurement.h>
|
||||||
|
|
||||||
/* TS 05.08, Chapter 8.4.1 */
|
/* Measurment reporting period and mapping of SACCH message block for TCHF
|
||||||
/* measurement period ends at fn % 104 == ? */
|
* and TCHH chan As per in 3GPP TS 45.008, secton 8.4.1.
|
||||||
|
*
|
||||||
|
* Timeslot number (TN) TDMA frame number (FN) modulo 104
|
||||||
|
* Half rate, Half rate, Reporting SACCH
|
||||||
|
* Full Rate subch.0 subch.1 period Message block
|
||||||
|
* 0 0 and 1 0 to 103 12, 38, 64, 90
|
||||||
|
* 1 0 and 1 13 to 12 25, 51, 77, 103
|
||||||
|
* 2 2 and 3 26 to 25 38, 64, 90, 12
|
||||||
|
* 3 2 and 3 39 to 38 51, 77, 103, 25
|
||||||
|
* 4 4 and 5 52 to 51 64, 90, 12, 38
|
||||||
|
* 5 4 and 5 65 to 64 77, 103, 25, 51
|
||||||
|
* 6 6 and 7 78 to 77 90, 12, 38, 64
|
||||||
|
* 7 6 and 7 91 to 90 103, 25, 51, 77 */
|
||||||
|
|
||||||
static const uint8_t tchf_meas_rep_fn104[] = {
|
static const uint8_t tchf_meas_rep_fn104[] = {
|
||||||
[0] = 103,
|
[0] = 90,
|
||||||
[1] = 12,
|
[1] = 103,
|
||||||
[2] = 25,
|
[2] = 12,
|
||||||
[3] = 38,
|
[3] = 25,
|
||||||
[4] = 51,
|
[4] = 38,
|
||||||
[5] = 64,
|
[5] = 51,
|
||||||
[6] = 77,
|
[6] = 64,
|
||||||
[7] = 90,
|
[7] = 77,
|
||||||
};
|
};
|
||||||
static const uint8_t tchh0_meas_rep_fn104[] = {
|
static const uint8_t tchh0_meas_rep_fn104[] = {
|
||||||
|
[0] = 90,
|
||||||
|
[1] = 90,
|
||||||
|
[2] = 12,
|
||||||
|
[3] = 12,
|
||||||
|
[4] = 38,
|
||||||
|
[5] = 38,
|
||||||
|
[6] = 64,
|
||||||
|
[7] = 64,
|
||||||
|
};
|
||||||
|
static const uint8_t tchh1_meas_rep_fn104[] = {
|
||||||
[0] = 103,
|
[0] = 103,
|
||||||
[1] = 103,
|
[1] = 103,
|
||||||
[2] = 25,
|
[2] = 25,
|
||||||
@@ -30,59 +53,130 @@ static const uint8_t tchh0_meas_rep_fn104[] = {
|
|||||||
[6] = 77,
|
[6] = 77,
|
||||||
[7] = 77,
|
[7] = 77,
|
||||||
};
|
};
|
||||||
static const uint8_t tchh1_meas_rep_fn104[] = {
|
|
||||||
[0] = 12,
|
/* Measurment reporting period for SDCCH8 and SDCCH4 chan
|
||||||
[1] = 12,
|
* As per in 3GPP TS 45.008, section 8.4.2.
|
||||||
[2] = 38,
|
*
|
||||||
[3] = 38,
|
* Logical Chan TDMA frame number
|
||||||
[4] = 64,
|
* (FN) modulo 102
|
||||||
[5] = 64,
|
*
|
||||||
[6] = 90,
|
* SDCCH/8 12 to 11
|
||||||
[7] = 90,
|
* SDCCH/4 37 to 36
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Added interleve offset to Meas period end Fn which
|
||||||
|
* would reduce the Meas Res msg load at Abis */
|
||||||
|
|
||||||
|
static const uint8_t sdcch8_meas_rep_fn102[] = {
|
||||||
|
[0] = 11 + 7,
|
||||||
|
[1] = 11 + 11,
|
||||||
|
[2] = 11 + 15,
|
||||||
|
[3] = 11 + 19,
|
||||||
|
[4] = 11 + 23,
|
||||||
|
[5] = 11 + 27,
|
||||||
|
[6] = 11 + 31,
|
||||||
|
[7] = 11 + 35
|
||||||
};
|
};
|
||||||
|
|
||||||
/* determine if a measurement period ends at the given frame number */
|
static const uint8_t sdcch4_meas_rep_fn102[] = {
|
||||||
static int is_meas_complete(enum gsm_phys_chan_config pchan, unsigned int ts,
|
[0] = 36 + 4,
|
||||||
unsigned int subch, uint32_t fn)
|
[1] = 36 + 8,
|
||||||
|
[2] = 36 + 14,
|
||||||
|
[3] = 36 + 18
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Note: The reporting of the measurement results is done via the SACCH channel.
|
||||||
|
* The measurement interval is not alligned with the interval in which the
|
||||||
|
* SACCH is tranmitted. When we receive the measurement indication with the
|
||||||
|
* SACCH block, the coresponding measurement interval will already have ended
|
||||||
|
* and we will get the results late, but on spot with the beginning of the
|
||||||
|
* next measurement interval.
|
||||||
|
*
|
||||||
|
* For example: We get a measurement indication on FN%104=38 in TS=2. Then we
|
||||||
|
* will have to look at 3GPP TS 45.008, secton 8.4.1 (or 3GPP TS 05.02 Clause 7
|
||||||
|
* Table 1 of 9) what value we need to feed into the lookup tables in order to
|
||||||
|
* detect the measurement period ending. In this example the "real" ending
|
||||||
|
* was on FN%104=12. This is the value we have to look for in
|
||||||
|
* tchf_meas_rep_fn104 to know that a measurement period has just ended. */
|
||||||
|
|
||||||
|
/* See also 3GPP TS 05.02 Clause 7 Table 1 of 9:
|
||||||
|
* Mapping of logical channels onto physical channels (see subclauses 6.3, 6.4, 6.5) */
|
||||||
|
static uint8_t translate_tch_meas_rep_fn104(uint8_t fn_mod)
|
||||||
{
|
{
|
||||||
unsigned int fn_mod;
|
switch (fn_mod) {
|
||||||
|
case 25:
|
||||||
|
return 103;
|
||||||
|
case 38:
|
||||||
|
return 12;
|
||||||
|
case 51:
|
||||||
|
return 25;
|
||||||
|
case 64:
|
||||||
|
return 38;
|
||||||
|
case 77:
|
||||||
|
return 51;
|
||||||
|
case 90:
|
||||||
|
return 64;
|
||||||
|
case 103:
|
||||||
|
return 77;
|
||||||
|
case 12:
|
||||||
|
return 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invalid / not of interest */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* determine if a measurement period ends at the given frame number */
|
||||||
|
static int is_meas_complete(struct gsm_lchan *lchan, uint32_t fn)
|
||||||
|
{
|
||||||
|
unsigned int fn_mod = -1;
|
||||||
const uint8_t *tbl;
|
const uint8_t *tbl;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
enum gsm_phys_chan_config pchan = ts_pchan(lchan->ts);
|
||||||
|
|
||||||
if (ts >= 8)
|
if (lchan->ts->nr >= 8)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (pchan >= _GSM_PCHAN_MAX)
|
if (pchan >= _GSM_PCHAN_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (pchan) {
|
switch (pchan) {
|
||||||
case GSM_PCHAN_TCH_F:
|
case GSM_PCHAN_TCH_F:
|
||||||
fn_mod = fn % 104;
|
fn_mod = translate_tch_meas_rep_fn104(fn % 104);
|
||||||
if (tchf_meas_rep_fn104[ts] == fn_mod)
|
if (tchf_meas_rep_fn104[lchan->ts->nr] == fn_mod)
|
||||||
rc = 1;
|
rc = 1;
|
||||||
break;
|
break;
|
||||||
case GSM_PCHAN_TCH_H:
|
case GSM_PCHAN_TCH_H:
|
||||||
fn_mod = fn % 104;
|
fn_mod = translate_tch_meas_rep_fn104(fn % 104);
|
||||||
if (subch == 0)
|
if (lchan->nr == 0)
|
||||||
tbl = tchh0_meas_rep_fn104;
|
tbl = tchh0_meas_rep_fn104;
|
||||||
else
|
else
|
||||||
tbl = tchh1_meas_rep_fn104;
|
tbl = tchh1_meas_rep_fn104;
|
||||||
if (tbl[ts] == fn_mod)
|
if (tbl[lchan->ts->nr] == fn_mod)
|
||||||
rc = 1;
|
rc = 1;
|
||||||
break;
|
break;
|
||||||
case GSM_PCHAN_SDCCH8_SACCH8C:
|
case GSM_PCHAN_SDCCH8_SACCH8C:
|
||||||
|
case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
|
||||||
fn_mod = fn % 102;
|
fn_mod = fn % 102;
|
||||||
if (fn_mod == 11)
|
if (sdcch8_meas_rep_fn102[lchan->nr] == fn_mod)
|
||||||
rc = 1;
|
rc = 1;
|
||||||
break;
|
break;
|
||||||
case GSM_PCHAN_CCCH_SDCCH4:
|
case GSM_PCHAN_CCCH_SDCCH4:
|
||||||
|
case GSM_PCHAN_CCCH_SDCCH4_CBCH:
|
||||||
fn_mod = fn % 102;
|
fn_mod = fn % 102;
|
||||||
if (fn_mod == 36)
|
if (sdcch4_meas_rep_fn102[lchan->nr] == fn_mod)
|
||||||
rc = 1;
|
rc = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rc = 0;
|
rc = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == 1) {
|
||||||
|
DEBUGP(DMEAS,
|
||||||
|
"%s meas period end fn:%u, fn_mod:%i, status:%d, pchan:%s\n",
|
||||||
|
gsm_lchan_name(lchan), fn, fn_mod, rc, gsm_pchan_name(pchan));
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,13 +187,16 @@ int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm)
|
|||||||
gsm_lchan_name(lchan), lchan->meas.num_ul_meas);
|
gsm_lchan_name(lchan), lchan->meas.num_ul_meas);
|
||||||
|
|
||||||
if (lchan->state != LCHAN_S_ACTIVE) {
|
if (lchan->state != LCHAN_S_ACTIVE) {
|
||||||
LOGP(DMEAS, LOGL_NOTICE, "%s measurement during state: %s\n",
|
LOGP(DMEAS, LOGL_NOTICE,
|
||||||
gsm_lchan_name(lchan), gsm_lchans_name(lchan->state));
|
"%s measurement during state: %s, num_ul_meas=%d\n",
|
||||||
|
gsm_lchan_name(lchan), gsm_lchans_name(lchan->state),
|
||||||
|
lchan->meas.num_ul_meas);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lchan->meas.num_ul_meas >= ARRAY_SIZE(lchan->meas.uplink)) {
|
if (lchan->meas.num_ul_meas >= ARRAY_SIZE(lchan->meas.uplink)) {
|
||||||
LOGP(DMEAS, LOGL_NOTICE, "%s no space for uplink measurement\n",
|
LOGP(DMEAS, LOGL_NOTICE,
|
||||||
gsm_lchan_name(lchan));
|
"%s no space for uplink measurement, num_ul_meas=%d\n",
|
||||||
|
gsm_lchan_name(lchan), lchan->meas.num_ul_meas);
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +209,20 @@ int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm)
|
|||||||
/* input: BER in steps of .01%, i.e. percent/100 */
|
/* input: BER in steps of .01%, i.e. percent/100 */
|
||||||
static uint8_t ber10k_to_rxqual(uint32_t ber10k)
|
static uint8_t ber10k_to_rxqual(uint32_t ber10k)
|
||||||
{
|
{
|
||||||
/* 05.08 / 8.2.4 */
|
/* Eight levels of Rx quality are defined and are mapped to the
|
||||||
|
* equivalent BER before channel decoding, as per in 3GPP TS 45.008,
|
||||||
|
* secton 8.2.4.
|
||||||
|
*
|
||||||
|
* RxQual: BER Range:
|
||||||
|
* RXQUAL_0 BER < 0,2 % Assumed value = 0,14 %
|
||||||
|
* RXQUAL_1 0,2 % < BER < 0,4 % Assumed value = 0,28 %
|
||||||
|
* RXQUAL_2 0,4 % < BER < 0,8 % Assumed value = 0,57 %
|
||||||
|
* RXQUAL_3 0,8 % < BER < 1,6 % Assumed value = 1,13 %
|
||||||
|
* RXQUAL_4 1,6 % < BER < 3,2 % Assumed value = 2,26 %
|
||||||
|
* RXQUAL_5 3,2 % < BER < 6,4 % Assumed value = 4,53 %
|
||||||
|
* RXQUAL_6 6,4 % < BER < 12,8 % Assumed value = 9,05 %
|
||||||
|
* RXQUAL_7 12,8 % < BER Assumed value = 18,10 % */
|
||||||
|
|
||||||
if (ber10k < 20)
|
if (ber10k < 20)
|
||||||
return 0;
|
return 0;
|
||||||
if (ber10k < 40)
|
if (ber10k < 40)
|
||||||
@@ -130,7 +240,51 @@ static uint8_t ber10k_to_rxqual(uint32_t ber10k)
|
|||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
/* Update order TA at end of meas period */
|
||||||
|
static void lchan_meas_update_ordered_TA(struct gsm_lchan *lchan,
|
||||||
|
int32_t taqb_sum)
|
||||||
|
{
|
||||||
|
int32_t ms_timing_offset = 0;
|
||||||
|
uint8_t l1_info_valid;
|
||||||
|
|
||||||
|
l1_info_valid = lchan->meas.flags & LC_UL_M_F_L1_VALID;
|
||||||
|
|
||||||
|
if (l1_info_valid) {
|
||||||
|
DEBUGP(DMEAS,
|
||||||
|
"%s Update TA TimingOffset_Mean:%d, UL RX TA:%d, DL ordered TA:%d, flags:%d \n",
|
||||||
|
gsm_lchan_name(lchan), taqb_sum, lchan->meas.l1_info[1],
|
||||||
|
lchan->rqd_ta, lchan->meas.flags);
|
||||||
|
|
||||||
|
ms_timing_offset =
|
||||||
|
taqb_sum + (lchan->meas.l1_info[1] - lchan->rqd_ta);
|
||||||
|
|
||||||
|
if (ms_timing_offset > 0) {
|
||||||
|
if (lchan->rqd_ta < MEAS_MAX_TIMING_ADVANCE) {
|
||||||
|
/* MS is moving away from BTS.
|
||||||
|
* So increment Ordered TA by 1 */
|
||||||
|
lchan->rqd_ta++;
|
||||||
|
}
|
||||||
|
} else if (ms_timing_offset < 0) {
|
||||||
|
if (lchan->rqd_ta > MEAS_MIN_TIMING_ADVANCE) {
|
||||||
|
/* MS is moving toward BTS. So decrement
|
||||||
|
* Ordered TA by 1 */
|
||||||
|
lchan->rqd_ta--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGP(DMEAS,
|
||||||
|
"%s New Update TA--> TimingOff_diff:%d, UL RX TA:%d, DL ordered TA:%d \n",
|
||||||
|
gsm_lchan_name(lchan), ms_timing_offset,
|
||||||
|
lchan->meas.l1_info[1], lchan->rqd_ta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear L1 INFO valid flag at Meas period end */
|
||||||
|
lchan->meas.flags &= ~LC_UL_M_F_L1_VALID;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||||
{
|
{
|
||||||
struct gsm_meas_rep_unidir *mru;
|
struct gsm_meas_rep_unidir *mru;
|
||||||
uint32_t ber_full_sum = 0;
|
uint32_t ber_full_sum = 0;
|
||||||
@@ -142,8 +296,7 @@ static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* if measurement period is not complete, abort */
|
/* if measurement period is not complete, abort */
|
||||||
if (!is_meas_complete(lchan->ts->pchan, lchan->ts->nr,
|
if (!is_meas_complete(lchan, fn))
|
||||||
lchan->nr, fn))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* if there are no measurements, skip computation */
|
/* if there are no measurements, skip computation */
|
||||||
@@ -175,6 +328,9 @@ static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
|||||||
if (num_meas_sub) {
|
if (num_meas_sub) {
|
||||||
ber_sub_sum = ber_sub_sum / num_meas_sub;
|
ber_sub_sum = ber_sub_sum / num_meas_sub;
|
||||||
irssi_sub_sum = irssi_sub_sum / num_meas_sub;
|
irssi_sub_sum = irssi_sub_sum / num_meas_sub;
|
||||||
|
} else {
|
||||||
|
ber_sub_sum = ber_full_sum;
|
||||||
|
irssi_sub_sum = irssi_full_sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGP(DMEAS, "%s Computed TA(% 4dqb) BER-FULL(%2u.%02u%%), RSSI-FULL(-%3udBm), "
|
DEBUGP(DMEAS, "%s Computed TA(% 4dqb) BER-FULL(%2u.%02u%%), RSSI-FULL(-%3udBm), "
|
||||||
@@ -183,6 +339,9 @@ static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
|||||||
ber_full_sum%100, irssi_full_sum, ber_sub_sum/100, ber_sub_sum%100,
|
ber_full_sum%100, irssi_full_sum, ber_sub_sum/100, ber_sub_sum%100,
|
||||||
irssi_sub_sum);
|
irssi_sub_sum);
|
||||||
|
|
||||||
|
/* Update ordered TA for DL SACCH L1 Header */
|
||||||
|
lchan_meas_update_ordered_TA(lchan, taqb_sum);
|
||||||
|
|
||||||
/* store results */
|
/* store results */
|
||||||
mru = &lchan->meas.ul_res;
|
mru = &lchan->meas.ul_res;
|
||||||
mru->full.rx_lev = dbm2rxlev((int)irssi_full_sum * -1);
|
mru->full.rx_lev = dbm2rxlev((int)irssi_full_sum * -1);
|
||||||
@@ -190,6 +349,14 @@ static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
|||||||
mru->full.rx_qual = ber10k_to_rxqual(ber_full_sum);
|
mru->full.rx_qual = ber10k_to_rxqual(ber_full_sum);
|
||||||
mru->sub.rx_qual = ber10k_to_rxqual(ber_sub_sum);
|
mru->sub.rx_qual = ber10k_to_rxqual(ber_sub_sum);
|
||||||
|
|
||||||
|
DEBUGP(DMEAS, "%s UL MEAS RXLEV_FULL(%u), RXLEV_SUB(%u),"
|
||||||
|
"RXQUAL_FULL(%u), RXQUAL_SUB(%u), num_meas_sub(%u), num_ul_meas(%u) \n",
|
||||||
|
gsm_lchan_name(lchan),
|
||||||
|
mru->full.rx_lev,
|
||||||
|
mru->sub.rx_lev,
|
||||||
|
mru->full.rx_qual,
|
||||||
|
mru->sub.rx_qual, num_meas_sub, lchan->meas.num_ul_meas);
|
||||||
|
|
||||||
lchan->meas.flags |= LC_UL_M_F_RES_VALID;
|
lchan->meas.flags |= LC_UL_M_F_RES_VALID;
|
||||||
lchan->meas.num_ul_meas = 0;
|
lchan->meas.num_ul_meas = 0;
|
||||||
|
|
||||||
@@ -197,63 +364,3 @@ static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build the 3 byte RSL uplinke measurement IE content */
|
|
||||||
int lchan_build_rsl_ul_meas(struct gsm_lchan *lchan, uint8_t *buf)
|
|
||||||
{
|
|
||||||
struct gsm_meas_rep_unidir *mru = &lchan->meas.ul_res;
|
|
||||||
buf[0] = (mru->full.rx_lev & 0x3f); /* FIXME: DTXu support */
|
|
||||||
buf[1] = (mru->sub.rx_lev & 0x3f);
|
|
||||||
buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
|
|
||||||
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copied from OpenBSC and enlarged to _GSM_PCHAN_MAX */
|
|
||||||
static const uint8_t subslots_per_pchan[_GSM_PCHAN_MAX] = {
|
|
||||||
[GSM_PCHAN_NONE] = 0,
|
|
||||||
[GSM_PCHAN_CCCH] = 0,
|
|
||||||
[GSM_PCHAN_CCCH_SDCCH4] = 4,
|
|
||||||
[GSM_PCHAN_TCH_F] = 1,
|
|
||||||
[GSM_PCHAN_TCH_H] = 2,
|
|
||||||
[GSM_PCHAN_SDCCH8_SACCH8C] = 8,
|
|
||||||
/* FIXME: what about dynamic TCH_F_TCH_H ? */
|
|
||||||
[GSM_PCHAN_TCH_F_PDCH] = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int ts_meas_check_compute(struct gsm_bts_trx_ts *ts, uint32_t fn)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const int num_subslots = subslots_per_pchan[ts->pchan];
|
|
||||||
|
|
||||||
for (i = 0; i < num_subslots; ++i) {
|
|
||||||
struct gsm_lchan *lchan = &ts->lchan[i];
|
|
||||||
|
|
||||||
if (lchan->state != LCHAN_S_ACTIVE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (lchan->type) {
|
|
||||||
case GSM_LCHAN_SDCCH:
|
|
||||||
case GSM_LCHAN_TCH_F:
|
|
||||||
case GSM_LCHAN_TCH_H:
|
|
||||||
case GSM_LCHAN_PDTCH:
|
|
||||||
lchan_meas_check_compute(lchan, fn);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* needs to be called once every TDMA frame ! */
|
|
||||||
int trx_meas_check_compute(struct gsm_bts_trx *trx, uint32_t fn)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
|
|
||||||
struct gsm_bts_trx_ts *ts = &trx->ts[i];
|
|
||||||
ts_meas_check_compute(ts, fn);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,17 +17,24 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||||
#include <osmo-bts/msg_utils.h>
|
#include <osmo-bts/msg_utils.h>
|
||||||
#include <osmo-bts/logging.h>
|
#include <osmo-bts/logging.h>
|
||||||
#include <osmo-bts/oml.h>
|
#include <osmo-bts/oml.h>
|
||||||
|
#include <osmo-bts/amr.h>
|
||||||
|
#include <osmo-bts/rsl.h>
|
||||||
|
|
||||||
#include <osmocom/gsm/protocol/ipaccess.h>
|
#include <osmocom/gsm/protocol/ipaccess.h>
|
||||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||||
#include <osmocom/gsm/abis_nm.h>
|
#include <osmocom/gsm/abis_nm.h>
|
||||||
#include <osmocom/core/msgb.h>
|
#include <osmocom/core/msgb.h>
|
||||||
|
#include <osmocom/core/fsm.h>
|
||||||
|
#include <osmocom/trau/osmo_ortp.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define STI_BIT_MASK 16
|
||||||
|
|
||||||
static int check_fom(struct abis_om_hdr *omh, size_t len)
|
static int check_fom(struct abis_om_hdr *omh, size_t len)
|
||||||
{
|
{
|
||||||
@@ -86,6 +93,425 @@ static int check_manuf(struct msgb *msg, struct abis_om_hdr *omh, size_t msg_siz
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check that DTX is in the middle of silence */
|
||||||
|
static inline bool dtx_is_update(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (!dtx_dl_amr_enabled(lchan))
|
||||||
|
return false;
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_SID_U ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_U_NOINH)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check that DTX is in the beginning of silence for AMR HR */
|
||||||
|
bool dtx_is_first_p1(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (!dtx_dl_amr_enabled(lchan))
|
||||||
|
return false;
|
||||||
|
if ((lchan->type == GSM_LCHAN_TCH_H &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F1))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update lchan SID status */
|
||||||
|
void lchan_set_marker(bool t, struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (t)
|
||||||
|
lchan->tch.dtx.ul_sid = true;
|
||||||
|
else if (lchan->tch.dtx.ul_sid) {
|
||||||
|
lchan->tch.dtx.ul_sid = false;
|
||||||
|
lchan->rtp_tx_marker = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Store the last SID frame in lchan context
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] l1_payload buffer with SID data
|
||||||
|
* \param[in] length length of l1_payload
|
||||||
|
* \param[in] fn Frame Number for which we check scheduling
|
||||||
|
* \param[in] update 0 if SID_FIRST, 1 if SID_UPDATE, -1 if not AMR SID
|
||||||
|
*/
|
||||||
|
void dtx_cache_payload(struct gsm_lchan *lchan, const uint8_t *l1_payload,
|
||||||
|
size_t length, uint32_t fn, int update)
|
||||||
|
{
|
||||||
|
size_t amr = (update < 0) ? 0 : 2,
|
||||||
|
copy_len = OSMO_MIN(length,
|
||||||
|
ARRAY_SIZE(lchan->tch.dtx.cache) - amr);
|
||||||
|
|
||||||
|
lchan->tch.dtx.len = copy_len + amr;
|
||||||
|
/* SID FIRST is special because it's both sent and cached: */
|
||||||
|
if (update == 0) {
|
||||||
|
lchan->tch.dtx.is_update = false; /* Mark SID FIRST explicitly */
|
||||||
|
/* for non-AMR case - always update FN for incoming SID FIRST */
|
||||||
|
if (!amr || !dtx_is_update(lchan))
|
||||||
|
lchan->tch.dtx.fn = fn;
|
||||||
|
/* for AMR case - do not update FN if SID FIRST arrives in a
|
||||||
|
middle of silence: this should not be happening according to
|
||||||
|
the spec */
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(lchan->tch.dtx.cache + amr, l1_payload, copy_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check current state of DTX DL AMR FSM and dispatch necessary events
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] rtp_pl buffer with RTP data
|
||||||
|
* \param[in] rtp_pl_len length of rtp_pl
|
||||||
|
* \param[in] fn Frame Number for which we check scheduling
|
||||||
|
* \param[in] l1_payload buffer where CMR and CMI prefix should be added
|
||||||
|
* \param[in] marker RTP Marker bit
|
||||||
|
* \param[out] len Length of expected L1 payload
|
||||||
|
* \param[out] ft_out Frame Type to be populated after decoding
|
||||||
|
* \returns 0 in case of success; negative on error
|
||||||
|
*/
|
||||||
|
int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl,
|
||||||
|
size_t rtp_pl_len, uint32_t fn, uint8_t *l1_payload,
|
||||||
|
bool marker, uint8_t *len, uint8_t *ft_out)
|
||||||
|
{
|
||||||
|
uint8_t cmr;
|
||||||
|
enum osmo_amr_type ft;
|
||||||
|
enum osmo_amr_quality bfi;
|
||||||
|
int8_t sti, cmi;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (dtx_dl_amr_enabled(lchan)) {
|
||||||
|
if (lchan->type == GSM_LCHAN_TCH_H && !rtp_pl) {
|
||||||
|
/* we're called by gen_empty_tch_msg() to handle states
|
||||||
|
specific to AMR HR DTX */
|
||||||
|
switch (lchan->tch.dtx.dl_amr_fsm->state) {
|
||||||
|
case ST_SID_F2:
|
||||||
|
*len = 3; /* SID-FIRST P1 -> P2 completion */
|
||||||
|
memcpy(l1_payload, lchan->tch.dtx.cache, 2);
|
||||||
|
rc = 0;
|
||||||
|
dtx_dispatch(lchan, E_COMPL);
|
||||||
|
break;
|
||||||
|
case ST_SID_U:
|
||||||
|
rc = -EBADMSG;
|
||||||
|
dtx_dispatch(lchan, E_SID_U);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = -EBADMSG;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rtp_pl_len)
|
||||||
|
return -EBADMSG;
|
||||||
|
|
||||||
|
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);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only needed for old sysmo firmware: */
|
||||||
|
*ft_out = ft;
|
||||||
|
|
||||||
|
/* CMI in downlink tells the L1 encoder which encoding function
|
||||||
|
* it will use, so we have to use the frame type */
|
||||||
|
if (osmo_amr_is_speech(ft))
|
||||||
|
cmi = ft;
|
||||||
|
|
||||||
|
/* populate L1 payload with CMR/CMI - might be ignored by caller: */
|
||||||
|
amr_set_mode_pref(l1_payload, &lchan->tch.amr_mr, cmi, cmr);
|
||||||
|
|
||||||
|
/* populate DTX cache with CMR/CMI - overwrite cache which will be
|
||||||
|
either updated or invalidated by caller anyway: */
|
||||||
|
amr_set_mode_pref(lchan->tch.dtx.cache, &lchan->tch.amr_mr, cmi, cmr);
|
||||||
|
*len = 3 + rtp_pl_len;
|
||||||
|
|
||||||
|
/* DTX DL is not enabled, move along */
|
||||||
|
if (!lchan->ts->trx->bts->dtxd)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (osmo_amr_is_speech(ft)) {
|
||||||
|
/* AMR HR - SID-FIRST_P1 Inhibition */
|
||||||
|
if (marker && lchan->tch.dtx.dl_amr_fsm->state == ST_VOICE)
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_INHIB, (void *)lchan);
|
||||||
|
|
||||||
|
/* AMR HR - SID-UPDATE Inhibition */
|
||||||
|
if (marker && lchan->type == GSM_LCHAN_TCH_H &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_U)
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_INHIB, (void *)lchan);
|
||||||
|
|
||||||
|
/* AMR FR & HR - generic */
|
||||||
|
if (marker && (lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F1 ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2 ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_U_NOINH))
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_ONSET, (void *)lchan);
|
||||||
|
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state != ST_VOICE)
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_VOICE, (void *)lchan);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ft == AMR_SID) {
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_VOICE) {
|
||||||
|
/* SID FIRST/UPDATE scheduling logic relies on SID FIRST
|
||||||
|
being sent first hence we have to force caching of SID
|
||||||
|
as FIRST regardless of actually decoded type */
|
||||||
|
dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, false);
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
sti ? E_SID_U : E_SID_F,
|
||||||
|
(void *)lchan);
|
||||||
|
} else if (lchan->tch.dtx.dl_amr_fsm->state != ST_FACCH)
|
||||||
|
dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, sti);
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2)
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_COMPL, (void *)lchan);
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
sti ? E_SID_U : E_SID_F,
|
||||||
|
(void *)lchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ft != AMR_NO_DATA) {
|
||||||
|
LOGP(DRTP, LOGL_ERROR, "unsupported AMR FT 0x%02x\n", ft);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (marker)
|
||||||
|
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm, E_VOICE,
|
||||||
|
(void *)lchan);
|
||||||
|
*len = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STI is located in payload byte 6, cache contains 2 byte prefix (CMR/CMI)
|
||||||
|
* STI set = SID UPDATE, STI unset = SID FIRST
|
||||||
|
*/
|
||||||
|
static inline void dtx_sti_set(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
lchan->tch.dtx.cache[6 + 2] |= STI_BIT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dtx_sti_unset(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
lchan->tch.dtx.cache[6 + 2] &= ~STI_BIT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check if enough time has passed since last SID (if any) to repeat it
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] fn Frame Number for which we check scheduling
|
||||||
|
* \returns true if transmission can be omitted, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool dtx_amr_sid_optional(struct gsm_lchan *lchan, uint32_t fn)
|
||||||
|
{
|
||||||
|
if (!dtx_dl_amr_enabled(lchan))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Compute approx. time delta x26 based on Fn duration */
|
||||||
|
uint32_t dx26 = 120 * (fn - lchan->tch.dtx.fn);
|
||||||
|
|
||||||
|
/* We're resuming after FACCH interruption */
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_FACCH) {
|
||||||
|
/* force STI bit to 0 so cache is treated as SID FIRST */
|
||||||
|
dtx_sti_unset(lchan);
|
||||||
|
lchan->tch.dtx.is_update = false;
|
||||||
|
/* check that this FN has not been used for FACCH message
|
||||||
|
already: we rely here on the order of RTS arrival from L1 - we
|
||||||
|
expect that PH-DATA.req ALWAYS comes before PH-TCH.req for the
|
||||||
|
same FN */
|
||||||
|
if(lchan->type == GSM_LCHAN_TCH_H) {
|
||||||
|
if (lchan->tch.dtx.fn != LCHAN_FN_DUMMY &&
|
||||||
|
lchan->tch.dtx.fn != LCHAN_FN_WAIT) {
|
||||||
|
/* FACCH interruption is over */
|
||||||
|
dtx_dispatch(lchan, E_COMPL);
|
||||||
|
return false;
|
||||||
|
} else if(lchan->tch.dtx.fn == LCHAN_FN_DUMMY) {
|
||||||
|
lchan->tch.dtx.fn = LCHAN_FN_WAIT;
|
||||||
|
} else
|
||||||
|
lchan->tch.dtx.fn = fn;
|
||||||
|
} else if(lchan->type == GSM_LCHAN_TCH_F) {
|
||||||
|
if (lchan->tch.dtx.fn != LCHAN_FN_DUMMY) {
|
||||||
|
/* FACCH interruption is over */
|
||||||
|
dtx_dispatch(lchan, E_COMPL);
|
||||||
|
return false;
|
||||||
|
} else
|
||||||
|
lchan->tch.dtx.fn = fn;
|
||||||
|
}
|
||||||
|
/* this FN was already used for FACCH or ONSET message so we just
|
||||||
|
prepare things for next one */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_VOICE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* according to 3GPP TS 26.093 A.5.1.1:
|
||||||
|
(*26) to avoid float math, add 1 FN tolerance (-120) */
|
||||||
|
if (lchan->tch.dtx.is_update) { /* SID UPDATE: every 8th RTP frame */
|
||||||
|
if (dx26 < GSM_RTP_FRAME_DURATION_MS * 8 * 26 - 120)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* 3rd frame after SID FIRST should be SID UPDATE */
|
||||||
|
if (dx26 < GSM_RTP_FRAME_DURATION_MS * 3 * 26 - 120)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool fn_chk(const uint8_t *t, uint32_t fn, uint8_t len)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
if (fn % 104 == t[i])
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check if TX scheduling is optional for a given FN in case of DTX
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] fn Frame Number for which we check scheduling
|
||||||
|
* \returns true if transmission can be omitted, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool dtx_sched_optional(struct gsm_lchan *lchan, uint32_t fn)
|
||||||
|
{
|
||||||
|
/* According to 3GPP TS 45.008 § 8.3: */
|
||||||
|
static const uint8_t f[] = { 52, 53, 54, 55, 56, 57, 58, 59 },
|
||||||
|
h0[] = { 0, 2, 4, 6, 52, 54, 56, 58 },
|
||||||
|
h1[] = { 14, 16, 18, 20, 66, 68, 70, 72 };
|
||||||
|
if (lchan->tch_mode == GSM48_CMODE_SPEECH_V1) {
|
||||||
|
if (lchan->type == GSM_LCHAN_TCH_F)
|
||||||
|
return fn_chk(f, fn, ARRAY_SIZE(f));
|
||||||
|
else
|
||||||
|
return fn_chk(lchan->nr ? h1 : h0, fn,
|
||||||
|
lchan->nr ? ARRAY_SIZE(h1) :
|
||||||
|
ARRAY_SIZE(h0));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check if DTX DL AMR is enabled for a given lchan (it have proper type,
|
||||||
|
* FSM is allocated etc.)
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \returns true if DTX DL AMR is enabled, false otherwise
|
||||||
|
*/
|
||||||
|
bool dtx_dl_amr_enabled(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (lchan->ts->trx->bts->dtxd &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm &&
|
||||||
|
lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check if DTX DL AMR FSM state is recursive: requires secondary
|
||||||
|
* response to a single RTS request from L1.
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \returns true if DTX DL AMR FSM state is recursive, false otherwise
|
||||||
|
*/
|
||||||
|
bool dtx_recursion(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (!dtx_dl_amr_enabled(lchan))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_V ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_V_REC ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F_REC ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_V ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_V_REC ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F_REC ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_V ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F_REC ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_V_REC)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Send signal to FSM: with proper check if DIX is enabled for this lchan
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] e DTX DL AMR FSM Event
|
||||||
|
*/
|
||||||
|
void dtx_dispatch(struct gsm_lchan *lchan, enum dtx_dl_amr_fsm_events e)
|
||||||
|
{
|
||||||
|
if (dtx_dl_amr_enabled(lchan))
|
||||||
|
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm, e,
|
||||||
|
(void *)lchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Send internal signal to FSM: check that DTX is enabled for this chan,
|
||||||
|
* check that current FSM and lchan states are permitting such signal.
|
||||||
|
* Note: this should be the only way to dispatch E_COMPL to FSM from
|
||||||
|
* BTS code.
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
*/
|
||||||
|
void dtx_int_signal(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (!dtx_dl_amr_enabled(lchan))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dtx_is_first_p1(lchan) || dtx_recursion(lchan))
|
||||||
|
dtx_dispatch(lchan, E_COMPL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Repeat last SID if possible in case of DTX
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] dst Buffer to copy last SID into
|
||||||
|
* \returns Number of bytes copied + 1 (to accommodate for extra byte with
|
||||||
|
* payload type), 0 if there's nothing to copy
|
||||||
|
*/
|
||||||
|
uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn)
|
||||||
|
{
|
||||||
|
/* FIXME: add EFR support */
|
||||||
|
if (lchan->tch_mode == GSM48_CMODE_SPEECH_EFR)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (lchan->tch_mode != GSM48_CMODE_SPEECH_AMR) {
|
||||||
|
if (dtx_sched_optional(lchan, fn))
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
if (dtx_amr_sid_optional(lchan, fn))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (lchan->tch.dtx.len) {
|
||||||
|
if (dtx_dl_amr_enabled(lchan)) {
|
||||||
|
if ((lchan->type == GSM_LCHAN_TCH_H &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2) ||
|
||||||
|
(lchan->type == GSM_LCHAN_TCH_F &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F1)) {
|
||||||
|
/* advance FSM in case we've just sent SID FIRST
|
||||||
|
to restore silence after FACCH interruption */
|
||||||
|
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_SID_U, (void *)lchan);
|
||||||
|
dtx_sti_unset(lchan);
|
||||||
|
} else if (dtx_is_update(lchan)) {
|
||||||
|
/* enforce SID UPDATE for next repetition: it
|
||||||
|
might have been altered by FACCH handling */
|
||||||
|
dtx_sti_set(lchan);
|
||||||
|
if (lchan->type == GSM_LCHAN_TCH_H &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state ==
|
||||||
|
ST_U_NOINH)
|
||||||
|
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_COMPL,
|
||||||
|
(void *)lchan);
|
||||||
|
lchan->tch.dtx.is_update = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(dst, lchan->tch.dtx.cache, lchan->tch.dtx.len);
|
||||||
|
lchan->tch.dtx.fn = 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));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return 0 in case the IPA structure is okay and in this
|
* Return 0 in case the IPA structure is okay and in this
|
||||||
* case the l2h will be set to the beginning of the data.
|
* case the l2h will be set to the beginning of the data.
|
||||||
@@ -96,28 +522,30 @@ int msg_verify_ipa_structure(struct msgb *msg)
|
|||||||
|
|
||||||
if (msgb_l1len(msg) < sizeof(struct ipaccess_head)) {
|
if (msgb_l1len(msg) < sizeof(struct ipaccess_head)) {
|
||||||
LOGP(DL1C, LOGL_ERROR,
|
LOGP(DL1C, LOGL_ERROR,
|
||||||
"Ipa header insufficient space %d %d\n",
|
"Ipa header insufficient space %d %zu\n",
|
||||||
msgb_l1len(msg), sizeof(struct ipaccess_head));
|
msgb_l1len(msg), sizeof(struct ipaccess_head));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
hh = (struct ipaccess_head *) msg->l1h;
|
hh = (struct ipaccess_head *) msg->l1h;
|
||||||
|
|
||||||
if (hh->proto != IPAC_PROTO_OML) {
|
|
||||||
LOGP(DL1C, LOGL_ERROR,
|
|
||||||
"Incorrect ipa header protocol 0x%x 0x%x\n",
|
|
||||||
hh->proto, IPAC_PROTO_OML);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ntohs(hh->len) != msgb_l1len(msg) - sizeof(struct ipaccess_head)) {
|
if (ntohs(hh->len) != msgb_l1len(msg) - sizeof(struct ipaccess_head)) {
|
||||||
LOGP(DL1C, LOGL_ERROR,
|
LOGP(DL1C, LOGL_ERROR,
|
||||||
"Incorrect ipa header msg size %d %d\n",
|
"Incorrect ipa header msg size %d %zu\n",
|
||||||
ntohs(hh->len), msgb_l1len(msg) - sizeof(struct ipaccess_head));
|
ntohs(hh->len), msgb_l1len(msg) - sizeof(struct ipaccess_head));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hh->proto == IPAC_PROTO_OSMO) {
|
||||||
|
struct ipaccess_head_ext *hh_ext = (struct ipaccess_head_ext *) hh->data;
|
||||||
|
if (ntohs(hh->len) < sizeof(*hh_ext)) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "IPA length shorter than OSMO header\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
msg->l2h = hh_ext->data;
|
||||||
|
} else
|
||||||
msg->l2h = hh->data;
|
msg->l2h = hh->data;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +568,7 @@ int msg_verify_oml_structure(struct msgb *msg)
|
|||||||
struct abis_om_hdr *omh;
|
struct abis_om_hdr *omh;
|
||||||
|
|
||||||
if (msgb_l2len(msg) < sizeof(*omh)) {
|
if (msgb_l2len(msg) < sizeof(*omh)) {
|
||||||
LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %d\n",
|
LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %zu\n",
|
||||||
msgb_l2len(msg), sizeof(*omh));
|
msgb_l2len(msg), sizeof(*omh));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
708
src/common/oml.c
708
src/common/oml.c
@@ -24,11 +24,16 @@
|
|||||||
* Operation and Maintainance Messages
|
* Operation and Maintainance Messages
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "btsconfig.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include <osmocom/core/talloc.h>
|
#include <osmocom/core/talloc.h>
|
||||||
|
#include <osmocom/core/msgb.h>
|
||||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||||
#include <osmocom/gsm/abis_nm.h>
|
#include <osmocom/gsm/abis_nm.h>
|
||||||
#include <osmocom/abis/e1_input.h>
|
#include <osmocom/abis/e1_input.h>
|
||||||
@@ -41,115 +46,19 @@
|
|||||||
#include <osmo-bts/bts_model.h>
|
#include <osmo-bts/bts_model.h>
|
||||||
#include <osmo-bts/bts.h>
|
#include <osmo-bts/bts.h>
|
||||||
#include <osmo-bts/signal.h>
|
#include <osmo-bts/signal.h>
|
||||||
|
#include <osmo-bts/phy_link.h>
|
||||||
/* FIXME: move this to libosmocore */
|
|
||||||
static struct tlv_definition abis_nm_att_tlvdef_ipa = {
|
|
||||||
.def = {
|
|
||||||
/* ip.access specifics */
|
|
||||||
[NM_ATT_IPACC_DST_IP] = { TLV_TYPE_FIXED, 4 },
|
|
||||||
[NM_ATT_IPACC_DST_IP_PORT] = { TLV_TYPE_FIXED, 2 },
|
|
||||||
[NM_ATT_IPACC_STREAM_ID] = { TLV_TYPE_TV, },
|
|
||||||
[NM_ATT_IPACC_SEC_OML_CFG] = { TLV_TYPE_FIXED, 6 },
|
|
||||||
[NM_ATT_IPACC_IP_IF_CFG] = { TLV_TYPE_FIXED, 8 },
|
|
||||||
[NM_ATT_IPACC_IP_GW_CFG] = { TLV_TYPE_FIXED, 12 },
|
|
||||||
[NM_ATT_IPACC_IN_SERV_TIME] = { TLV_TYPE_FIXED, 4 },
|
|
||||||
[NM_ATT_IPACC_LOCATION] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_PAGING_CFG] = { TLV_TYPE_FIXED, 2 },
|
|
||||||
[NM_ATT_IPACC_UNIT_ID] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_UNIT_NAME] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_SNMP_CFG] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_PRIM_OML_CFG_LIST] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_NV_FLAGS] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_FREQ_CTRL] = { TLV_TYPE_FIXED, 2 },
|
|
||||||
[NM_ATT_IPACC_PRIM_OML_FB_TOUT] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_CUR_SW_CFG] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_TIMING_BUS] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_CGI] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_RAC] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_OBJ_VERSION] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_GPRS_PAGING_CFG]= { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_NSEI] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_BVCI] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_NSVCI] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_NS_CFG] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_BSSGP_CFG] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_NS_LINK_CFG] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_RLC_CFG] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_ALM_THRESH_LIST]= { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_MONIT_VAL_LIST] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_TIB_CONTROL] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_SUPP_FEATURES] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_CODING_SCHEMES] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_RLC_CFG_2] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_HEARTB_TOUT] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_UPTIME] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_RLC_CFG_3] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_SSL_CFG] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_SEC_POSSIBLE] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_IML_SSL_STATE] = { TLV_TYPE_TL16V },
|
|
||||||
[NM_ATT_IPACC_REVOC_DATE] = { TLV_TYPE_TL16V },
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int oml_ipa_set_attr(struct gsm_bts *bts, struct msgb *msg);
|
static int oml_ipa_set_attr(struct gsm_bts *bts, struct msgb *msg);
|
||||||
|
|
||||||
|
static struct tlv_definition abis_nm_att_tlvdef_ipa_local = {};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* support
|
* support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct tlv_parsed *tlvp_copy(const struct tlv_parsed *tp_orig, void *ctx)
|
|
||||||
{
|
|
||||||
struct tlv_parsed *tp_out;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
tp_out = talloc_zero(ctx, struct tlv_parsed);
|
|
||||||
if (!tp_out)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* if the original is NULL, return empty tlvp */
|
|
||||||
if (!tp_orig)
|
|
||||||
return tp_out;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(tp_orig->lv); i++) {
|
|
||||||
unsigned int len = tp_orig->lv[i].len;
|
|
||||||
tp_out->lv[i].len = len;
|
|
||||||
if (len && tp_out->lv[i].val) {
|
|
||||||
tp_out->lv[i].val = talloc_zero_size(tp_out, len);
|
|
||||||
if (!tp_out->lv[i].val) {
|
|
||||||
talloc_free(tp_out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy((uint8_t *)tp_out->lv[i].val, tp_orig->lv[i].val, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tp_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* merge all attributes of 'new' into 'out' */
|
|
||||||
int tlvp_merge(struct tlv_parsed *out, const struct tlv_parsed *new)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(out->lv); i++) {
|
|
||||||
unsigned int len = new->lv[i].len;
|
|
||||||
if (len == 0 || new->lv[i].val == NULL)
|
|
||||||
continue;
|
|
||||||
if (out->lv[i].val) {
|
|
||||||
talloc_free((uint8_t *) out->lv[i].val);
|
|
||||||
out->lv[i].len = 0;
|
|
||||||
}
|
|
||||||
out->lv[i].val = talloc_zero_size(out, len);
|
|
||||||
if (!out->lv[i].val)
|
|
||||||
return -ENOMEM;
|
|
||||||
memcpy((uint8_t *) out->lv[i].val, new->lv[i].val, len);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int oml_tlv_parse(struct tlv_parsed *tp, const uint8_t *buf, int len)
|
static int oml_tlv_parse(struct tlv_parsed *tp, const uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
return tlv_parse(tp, &abis_nm_att_tlvdef_ipa, buf, len, 0, 0);
|
return tlv_parse(tp, &abis_nm_att_tlvdef_ipa_local, buf, len, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct msgb *oml_msgb_alloc(void)
|
struct msgb *oml_msgb_alloc(void)
|
||||||
@@ -157,6 +66,42 @@ struct msgb *oml_msgb_alloc(void)
|
|||||||
return msgb_alloc_headroom(1024, 128, "OML");
|
return msgb_alloc_headroom(1024, 128, "OML");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 3GPP TS 12.21 § 8.8.2 */
|
||||||
|
static int oml_tx_failure_event_rep(struct gsm_abis_mo *mo, uint16_t cause_value,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct msgb *nmsg;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
LOGP(DOML, LOGL_NOTICE, "Reporting FAILURE to BSC: ");
|
||||||
|
va_start(ap, fmt);
|
||||||
|
osmo_vlogp(DOML, LOGL_NOTICE, __FILE__, __LINE__, 1, fmt, ap);
|
||||||
|
nmsg = abis_nm_fail_evt_vrep(NM_EVT_PROC_FAIL, NM_SEVER_CRITICAL,
|
||||||
|
NM_PCAUSE_T_MANUF, cause_value, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
LOGPC(DOML, LOGL_NOTICE, "\n");
|
||||||
|
|
||||||
|
if (!nmsg)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return oml_mo_send_msg(mo, nmsg, NM_MT_FAILURE_EVENT_REP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void oml_fail_rep(uint16_t cause_value, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char *rep;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
rep = talloc_asprintf(tall_bts_ctx, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
osmo_signal_dispatch(SS_FAIL, cause_value, rep);
|
||||||
|
/* signal dispatch is synchronous so all the signal handlers are
|
||||||
|
finished already: we're free to free */
|
||||||
|
talloc_free(rep);
|
||||||
|
}
|
||||||
|
|
||||||
int oml_send_msg(struct msgb *msg, int is_manuf)
|
int oml_send_msg(struct msgb *msg, int is_manuf)
|
||||||
{
|
{
|
||||||
struct abis_om_hdr *omh;
|
struct abis_om_hdr *omh;
|
||||||
@@ -209,6 +154,147 @@ char *gsm_abis_mo_name(const struct gsm_abis_mo *mo)
|
|||||||
return mo_buf;
|
return mo_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void add_bts_attrs(struct msgb *msg, const struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
abis_nm_put_sw_file(msg, btstype2str(GSM_BTS_TYPE_OSMOBTS), PACKAGE_VERSION, true);
|
||||||
|
abis_nm_put_sw_file(msg, btsatttr2str(BTS_TYPE_VARIANT), btsvariant2str(bts->variant), true);
|
||||||
|
|
||||||
|
if (strlen(bts->sub_model))
|
||||||
|
abis_nm_put_sw_file(msg, btsatttr2str(BTS_SUB_MODEL), bts->sub_model, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add BTS features as 3GPP TS 52.021 §9.4.30 Manufacturer Id */
|
||||||
|
static inline void add_bts_feat(struct msgb *msg, const struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
msgb_tl16v_put(msg, NM_ATT_MANUF_ID, _NUM_BTS_FEAT/8 + 1, bts->_features_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void add_trx_attr(struct msgb *msg, struct gsm_bts_trx *trx)
|
||||||
|
{
|
||||||
|
const struct phy_instance *pinst = trx_phy_instance(trx);
|
||||||
|
|
||||||
|
abis_nm_put_sw_file(msg, btsatttr2str(TRX_PHY_VERSION), strlen(pinst->version) ? pinst->version : "Unknown",
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The number of attributes in §9.4.26 List of Required Attributes is 2 bytes,
|
||||||
|
but the Count of not-reported attributes from §9.4.64 is 1 byte */
|
||||||
|
static inline uint8_t pack_num_unreported_attr(uint16_t attrs)
|
||||||
|
{
|
||||||
|
if (attrs > 255) {
|
||||||
|
LOGP(DOML, LOGL_ERROR, "O&M Get Attributes, Count of not-reported attributes is too big: %u\n",
|
||||||
|
attrs);
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
return attrs; /* Return number of unhandled attributes */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy all the attributes accumulated in msg to out and return the total length of out buffer */
|
||||||
|
static inline int cleanup_attr_msg(uint8_t *out, int out_offset, struct msgb *msg)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
out[0] = pack_num_unreported_attr(out_offset - 1);
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
memcpy(out + out_offset, msgb_data(msg), msg->len);
|
||||||
|
len = msg->len;
|
||||||
|
msgb_free(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len + out_offset + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int handle_attrs_trx(uint8_t *out, struct gsm_bts_trx *trx, const uint8_t *attr, uint16_t attr_len)
|
||||||
|
{
|
||||||
|
uint16_t i, attr_out_index = 1; /* byte 0 is reserved for unsupported attributes counter */
|
||||||
|
struct msgb *attr_buf = oml_msgb_alloc();
|
||||||
|
|
||||||
|
if (!attr_buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (i = 0; i < attr_len; i++) {
|
||||||
|
switch (attr[i]) {
|
||||||
|
case NM_ATT_SW_CONFIG:
|
||||||
|
add_trx_attr(attr_buf, trx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DOML, LOGL_ERROR, "O&M Get Attributes [%u], %s is unsupported by TRX.\n", i,
|
||||||
|
get_value_string(abis_nm_att_names, attr[i]));
|
||||||
|
out[attr_out_index] = attr[i]; /* assemble values of supported attributes and list of unsupported ones */
|
||||||
|
attr_out_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cleanup_attr_msg(out, attr_out_index, attr_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int handle_attrs_bts(uint8_t *out, const struct gsm_bts *bts, const uint8_t *attr, uint16_t attr_len)
|
||||||
|
{
|
||||||
|
uint16_t i, attr_out_index = 1; /* byte 0 is reserved for unsupported attributes counter */
|
||||||
|
struct msgb *attr_buf = oml_msgb_alloc();
|
||||||
|
|
||||||
|
if (!attr_buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (i = 0; i < attr_len; i++) {
|
||||||
|
switch (attr[i]) {
|
||||||
|
case NM_ATT_SW_CONFIG:
|
||||||
|
add_bts_attrs(attr_buf, bts);
|
||||||
|
break;
|
||||||
|
case NM_ATT_MANUF_ID:
|
||||||
|
add_bts_feat(attr_buf, bts);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DOML, LOGL_ERROR, "O&M Get Attributes [%u], %s is unsupported by BTS.\n", i,
|
||||||
|
get_value_string(abis_nm_att_names, attr[i]));
|
||||||
|
out[attr_out_index] = attr[i]; /* assemble values of supported attributes and list of unsupported ones */
|
||||||
|
attr_out_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cleanup_attr_msg(out, attr_out_index, attr_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send 3GPP TS 52.021 §8.11.2 Get Attribute Response */
|
||||||
|
static int oml_tx_attr_resp(struct gsm_bts *bts, const struct abis_om_fom_hdr *foh, const uint8_t *attr,
|
||||||
|
uint16_t attr_len)
|
||||||
|
{
|
||||||
|
struct msgb *nmsg = oml_msgb_alloc();
|
||||||
|
uint8_t resp[MAX_VERSION_LENGTH * attr_len * 2]; /* heuristic for Attribute Response Info space requirements */
|
||||||
|
int len;
|
||||||
|
|
||||||
|
LOGP(DOML, LOGL_INFO, "%s Tx Get Attribute Response\n",
|
||||||
|
get_value_string(abis_nm_obj_class_names, foh->obj_class));
|
||||||
|
|
||||||
|
if (!nmsg)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
switch (foh->obj_class) {
|
||||||
|
case NM_OC_BTS:
|
||||||
|
len = handle_attrs_bts(resp, bts, attr, attr_len);
|
||||||
|
break;
|
||||||
|
case NM_OC_BASEB_TRANSC:
|
||||||
|
len = handle_attrs_trx(resp, gsm_bts_trx_num(bts, foh->obj_inst.trx_nr), attr, attr_len);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DOML, LOGL_ERROR, "Unsupported MO class %s in Get Attribute Response\n",
|
||||||
|
get_value_string(abis_nm_obj_class_names, foh->obj_class));
|
||||||
|
len = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
LOGP(DOML, LOGL_ERROR, "Tx Get Attribute Response FAILED with %d\n", len);
|
||||||
|
msgb_free(nmsg);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* §9.4.64 Get Attribute Response Info */
|
||||||
|
msgb_tl16v_put(nmsg, NM_ATT_GET_ARI, len, resp);
|
||||||
|
|
||||||
|
return oml_mo_send_msg(&bts->mo, nmsg, NM_MT_GET_ATTR_RESP);
|
||||||
|
}
|
||||||
|
|
||||||
/* 8.8.1 sending State Changed Event Report */
|
/* 8.8.1 sending State Changed Event Report */
|
||||||
int oml_tx_state_changed(struct gsm_abis_mo *mo)
|
int oml_tx_state_changed(struct gsm_abis_mo *mo)
|
||||||
{
|
{
|
||||||
@@ -369,27 +455,108 @@ int oml_mo_tx_sw_act_rep(struct gsm_abis_mo *mo)
|
|||||||
return oml_mo_send_msg(mo, nmsg, NM_MT_SW_ACTIVATED_REP);
|
return oml_mo_send_msg(mo, nmsg, NM_MT_SW_ACTIVATED_REP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TS 12.21 9.4.53 */
|
/* the below defaults correpsond to the libocmocore default of 1s for
|
||||||
enum abis_nm_t200_idx {
|
* DCCH and 2s for ACCH. The BSC should overried this via OML anyway. */
|
||||||
T200_SDCCH = 0,
|
const unsigned int oml_default_t200_ms[7] = {
|
||||||
T200_FACCH_F = 1,
|
[T200_SDCCH] = 1000,
|
||||||
T200_FACCH_H = 2,
|
[T200_FACCH_F] = 1000,
|
||||||
T200_SACCH_TCH_SAPI0 = 3,
|
[T200_FACCH_H] = 1000,
|
||||||
T200_SACCH_SDCCH = 4,
|
[T200_SACCH_TCH_SAPI0] = 2000,
|
||||||
T200_SDCCH_SAPI3 = 5,
|
[T200_SACCH_SDCCH] = 2000,
|
||||||
T200_SACCH_TCH_SAPI3 = 6
|
[T200_SDCCH_SAPI3] = 1000,
|
||||||
|
[T200_SACCH_TCH_SAPI3] = 2000,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TS 12.21 9.4.53 */
|
static void dl_set_t200(struct lapdm_datalink *dl, unsigned int t200_msec)
|
||||||
static const uint8_t abis_nm_t200_mult[] = {
|
{
|
||||||
[T200_SDCCH] = 5,
|
dl->dl.t200_sec = t200_msec / 1000;
|
||||||
[T200_FACCH_F] = 5,
|
dl->dl.t200_usec = (t200_msec % 1000) * 1000;
|
||||||
[T200_FACCH_H] = 5,
|
}
|
||||||
[T200_SACCH_TCH_SAPI0] = 10,
|
|
||||||
[T200_SACCH_SDCCH] = 10,
|
/* Configure LAPDm T200 timers for this lchan according to OML */
|
||||||
[T200_SDCCH_SAPI3] = 5,
|
int oml_set_lchan_t200(struct gsm_lchan *lchan)
|
||||||
[T200_SACCH_TCH_SAPI3] = 10
|
{
|
||||||
};
|
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
struct lapdm_channel *lc = &lchan->lapdm_ch;
|
||||||
|
unsigned int t200_dcch, t200_dcch_sapi3, t200_acch, t200_acch_sapi3;
|
||||||
|
|
||||||
|
/* set T200 for main and associated channel */
|
||||||
|
switch (lchan->type) {
|
||||||
|
case GSM_LCHAN_SDCCH:
|
||||||
|
t200_dcch = btsb->t200_ms[T200_SDCCH];
|
||||||
|
t200_dcch_sapi3 = btsb->t200_ms[T200_SDCCH_SAPI3];
|
||||||
|
t200_acch = btsb->t200_ms[T200_SACCH_SDCCH];
|
||||||
|
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_SDCCH];
|
||||||
|
break;
|
||||||
|
case GSM_LCHAN_TCH_F:
|
||||||
|
t200_dcch = btsb->t200_ms[T200_FACCH_F];
|
||||||
|
t200_dcch_sapi3 = btsb->t200_ms[T200_FACCH_F];
|
||||||
|
t200_acch = btsb->t200_ms[T200_SACCH_TCH_SAPI0];
|
||||||
|
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_TCH_SAPI3];
|
||||||
|
break;
|
||||||
|
case GSM_LCHAN_TCH_H:
|
||||||
|
t200_dcch = btsb->t200_ms[T200_FACCH_H];
|
||||||
|
t200_dcch_sapi3 = btsb->t200_ms[T200_FACCH_H];
|
||||||
|
t200_acch = btsb->t200_ms[T200_SACCH_TCH_SAPI0];
|
||||||
|
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_TCH_SAPI3];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGP(DLLAPD, "%s: Setting T200 D0=%u, D3=%u, S0=%u, S3=%u"
|
||||||
|
"(all in ms)\n", gsm_lchan_name(lchan), t200_dcch,
|
||||||
|
t200_dcch_sapi3, t200_acch, t200_acch_sapi3);
|
||||||
|
|
||||||
|
dl_set_t200(&lc->lapdm_dcch.datalink[DL_SAPI0], t200_dcch);
|
||||||
|
dl_set_t200(&lc->lapdm_dcch.datalink[DL_SAPI3], t200_dcch_sapi3);
|
||||||
|
dl_set_t200(&lc->lapdm_acch.datalink[DL_SAPI0], t200_acch);
|
||||||
|
dl_set_t200(&lc->lapdm_acch.datalink[DL_SAPI3], t200_acch_sapi3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3GPP TS 52.021 §8.11.1 Get Attributes has been received */
|
||||||
|
static int oml_rx_get_attr(struct gsm_bts *bts, struct msgb *msg)
|
||||||
|
{
|
||||||
|
struct abis_om_fom_hdr *foh = msgb_l3(msg);
|
||||||
|
struct tlv_parsed tp;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!foh || !bts)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
abis_nm_debugp_foh(DOML, foh);
|
||||||
|
DEBUGPC(DOML, "Rx GET ATTR\n");
|
||||||
|
|
||||||
|
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
||||||
|
if (rc < 0) {
|
||||||
|
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR, "Get Attribute parsing failure");
|
||||||
|
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TLVP_PRES_LEN(&tp, NM_ATT_LIST_REQ_ATTR, 1)) {
|
||||||
|
LOGP(DOML, LOGL_ERROR, "O&M Get Attributes message without Attribute List?!\n");
|
||||||
|
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR, "Get Attribute without Attribute List");
|
||||||
|
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = oml_tx_attr_resp(bts, foh, TLVP_VAL(&tp, NM_ATT_LIST_REQ_ATTR), TLVP_LEN(&tp, NM_ATT_LIST_REQ_ATTR));
|
||||||
|
if (rc < 0) {
|
||||||
|
LOGP(DOML, LOGL_ERROR, "Failed to respond to O&M Get Attributes message: %s\n", strerror(-rc));
|
||||||
|
switch (-rc) {
|
||||||
|
case ENOMEM:
|
||||||
|
return oml_fom_ack_nack(msg, NM_NACK_CANT_PERFORM);
|
||||||
|
case ENOTSUP:
|
||||||
|
return oml_fom_ack_nack(msg, NM_NACK_OBJCLASS_NOTSUPP);
|
||||||
|
default:
|
||||||
|
return oml_fom_ack_nack(msg, NM_NACK_RES_NOTIMPL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* 8.6.1 Set BTS Attributes has been received */
|
/* 8.6.1 Set BTS Attributes has been received */
|
||||||
static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
||||||
@@ -404,31 +571,34 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
DEBUGPC(DOML, "Rx SET BTS ATTR\n");
|
DEBUGPC(DOML, "Rx SET BTS ATTR\n");
|
||||||
|
|
||||||
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
||||||
if (rc < 0)
|
if (rc < 0) {
|
||||||
|
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR,
|
||||||
|
"New value for Attribute not supported");
|
||||||
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Test for globally unsupported stuff here */
|
/* Test for globally unsupported stuff here */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_BCCH_ARFCN)) {
|
if (TLVP_PRES_LEN(&tp, NM_ATT_BCCH_ARFCN, 2)) {
|
||||||
const uint16_t *value = (const uint16_t *) TLVP_VAL(&tp, NM_ATT_BCCH_ARFCN);
|
|
||||||
uint16_t arfcn = ntohs(tlvp_val16_unal(&tp, NM_ATT_BCCH_ARFCN));
|
uint16_t arfcn = ntohs(tlvp_val16_unal(&tp, NM_ATT_BCCH_ARFCN));
|
||||||
|
|
||||||
LOGP(DOML, LOGL_NOTICE, "MSG: %s\n", osmo_hexdump(msgb_l3(msg), msgb_l3len(msg)));
|
|
||||||
LOGP(DOML, LOGL_NOTICE, "L3=%p, VAL=%p, DIF=%tu\n", msgb_l3(msg), value,
|
|
||||||
(void *)value - (void *) msgb_l3(msg));
|
|
||||||
|
|
||||||
if (arfcn > 1024) {
|
if (arfcn > 1024) {
|
||||||
|
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_WARN_SW_WARN,
|
||||||
|
"Given ARFCN %u is not supported",
|
||||||
|
arfcn);
|
||||||
LOGP(DOML, LOGL_NOTICE, "Given ARFCN %d is not supported.\n", arfcn);
|
LOGP(DOML, LOGL_NOTICE, "Given ARFCN %d is not supported.\n", arfcn);
|
||||||
return oml_fom_ack_nack(msg, NM_NACK_FREQ_NOTAVAIL);
|
return oml_fom_ack_nack(msg, NM_NACK_FREQ_NOTAVAIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* 9.4.52 Starting Time */
|
/* 9.4.52 Starting Time */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_START_TIME)) {
|
if (TLVP_PRESENT(&tp, NM_ATT_START_TIME)) {
|
||||||
|
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR,
|
||||||
|
"NM_ATT_START_TIME Attribute not "
|
||||||
|
"supported");
|
||||||
return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP);
|
return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* merge existing BTS attributes with new attributes */
|
/* merge existing BTS attributes with new attributes */
|
||||||
tp_merged = tlvp_copy(bts->mo.nm_attr, bts);
|
tp_merged = osmo_tlvp_copy(bts->mo.nm_attr, bts);
|
||||||
tlvp_merge(tp_merged, &tp);
|
osmo_tlvp_merge(tp_merged, &tp);
|
||||||
|
|
||||||
/* Ask BTS driver to validate new merged attributes */
|
/* Ask BTS driver to validate new merged attributes */
|
||||||
rc = bts_model_check_oml(bts, foh->msg_type, bts->mo.nm_attr, tp_merged, bts);
|
rc = bts_model_check_oml(bts, foh->msg_type, bts->mo.nm_attr, tp_merged, bts);
|
||||||
@@ -444,7 +614,7 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
/* ... and actually still parse them */
|
/* ... and actually still parse them */
|
||||||
|
|
||||||
/* 9.4.25 Interference Level Boundaries */
|
/* 9.4.25 Interference Level Boundaries */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_INTERF_BOUND)) {
|
if (TLVP_PRES_LEN(&tp, NM_ATT_INTERF_BOUND, 6)) {
|
||||||
payload = TLVP_VAL(&tp, NM_ATT_INTERF_BOUND);
|
payload = TLVP_VAL(&tp, NM_ATT_INTERF_BOUND);
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
int16_t boundary = *payload;
|
int16_t boundary = *payload;
|
||||||
@@ -452,62 +622,87 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* 9.4.24 Intave Parameter */
|
/* 9.4.24 Intave Parameter */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_INTAVE_PARAM))
|
if (TLVP_PRES_LEN(&tp, NM_ATT_INTAVE_PARAM, 1))
|
||||||
btsb->interference.intave = *TLVP_VAL(&tp, NM_ATT_INTAVE_PARAM);
|
btsb->interference.intave = *TLVP_VAL(&tp, NM_ATT_INTAVE_PARAM);
|
||||||
|
|
||||||
/* 9.4.14 Connection Failure Criterion */
|
/* 9.4.14 Connection Failure Criterion */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_CONN_FAIL_CRIT)) {
|
if (TLVP_PRES_LEN(&tp, NM_ATT_CONN_FAIL_CRIT, 1)) {
|
||||||
const uint8_t *val = TLVP_VAL(&tp, NM_ATT_CONN_FAIL_CRIT);
|
const uint8_t *val = TLVP_VAL(&tp, NM_ATT_CONN_FAIL_CRIT);
|
||||||
|
|
||||||
if (TLVP_LEN(&tp, NM_ATT_CONN_FAIL_CRIT) < 2
|
switch (val[0]) {
|
||||||
|| val[0] != 0x01 || val[1] < 4 || val[1] > 64) {
|
case 0xFF: /* Osmocom specific Extension of TS 12.21 */
|
||||||
|
LOGP(DOML, LOGL_NOTICE, "WARNING: Radio Link Timeout "
|
||||||
|
"explicitly disabled, only use this for lab testing!\n");
|
||||||
|
btsb->radio_link_timeout = -1;
|
||||||
|
break;
|
||||||
|
case 0x01: /* Based on uplink SACCH (radio link timeout) */
|
||||||
|
if (TLVP_LEN(&tp, NM_ATT_CONN_FAIL_CRIT) >= 2 &&
|
||||||
|
val[1] >= 4 && val[1] <= 64) {
|
||||||
|
btsb->radio_link_timeout = val[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fall-through */
|
||||||
|
case 0x02: /* Based on RXLEV/RXQUAL measurements */
|
||||||
|
default:
|
||||||
LOGP(DOML, LOGL_NOTICE, "Given Conn. Failure Criterion "
|
LOGP(DOML, LOGL_NOTICE, "Given Conn. Failure Criterion "
|
||||||
"not supported. Please use critetion 0x01 with "
|
"not supported. Please use critetion 0x01 with "
|
||||||
"RADIO_LINK_TIMEOUT value of 4..64\n");
|
"RADIO_LINK_TIMEOUT value of 4..64\n");
|
||||||
return oml_fom_ack_nack(msg, NM_NACK_PARAM_RANGE);
|
return oml_fom_ack_nack(msg, NM_NACK_PARAM_RANGE);
|
||||||
}
|
}
|
||||||
btsb->radio_link_timeout = val[1];
|
|
||||||
}
|
}
|
||||||
/* if val[0] != 0x01: can be 'operator dependent' and needs to
|
|
||||||
* be parsed by bts driver */
|
|
||||||
|
|
||||||
/* 9.4.53 T200 */
|
/* 9.4.53 T200 */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_T200)) {
|
if (TLVP_PRES_LEN(&tp, NM_ATT_T200, ARRAY_SIZE(btsb->t200_ms))) {
|
||||||
payload = TLVP_VAL(&tp, NM_ATT_T200);
|
payload = TLVP_VAL(&tp, NM_ATT_T200);
|
||||||
for (i = 0; i < ARRAY_SIZE(btsb->t200_ms); i++)
|
for (i = 0; i < ARRAY_SIZE(btsb->t200_ms); i++) {
|
||||||
btsb->t200_ms[i] = payload[i] * abis_nm_t200_mult[i];
|
uint32_t t200_ms = payload[i] * abis_nm_t200_ms[i];
|
||||||
|
#if 0
|
||||||
|
btsb->t200_ms[i] = t200_ms;
|
||||||
|
DEBUGP(DOML, "T200[%u]: OML=%u, mult=%u => %u ms\n",
|
||||||
|
i, payload[i], abis_nm_t200_mult[i],
|
||||||
|
btsb->t200_ms[i]);
|
||||||
|
#else
|
||||||
|
/* we'd rather use the 1s/2s (long) defaults by
|
||||||
|
* libosmocore, as we appear to have some bug(s)
|
||||||
|
* related to handling T200 expiration in
|
||||||
|
* libosmogsm lapd(m) code? */
|
||||||
|
LOGP(DOML, LOGL_NOTICE, "Ignoring T200[%u] (%u ms) "
|
||||||
|
"as sent by BSC due to suspected LAPDm bug!\n",
|
||||||
|
i, t200_ms);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 9.4.31 Maximum Timing Advance */
|
/* 9.4.31 Maximum Timing Advance */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_MAX_TA))
|
if (TLVP_PRES_LEN(&tp, NM_ATT_MAX_TA, 1))
|
||||||
btsb->max_ta = *TLVP_VAL(&tp, NM_ATT_MAX_TA);
|
btsb->max_ta = *TLVP_VAL(&tp, NM_ATT_MAX_TA);
|
||||||
|
|
||||||
/* 9.4.39 Overload Period */
|
/* 9.4.39 Overload Period */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_OVERL_PERIOD))
|
if (TLVP_PRES_LEN(&tp, NM_ATT_OVERL_PERIOD, 1))
|
||||||
btsb->load.overload_period = *TLVP_VAL(&tp, NM_ATT_OVERL_PERIOD);
|
btsb->load.overload_period = *TLVP_VAL(&tp, NM_ATT_OVERL_PERIOD);
|
||||||
|
|
||||||
/* 9.4.12 CCCH Load Threshold */
|
/* 9.4.12 CCCH Load Threshold */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_CCCH_L_T))
|
if (TLVP_PRES_LEN(&tp, NM_ATT_CCCH_L_T, 1))
|
||||||
btsb->load.ccch.load_ind_thresh = *TLVP_VAL(&tp, NM_ATT_CCCH_L_T);
|
btsb->load.ccch.load_ind_thresh = *TLVP_VAL(&tp, NM_ATT_CCCH_L_T);
|
||||||
|
|
||||||
/* 9.4.11 CCCH Load Indication Period */
|
/* 9.4.11 CCCH Load Indication Period */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_CCCH_L_I_P))
|
if (TLVP_PRES_LEN(&tp, NM_ATT_CCCH_L_I_P, 1))
|
||||||
btsb->load.ccch.load_ind_period = *TLVP_VAL(&tp, NM_ATT_CCCH_L_I_P);
|
btsb->load.ccch.load_ind_period = *TLVP_VAL(&tp, NM_ATT_CCCH_L_I_P);
|
||||||
|
|
||||||
/* 9.4.44 RACH Busy Threshold */
|
/* 9.4.44 RACH Busy Threshold */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_RACH_B_THRESH)) {
|
if (TLVP_PRES_LEN(&tp, NM_ATT_RACH_B_THRESH, 1)) {
|
||||||
int16_t thresh = *TLVP_VAL(&tp, NM_ATT_RACH_B_THRESH);
|
int16_t thresh = *TLVP_VAL(&tp, NM_ATT_RACH_B_THRESH);
|
||||||
btsb->load.rach.busy_thresh = -1 * thresh;
|
btsb->load.rach.busy_thresh = -1 * thresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 9.4.45 RACH Load Averaging Slots */
|
/* 9.4.45 RACH Load Averaging Slots */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_LDAVG_SLOTS)) {
|
if (TLVP_PRES_LEN(&tp, NM_ATT_LDAVG_SLOTS, 2)) {
|
||||||
btsb->load.rach.averaging_slots =
|
btsb->load.rach.averaging_slots =
|
||||||
ntohs(tlvp_val16_unal(&tp, NM_ATT_LDAVG_SLOTS));
|
ntohs(tlvp_val16_unal(&tp, NM_ATT_LDAVG_SLOTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 9.4.10 BTS Air Timer */
|
/* 9.4.10 BTS Air Timer */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_BTS_AIR_TIMER)) {
|
if (TLVP_PRES_LEN(&tp, NM_ATT_BTS_AIR_TIMER, 1)) {
|
||||||
uint8_t t3105 = *TLVP_VAL(&tp, NM_ATT_BTS_AIR_TIMER);
|
uint8_t t3105 = *TLVP_VAL(&tp, NM_ATT_BTS_AIR_TIMER);
|
||||||
if (t3105 == 0) {
|
if (t3105 == 0) {
|
||||||
LOGP(DOML, LOGL_NOTICE,
|
LOGP(DOML, LOGL_NOTICE,
|
||||||
@@ -518,15 +713,15 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 9.4.37 NY1 */
|
/* 9.4.37 NY1 */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_NY1))
|
if (TLVP_PRES_LEN(&tp, NM_ATT_NY1, 1))
|
||||||
btsb->ny1 = *TLVP_VAL(&tp, NM_ATT_NY1);
|
btsb->ny1 = *TLVP_VAL(&tp, NM_ATT_NY1);
|
||||||
|
|
||||||
/* 9.4.8 BCCH ARFCN */
|
/* 9.4.8 BCCH ARFCN */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_BCCH_ARFCN))
|
if (TLVP_PRES_LEN(&tp, NM_ATT_BCCH_ARFCN, 2))
|
||||||
bts->c0->arfcn = ntohs(tlvp_val16_unal(&tp, NM_ATT_BCCH_ARFCN));
|
bts->c0->arfcn = ntohs(tlvp_val16_unal(&tp, NM_ATT_BCCH_ARFCN));
|
||||||
|
|
||||||
/* 9.4.9 BSIC */
|
/* 9.4.9 BSIC */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_BSIC))
|
if (TLVP_PRES_LEN(&tp, NM_ATT_BSIC, 1))
|
||||||
bts->bsic = *TLVP_VAL(&tp, NM_ATT_BSIC);
|
bts->bsic = *TLVP_VAL(&tp, NM_ATT_BSIC);
|
||||||
|
|
||||||
/* call into BTS driver to apply new attributes to hardware */
|
/* call into BTS driver to apply new attributes to hardware */
|
||||||
@@ -544,12 +739,16 @@ static int oml_rx_set_radio_attr(struct gsm_bts_trx *trx, struct msgb *msg)
|
|||||||
DEBUGPC(DOML, "Rx SET RADIO CARRIER ATTR\n");
|
DEBUGPC(DOML, "Rx SET RADIO CARRIER ATTR\n");
|
||||||
|
|
||||||
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
||||||
if (rc < 0)
|
if (rc < 0) {
|
||||||
|
oml_tx_failure_event_rep(&trx->mo, OSMO_EVT_MAJ_UNSUP_ATTR,
|
||||||
|
"New value for Set Radio Attribute not"
|
||||||
|
" supported");
|
||||||
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||||
|
}
|
||||||
|
|
||||||
/* merge existing BTS attributes with new attributes */
|
/* merge existing BTS attributes with new attributes */
|
||||||
tp_merged = tlvp_copy(trx->mo.nm_attr, trx->bts);
|
tp_merged = osmo_tlvp_copy(trx->mo.nm_attr, trx->bts);
|
||||||
tlvp_merge(tp_merged, &tp);
|
osmo_tlvp_merge(tp_merged, &tp);
|
||||||
|
|
||||||
/* Ask BTS driver to validate new merged attributes */
|
/* Ask BTS driver to validate new merged attributes */
|
||||||
rc = bts_model_check_oml(trx->bts, foh->msg_type, trx->mo.nm_attr, tp_merged, trx);
|
rc = bts_model_check_oml(trx->bts, foh->msg_type, trx->mo.nm_attr, tp_merged, trx);
|
||||||
@@ -565,7 +764,7 @@ static int oml_rx_set_radio_attr(struct gsm_bts_trx *trx, struct msgb *msg)
|
|||||||
/* ... and actually still parse them */
|
/* ... and actually still parse them */
|
||||||
|
|
||||||
/* 9.4.47 RF Max Power Reduction */
|
/* 9.4.47 RF Max Power Reduction */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_RF_MAXPOWR_R)) {
|
if (TLVP_PRES_LEN(&tp, NM_ATT_RF_MAXPOWR_R, 1)) {
|
||||||
trx->max_power_red = *TLVP_VAL(&tp, NM_ATT_RF_MAXPOWR_R) * 2;
|
trx->max_power_red = *TLVP_VAL(&tp, NM_ATT_RF_MAXPOWR_R) * 2;
|
||||||
LOGP(DOML, LOGL_INFO, "Set RF Max Power Reduction = %d dBm\n",
|
LOGP(DOML, LOGL_INFO, "Set RF Max Power Reduction = %d dBm\n",
|
||||||
trx->max_power_red);
|
trx->max_power_red);
|
||||||
@@ -590,25 +789,80 @@ static int oml_rx_set_radio_attr(struct gsm_bts_trx *trx, struct msgb *msg)
|
|||||||
trx->arfcn_num = length;
|
trx->arfcn_num = length;
|
||||||
} else
|
} else
|
||||||
trx->arfcn_num = 0;
|
trx->arfcn_num = 0;
|
||||||
|
#else
|
||||||
|
if (trx != trx->bts->c0 && TLVP_PRESENT(&tp, NM_ATT_ARFCN_LIST)) {
|
||||||
|
const uint8_t *value = TLVP_VAL(&tp, NM_ATT_ARFCN_LIST);
|
||||||
|
uint16_t _value;
|
||||||
|
uint16_t length = TLVP_LEN(&tp, NM_ATT_ARFCN_LIST);
|
||||||
|
uint16_t arfcn;
|
||||||
|
if (length != 2) {
|
||||||
|
LOGP(DOML, LOGL_ERROR, "Expecting only one ARFCN, "
|
||||||
|
"because hopping not supported\n");
|
||||||
|
/* FIXME: send NACK */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
memcpy(&_value, value, 2);
|
||||||
|
arfcn = ntohs(_value);
|
||||||
|
value += 2;
|
||||||
|
if (arfcn > 1024) {
|
||||||
|
oml_tx_failure_event_rep(&trx->bts->mo,
|
||||||
|
OSMO_EVT_WARN_SW_WARN,
|
||||||
|
"Given ARFCN %u is unsupported",
|
||||||
|
arfcn);
|
||||||
|
LOGP(DOML, LOGL_NOTICE,
|
||||||
|
"Given ARFCN %u is unsupported.\n", arfcn);
|
||||||
|
return oml_fom_ack_nack(msg, NM_NACK_FREQ_NOTAVAIL);
|
||||||
|
}
|
||||||
|
trx->arfcn = arfcn;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
/* call into BTS driver to apply new attributes to hardware */
|
/* call into BTS driver to apply new attributes to hardware */
|
||||||
return bts_model_apply_oml(trx->bts, msg, tp_merged, NM_OC_RADIO_CARRIER, trx);
|
return bts_model_apply_oml(trx->bts, msg, tp_merged, NM_OC_RADIO_CARRIER, trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int conf_lchans_for_pchan(struct gsm_bts_trx_ts *ts)
|
static int conf_lchans(struct gsm_bts_trx_ts *ts)
|
||||||
|
{
|
||||||
|
enum gsm_phys_chan_config pchan = ts->pchan;
|
||||||
|
|
||||||
|
/* RSL_MT_IPAC_PDCH_ACT style dyn PDCH */
|
||||||
|
if (pchan == GSM_PCHAN_TCH_F_PDCH)
|
||||||
|
pchan = ts->flags & TS_F_PDCH_ACTIVE? GSM_PCHAN_PDCH
|
||||||
|
: GSM_PCHAN_TCH_F;
|
||||||
|
|
||||||
|
/* Osmocom RSL CHAN ACT style dyn TS */
|
||||||
|
if (pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) {
|
||||||
|
pchan = ts->dyn.pchan_is;
|
||||||
|
|
||||||
|
/* If the dyn TS doesn't have a pchan yet, do nothing. */
|
||||||
|
if (pchan == GSM_PCHAN_NONE)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf_lchans_as_pchan(ts, pchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
int conf_lchans_as_pchan(struct gsm_bts_trx_ts *ts,
|
||||||
|
enum gsm_phys_chan_config pchan)
|
||||||
{
|
{
|
||||||
struct gsm_lchan *lchan;
|
struct gsm_lchan *lchan;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
switch (ts->pchan) {
|
switch (pchan) {
|
||||||
|
case GSM_PCHAN_CCCH_SDCCH4_CBCH:
|
||||||
|
/* fallthrough */
|
||||||
case GSM_PCHAN_CCCH_SDCCH4:
|
case GSM_PCHAN_CCCH_SDCCH4:
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
lchan = &ts->lchan[i];
|
lchan = &ts->lchan[i];
|
||||||
|
if (pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH
|
||||||
|
&& i == 2) {
|
||||||
|
lchan->type = GSM_LCHAN_CBCH;
|
||||||
|
} else {
|
||||||
lchan->type = GSM_LCHAN_SDCCH;
|
lchan->type = GSM_LCHAN_SDCCH;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case GSM_PCHAN_CCCH:
|
case GSM_PCHAN_CCCH:
|
||||||
lchan = &ts->lchan[4];
|
lchan = &ts->lchan[CCCH_LCHAN];
|
||||||
lchan->type = GSM_LCHAN_CCCH;
|
lchan->type = GSM_LCHAN_CCCH;
|
||||||
break;
|
break;
|
||||||
case GSM_PCHAN_TCH_F:
|
case GSM_PCHAN_TCH_F:
|
||||||
@@ -621,19 +875,27 @@ static int conf_lchans_for_pchan(struct gsm_bts_trx_ts *ts)
|
|||||||
lchan->type = GSM_LCHAN_TCH_H;
|
lchan->type = GSM_LCHAN_TCH_H;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
|
||||||
|
/* fallthrough */
|
||||||
case GSM_PCHAN_SDCCH8_SACCH8C:
|
case GSM_PCHAN_SDCCH8_SACCH8C:
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
lchan = &ts->lchan[i];
|
lchan = &ts->lchan[i];
|
||||||
|
if (pchan == GSM_PCHAN_SDCCH8_SACCH8C_CBCH
|
||||||
|
&& i == 2) {
|
||||||
|
lchan->type = GSM_LCHAN_CBCH;
|
||||||
|
} else {
|
||||||
lchan->type = GSM_LCHAN_SDCCH;
|
lchan->type = GSM_LCHAN_SDCCH;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GSM_PCHAN_PDCH:
|
case GSM_PCHAN_PDCH:
|
||||||
lchan = &ts->lchan[0];
|
lchan = &ts->lchan[0];
|
||||||
lchan->type = GSM_LCHAN_PDTCH;
|
lchan->type = GSM_LCHAN_PDTCH;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* FIXME */
|
LOGP(DOML, LOGL_ERROR, "Unknown/unhandled PCHAN type: %u %s\n",
|
||||||
break;
|
ts->pchan, gsm_pchan_name(ts->pchan));
|
||||||
|
return -NM_NACK_PARAM_RANGE;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -650,8 +912,12 @@ static int oml_rx_set_chan_attr(struct gsm_bts_trx_ts *ts, struct msgb *msg)
|
|||||||
DEBUGPC(DOML, "Rx SET CHAN ATTR\n");
|
DEBUGPC(DOML, "Rx SET CHAN ATTR\n");
|
||||||
|
|
||||||
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
||||||
if (rc < 0)
|
if (rc < 0) {
|
||||||
|
oml_tx_failure_event_rep(&ts->mo, OSMO_EVT_MAJ_UNSUP_ATTR,
|
||||||
|
"New value for Set Channel Attribute "
|
||||||
|
"not supported");
|
||||||
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||||
|
}
|
||||||
|
|
||||||
/* 9.4.21 HSN... */
|
/* 9.4.21 HSN... */
|
||||||
/* 9.4.27 MAIO */
|
/* 9.4.27 MAIO */
|
||||||
@@ -667,8 +933,8 @@ static int oml_rx_set_chan_attr(struct gsm_bts_trx_ts *ts, struct msgb *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* merge existing BTS attributes with new attributes */
|
/* merge existing BTS attributes with new attributes */
|
||||||
tp_merged = tlvp_copy(ts->mo.nm_attr, bts);
|
tp_merged = osmo_tlvp_copy(ts->mo.nm_attr, bts);
|
||||||
tlvp_merge(tp_merged, &tp);
|
osmo_tlvp_merge(tp_merged, &tp);
|
||||||
|
|
||||||
/* Call into BTS driver to check attribute values */
|
/* Call into BTS driver to check attribute values */
|
||||||
rc = bts_model_check_oml(bts, foh->msg_type, ts->mo.nm_attr, tp_merged, ts);
|
rc = bts_model_check_oml(bts, foh->msg_type, ts->mo.nm_attr, tp_merged, ts);
|
||||||
@@ -683,16 +949,21 @@ static int oml_rx_set_chan_attr(struct gsm_bts_trx_ts *ts, struct msgb *msg)
|
|||||||
ts->mo.nm_attr = tp_merged;
|
ts->mo.nm_attr = tp_merged;
|
||||||
|
|
||||||
/* 9.4.13 Channel Combination */
|
/* 9.4.13 Channel Combination */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_CHAN_COMB)) {
|
if (TLVP_PRES_LEN(&tp, NM_ATT_CHAN_COMB, 1)) {
|
||||||
uint8_t comb = *TLVP_VAL(&tp, NM_ATT_CHAN_COMB);
|
uint8_t comb = *TLVP_VAL(&tp, NM_ATT_CHAN_COMB);
|
||||||
ts->pchan = abis_nm_pchan4chcomb(comb);
|
ts->pchan = abis_nm_pchan4chcomb(comb);
|
||||||
conf_lchans_for_pchan(ts);
|
rc = conf_lchans(ts);
|
||||||
|
if (rc < 0) {
|
||||||
|
talloc_free(tp_merged);
|
||||||
|
/* Send NACK */
|
||||||
|
return oml_fom_ack_nack(msg, -rc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 9.4.5 ARFCN List */
|
/* 9.4.5 ARFCN List */
|
||||||
|
|
||||||
/* 9.4.60 TSC */
|
/* 9.4.60 TSC */
|
||||||
if (TLVP_PRESENT(&tp, NM_ATT_TSC) && TLVP_LEN(&tp, NM_ATT_TSC) >= 1) {
|
if (TLVP_PRES_LEN(&tp, NM_ATT_TSC, 1)) {
|
||||||
ts->tsc = *TLVP_VAL(&tp, NM_ATT_TSC);
|
ts->tsc = *TLVP_VAL(&tp, NM_ATT_TSC);
|
||||||
} else {
|
} else {
|
||||||
/* If there is no TSC specified, use the BCC */
|
/* If there is no TSC specified, use the BCC */
|
||||||
@@ -772,6 +1043,38 @@ static int oml_rx_chg_adm_state(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
return bts_model_chg_adm_state(bts, mo, obj, adm_state);
|
return bts_model_chg_adm_state(bts, mo, obj, adm_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check and report if the BTS number received via OML is incorrect:
|
||||||
|
according to 3GPP TS 52.021 §9.3 BTS number is used to distinguish between different BTS of the same Site Manager.
|
||||||
|
As we always have only single BTS per Site Manager (in case of Abis/IP with each BTS having dedicated OML connection
|
||||||
|
to BSC), the only valid values are 0 and 0xFF (means all BTS' of a given Site Manager). */
|
||||||
|
static inline bool report_bts_number_incorrect(struct gsm_bts *bts, const struct abis_om_fom_hdr *foh, bool is_formatted)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
struct gsm_abis_mo *mo = &bts->mo;
|
||||||
|
const char *form = is_formatted ?
|
||||||
|
"Unexpected BTS %d in formatted O&M %s (exp. 0 or 0xFF)" :
|
||||||
|
"Unexpected BTS %d in manufacturer O&M %s (exp. 0 or 0xFF)";
|
||||||
|
|
||||||
|
if (foh->obj_inst.bts_nr != 0 && foh->obj_inst.bts_nr != 0xff) {
|
||||||
|
LOGP(DOML, LOGL_ERROR, form, foh->obj_inst.bts_nr, get_value_string(abis_nm_msgtype_names,
|
||||||
|
foh->msg_type));
|
||||||
|
LOGPC(DOML, LOGL_ERROR, "\n");
|
||||||
|
trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
|
||||||
|
if (trx) {
|
||||||
|
trx->mo.obj_inst.bts_nr = 0;
|
||||||
|
trx->mo.obj_inst.trx_nr = foh->obj_inst.trx_nr;
|
||||||
|
trx->mo.obj_inst.ts_nr = 0xff;
|
||||||
|
mo = &trx->mo;
|
||||||
|
}
|
||||||
|
oml_tx_failure_event_rep(mo, OSMO_EVT_MAJ_UKWN_MSG, form, foh->obj_inst.bts_nr,
|
||||||
|
get_value_string(abis_nm_msgtype_names, foh->msg_type));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int down_fom(struct gsm_bts *bts, struct msgb *msg)
|
static int down_fom(struct gsm_bts *bts, struct msgb *msg)
|
||||||
{
|
{
|
||||||
struct abis_om_fom_hdr *foh = msgb_l3(msg);
|
struct abis_om_fom_hdr *foh = msgb_l3(msg);
|
||||||
@@ -780,13 +1083,19 @@ static int down_fom(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
|
|
||||||
if (msgb_l2len(msg) < sizeof(*foh)) {
|
if (msgb_l2len(msg) < sizeof(*foh)) {
|
||||||
LOGP(DOML, LOGL_NOTICE, "Formatted O&M message too short\n");
|
LOGP(DOML, LOGL_NOTICE, "Formatted O&M message too short\n");
|
||||||
|
trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
|
||||||
|
if (trx) {
|
||||||
|
trx->mo.obj_inst.bts_nr = 0;
|
||||||
|
trx->mo.obj_inst.trx_nr = foh->obj_inst.trx_nr;
|
||||||
|
trx->mo.obj_inst.ts_nr = 0xff;
|
||||||
|
oml_tx_failure_event_rep(&trx->mo, OSMO_EVT_MAJ_UKWN_MSG,
|
||||||
|
"Formatted O&M message too short");
|
||||||
|
}
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foh->obj_inst.bts_nr != 0 && foh->obj_inst.bts_nr != 0xff) {
|
if (report_bts_number_incorrect(bts, foh, true))
|
||||||
LOGP(DOML, LOGL_INFO, "Formatted O&M with BTS %d out of range.\n", foh->obj_inst.bts_nr);
|
|
||||||
return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN);
|
return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN);
|
||||||
}
|
|
||||||
|
|
||||||
switch (foh->msg_type) {
|
switch (foh->msg_type) {
|
||||||
case NM_MT_SET_BTS_ATTR:
|
case NM_MT_SET_BTS_ATTR:
|
||||||
@@ -815,9 +1124,26 @@ static int down_fom(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
case NM_MT_IPACC_SET_ATTR:
|
case NM_MT_IPACC_SET_ATTR:
|
||||||
ret = oml_ipa_set_attr(bts, msg);
|
ret = oml_ipa_set_attr(bts, msg);
|
||||||
break;
|
break;
|
||||||
|
case NM_MT_GET_ATTR:
|
||||||
|
ret = oml_rx_get_attr(bts, msg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOGP(DOML, LOGL_INFO, "unknown Formatted O&M msg_type 0x%02x\n",
|
LOGP(DOML, LOGL_INFO, "unknown Formatted O&M msg_type 0x%02x\n",
|
||||||
foh->msg_type);
|
foh->msg_type);
|
||||||
|
trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
|
||||||
|
if (trx) {
|
||||||
|
trx->mo.obj_inst.bts_nr = 0;
|
||||||
|
trx->mo.obj_inst.trx_nr = foh->obj_inst.trx_nr;
|
||||||
|
trx->mo.obj_inst.ts_nr = 0xff;
|
||||||
|
oml_tx_failure_event_rep(&trx->mo, OSMO_EVT_MAJ_UKWN_MSG,
|
||||||
|
"unknown Formatted O&M "
|
||||||
|
"msg_type 0x%02x",
|
||||||
|
foh->msg_type);
|
||||||
|
} else
|
||||||
|
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UKWN_MSG,
|
||||||
|
"unknown Formatted O&M "
|
||||||
|
"msg_type 0x%02x",
|
||||||
|
foh->msg_type);
|
||||||
ret = oml_fom_ack_nack(msg, NM_NACK_MSGTYPE_INVAL);
|
ret = oml_fom_ack_nack(msg, NM_NACK_MSGTYPE_INVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,11 +1154,6 @@ static int down_fom(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
* manufacturer related messages
|
* manufacturer related messages
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TLVP_PRES_LEN /* old libosmocore */
|
|
||||||
#define TLVP_PRES_LEN(tp, tag, min_len) \
|
|
||||||
(TLVP_PRESENT(tp, tag) && TLVP_LEN(tp, tag) >= min_len)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int oml_ipa_mo_set_attr_nse(void *obj, struct tlv_parsed *tp)
|
static int oml_ipa_mo_set_attr_nse(void *obj, struct tlv_parsed *tp)
|
||||||
{
|
{
|
||||||
struct gsm_bts *bts = container_of(obj, struct gsm_bts, gprs.nse);
|
struct gsm_bts *bts = container_of(obj, struct gsm_bts, gprs.nse);
|
||||||
@@ -986,8 +1307,15 @@ static int oml_ipa_set_attr(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
DEBUGPC(DOML, "Rx IPA SET ATTR\n");
|
DEBUGPC(DOML, "Rx IPA SET ATTR\n");
|
||||||
|
|
||||||
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
||||||
if (rc < 0)
|
if (rc < 0) {
|
||||||
|
mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);
|
||||||
|
if (!mo)
|
||||||
|
return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN);
|
||||||
|
oml_tx_failure_event_rep(mo, OSMO_EVT_MAJ_UNSUP_ATTR,
|
||||||
|
"New value for IPAC Set Attribute not "
|
||||||
|
"supported\n");
|
||||||
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Resolve MO by obj_class/obj_inst */
|
/* Resolve MO by obj_class/obj_inst */
|
||||||
mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);
|
mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);
|
||||||
@@ -1011,13 +1339,13 @@ static int rx_oml_ipa_rsl_connect(struct gsm_bts_trx *trx, struct msgb *msg,
|
|||||||
|
|
||||||
uint8_t stream_id = 0;
|
uint8_t stream_id = 0;
|
||||||
|
|
||||||
if (TLVP_PRESENT(tp, NM_ATT_IPACC_DST_IP)) {
|
if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_DST_IP, 4)) {
|
||||||
ip = ntohl(tlvp_val32_unal(tp, NM_ATT_IPACC_DST_IP));
|
ip = ntohl(tlvp_val32_unal(tp, NM_ATT_IPACC_DST_IP));
|
||||||
}
|
}
|
||||||
if (TLVP_PRESENT(tp, NM_ATT_IPACC_DST_IP_PORT)) {
|
if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_DST_IP_PORT, 2)) {
|
||||||
port = ntohs(tlvp_val16_unal(tp, NM_ATT_IPACC_DST_IP_PORT));
|
port = ntohs(tlvp_val16_unal(tp, NM_ATT_IPACC_DST_IP_PORT));
|
||||||
}
|
}
|
||||||
if (TLVP_PRESENT(tp, NM_ATT_IPACC_STREAM_ID)) {
|
if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_STREAM_ID, 1)) {
|
||||||
stream_id = *TLVP_VAL(tp, NM_ATT_IPACC_STREAM_ID);
|
stream_id = *TLVP_VAL(tp, NM_ATT_IPACC_STREAM_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1025,7 +1353,8 @@ static int rx_oml_ipa_rsl_connect(struct gsm_bts_trx *trx, struct msgb *msg,
|
|||||||
LOGP(DOML, LOGL_INFO, "Rx IPA RSL CONNECT IP=%s PORT=%u STREAM=0x%02x\n",
|
LOGP(DOML, LOGL_INFO, "Rx IPA RSL CONNECT IP=%s PORT=%u STREAM=0x%02x\n",
|
||||||
inet_ntoa(in), port, stream_id);
|
inet_ntoa(in), port, stream_id);
|
||||||
|
|
||||||
rc = e1inp_ipa_bts_rsl_connect(oml_link->ts->line, inet_ntoa(in), port);
|
rc = e1inp_ipa_bts_rsl_connect_n(oml_link->ts->line, inet_ntoa(in), port,
|
||||||
|
trx->nr);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
LOGP(DOML, LOGL_ERROR, "Error in abis_open(RSL): %d\n", rc);
|
LOGP(DOML, LOGL_ERROR, "Error in abis_open(RSL): %d\n", rc);
|
||||||
return oml_fom_ack_nack(msg, NM_NACK_CANT_PERFORM);
|
return oml_fom_ack_nack(msg, NM_NACK_CANT_PERFORM);
|
||||||
@@ -1056,10 +1385,8 @@ static int down_mom(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
msg->l3h = oh->data + 1 + idstrlen;
|
msg->l3h = oh->data + 1 + idstrlen;
|
||||||
foh = (struct abis_om_fom_hdr *) msg->l3h;
|
foh = (struct abis_om_fom_hdr *) msg->l3h;
|
||||||
|
|
||||||
if (foh->obj_inst.bts_nr != 0 && foh->obj_inst.bts_nr != 0xff) {
|
if (report_bts_number_incorrect(bts, foh, false))
|
||||||
LOGP(DOML, LOGL_INFO, "Manufacturer O&M with BTS %d out of range.\n", foh->obj_inst.bts_nr);
|
|
||||||
return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN);
|
return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN);
|
||||||
}
|
|
||||||
|
|
||||||
ret = oml_tlv_parse(&tp, foh->data, oh->length - sizeof(*foh));
|
ret = oml_tlv_parse(&tp, foh->data, oh->length - sizeof(*foh));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -1128,10 +1455,23 @@ int down_oml(struct gsm_bts *bts, struct msgb *msg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int oml_init(void)
|
static int handle_fail_sig(unsigned int subsys, unsigned int signal, void *handle,
|
||||||
|
void *signal_data)
|
||||||
{
|
{
|
||||||
DEBUGP(DOML, "Initializing OML attribute definitions\n");
|
if (signal_data)
|
||||||
tlv_def_patch(&abis_nm_att_tlvdef_ipa, &abis_nm_att_tlvdef);
|
oml_tx_failure_event_rep(handle, signal, "%s", signal_data);
|
||||||
|
else
|
||||||
|
oml_tx_failure_event_rep(handle, signal, "");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oml_init(struct gsm_abis_mo *mo)
|
||||||
|
{
|
||||||
|
DEBUGP(DOML, "Initializing OML attribute definitions\n");
|
||||||
|
tlv_def_patch(&abis_nm_att_tlvdef_ipa_local, &abis_nm_att_tlvdef_ipa);
|
||||||
|
tlv_def_patch(&abis_nm_att_tlvdef_ipa_local, &abis_nm_att_tlvdef);
|
||||||
|
osmo_signal_register_handler(SS_FAIL, handle_fail_sig, mo);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -538,12 +538,6 @@ static int paging_signal_cbfn(unsigned int subsys, unsigned int signal, void *hd
|
|||||||
struct paging_state *ps = btsb->paging_state;
|
struct paging_state *ps = btsb->paging_state;
|
||||||
struct gsm48_system_information_type_3 *si3 = (void *) bts->si_buf[SYSINFO_TYPE_3];
|
struct gsm48_system_information_type_3 *si3 = (void *) bts->si_buf[SYSINFO_TYPE_3];
|
||||||
|
|
||||||
#warning "TODO: Remove this when setting u8NbrOfAgch is implemented properly"
|
|
||||||
if (si3->control_channel_desc.bs_ag_blks_res != 1)
|
|
||||||
LOGP(DPAG, LOGL_ERROR,
|
|
||||||
"Paging: BS_AG_BLKS_RES = %d != 1 not fully supported\n",
|
|
||||||
si3->control_channel_desc.bs_ag_blks_res);
|
|
||||||
|
|
||||||
paging_si_update(ps, &si3->control_channel_desc);
|
paging_si_update(ps, &si3->control_channel_desc);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -29,9 +29,11 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include <osmocom/core/talloc.h>
|
#include <osmocom/core/talloc.h>
|
||||||
#include <osmocom/core/select.h>
|
#include <osmocom/core/select.h>
|
||||||
|
#include <osmocom/core/socket.h>
|
||||||
#include <osmo-bts/logging.h>
|
#include <osmo-bts/logging.h>
|
||||||
#include <osmo-bts/gsm_data.h>
|
#include <osmo-bts/gsm_data.h>
|
||||||
#include <osmo-bts/pcu_if.h>
|
#include <osmo-bts/pcu_if.h>
|
||||||
@@ -39,12 +41,12 @@
|
|||||||
#include <osmo-bts/bts.h>
|
#include <osmo-bts/bts.h>
|
||||||
#include <osmo-bts/rsl.h>
|
#include <osmo-bts/rsl.h>
|
||||||
#include <osmo-bts/signal.h>
|
#include <osmo-bts/signal.h>
|
||||||
#include <osmo-bts/bts_model.h>
|
#include <osmo-bts/l1sap.h>
|
||||||
|
|
||||||
uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
|
uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
|
||||||
|
|
||||||
extern struct gsm_network bts_gsmnet;
|
extern struct gsm_network bts_gsmnet;
|
||||||
extern int pcu_direct;
|
int pcu_direct = 0;
|
||||||
static int avail_lai = 0, avail_nse = 0, avail_cell = 0, avail_nsvc[2] = {0, 0};
|
static int avail_lai = 0, avail_nse = 0, avail_cell = 0, avail_nsvc[2] = {0, 0};
|
||||||
|
|
||||||
static const char *sapi_string[] = {
|
static const char *sapi_string[] = {
|
||||||
@@ -57,27 +59,7 @@ static const char *sapi_string[] = {
|
|||||||
[PCU_IF_SAPI_PTCCH] = "PTCCH",
|
[PCU_IF_SAPI_PTCCH] = "PTCCH",
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FIXME: common l1if include ? */
|
|
||||||
int l1if_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);
|
|
||||||
|
|
||||||
static int pcu_sock_send(struct gsm_network *net, struct msgb *msg);
|
static int pcu_sock_send(struct gsm_network *net, struct msgb *msg);
|
||||||
/* FIXME: move this to libosmocore */
|
|
||||||
int osmo_unixsock_listen(struct osmo_fd *bfd, int type, const char *path);
|
|
||||||
|
|
||||||
|
|
||||||
static struct gsm_bts_trx *trx_by_nr(struct gsm_bts *bts, uint8_t trx_nr)
|
|
||||||
{
|
|
||||||
struct gsm_bts_trx *trx;
|
|
||||||
|
|
||||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
|
||||||
if (trx->nr == trx_nr)
|
|
||||||
return trx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PCU messages
|
* PCU messages
|
||||||
@@ -99,6 +81,32 @@ struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr)
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ts_should_be_pdch(struct gsm_bts_trx_ts *ts) {
|
||||||
|
if (ts->pchan == GSM_PCHAN_PDCH)
|
||||||
|
return true;
|
||||||
|
if (ts->pchan == GSM_PCHAN_TCH_F_PDCH) {
|
||||||
|
/* When we're busy deactivating the PDCH, we first set
|
||||||
|
* DEACT_PENDING, tell the PCU about it and wait for a
|
||||||
|
* response. So DEACT_PENDING means "no PDCH" to the PCU.
|
||||||
|
* Similarly, when we're activating PDCH, we set the
|
||||||
|
* ACT_PENDING and wait for an activation response from the
|
||||||
|
* PCU, so ACT_PENDING means "is PDCH". */
|
||||||
|
if (ts->flags & TS_F_PDCH_ACTIVE)
|
||||||
|
return !(ts->flags & TS_F_PDCH_DEACT_PENDING);
|
||||||
|
else
|
||||||
|
return (ts->flags & TS_F_PDCH_ACT_PENDING);
|
||||||
|
}
|
||||||
|
if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) {
|
||||||
|
/*
|
||||||
|
* When we're busy de-/activating the PDCH, we first set
|
||||||
|
* ts->dyn.pchan_want, tell the PCU about it and wait for a
|
||||||
|
* response. So only care about dyn.pchan_want here.
|
||||||
|
*/
|
||||||
|
return ts->dyn.pchan_want == GSM_PCHAN_PDCH;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int pcu_tx_info_ind(void)
|
int pcu_tx_info_ind(void)
|
||||||
{
|
{
|
||||||
struct gsm_network *net = &bts_gsmnet;
|
struct gsm_network *net = &bts_gsmnet;
|
||||||
@@ -202,7 +210,7 @@ int pcu_tx_info_ind(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
trx = trx_by_nr(bts, i);
|
trx = gsm_bts_trx_num(bts, i);
|
||||||
if (!trx)
|
if (!trx)
|
||||||
break;
|
break;
|
||||||
info_ind->trx[i].pdch_mask = 0;
|
info_ind->trx[i].pdch_mask = 0;
|
||||||
@@ -211,10 +219,10 @@ int pcu_tx_info_ind(void)
|
|||||||
for (j = 0; j < 8; j++) {
|
for (j = 0; j < 8; j++) {
|
||||||
ts = &trx->ts[j];
|
ts = &trx->ts[j];
|
||||||
if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED
|
if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED
|
||||||
&& ts->pchan == GSM_PCHAN_PDCH) {
|
&& ts_should_be_pdch(ts)) {
|
||||||
info_ind->trx[i].pdch_mask |= (1 << j);
|
info_ind->trx[i].pdch_mask |= (1 << j);
|
||||||
info_ind->trx[i].tsc[j] =
|
info_ind->trx[i].tsc[j] =
|
||||||
(ts->tsc >= 0) ? ts->tsc : bts->tsc;
|
(ts->tsc >= 0) ? ts->tsc : bts->bsic & 7;
|
||||||
LOGP(DPCU, LOGL_INFO, "trx=%d ts=%d: "
|
LOGP(DPCU, LOGL_INFO, "trx=%d ts=%d: "
|
||||||
"available (tsc=%d arfcn=%d)\n",
|
"available (tsc=%d arfcn=%d)\n",
|
||||||
trx->nr, ts->nr,
|
trx->nr, ts->nr,
|
||||||
@@ -316,17 +324,24 @@ int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
|||||||
|
|
||||||
int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
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,
|
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len,
|
||||||
int8_t rssi)
|
int8_t rssi, uint16_t ber10k, int16_t bto, int16_t lqual)
|
||||||
{
|
{
|
||||||
struct msgb *msg;
|
struct msgb *msg;
|
||||||
struct gsm_pcu_if *pcu_prim;
|
struct gsm_pcu_if *pcu_prim;
|
||||||
struct gsm_pcu_if_data *data_ind;
|
struct gsm_pcu_if_data *data_ind;
|
||||||
struct gsm_bts *bts = ts->trx->bts;
|
struct gsm_bts *bts = ts->trx->bts;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
LOGP(DPCU, LOGL_DEBUG, "Sending data indication: is_ptcch=%d arfcn=%d "
|
LOGP(DPCU, LOGL_DEBUG, "Sending data indication: is_ptcch=%d arfcn=%d "
|
||||||
"block=%d data=%s\n", is_ptcch, arfcn, block_nr,
|
"block=%d data=%s\n", is_ptcch, arfcn, block_nr,
|
||||||
osmo_hexdump(data, len));
|
osmo_hexdump(data, len));
|
||||||
|
|
||||||
|
if (lqual / 10 < btsb->min_qual_norm) {
|
||||||
|
LOGP(DPCU, LOGL_DEBUG, "Link quality %"PRId16" is below threshold %f, dropping packet\n",
|
||||||
|
lqual, btsb->min_qual_norm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
msg = pcu_msgb_alloc(PCU_IF_MSG_DATA_IND, bts->nr);
|
msg = pcu_msgb_alloc(PCU_IF_MSG_DATA_IND, bts->nr);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -334,19 +349,24 @@ int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
|||||||
data_ind = &pcu_prim->u.data_ind;
|
data_ind = &pcu_prim->u.data_ind;
|
||||||
|
|
||||||
data_ind->sapi = (is_ptcch) ? PCU_IF_SAPI_PTCCH : PCU_IF_SAPI_PDTCH;
|
data_ind->sapi = (is_ptcch) ? PCU_IF_SAPI_PTCCH : PCU_IF_SAPI_PDTCH;
|
||||||
|
data_ind->rssi = rssi;
|
||||||
data_ind->fn = fn;
|
data_ind->fn = fn;
|
||||||
data_ind->arfcn = arfcn;
|
data_ind->arfcn = arfcn;
|
||||||
data_ind->trx_nr = ts->trx->nr;
|
data_ind->trx_nr = ts->trx->nr;
|
||||||
data_ind->ts_nr = ts->nr;
|
data_ind->ts_nr = ts->nr;
|
||||||
data_ind->block_nr = block_nr;
|
data_ind->block_nr = block_nr;
|
||||||
data_ind->rssi = rssi;
|
data_ind->rssi = rssi;
|
||||||
|
data_ind->ber10k = ber10k;
|
||||||
|
data_ind->ta_offs_qbits = bto;
|
||||||
|
data_ind->lqual_cb = lqual;
|
||||||
memcpy(data_ind->data, data, len);
|
memcpy(data_ind->data, data, len);
|
||||||
data_ind->len = len;
|
data_ind->len = len;
|
||||||
|
|
||||||
return pcu_sock_send(&bts_gsmnet, msg);
|
return pcu_sock_send(&bts_gsmnet, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint8_t ra, uint32_t fn)
|
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)
|
||||||
{
|
{
|
||||||
struct msgb *msg;
|
struct msgb *msg;
|
||||||
struct gsm_pcu_if *pcu_prim;
|
struct gsm_pcu_if *pcu_prim;
|
||||||
@@ -365,6 +385,8 @@ int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint8_t ra, uint32_t fn)
|
|||||||
rach_ind->ra = ra;
|
rach_ind->ra = ra;
|
||||||
rach_ind->qta = qta;
|
rach_ind->qta = qta;
|
||||||
rach_ind->fn = fn;
|
rach_ind->fn = fn;
|
||||||
|
rach_ind->is_11bit = is_11bit;
|
||||||
|
rach_ind->burst_type = burst_type;
|
||||||
|
|
||||||
return pcu_sock_send(&bts_gsmnet, msg);
|
return pcu_sock_send(&bts_gsmnet, msg);
|
||||||
}
|
}
|
||||||
@@ -503,7 +525,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
|
|||||||
break;
|
break;
|
||||||
case PCU_IF_SAPI_PDTCH:
|
case PCU_IF_SAPI_PDTCH:
|
||||||
case PCU_IF_SAPI_PTCCH:
|
case PCU_IF_SAPI_PTCCH:
|
||||||
trx = trx_by_nr(bts, data_req->trx_nr);
|
trx = gsm_bts_trx_num(bts, data_req->trx_nr);
|
||||||
if (!trx) {
|
if (!trx) {
|
||||||
LOGP(DPCU, LOGL_ERROR, "Received PCU data request with "
|
LOGP(DPCU, LOGL_ERROR, "Received PCU data request with "
|
||||||
"not existing TRX %d\n", data_req->trx_nr);
|
"not existing TRX %d\n", data_req->trx_nr);
|
||||||
@@ -512,7 +534,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
|
|||||||
}
|
}
|
||||||
ts = &trx->ts[data_req->ts_nr];
|
ts = &trx->ts[data_req->ts_nr];
|
||||||
is_ptcch = (data_req->sapi == PCU_IF_SAPI_PTCCH);
|
is_ptcch = (data_req->sapi == PCU_IF_SAPI_PTCCH);
|
||||||
rc = l1if_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn,
|
rc = l1sap_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn,
|
||||||
data_req->block_nr, data_req->data, data_req->len);
|
data_req->block_nr, data_req->data, data_req->len);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -524,6 +546,28 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pcu_rx_txt_ind(struct gsm_bts *bts,
|
||||||
|
struct gsm_pcu_if_txt_ind *txt)
|
||||||
|
{
|
||||||
|
switch (txt->type) {
|
||||||
|
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);
|
||||||
|
osmo_strlcpy(bts->pcu_version, txt->text, MAX_VERSION_LENGTH);
|
||||||
|
break;
|
||||||
|
case PCU_OML_ALERT:
|
||||||
|
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_EXT_ALARM, txt->text);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DPCU, LOGL_ERROR, "Unknown TXT_IND type %u received\n",
|
||||||
|
txt->type);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int pcu_rx_act_req(struct gsm_bts *bts,
|
static int pcu_rx_act_req(struct gsm_bts *bts,
|
||||||
struct gsm_pcu_if_act_req *act_req)
|
struct gsm_pcu_if_act_req *act_req)
|
||||||
{
|
{
|
||||||
@@ -534,21 +578,23 @@ static int pcu_rx_act_req(struct gsm_bts *bts,
|
|||||||
(act_req->activate) ? "Activate" : "Deactivate",
|
(act_req->activate) ? "Activate" : "Deactivate",
|
||||||
act_req->trx_nr, act_req->ts_nr);
|
act_req->trx_nr, act_req->ts_nr);
|
||||||
|
|
||||||
trx = trx_by_nr(bts, act_req->trx_nr);
|
trx = gsm_bts_trx_num(bts, act_req->trx_nr);
|
||||||
if (!trx || act_req->ts_nr >= 8)
|
if (!trx || act_req->ts_nr >= 8)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
lchan = trx->ts[act_req->ts_nr].lchan;
|
lchan = trx->ts[act_req->ts_nr].lchan;
|
||||||
lchan->rel_act_kind = LCHAN_REL_ACT_PCU;
|
lchan->rel_act_kind = LCHAN_REL_ACT_PCU;
|
||||||
if (lchan->type != GSM_LCHAN_PDTCH) {
|
if (lchan->type != GSM_LCHAN_PDTCH) {
|
||||||
LOGP(DPCU, LOGL_ERROR, "Lchan is not of type PDCH, but %d.\n",
|
LOGP(DPCU, LOGL_ERROR,
|
||||||
lchan->type);
|
"%s request, but lchan is not of type PDTCH (is %s)\n",
|
||||||
|
(act_req->activate) ? "Activate" : "Deactivate",
|
||||||
|
gsm_lchant_name(lchan->type));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (act_req->activate)
|
if (act_req->activate)
|
||||||
bts_model_rsl_chan_act(lchan, NULL);
|
l1sap_chan_act(trx, gsm_lchan2chan_nr(lchan), NULL);
|
||||||
else
|
else
|
||||||
bts_model_rsl_chan_rel(lchan);
|
l1sap_chan_rel(trx, gsm_lchan2chan_nr(lchan));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -570,6 +616,9 @@ static int pcu_rx(struct gsm_network *net, uint8_t msg_type,
|
|||||||
case PCU_IF_MSG_ACT_REQ:
|
case PCU_IF_MSG_ACT_REQ:
|
||||||
rc = pcu_rx_act_req(bts, &pcu_prim->u.act_req);
|
rc = pcu_rx_act_req(bts, &pcu_prim->u.act_req);
|
||||||
break;
|
break;
|
||||||
|
case PCU_IF_MSG_TXT_IND:
|
||||||
|
rc = pcu_rx_txt_ind(bts, &pcu_prim->u.txt_ind);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOGP(DPCU, LOGL_ERROR, "Received unknwon PCU msg type %d\n",
|
LOGP(DPCU, LOGL_ERROR, "Received unknwon PCU msg type %d\n",
|
||||||
msg_type);
|
msg_type);
|
||||||
@@ -629,6 +678,8 @@ static void pcu_sock_close(struct pcu_sock_state *state)
|
|||||||
bts = llist_entry(state->net->bts_list.next, struct gsm_bts, list);
|
bts = llist_entry(state->net->bts_list.next, struct gsm_bts, list);
|
||||||
|
|
||||||
LOGP(DPCU, LOGL_NOTICE, "PCU socket has LOST connection\n");
|
LOGP(DPCU, LOGL_NOTICE, "PCU socket has LOST connection\n");
|
||||||
|
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_PCU_VERS, NULL);
|
||||||
|
bts->pcu_version[0] = '\0';
|
||||||
|
|
||||||
close(bfd->fd);
|
close(bfd->fd);
|
||||||
bfd->fd = -1;
|
bfd->fd = -1;
|
||||||
@@ -645,7 +696,7 @@ static void pcu_sock_close(struct pcu_sock_state *state)
|
|||||||
|
|
||||||
/* release PDCH */
|
/* release PDCH */
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
trx = trx_by_nr(bts, i);
|
trx = gsm_bts_trx_num(bts, i);
|
||||||
if (!trx)
|
if (!trx)
|
||||||
break;
|
break;
|
||||||
for (j = 0; j < 8; j++) {
|
for (j = 0; j < 8; j++) {
|
||||||
@@ -653,7 +704,8 @@ static void pcu_sock_close(struct pcu_sock_state *state)
|
|||||||
if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED
|
if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED
|
||||||
&& ts->pchan == GSM_PCHAN_PDCH) {
|
&& ts->pchan == GSM_PCHAN_PDCH) {
|
||||||
ts->lchan->rel_act_kind = LCHAN_REL_ACT_PCU;
|
ts->lchan->rel_act_kind = LCHAN_REL_ACT_PCU;
|
||||||
bts_model_rsl_chan_rel(ts->lchan);
|
l1sap_chan_rel(trx,
|
||||||
|
gsm_lchan2chan_nr(ts->lchan));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -811,7 +863,7 @@ static int pcu_sock_accept(struct osmo_fd *bfd, unsigned int flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pcu_sock_init(void)
|
int pcu_sock_init(const char *path)
|
||||||
{
|
{
|
||||||
struct pcu_sock_state *state;
|
struct pcu_sock_state *state;
|
||||||
struct osmo_fd *bfd;
|
struct osmo_fd *bfd;
|
||||||
@@ -827,12 +879,13 @@ int pcu_sock_init(void)
|
|||||||
|
|
||||||
bfd = &state->listen_bfd;
|
bfd = &state->listen_bfd;
|
||||||
|
|
||||||
rc = osmo_unixsock_listen(bfd, SOCK_SEQPACKET, "/tmp/pcu_bts");
|
bfd->fd = osmo_sock_unix_init(SOCK_SEQPACKET, 0, path,
|
||||||
if (rc < 0) {
|
OSMO_SOCK_F_BIND);
|
||||||
LOGP(DPCU, LOGL_ERROR, "Could not create unix socket: %s\n",
|
if (bfd->fd < 0) {
|
||||||
strerror(errno));
|
LOGP(DPCU, LOGL_ERROR, "Could not create %s unix socket: %s\n",
|
||||||
|
path, strerror(errno));
|
||||||
talloc_free(state);
|
talloc_free(state);
|
||||||
return rc;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bfd->when = BSC_FD_READ;
|
bfd->when = BSC_FD_READ;
|
||||||
@@ -874,53 +927,13 @@ void pcu_sock_exit(void)
|
|||||||
bts_gsmnet.pcu_state = NULL;
|
bts_gsmnet.pcu_state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: move this to libosmocore */
|
bool pcu_connected(void) {
|
||||||
int osmo_unixsock_listen(struct osmo_fd *bfd, int type, const char *path)
|
struct gsm_network *net = &bts_gsmnet;
|
||||||
{
|
struct pcu_sock_state *state = net->pcu_state;
|
||||||
struct sockaddr_un local;
|
|
||||||
unsigned int namelen;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
bfd->fd = socket(AF_UNIX, type, 0);
|
if (!state)
|
||||||
|
return false;
|
||||||
if (bfd->fd < 0) {
|
if (state->conn_bfd.fd <= 0)
|
||||||
fprintf(stderr, "Failed to create Unix Domain Socket.\n");
|
return false;
|
||||||
return -1;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
local.sun_family = AF_UNIX;
|
|
||||||
strncpy(local.sun_path, path, sizeof(local.sun_path));
|
|
||||||
local.sun_path[sizeof(local.sun_path) - 1] = '\0';
|
|
||||||
unlink(local.sun_path);
|
|
||||||
|
|
||||||
/* we use the same magic that X11 uses in Xtranssock.c for
|
|
||||||
* calculating the proper length of the sockaddr */
|
|
||||||
#if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
|
|
||||||
local.sun_len = strlen(local.sun_path);
|
|
||||||
#endif
|
|
||||||
#if defined(BSD44SOCKETS) || defined(SUN_LEN)
|
|
||||||
namelen = SUN_LEN(&local);
|
|
||||||
#else
|
|
||||||
namelen = strlen(local.sun_path) +
|
|
||||||
offsetof(struct sockaddr_un, sun_path);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rc = bind(bfd->fd, (struct sockaddr *) &local, namelen);
|
|
||||||
if (rc != 0) {
|
|
||||||
fprintf(stderr, "Failed to bind the unix domain socket. '%s'\n",
|
|
||||||
local.sun_path);
|
|
||||||
close(bfd->fd);
|
|
||||||
bfd->fd = -1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listen(bfd->fd, 0) != 0) {
|
|
||||||
fprintf(stderr, "Failed to listen.\n");
|
|
||||||
close(bfd->fd);
|
|
||||||
bfd->fd = -1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
163
src/common/phy_link.c
Normal file
163
src/common/phy_link.c
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
#include <osmocom/core/talloc.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/phy_link.h>
|
||||||
|
#include <osmo-bts/oml.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/bts_model.h>
|
||||||
|
|
||||||
|
static LLIST_HEAD(g_phy_links);
|
||||||
|
|
||||||
|
struct phy_link *phy_link_by_num(int num)
|
||||||
|
{
|
||||||
|
struct phy_link *plink;
|
||||||
|
|
||||||
|
llist_for_each_entry(plink, &g_phy_links, list) {
|
||||||
|
if (plink->num == num)
|
||||||
|
return plink;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct phy_link *phy_link_create(void *ctx, int num)
|
||||||
|
{
|
||||||
|
struct phy_link *plink;
|
||||||
|
|
||||||
|
if (phy_link_by_num(num))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
plink = talloc_zero(ctx, struct phy_link);
|
||||||
|
plink->num = num;
|
||||||
|
plink->state = PHY_LINK_SHUTDOWN;
|
||||||
|
INIT_LLIST_HEAD(&plink->instances);
|
||||||
|
llist_add_tail(&plink->list, &g_phy_links);
|
||||||
|
|
||||||
|
bts_model_phy_link_set_defaults(plink);
|
||||||
|
|
||||||
|
return plink;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct value_string phy_link_state_vals[] = {
|
||||||
|
{ PHY_LINK_SHUTDOWN, "shutdown" },
|
||||||
|
{ PHY_LINK_CONNECTING, "connecting" },
|
||||||
|
{ PHY_LINK_CONNECTED, "connected" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
void phy_link_state_set(struct phy_link *plink, enum phy_link_state state)
|
||||||
|
{
|
||||||
|
struct phy_instance *pinst;
|
||||||
|
|
||||||
|
LOGP(DL1C, LOGL_INFO, "PHY link state change %s -> %s\n",
|
||||||
|
get_value_string(phy_link_state_vals, plink->state),
|
||||||
|
get_value_string(phy_link_state_vals, state));
|
||||||
|
|
||||||
|
/* notify all TRX associated with this phy */
|
||||||
|
llist_for_each_entry(pinst, &plink->instances, list) {
|
||||||
|
struct gsm_bts_trx *trx = pinst->trx;
|
||||||
|
if (!trx)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case PHY_LINK_CONNECTED:
|
||||||
|
LOGP(DL1C, LOGL_INFO, "trx_set_avail(1)\n");
|
||||||
|
trx_set_available(trx, 1);
|
||||||
|
break;
|
||||||
|
case PHY_LINK_SHUTDOWN:
|
||||||
|
LOGP(DL1C, LOGL_INFO, "trx_set_avail(0)\n");
|
||||||
|
trx_set_available(trx, 0);
|
||||||
|
break;
|
||||||
|
case PHY_LINK_CONNECTING:
|
||||||
|
/* nothing to do */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plink->state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num)
|
||||||
|
{
|
||||||
|
struct phy_instance *pinst;
|
||||||
|
|
||||||
|
llist_for_each_entry(pinst, &plink->instances, list) {
|
||||||
|
if (pinst->num == num)
|
||||||
|
return pinst;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct phy_instance *phy_instance_create(struct phy_link *plink, int num)
|
||||||
|
{
|
||||||
|
struct phy_instance *pinst;
|
||||||
|
|
||||||
|
if (phy_instance_by_num(plink, num))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pinst = talloc_zero(plink, struct phy_instance);
|
||||||
|
pinst->num = num;
|
||||||
|
pinst->phy_link = plink;
|
||||||
|
llist_add_tail(&pinst->list, &plink->instances);
|
||||||
|
|
||||||
|
bts_model_phy_instance_set_defaults(pinst);
|
||||||
|
|
||||||
|
return pinst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void phy_instance_link_to_trx(struct phy_instance *pinst, struct gsm_bts_trx *trx)
|
||||||
|
{
|
||||||
|
trx->role_bts.l1h = pinst;
|
||||||
|
pinst->trx = trx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void phy_instance_destroy(struct phy_instance *pinst)
|
||||||
|
{
|
||||||
|
/* remove from list of instances in the link */
|
||||||
|
llist_del(&pinst->list);
|
||||||
|
|
||||||
|
/* remove reverse link from TRX */
|
||||||
|
OSMO_ASSERT(pinst->trx->role_bts.l1h == pinst);
|
||||||
|
pinst->trx->role_bts.l1h = NULL;
|
||||||
|
pinst->trx = NULL;
|
||||||
|
|
||||||
|
talloc_free(pinst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void phy_link_destroy(struct phy_link *plink)
|
||||||
|
{
|
||||||
|
struct phy_instance *pinst, *pinst2;
|
||||||
|
|
||||||
|
llist_for_each_entry_safe(pinst, pinst2, &plink->instances, list)
|
||||||
|
phy_instance_destroy(pinst);
|
||||||
|
|
||||||
|
talloc_free(plink);
|
||||||
|
}
|
||||||
|
|
||||||
|
int phy_links_open(void)
|
||||||
|
{
|
||||||
|
struct phy_link *plink;
|
||||||
|
|
||||||
|
llist_for_each_entry(plink, &g_phy_links, list) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = bts_model_phy_link_open(plink);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *phy_instance_name(struct phy_instance *pinst)
|
||||||
|
{
|
||||||
|
static char buf[32];
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "phy%u.%u", pinst->phy_link->num,
|
||||||
|
pinst->num);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
99
src/common/power_control.c
Normal file
99
src/common/power_control.c
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/* MS Power Control Loop L1 */
|
||||||
|
|
||||||
|
/* (C) 2014 by Holger Hans Peter Freyther
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/measurement.h>
|
||||||
|
#include <osmo-bts/bts_model.h>
|
||||||
|
#include <osmo-bts/l1sap.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.
|
||||||
|
*/
|
||||||
|
int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
|
||||||
|
const uint8_t ms_power, const int rxLevel)
|
||||||
|
{
|
||||||
|
int rx;
|
||||||
|
int cur_dBm, new_dBm, new_pwr;
|
||||||
|
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
const enum gsm_band band = bts->band;
|
||||||
|
|
||||||
|
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)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* What is the difference between what we want and received?
|
||||||
|
* Ignore a margin that is within the range of measurement
|
||||||
|
* and MS output issues.
|
||||||
|
*/
|
||||||
|
rx = btsb->ul_power_target - rxLevel;
|
||||||
|
if (rx >= 0 && rx < 1)
|
||||||
|
return 0;
|
||||||
|
if (rx < 0 && rx > -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* We don't really care about the truncation of int + float */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1059
src/common/rsl.c
1059
src/common/rsl.c
File diff suppressed because it is too large
Load Diff
1712
src/common/scheduler.c
Normal file
1712
src/common/scheduler.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,82 +0,0 @@
|
|||||||
/* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
|
|
||||||
*
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU 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 <sys/types.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
|
||||||
//#include <osmocom/bb/common/osmocom_data.h>
|
|
||||||
#include <osmo-bts/support.h>
|
|
||||||
|
|
||||||
struct bts_support bts_support;
|
|
||||||
|
|
||||||
void bts_support_init(void)
|
|
||||||
{
|
|
||||||
struct bts_support *sup = &bts_support;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
memset(sup, 0, sizeof(*sup));
|
|
||||||
|
|
||||||
/* crypto supprot */
|
|
||||||
sup->a5_1 = 0;
|
|
||||||
sup->a5_2 = 0;
|
|
||||||
sup->a5_3 = 0;
|
|
||||||
sup->a5_4 = 0;
|
|
||||||
sup->a5_5 = 0;
|
|
||||||
sup->a5_6 = 0;
|
|
||||||
sup->a5_7 = 0;
|
|
||||||
/* set supported frequencies */
|
|
||||||
for(i = 1; i <= 124; i++) // P-GSM
|
|
||||||
sup->freq_map[i >> 3] |= (1 << (i & 7));
|
|
||||||
for(i = 512; i <= 885; i++) // DCS
|
|
||||||
sup->freq_map[i >> 3] |= (1 << (i & 7));
|
|
||||||
for(i = 975; i <= 1023; i++) // E-GSM extension
|
|
||||||
sup->freq_map[i >> 3] |= (1 << (i & 7));
|
|
||||||
sup->freq_map[0] |= 1; // channel 0
|
|
||||||
for(i = 955; i <= 974; i++) // R-GSM extension
|
|
||||||
sup->freq_map[i >> 3] |= (1 << (i & 7));
|
|
||||||
/* channel combinations */
|
|
||||||
sup->chan_comb[NM_CHANC_mainBCCH] = 1;
|
|
||||||
sup->chan_comb[NM_CHANC_BCCHComb] = 1;
|
|
||||||
sup->chan_comb[NM_CHANC_SDCCH] = 1;
|
|
||||||
sup->chan_comb[NM_CHANC_TCHFull] = 1;
|
|
||||||
sup->chan_comb[NM_CHANC_TCHHalf] = 1;
|
|
||||||
/* codec */
|
|
||||||
sup->full_v1 = 1;
|
|
||||||
sup->full_v2 = 1;
|
|
||||||
sup->full_v3 = 1;
|
|
||||||
sup->half_v1 = 1;
|
|
||||||
sup->half_v3 = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *bts_support_comb_name(uint8_t chan_comb)
|
|
||||||
{
|
|
||||||
if (chan_comb == NM_CHANC_mainBCCH)
|
|
||||||
return("BCCH");
|
|
||||||
if (chan_comb == NM_CHANC_BCCHComb)
|
|
||||||
return("BCCH+SDCCH/4");
|
|
||||||
if (chan_comb == NM_CHANC_SDCCH)
|
|
||||||
return("SDCCH/8");
|
|
||||||
if (chan_comb == NM_CHANC_TCHFull)
|
|
||||||
return("TCH/F");
|
|
||||||
if (chan_comb == NM_CHANC_TCHHalf)
|
|
||||||
return("TCH/H");
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -22,12 +22,21 @@
|
|||||||
#include <osmocom/gsm/gsm_utils.h>
|
#include <osmocom/gsm/gsm_utils.h>
|
||||||
#include <osmocom/gsm/sysinfo.h>
|
#include <osmocom/gsm/sysinfo.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
#include <osmo-bts/gsm_data.h>
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
#define BTS_HAS_SI(bts, sinum) ((bts)->si_valid & (1 << sinum))
|
/* properly increment SI2q index and return SI2q data for scheduling */
|
||||||
|
static inline uint8_t *get_si2q_inc_index(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
uint8_t i = bts->si2q_index;
|
||||||
|
/* si2q_count is the max si2q_index value, not the number of messages */
|
||||||
|
bts->si2q_index = (bts->si2q_index + 1) % (bts->si2q_count + 1);
|
||||||
|
|
||||||
|
return (uint8_t *)GSM_BTS_SI2Q(bts, i);
|
||||||
|
}
|
||||||
|
|
||||||
/* Apply the rules from 05.02 6.3.1.3 Mapping of BCCH Data */
|
/* Apply the rules from 05.02 6.3.1.3 Mapping of BCCH Data */
|
||||||
uint8_t *bts_sysinfo_get(struct gsm_bts *bts, struct gsm_time *g_time)
|
uint8_t *bts_sysinfo_get(struct gsm_bts *bts, const struct gsm_time *g_time)
|
||||||
{
|
{
|
||||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
unsigned int tc4_cnt = 0;
|
unsigned int tc4_cnt = 0;
|
||||||
@@ -76,21 +85,20 @@ uint8_t *bts_sysinfo_get(struct gsm_bts *bts, struct gsm_time *g_time)
|
|||||||
/* iterate over 2ter, 2quater, 9, 13 */
|
/* iterate over 2ter, 2quater, 9, 13 */
|
||||||
/* determine how many SI we need to send on TC=4,
|
/* determine how many SI we need to send on TC=4,
|
||||||
* and which of them we send when */
|
* and which of them we send when */
|
||||||
if (BTS_HAS_SI(bts, SYSINFO_TYPE_2ter)) {
|
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter) && GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis)) {
|
||||||
tc4_sub[tc4_cnt] = SYSINFO_TYPE_2ter;
|
tc4_sub[tc4_cnt] = SYSINFO_TYPE_2ter;
|
||||||
tc4_cnt += 1; /* 2bis */
|
tc4_cnt += 1;
|
||||||
}
|
}
|
||||||
if (BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) &&
|
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) &&
|
||||||
(BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) ||
|
(GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) || GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))) {
|
||||||
BTS_HAS_SI(bts, SYSINFO_TYPE_2bis))) {
|
|
||||||
tc4_sub[tc4_cnt] = SYSINFO_TYPE_2quater;
|
tc4_sub[tc4_cnt] = SYSINFO_TYPE_2quater;
|
||||||
tc4_cnt += 1;
|
tc4_cnt += 1;
|
||||||
}
|
}
|
||||||
if (BTS_HAS_SI(bts, SYSINFO_TYPE_13)) {
|
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_13)) {
|
||||||
tc4_sub[tc4_cnt] = SYSINFO_TYPE_13;
|
tc4_sub[tc4_cnt] = SYSINFO_TYPE_13;
|
||||||
tc4_cnt += 1;
|
tc4_cnt += 1;
|
||||||
}
|
}
|
||||||
if (BTS_HAS_SI(bts, SYSINFO_TYPE_9)) {
|
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_9)) {
|
||||||
/* FIXME: check SI3 scheduling info! */
|
/* FIXME: check SI3 scheduling info! */
|
||||||
tc4_sub[tc4_cnt] = SYSINFO_TYPE_9;
|
tc4_sub[tc4_cnt] = SYSINFO_TYPE_9;
|
||||||
tc4_cnt += 1;
|
tc4_cnt += 1;
|
||||||
@@ -101,26 +109,30 @@ uint8_t *bts_sysinfo_get(struct gsm_bts *bts, struct gsm_time *g_time)
|
|||||||
else {
|
else {
|
||||||
/* increment static counter by one, modulo count */
|
/* increment static counter by one, modulo count */
|
||||||
btsb->si.tc4_ctr = (btsb->si.tc4_ctr + 1) % tc4_cnt;
|
btsb->si.tc4_ctr = (btsb->si.tc4_ctr + 1) % tc4_cnt;
|
||||||
|
|
||||||
|
if (tc4_sub[btsb->si.tc4_ctr] == SYSINFO_TYPE_2quater)
|
||||||
|
return get_si2q_inc_index(bts);
|
||||||
|
|
||||||
return GSM_BTS_SI(bts, tc4_sub[btsb->si.tc4_ctr]);
|
return GSM_BTS_SI(bts, tc4_sub[btsb->si.tc4_ctr]);
|
||||||
}
|
}
|
||||||
case 5:
|
case 5:
|
||||||
/* 2bis, 2ter, 2quater */
|
/* 2bis, 2ter, 2quater */
|
||||||
if (BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) &&
|
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) && !GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
||||||
!BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
|
||||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_2bis);
|
return GSM_BTS_SI(bts, SYSINFO_TYPE_2bis);
|
||||||
|
|
||||||
else if (BTS_HAS_SI(bts, SYSINFO_TYPE_2ter) &&
|
else if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter) && !GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis))
|
||||||
!BTS_HAS_SI(bts, SYSINFO_TYPE_2bis))
|
|
||||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_2ter);
|
return GSM_BTS_SI(bts, SYSINFO_TYPE_2ter);
|
||||||
|
|
||||||
else if (BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) &&
|
else if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) && GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
||||||
BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
|
||||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_2bis);
|
return GSM_BTS_SI(bts, SYSINFO_TYPE_2bis);
|
||||||
|
|
||||||
else if (BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) &&
|
else if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) &&
|
||||||
!BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) &&
|
!GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) && !GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
||||||
!BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
return get_si2q_inc_index(bts);
|
||||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_2quater);
|
|
||||||
|
/* simply send SI2 if we have nothing else to send */
|
||||||
|
else
|
||||||
|
return GSM_BTS_SI(bts, SYSINFO_TYPE_2);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_3);
|
return GSM_BTS_SI(bts, SYSINFO_TYPE_3);
|
||||||
@@ -128,7 +140,22 @@ uint8_t *bts_sysinfo_get(struct gsm_bts *bts, struct gsm_time *g_time)
|
|||||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_4);
|
return GSM_BTS_SI(bts, SYSINFO_TYPE_4);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
/* this should never bve reached. We must transmit a BCCH
|
||||||
|
* message on the normal BCCH in all cases. */
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t num_agch(struct gsm_bts_trx *trx, const char * arg)
|
||||||
|
{
|
||||||
|
struct gsm_bts *b = trx->bts;
|
||||||
|
struct gsm48_system_information_type_3 *si3;
|
||||||
|
if (GSM_BTS_HAS_SI(b, SYSINFO_TYPE_3)) {
|
||||||
|
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 "
|
||||||
|
"value as SI3 is not available yet, fallback to 1\n", arg);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *lchan_sacch_get(struct gsm_lchan *lchan)
|
uint8_t *lchan_sacch_get(struct gsm_lchan *lchan)
|
||||||
@@ -136,10 +163,10 @@ uint8_t *lchan_sacch_get(struct gsm_lchan *lchan)
|
|||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
|
|
||||||
for (tmp = lchan->si.last + 1; tmp != lchan->si.last; tmp = (tmp + 1) % _MAX_SYSINFO_TYPE) {
|
for (tmp = lchan->si.last + 1; tmp != lchan->si.last; tmp = (tmp + 1) % _MAX_SYSINFO_TYPE) {
|
||||||
if (lchan->si.valid & (1 << tmp)) {
|
if (!(lchan->si.valid & (1 << tmp)))
|
||||||
|
continue;
|
||||||
lchan->si.last = tmp;
|
lchan->si.last = tmp;
|
||||||
return lchan->si.buf[tmp];
|
return GSM_LCHAN_SI(lchan, tmp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,12 +33,12 @@
|
|||||||
static int get_pa_drive_level_mdBm(const struct power_amp *pa,
|
static int get_pa_drive_level_mdBm(const struct power_amp *pa,
|
||||||
int desired_p_out_mdBm, unsigned int arfcn)
|
int desired_p_out_mdBm, unsigned int arfcn)
|
||||||
{
|
{
|
||||||
if (arfcn >= ARRAY_SIZE(pa->calib.gain_mdB))
|
if (arfcn >= ARRAY_SIZE(pa->calib.delta_mdB))
|
||||||
return INT_MIN;
|
return INT_MIN;
|
||||||
|
|
||||||
/* FIXME: temperature compensation */
|
/* FIXME: temperature compensation */
|
||||||
|
|
||||||
return desired_p_out_mdBm - pa->calib.gain_mdB[arfcn];
|
return desired_p_out_mdBm - pa->nominal_gain_mdB - pa->calib.delta_mdB[arfcn];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* maximum output power of the system */
|
/* maximum output power of the system */
|
||||||
@@ -58,7 +58,7 @@ int get_p_nominal_mdBm(struct gsm_bts_trx *trx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* calculate the target total output power required, reduced by both
|
/* calculate the target total output power required, reduced by both
|
||||||
* OML and RSL, but ignoring the attenutation required for power ramping and
|
* OML and RSL, but ignoring the attenuation required for power ramping and
|
||||||
* thermal management */
|
* thermal management */
|
||||||
int get_p_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie)
|
int get_p_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie)
|
||||||
{
|
{
|
||||||
@@ -71,7 +71,7 @@ int get_p_target_mdBm_lchan(struct gsm_lchan *lchan)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* calculate the actual total output power required, taking into account the
|
/* calculate the actual total output power required, taking into account the
|
||||||
* attenutation required for power ramping but not thermal management */
|
* attenuation required for power ramping but not thermal management */
|
||||||
int get_p_actual_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm)
|
int get_p_actual_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm)
|
||||||
{
|
{
|
||||||
struct trx_power_params *tpp = &trx->power_params;
|
struct trx_power_params *tpp = &trx->power_params;
|
||||||
@@ -81,7 +81,7 @@ int get_p_actual_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* calculate the effective total output power required, taking into account the
|
/* calculate the effective total output power required, taking into account the
|
||||||
* attenutation required for power ramping and thermal management */
|
* attenuation required for power ramping and thermal management */
|
||||||
int get_p_eff_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm)
|
int get_p_eff_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm)
|
||||||
{
|
{
|
||||||
struct trx_power_params *tpp = &trx->power_params;
|
struct trx_power_params *tpp = &trx->power_params;
|
||||||
@@ -144,7 +144,7 @@ int get_p_trxout_target_mdBm_lchan(struct gsm_lchan *lchan)
|
|||||||
* one hand side to avoid very fast dynamic load changes towards the PA power
|
* one hand side to avoid very fast dynamic load changes towards the PA power
|
||||||
* supply, but is also needed in order to avoid a DoS by too many subscriber
|
* supply, but is also needed in order to avoid a DoS by too many subscriber
|
||||||
* attempting to register at the same time. Rather, grow the cell slowly in
|
* attempting to register at the same time. Rather, grow the cell slowly in
|
||||||
* radius than start with the full raduis at once. */
|
* radius than start with the full radius at once. */
|
||||||
|
|
||||||
static int we_are_ramping_up(struct gsm_bts_trx *trx)
|
static int we_are_ramping_up(struct gsm_bts_trx *trx)
|
||||||
{
|
{
|
||||||
@@ -158,7 +158,7 @@ static int we_are_ramping_up(struct gsm_bts_trx *trx)
|
|||||||
|
|
||||||
static void power_ramp_do_step(struct gsm_bts_trx *trx, int first);
|
static void power_ramp_do_step(struct gsm_bts_trx *trx, int first);
|
||||||
|
|
||||||
/* timer call-back for the ramp tumer */
|
/* timer call-back for the ramp timer */
|
||||||
static void power_ramp_timer_cb(void *_trx)
|
static void power_ramp_timer_cb(void *_trx)
|
||||||
{
|
{
|
||||||
struct gsm_bts_trx *trx = _trx;
|
struct gsm_bts_trx *trx = _trx;
|
||||||
@@ -289,3 +289,18 @@ int power_ramp_start(struct gsm_bts_trx *trx, int p_total_tgt_mdBm, int bypass)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* determine the initial transceiver output power at start-up time */
|
||||||
|
int power_ramp_initial_power_mdBm(struct gsm_bts_trx *trx)
|
||||||
|
{
|
||||||
|
struct trx_power_params *tpp = &trx->power_params;
|
||||||
|
int pout_mdBm;
|
||||||
|
|
||||||
|
/* this is the maximum initial output on the antenna connector
|
||||||
|
* towards the antenna */
|
||||||
|
pout_mdBm = tpp->ramp.max_initial_pout_mdBm;
|
||||||
|
|
||||||
|
/* use this as input to compute transceiver board power
|
||||||
|
* (reflecting gains in internal/external amplifiers */
|
||||||
|
return get_p_trxout_eff_mdBm(trx, pout_mdBm);
|
||||||
|
}
|
||||||
|
|||||||
507
src/common/vty.c
507
src/common/vty.c
@@ -1,6 +1,6 @@
|
|||||||
/* OsmoBTS VTY interface */
|
/* OsmoBTS VTY interface */
|
||||||
|
|
||||||
/* (C) 2011 by Harald Welte <laforge@gnumonks.org>
|
/* (C) 2011-2014 by Harald Welte <laforge@gnumonks.org>
|
||||||
*
|
*
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*
|
*
|
||||||
@@ -21,34 +21,72 @@
|
|||||||
|
|
||||||
#include "btsconfig.h"
|
#include "btsconfig.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include <osmocom/core/talloc.h>
|
#include <osmocom/core/talloc.h>
|
||||||
#include <osmocom/gsm/abis_nm.h>
|
#include <osmocom/gsm/abis_nm.h>
|
||||||
#include <osmocom/vty/vty.h>
|
#include <osmocom/vty/vty.h>
|
||||||
#include <osmocom/vty/command.h>
|
#include <osmocom/vty/command.h>
|
||||||
#include <osmocom/vty/logging.h>
|
#include <osmocom/vty/logging.h>
|
||||||
|
#include <osmocom/vty/misc.h>
|
||||||
|
#include <osmocom/vty/ports.h>
|
||||||
|
#include <osmocom/core/gsmtap.h>
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
#include <osmocom/trau/osmo_ortp.h>
|
#include <osmocom/trau/osmo_ortp.h>
|
||||||
|
|
||||||
|
|
||||||
#include <osmo-bts/logging.h>
|
#include <osmo-bts/logging.h>
|
||||||
#include <osmo-bts/gsm_data.h>
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/phy_link.h>
|
||||||
#include <osmo-bts/abis.h>
|
#include <osmo-bts/abis.h>
|
||||||
#include <osmo-bts/bts.h>
|
#include <osmo-bts/bts.h>
|
||||||
#include <osmo-bts/rsl.h>
|
#include <osmo-bts/rsl.h>
|
||||||
#include <osmo-bts/oml.h>
|
#include <osmo-bts/oml.h>
|
||||||
#include <osmo-bts/signal.h>
|
#include <osmo-bts/signal.h>
|
||||||
#include <osmo-bts/bts_model.h>
|
#include <osmo-bts/bts_model.h>
|
||||||
|
#include <osmo-bts/pcu_if.h>
|
||||||
#include <osmo-bts/measurement.h>
|
#include <osmo-bts/measurement.h>
|
||||||
#include <osmo-bts/vty.h>
|
#include <osmo-bts/vty.h>
|
||||||
|
#include <osmo-bts/l1sap.h>
|
||||||
|
|
||||||
|
#define VTY_STR "Configure the VTY\n"
|
||||||
|
|
||||||
enum node_type bts_vty_go_parent(struct vty *vty)
|
int g_vty_port_num = OSMO_VTY_PORT_BTS;
|
||||||
|
|
||||||
|
struct phy_instance *vty_get_phy_instance(struct vty *vty, int phy_nr, int inst_nr)
|
||||||
|
{
|
||||||
|
struct phy_link *plink = phy_link_by_num(phy_nr);
|
||||||
|
struct phy_instance *pinst;
|
||||||
|
|
||||||
|
if (!plink) {
|
||||||
|
vty_out(vty, "Cannot find PHY link number %d%s",
|
||||||
|
phy_nr, VTY_NEWLINE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pinst = phy_instance_by_num(plink, inst_nr);
|
||||||
|
if (!pinst) {
|
||||||
|
vty_out(vty, "Cannot find PHY instance number %d%s",
|
||||||
|
inst_nr, VTY_NEWLINE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return pinst;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_vty_go_parent(struct vty *vty)
|
||||||
{
|
{
|
||||||
switch (vty->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 TRX_NODE:
|
case TRX_NODE:
|
||||||
vty->node = BTS_NODE;
|
vty->node = BTS_NODE;
|
||||||
{
|
{
|
||||||
@@ -56,6 +94,7 @@ enum node_type bts_vty_go_parent(struct vty *vty)
|
|||||||
vty->index = trx->bts;
|
vty->index = trx->bts;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PHY_NODE:
|
||||||
default:
|
default:
|
||||||
vty->node = CONFIG_NODE;
|
vty->node = CONFIG_NODE;
|
||||||
}
|
}
|
||||||
@@ -67,6 +106,8 @@ int bts_vty_is_config_node(struct vty *vty, int node)
|
|||||||
switch (node) {
|
switch (node) {
|
||||||
case TRX_NODE:
|
case TRX_NODE:
|
||||||
case BTS_NODE:
|
case BTS_NODE:
|
||||||
|
case PHY_NODE:
|
||||||
|
case PHY_INST_NODE:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
@@ -77,6 +118,17 @@ gDEFUN(ournode_exit, ournode_exit_cmd, "exit",
|
|||||||
"Exit current node, go down to provious node")
|
"Exit current node, go down to provious node")
|
||||||
{
|
{
|
||||||
switch (vty->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:
|
case TRX_NODE:
|
||||||
vty->node = BTS_NODE;
|
vty->node = BTS_NODE;
|
||||||
{
|
{
|
||||||
@@ -127,18 +179,41 @@ struct gsm_network *gsmnet_from_vty(struct vty *v)
|
|||||||
|
|
||||||
static struct cmd_node bts_node = {
|
static struct cmd_node bts_node = {
|
||||||
BTS_NODE,
|
BTS_NODE,
|
||||||
"%s(bts)#",
|
"%s(bts)# ",
|
||||||
1,
|
1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct cmd_node trx_node = {
|
static struct cmd_node trx_node = {
|
||||||
TRX_NODE,
|
TRX_NODE,
|
||||||
"%s(trx)#",
|
"%s(trx)# ",
|
||||||
1,
|
1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
gDEFUN(cfg_bts_auto_band, cfg_bts_auto_band_cmd,
|
||||||
|
"auto-band",
|
||||||
|
"Automatically select band for ARFCN based on configured band\n")
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = vty->index;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
|
btsb->auto_band = 1;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
gDEFUN(cfg_bts_no_auto_band, cfg_bts_no_auto_band_cmd,
|
||||||
|
"no auto-band",
|
||||||
|
NO_STR "Automatically select band for ARFCN based on configured band\n")
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = vty->index;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
|
btsb->auto_band = 0;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DEFUN(cfg_bts_trx, cfg_bts_trx_cmd,
|
DEFUN(cfg_bts_trx, cfg_bts_trx_cmd,
|
||||||
"trx <0-0>",
|
"trx <0-254>",
|
||||||
"Select a TRX to configure\n" "TRX number\n")
|
"Select a TRX to configure\n" "TRX number\n")
|
||||||
{
|
{
|
||||||
int trx_nr = atoi(argv[0]);
|
int trx_nr = atoi(argv[0]);
|
||||||
@@ -147,7 +222,10 @@ DEFUN(cfg_bts_trx, cfg_bts_trx_cmd,
|
|||||||
|
|
||||||
trx = gsm_bts_trx_num(bts, trx_nr);
|
trx = gsm_bts_trx_num(bts, trx_nr);
|
||||||
if (!trx) {
|
if (!trx) {
|
||||||
vty_out(vty, "Unknown TRX %u%s", trx_nr, VTY_NEWLINE);
|
vty_out(vty, "Unknown TRX %u. Available TRX are: 0..%u%s",
|
||||||
|
trx_nr, bts->num_trx - 1, VTY_NEWLINE);
|
||||||
|
vty_out(vty, "Hint: Check if commandline option -t matches the"
|
||||||
|
"number of available transceivers!%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,20 +240,27 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
|||||||
{
|
{
|
||||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
struct gsm_bts_trx *trx;
|
struct gsm_bts_trx *trx;
|
||||||
|
char buf_casecnvt[256];
|
||||||
|
int i;
|
||||||
|
|
||||||
vty_out(vty, "bts %u%s", bts->nr, VTY_NEWLINE);
|
vty_out(vty, "bts %u%s", bts->nr, VTY_NEWLINE);
|
||||||
if (bts->description)
|
if (bts->description)
|
||||||
vty_out(vty, " description %s%s", bts->description, VTY_NEWLINE);
|
vty_out(vty, " description %s%s", bts->description, VTY_NEWLINE);
|
||||||
vty_out(vty, " band %s%s", gsm_band_name(bts->band), VTY_NEWLINE);
|
vty_out(vty, " band %s%s", gsm_band_name(bts->band), VTY_NEWLINE);
|
||||||
|
if (btsb->auto_band)
|
||||||
|
vty_out(vty, " auto-band%s", VTY_NEWLINE);
|
||||||
vty_out(vty, " ipa unit-id %u %u%s",
|
vty_out(vty, " ipa unit-id %u %u%s",
|
||||||
bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE);
|
bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE);
|
||||||
vty_out(vty, " oml remote-ip %s%s", btsb->bsc_oml_host, VTY_NEWLINE);
|
vty_out(vty, " oml remote-ip %s%s", btsb->bsc_oml_host, VTY_NEWLINE);
|
||||||
vty_out(vty, " rtp jitter-buffer %u%s", btsb->rtp_jitter_buf_ms,
|
vty_out(vty, " rtp jitter-buffer %u", btsb->rtp_jitter_buf_ms);
|
||||||
VTY_NEWLINE);
|
if (btsb->rtp_jitter_adaptive)
|
||||||
|
vty_out(vty, " adaptive");
|
||||||
|
vty_out(vty, "%s", VTY_NEWLINE);
|
||||||
vty_out(vty, " paging queue-size %u%s", paging_get_queue_max(btsb->paging_state),
|
vty_out(vty, " paging queue-size %u%s", paging_get_queue_max(btsb->paging_state),
|
||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
vty_out(vty, " paging lifetime %u%s", paging_get_lifetime(btsb->paging_state),
|
vty_out(vty, " paging lifetime %u%s", paging_get_lifetime(btsb->paging_state),
|
||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
|
vty_out(vty, " uplink-power-target %d%s", btsb->ul_power_target, VTY_NEWLINE);
|
||||||
if (btsb->agch_queue_thresh_level != GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT
|
if (btsb->agch_queue_thresh_level != GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT
|
||||||
|| btsb->agch_queue_low_level != GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT
|
|| btsb->agch_queue_low_level != GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT
|
||||||
|| btsb->agch_queue_high_level != GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT)
|
|| btsb->agch_queue_high_level != GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT)
|
||||||
@@ -183,10 +268,28 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
|||||||
btsb->agch_queue_thresh_level, btsb->agch_queue_low_level,
|
btsb->agch_queue_thresh_level, btsb->agch_queue_low_level,
|
||||||
btsb->agch_queue_high_level, VTY_NEWLINE);
|
btsb->agch_queue_high_level, VTY_NEWLINE);
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
if (gsmtap_sapi_mask & (1 << i)) {
|
||||||
|
osmo_str2lower(buf_casecnvt, get_value_string(gsmtap_sapi_names, i));
|
||||||
|
vty_out(vty, " gsmtap-sapi %s%s", buf_casecnvt, VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gsmtap_sapi_acch) {
|
||||||
|
osmo_str2lower(buf_casecnvt, get_value_string(gsmtap_sapi_names, GSMTAP_CHANNEL_ACCH));
|
||||||
|
vty_out(vty, " gsmtap-sapi %s%s", buf_casecnvt, VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
vty_out(vty, " min-qual-rach %.0f%s", btsb->min_qual_rach * 10.0f,
|
||||||
|
VTY_NEWLINE);
|
||||||
|
vty_out(vty, " min-qual-norm %.0f%s", btsb->min_qual_norm * 10.0f,
|
||||||
|
VTY_NEWLINE);
|
||||||
|
if (strcmp(btsb->pcu.sock_path, PCU_SOCK_DEFAULT))
|
||||||
|
vty_out(vty, " pcu-socket %s%s", btsb->pcu.sock_path, VTY_NEWLINE);
|
||||||
|
|
||||||
bts_model_config_write_bts(vty, bts);
|
bts_model_config_write_bts(vty, bts);
|
||||||
|
|
||||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||||
struct trx_power_params *tpp = &trx->power_params;
|
struct trx_power_params *tpp = &trx->power_params;
|
||||||
|
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||||
vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE);
|
vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE);
|
||||||
|
|
||||||
if (trx->power_params.user_gain_mdB)
|
if (trx->power_params.user_gain_mdB)
|
||||||
@@ -198,6 +301,11 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
|||||||
tpp->ramp.step_size_mdB, VTY_NEWLINE);
|
tpp->ramp.step_size_mdB, VTY_NEWLINE);
|
||||||
vty_out(vty, " power-ramp step-interval %d%s",
|
vty_out(vty, " power-ramp step-interval %d%s",
|
||||||
tpp->ramp.step_interval_sec, VTY_NEWLINE);
|
tpp->ramp.step_interval_sec, VTY_NEWLINE);
|
||||||
|
vty_out(vty, " ms-power-control %s%s",
|
||||||
|
trx->ms_power_control == 0 ? "dsp" : "osmo",
|
||||||
|
VTY_NEWLINE);
|
||||||
|
vty_out(vty, " phy %u instance %u%s", pinst->phy_link->num,
|
||||||
|
pinst->num, VTY_NEWLINE);
|
||||||
|
|
||||||
bts_model_config_write_trx(vty, trx);
|
bts_model_config_write_trx(vty, trx);
|
||||||
}
|
}
|
||||||
@@ -214,11 +322,50 @@ static int config_write_bts(struct vty *vty)
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void config_write_phy_single(struct vty *vty, struct phy_link *plink)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
vty_out(vty, "phy %u%s", plink->num, VTY_NEWLINE);
|
||||||
|
bts_model_config_write_phy(vty, plink);
|
||||||
|
|
||||||
|
for (i = 0; i < 255; i++) {
|
||||||
|
struct phy_instance *pinst = phy_instance_by_num(plink, i);
|
||||||
|
if (!pinst)
|
||||||
|
break;
|
||||||
|
vty_out(vty, " instance %u%s", pinst->num, VTY_NEWLINE);
|
||||||
|
bts_model_config_write_phy_inst(vty, pinst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int config_write_phy(struct vty *vty)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 255; i++) {
|
||||||
|
struct phy_link *plink = phy_link_by_num(i);
|
||||||
|
if (!plink)
|
||||||
|
break;
|
||||||
|
config_write_phy_single(vty, plink);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int config_write_dummy(struct vty *vty)
|
static int config_write_dummy(struct vty *vty)
|
||||||
{
|
{
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_vty_telnet_port, cfg_vty_telnet_port_cmd,
|
||||||
|
"vty telnet-port <0-65535>",
|
||||||
|
VTY_STR "Set the VTY telnet port\n"
|
||||||
|
"TCP Port number\n")
|
||||||
|
{
|
||||||
|
g_vty_port_num = atoi(argv[0]);
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* per-BTS configuration */
|
/* per-BTS configuration */
|
||||||
DEFUN(cfg_bts,
|
DEFUN(cfg_bts,
|
||||||
cfg_bts_cmd,
|
cfg_bts_cmd,
|
||||||
@@ -319,13 +466,15 @@ DEFUN_HIDDEN(cfg_bts_rtp_bind_ip,
|
|||||||
|
|
||||||
DEFUN(cfg_bts_rtp_jitbuf,
|
DEFUN(cfg_bts_rtp_jitbuf,
|
||||||
cfg_bts_rtp_jitbuf_cmd,
|
cfg_bts_rtp_jitbuf_cmd,
|
||||||
"rtp jitter-buffer <0-10000>",
|
"rtp jitter-buffer <0-10000> [adaptive]",
|
||||||
RTP_STR "RTP jitter buffer\n" "jitter buffer in ms\n")
|
RTP_STR "RTP jitter buffer\n" "jitter buffer in ms\n")
|
||||||
{
|
{
|
||||||
struct gsm_bts *bts = vty->index;
|
struct gsm_bts *bts = vty->index;
|
||||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
btsb->rtp_jitter_buf_ms = atoi(argv[0]);
|
btsb->rtp_jitter_buf_ms = atoi(argv[0]);
|
||||||
|
if (argc > 1)
|
||||||
|
btsb->rtp_jitter_adaptive = true;
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -396,6 +545,63 @@ DEFUN(cfg_bts_agch_queue_mgmt_default,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_bts_ul_power_target, cfg_bts_ul_power_target_cmd,
|
||||||
|
"uplink-power-target <-110-0>",
|
||||||
|
"Set the nominal target Rx Level for uplink power control loop\n"
|
||||||
|
"Target uplink Rx level in dBm\n")
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = vty->index;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
|
btsb->ul_power_target = atoi(argv[0]);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = vty->index;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
|
btsb->min_qual_rach = strtof(argv[0], NULL) / 10.0f;
|
||||||
|
|
||||||
|
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")
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = vty->index;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
|
btsb->min_qual_norm = strtof(argv[0], NULL) / 10.0f;
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_bts_pcu_sock, cfg_bts_pcu_sock_cmd,
|
||||||
|
"pcu-socket PATH",
|
||||||
|
"Configure the PCU socket file/path name\n")
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = vty->index;
|
||||||
|
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||||
|
|
||||||
|
if (btsb->pcu.sock_path) {
|
||||||
|
/* FIXME: close the interface? */
|
||||||
|
talloc_free(btsb->pcu.sock_path);
|
||||||
|
}
|
||||||
|
btsb->pcu.sock_path = talloc_strdup(btsb, argv[0]);
|
||||||
|
/* FIXME: re-open the interface? */
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define DB_DBM_STR \
|
#define DB_DBM_STR \
|
||||||
"Unit is dB (decibels)\n" \
|
"Unit is dB (decibels)\n" \
|
||||||
"Unit is mdB (milli-decibels, or rather 1/10000 bel)\n"
|
"Unit is mdB (milli-decibels, or rather 1/10000 bel)\n"
|
||||||
@@ -460,7 +666,44 @@ DEFUN(cfg_trx_pr_step_interval, cfg_trx_pr_step_interval_cmd,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_trx_ms_power_control, cfg_trx_ms_power_control_cmd,
|
||||||
|
"ms-power-control (dsp|osmo)",
|
||||||
|
"Mobile Station Power Level Control (change requires restart)\n"
|
||||||
|
"Handled by DSP\n" "Handled by OsmoBTS\n")
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx = vty->index;
|
||||||
|
|
||||||
|
trx->ms_power_control = argv[0][0] == 'd' ? 0 : 1;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_trx_phy, cfg_trx_phy_cmd,
|
||||||
|
"phy <0-255> instance <0-255>",
|
||||||
|
"Configure PHY Link+Instance for this TRX\n"
|
||||||
|
"PHY Link number\n" "PHY instance\n" "PHY Instance number")
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx = vty->index;
|
||||||
|
struct phy_link *plink = phy_link_by_num(atoi(argv[0]));
|
||||||
|
struct phy_instance *pinst;
|
||||||
|
|
||||||
|
if (!plink) {
|
||||||
|
vty_out(vty, "phy%s does not exist%s",
|
||||||
|
argv[0], VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
pinst = phy_instance_by_num(plink, atoi(argv[1]));
|
||||||
|
if (!pinst) {
|
||||||
|
vty_out(vty, "phy%s instance %s does not exit%s",
|
||||||
|
argv[0], argv[1], VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
trx->role_bts.l1h = pinst;
|
||||||
|
pinst->trx = trx;
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* ======================================================================
|
/* ======================================================================
|
||||||
* SHOW
|
* SHOW
|
||||||
@@ -473,15 +716,26 @@ static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms)
|
|||||||
abis_nm_avail_name(nms->availability), VTY_NEWLINE);
|
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(struct vty *vty, struct gsm_bts *bts)
|
static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
|
||||||
{
|
{
|
||||||
struct gsm_bts_role_bts *btsb = bts->role;
|
struct gsm_bts_role_bts *btsb = bts->role;
|
||||||
|
|
||||||
vty_out(vty, "BTS %u is of %s type in band %s, has CI %u LAC %u, "
|
vty_out(vty, "BTS %u is of %s type in band %s, has CI %u LAC %u, "
|
||||||
"BSIC %u, TSC %u and %u TRX%s",
|
"BSIC %u and %u TRX%s",
|
||||||
bts->nr, "FIXME", gsm_band_name(bts->band),
|
bts->nr, "FIXME", gsm_band_name(bts->band),
|
||||||
bts->cell_identity,
|
bts->cell_identity,
|
||||||
bts->location_area_code, bts->bsic, bts->tsc,
|
bts->location_area_code, bts->bsic,
|
||||||
bts->num_trx, VTY_NEWLINE);
|
bts->num_trx, VTY_NEWLINE);
|
||||||
vty_out(vty, " Description: %s%s",
|
vty_out(vty, " Description: %s%s",
|
||||||
bts->description ? bts->description : "(null)", VTY_NEWLINE);
|
bts->description ? bts->description : "(null)", VTY_NEWLINE);
|
||||||
@@ -492,17 +746,22 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
|
|||||||
net_dump_nmstate(vty, &bts->mo.nm_state);
|
net_dump_nmstate(vty, &bts->mo.nm_state);
|
||||||
vty_out(vty, " Site Mgr NM State: ");
|
vty_out(vty, " Site Mgr NM State: ");
|
||||||
net_dump_nmstate(vty, &bts->site_mgr.mo.nm_state);
|
net_dump_nmstate(vty, &bts->site_mgr.mo.nm_state);
|
||||||
|
if (strnlen(bts->pcu_version, MAX_VERSION_LENGTH))
|
||||||
|
vty_out(vty, " PCU version %s connected%s",
|
||||||
|
bts->pcu_version, VTY_NEWLINE);
|
||||||
vty_out(vty, " Paging: Queue size %u, occupied %u, lifetime %us%s",
|
vty_out(vty, " Paging: Queue size %u, occupied %u, lifetime %us%s",
|
||||||
paging_get_queue_max(btsb->paging_state), paging_queue_length(btsb->paging_state),
|
paging_get_queue_max(btsb->paging_state), paging_queue_length(btsb->paging_state),
|
||||||
paging_get_lifetime(btsb->paging_state), VTY_NEWLINE);
|
paging_get_lifetime(btsb->paging_state), VTY_NEWLINE);
|
||||||
vty_out(vty, " AGCH: Queue limit %u, occupied %d, "
|
vty_out(vty, " AGCH: Queue limit %u, occupied %d, "
|
||||||
"dropped %llu, merged %llu, rejected %llu, "
|
"dropped %"PRIu64", merged %"PRIu64", rejected %"PRIu64", "
|
||||||
"ag-res %llu, non-res %llu%s",
|
"ag-res %"PRIu64", non-res %"PRIu64"%s",
|
||||||
btsb->agch_max_queue_length, btsb->agch_queue_length,
|
btsb->agch_max_queue_length, btsb->agch_queue_length,
|
||||||
btsb->agch_queue_dropped_msgs, btsb->agch_queue_merged_msgs,
|
btsb->agch_queue_dropped_msgs, btsb->agch_queue_merged_msgs,
|
||||||
btsb->agch_queue_rejected_msgs, btsb->agch_queue_agch_msgs,
|
btsb->agch_queue_rejected_msgs, btsb->agch_queue_agch_msgs,
|
||||||
btsb->agch_queue_pch_msgs,
|
btsb->agch_queue_pch_msgs,
|
||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
|
vty_out(vty, " CBCH backlog queue length: %u%s",
|
||||||
|
llist_length(&btsb->smscb_state.queue), VTY_NEWLINE);
|
||||||
#if 0
|
#if 0
|
||||||
vty_out(vty, " Paging: %u pending requests, %u free slots%s",
|
vty_out(vty, " Paging: %u pending requests, %u free slots%s",
|
||||||
paging_pending_requests_nr(bts),
|
paging_pending_requests_nr(bts),
|
||||||
@@ -588,6 +847,138 @@ static struct gsm_lchan *resolve_lchan(struct gsm_network *net,
|
|||||||
"logical channel commands\n" \
|
"logical channel commands\n" \
|
||||||
"logical channel number\n"
|
"logical channel number\n"
|
||||||
|
|
||||||
|
DEFUN(cfg_trx_gsmtap_sapi, cfg_trx_gsmtap_sapi_cmd,
|
||||||
|
"HIDDEN", "HIDDEN")
|
||||||
|
{
|
||||||
|
int sapi;
|
||||||
|
|
||||||
|
sapi = get_string_value(gsmtap_sapi_names, argv[0]);
|
||||||
|
OSMO_ASSERT(sapi >= 0);
|
||||||
|
|
||||||
|
if (sapi == GSMTAP_CHANNEL_ACCH)
|
||||||
|
gsmtap_sapi_acch = 1;
|
||||||
|
else
|
||||||
|
gsmtap_sapi_mask |= (1 << sapi);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_trx_no_gsmtap_sapi, cfg_trx_no_gsmtap_sapi_cmd,
|
||||||
|
"HIDDEN", "HIDDEN")
|
||||||
|
{
|
||||||
|
int sapi;
|
||||||
|
|
||||||
|
sapi = get_string_value(gsmtap_sapi_names, argv[0]);
|
||||||
|
OSMO_ASSERT(sapi >= 0);
|
||||||
|
|
||||||
|
if (sapi == GSMTAP_CHANNEL_ACCH)
|
||||||
|
gsmtap_sapi_acch = 0;
|
||||||
|
else
|
||||||
|
gsmtap_sapi_mask &= ~(1 << sapi);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_node phy_node = {
|
||||||
|
PHY_NODE,
|
||||||
|
"%s(phy)# ",
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cmd_node phy_inst_node = {
|
||||||
|
PHY_INST_NODE,
|
||||||
|
"%s(phy-inst)# ",
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFUN(cfg_phy, cfg_phy_cmd,
|
||||||
|
"phy <0-255>",
|
||||||
|
"Select a PHY to configure\n" "PHY number\n")
|
||||||
|
{
|
||||||
|
int phy_nr = atoi(argv[0]);
|
||||||
|
struct phy_link *plink;
|
||||||
|
|
||||||
|
plink = phy_link_by_num(phy_nr);
|
||||||
|
if (!plink)
|
||||||
|
plink = phy_link_create(tall_bts_ctx, phy_nr);
|
||||||
|
if (!plink)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
vty->index = plink;
|
||||||
|
vty->index_sub = &plink->description;
|
||||||
|
vty->node = PHY_NODE;
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_phy_inst, cfg_phy_inst_cmd,
|
||||||
|
"instance <0-255>",
|
||||||
|
"Select a PHY instance to configure\n" "PHY Instance number\n")
|
||||||
|
{
|
||||||
|
int inst_nr = atoi(argv[0]);
|
||||||
|
struct phy_link *plink = vty->index;
|
||||||
|
struct phy_instance *pinst;
|
||||||
|
|
||||||
|
pinst = phy_instance_by_num(plink, inst_nr);
|
||||||
|
if (!pinst) {
|
||||||
|
pinst = phy_instance_create(plink, inst_nr);
|
||||||
|
if (!pinst) {
|
||||||
|
vty_out(vty, "Unable to create phy%u instance %u%s",
|
||||||
|
plink->num, inst_nr, VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vty->index = pinst;
|
||||||
|
vty->index_sub = &pinst->description;
|
||||||
|
vty->node = PHY_INST_NODE;
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
{
|
||||||
|
int inst_nr = atoi(argv[0]);
|
||||||
|
struct phy_link *plink = vty->index;
|
||||||
|
struct phy_instance *pinst;
|
||||||
|
|
||||||
|
pinst = phy_instance_by_num(plink, inst_nr);
|
||||||
|
if (!pinst) {
|
||||||
|
vty_out(vty, "No such instance %u%s", inst_nr, VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
phy_instance_destroy(pinst);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
DEFUN(cfg_phy_type, cfg_phy_type_cmd,
|
||||||
|
"type (sysmobts|osmo-trx|virtual)",
|
||||||
|
"configure the type of the PHY\n"
|
||||||
|
"sysmocom sysmoBTS PHY\n"
|
||||||
|
"OsmoTRX based PHY\n"
|
||||||
|
"Virtual PHY (GSMTAP based)\n")
|
||||||
|
{
|
||||||
|
struct phy_link *plink = vty->index;
|
||||||
|
|
||||||
|
if (plink->state != PHY_LINK_SHUTDOWN) {
|
||||||
|
vty_out(vty, "Cannot change type of active PHY%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[0], "sysmobts"))
|
||||||
|
plink->type = PHY_LINK_T_SYSMOBTS;
|
||||||
|
else if (!strcmp(argv[0], "osmo-trx"))
|
||||||
|
plink->type = PHY_LINK_T_OSMOTRX;
|
||||||
|
else if (!strcmp(argv[0], "virtual"))
|
||||||
|
plink->type = PHY_LINK_T_VIRTUAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
DEFUN(bts_t_t_l_jitter_buf,
|
DEFUN(bts_t_t_l_jitter_buf,
|
||||||
bts_t_t_l_jitter_buf_cmd,
|
bts_t_t_l_jitter_buf_cmd,
|
||||||
"bts <0-0> trx <0-0> ts <0-7> lchan <0-1> rtp jitter-buffer <0-10000>",
|
"bts <0-0> trx <0-0> ts <0-7> lchan <0-1> rtp jitter-buffer <0-10000>",
|
||||||
@@ -596,7 +987,8 @@ DEFUN(bts_t_t_l_jitter_buf,
|
|||||||
{
|
{
|
||||||
struct gsm_network *net = gsmnet_from_vty(vty);
|
struct gsm_network *net = gsmnet_from_vty(vty);
|
||||||
struct gsm_lchan *lchan;
|
struct gsm_lchan *lchan;
|
||||||
int jitbuf_ms = atoi(argv[4]);
|
struct gsm_bts_role_bts *btsb;
|
||||||
|
int jitbuf_ms = atoi(argv[4]), rc;
|
||||||
|
|
||||||
lchan = resolve_lchan(net, argv, 0);
|
lchan = resolve_lchan(net, argv, 0);
|
||||||
if (!lchan) {
|
if (!lchan) {
|
||||||
@@ -608,20 +1000,79 @@ DEFUN(bts_t_t_l_jitter_buf,
|
|||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
osmo_rtp_socket_set_param(lchan->abis_ip.rtp_socket,
|
btsb = bts_role_bts(lchan->ts->trx->bts);
|
||||||
OSMO_RTP_P_JITBUF, jitbuf_ms);
|
rc = osmo_rtp_socket_set_param(lchan->abis_ip.rtp_socket,
|
||||||
|
btsb->rtp_jitter_adaptive ?
|
||||||
|
OSMO_RTP_P_JIT_ADAP : OSMO_RTP_P_JITBUF,
|
||||||
|
jitbuf_ms);
|
||||||
|
if (rc < 0)
|
||||||
|
vty_out(vty, "%% error setting jitter parameters: %s%s",
|
||||||
|
strerror(-rc), VTY_NEWLINE);
|
||||||
|
else
|
||||||
|
vty_out(vty, "%% jitter parameters set: %d%s", rc, VTY_NEWLINE);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bts_vty_init(const struct log_info *cat)
|
DEFUN(bts_t_t_l_loopback,
|
||||||
|
bts_t_t_l_loopback_cmd,
|
||||||
|
"bts <0-0> trx <0-0> ts <0-7> lchan <0-1> loopback",
|
||||||
|
BTS_T_T_L_STR "Set loopback\n")
|
||||||
{
|
{
|
||||||
|
struct gsm_network *net = gsmnet_from_vty(vty);
|
||||||
|
struct gsm_lchan *lchan;
|
||||||
|
|
||||||
|
lchan = resolve_lchan(net, argv, 0);
|
||||||
|
if (!lchan) {
|
||||||
|
vty_out(vty, "%% can't find BTS%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
lchan->loopback = 1;
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(no_bts_t_t_l_loopback,
|
||||||
|
no_bts_t_t_l_loopback_cmd,
|
||||||
|
"no bts <0-0> trx <0-0> ts <0-7> lchan <0-1> loopback",
|
||||||
|
NO_STR BTS_T_T_L_STR "Set loopback\n")
|
||||||
|
{
|
||||||
|
struct gsm_network *net = gsmnet_from_vty(vty);
|
||||||
|
struct gsm_lchan *lchan;
|
||||||
|
|
||||||
|
lchan = resolve_lchan(net, argv, 0);
|
||||||
|
if (!lchan) {
|
||||||
|
vty_out(vty, "%% can't find BTS%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
lchan->loopback = 0;
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
|
||||||
|
{
|
||||||
|
cfg_trx_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names,
|
||||||
|
"gsmtap-sapi (",
|
||||||
|
"|",")", VTY_DO_LOWER);
|
||||||
|
cfg_trx_gsmtap_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names,
|
||||||
|
"GSMTAP SAPI\n",
|
||||||
|
"\n", "", 0);
|
||||||
|
|
||||||
|
cfg_trx_no_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names,
|
||||||
|
"no gsmtap-sapi (",
|
||||||
|
"|",")", VTY_DO_LOWER);
|
||||||
|
cfg_trx_no_gsmtap_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names,
|
||||||
|
NO_STR "GSMTAP SAPI\n",
|
||||||
|
"\n", "", 0);
|
||||||
|
|
||||||
install_element_ve(&show_bts_cmd);
|
install_element_ve(&show_bts_cmd);
|
||||||
|
|
||||||
logging_vty_add_cmds(cat);
|
logging_vty_add_cmds(cat);
|
||||||
|
|
||||||
install_node(&bts_node, config_write_bts);
|
install_node(&bts_node, config_write_bts);
|
||||||
install_element(CONFIG_NODE, &cfg_bts_cmd);
|
install_element(CONFIG_NODE, &cfg_bts_cmd);
|
||||||
|
install_element(CONFIG_NODE, &cfg_vty_telnet_port_cmd);
|
||||||
install_default(BTS_NODE);
|
install_default(BTS_NODE);
|
||||||
install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
|
install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
|
||||||
install_element(BTS_NODE, &cfg_bts_oml_ip_cmd);
|
install_element(BTS_NODE, &cfg_bts_oml_ip_cmd);
|
||||||
@@ -634,6 +1085,13 @@ int bts_vty_init(const struct log_info *cat)
|
|||||||
install_element(BTS_NODE, &cfg_bts_paging_lifetime_cmd);
|
install_element(BTS_NODE, &cfg_bts_paging_lifetime_cmd);
|
||||||
install_element(BTS_NODE, &cfg_bts_agch_queue_mgmt_default_cmd);
|
install_element(BTS_NODE, &cfg_bts_agch_queue_mgmt_default_cmd);
|
||||||
install_element(BTS_NODE, &cfg_bts_agch_queue_mgmt_params_cmd);
|
install_element(BTS_NODE, &cfg_bts_agch_queue_mgmt_params_cmd);
|
||||||
|
install_element(BTS_NODE, &cfg_bts_ul_power_target_cmd);
|
||||||
|
install_element(BTS_NODE, &cfg_bts_min_qual_rach_cmd);
|
||||||
|
install_element(BTS_NODE, &cfg_bts_min_qual_norm_cmd);
|
||||||
|
install_element(BTS_NODE, &cfg_bts_pcu_sock_cmd);
|
||||||
|
|
||||||
|
install_element(BTS_NODE, &cfg_trx_gsmtap_sapi_cmd);
|
||||||
|
install_element(BTS_NODE, &cfg_trx_no_gsmtap_sapi_cmd);
|
||||||
|
|
||||||
/* add and link to TRX config node */
|
/* add and link to TRX config node */
|
||||||
install_element(BTS_NODE, &cfg_bts_trx_cmd);
|
install_element(BTS_NODE, &cfg_bts_trx_cmd);
|
||||||
@@ -644,8 +1102,21 @@ int bts_vty_init(const struct log_info *cat)
|
|||||||
install_element(TRX_NODE, &cfg_trx_pr_max_initial_cmd);
|
install_element(TRX_NODE, &cfg_trx_pr_max_initial_cmd);
|
||||||
install_element(TRX_NODE, &cfg_trx_pr_step_size_cmd);
|
install_element(TRX_NODE, &cfg_trx_pr_step_size_cmd);
|
||||||
install_element(TRX_NODE, &cfg_trx_pr_step_interval_cmd);
|
install_element(TRX_NODE, &cfg_trx_pr_step_interval_cmd);
|
||||||
|
install_element(TRX_NODE, &cfg_trx_ms_power_control_cmd);
|
||||||
|
install_element(TRX_NODE, &cfg_trx_phy_cmd);
|
||||||
|
|
||||||
install_element(ENABLE_NODE, &bts_t_t_l_jitter_buf_cmd);
|
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(CONFIG_NODE, &cfg_phy_cmd);
|
||||||
|
install_node(&phy_node, config_write_phy);
|
||||||
|
install_default(PHY_NODE);
|
||||||
|
install_element(PHY_NODE, &cfg_phy_inst_cmd);
|
||||||
|
install_element(PHY_NODE, &cfg_phy_no_inst_cmd);
|
||||||
|
|
||||||
|
install_node(&phy_inst_node, config_write_dummy);
|
||||||
|
install_default(PHY_INST_NODE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
38
src/osmo-bts-litecell15/Makefile.am
Normal file
38
src/osmo-bts-litecell15/Makefile.am
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
AUTOMAKE_OPTIONS = subdir-objects
|
||||||
|
|
||||||
|
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(OPENBSC_INCDIR) -I$(LITECELL15_INCDIR)
|
||||||
|
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBGPS_CFLAGS) $(ORTP_CFLAGS) $(LIBSYSTEMD_CFLAGS)
|
||||||
|
COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) $(ORTP_LIBS)
|
||||||
|
|
||||||
|
AM_CFLAGS += -DENABLE_LC15BTS
|
||||||
|
|
||||||
|
EXTRA_DIST = misc/lc15bts_mgr.h misc/lc15bts_misc.h misc/lc15bts_par.h misc/lc15bts_led.h \
|
||||||
|
misc/lc15bts_temp.h misc/lc15bts_power.h misc/lc15bts_clock.h \
|
||||||
|
misc/lc15bts_bid.h misc/lc15bts_nl.h misc/lc15bts_bts.h misc/lc15bts_swd.h \
|
||||||
|
hw_misc.h l1_if.h l1_transp.h lc15bts.h oml_router.h utils.h
|
||||||
|
|
||||||
|
bin_PROGRAMS = osmo-bts-lc15 lc15bts-mgr lc15bts-util
|
||||||
|
|
||||||
|
COMMON_SOURCES = main.c lc15bts.c l1_if.c oml.c lc15bts_vty.c tch.c hw_misc.c calib_file.c \
|
||||||
|
utils.c misc/lc15bts_par.c misc/lc15bts_bid.c oml_router.c
|
||||||
|
|
||||||
|
osmo_bts_lc15_SOURCES = $(COMMON_SOURCES) l1_transp_hw.c
|
||||||
|
osmo_bts_lc15_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD)
|
||||||
|
|
||||||
|
lc15bts_mgr_SOURCES = \
|
||||||
|
misc/lc15bts_mgr.c misc/lc15bts_misc.c \
|
||||||
|
misc/lc15bts_par.c misc/lc15bts_nl.c \
|
||||||
|
misc/lc15bts_temp.c misc/lc15bts_power.c \
|
||||||
|
misc/lc15bts_clock.c misc/lc15bts_bid.c \
|
||||||
|
misc/lc15bts_mgr_vty.c \
|
||||||
|
misc/lc15bts_mgr_nl.c \
|
||||||
|
misc/lc15bts_mgr_temp.c \
|
||||||
|
misc/lc15bts_mgr_calib.c \
|
||||||
|
misc/lc15bts_led.c \
|
||||||
|
misc/lc15bts_bts.c \
|
||||||
|
misc/lc15bts_swd.c
|
||||||
|
|
||||||
|
lc15bts_mgr_LDADD = $(top_builddir)/src/common/libbts.a $(LIBGPS_LIBS) $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBSYSTEMD_LIBS) $(COMMON_LDADD)
|
||||||
|
|
||||||
|
lc15bts_util_SOURCES = misc/lc15bts_util.c misc/lc15bts_par.c
|
||||||
|
lc15bts_util_LDADD = $(LIBOSMOCORE_LIBS)
|
||||||
456
src/osmo-bts-litecell15/calib_file.c
Normal file
456
src/osmo-bts-litecell15/calib_file.c
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
/* NuRAN Wireless Litecell 1.5 BTS L1 calibration file routines*/
|
||||||
|
|
||||||
|
/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com>
|
||||||
|
* Copyright (C) 2016 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* Based on sysmoBTS:
|
||||||
|
* (C) 2012 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
|
||||||
|
#include <nrw/litecell15/litecell15.h>
|
||||||
|
#include <nrw/litecell15/gsml1const.h>
|
||||||
|
|
||||||
|
#include "l1_if.h"
|
||||||
|
#include "lc15bts.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
/* Maximum calibration data chunk size */
|
||||||
|
#define MAX_CALIB_TBL_SIZE 65536
|
||||||
|
/* Calibration header version */
|
||||||
|
#define CALIB_HDR_V1 0x01
|
||||||
|
|
||||||
|
struct calib_file_desc {
|
||||||
|
const char *fname;
|
||||||
|
int rx;
|
||||||
|
int trx;
|
||||||
|
int rxpath;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct calib_file_desc calib_files[] = {
|
||||||
|
{
|
||||||
|
.fname = "calib_rx0a.conf",
|
||||||
|
.rx = 1,
|
||||||
|
.trx = 0,
|
||||||
|
.rxpath = 0,
|
||||||
|
}, {
|
||||||
|
.fname = "calib_rx0b.conf",
|
||||||
|
.rx = 1,
|
||||||
|
.trx = 0,
|
||||||
|
.rxpath = 1,
|
||||||
|
}, {
|
||||||
|
.fname = "calib_rx1a.conf",
|
||||||
|
.rx = 1,
|
||||||
|
.trx = 1,
|
||||||
|
.rxpath = 0,
|
||||||
|
}, {
|
||||||
|
.fname = "calib_rx1b.conf",
|
||||||
|
.rx = 1,
|
||||||
|
.trx = 1,
|
||||||
|
.rxpath = 1,
|
||||||
|
}, {
|
||||||
|
.fname = "calib_tx0.conf",
|
||||||
|
.rx = 0,
|
||||||
|
.trx = 0,
|
||||||
|
}, {
|
||||||
|
.fname = "calib_tx1.conf",
|
||||||
|
.rx = 0,
|
||||||
|
.trx = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct calTbl_t
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t u8Version; /* Header version (1) */
|
||||||
|
uint8_t u8Parity; /* Parity byte (xor) */
|
||||||
|
uint8_t u8Type; /* Table type (0:TX Downlink, 1:RX-A Uplink, 2:RX-B Uplink) */
|
||||||
|
uint8_t u8Band; /* GSM Band (0:GSM-850, 1:EGSM-900, 2:DCS-1800, 3:PCS-1900) */
|
||||||
|
uint32_t u32Len; /* Table length in bytes including the header */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t u32DescOfst; /* Description section offset */
|
||||||
|
uint32_t u32DateOfst; /* Date section offset */
|
||||||
|
uint32_t u32StationOfst; /* Calibration test station section offset */
|
||||||
|
uint32_t u32FpgaFwVerOfst; /* Calibration FPGA firmware version section offset */
|
||||||
|
uint32_t u32DspFwVerOfst; /* Calibration DSP firmware section offset */
|
||||||
|
uint32_t u32DataOfst; /* Calibration data section offset */
|
||||||
|
} toc;
|
||||||
|
} v1;
|
||||||
|
} hdr;
|
||||||
|
|
||||||
|
uint8_t u8RawData[MAX_CALIB_TBL_SIZE - 32];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int calib_file_send(struct lc15l1_hdl *fl1h,
|
||||||
|
const struct calib_file_desc *desc);
|
||||||
|
static int calib_verify(struct lc15l1_hdl *fl1h,
|
||||||
|
const struct calib_file_desc *desc);
|
||||||
|
|
||||||
|
/* determine next calibration file index based on supported bands */
|
||||||
|
static int get_next_calib_file_idx(struct lc15l1_hdl *fl1h, int last_idx)
|
||||||
|
{
|
||||||
|
struct phy_link *plink = fl1h->phy_inst->phy_link;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = last_idx+1; i < ARRAY_SIZE(calib_files); i++) {
|
||||||
|
if (calib_files[i].trx == plink->num)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int calib_file_open(struct lc15l1_hdl *fl1h,
|
||||||
|
const struct calib_file_desc *desc)
|
||||||
|
{
|
||||||
|
struct calib_send_state *st = &fl1h->st;
|
||||||
|
char *calib_path = fl1h->phy_inst->u.lc15.calib_path;
|
||||||
|
char fname[PATH_MAX];
|
||||||
|
|
||||||
|
if (st->fp) {
|
||||||
|
LOGP(DL1C, LOGL_NOTICE, "L1 calibration file was left opened !!\n");
|
||||||
|
fclose(st->fp);
|
||||||
|
st->fp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fname[0] = '\0';
|
||||||
|
snprintf(fname, sizeof(fname)-1, "%s/%s", calib_path, desc->fname);
|
||||||
|
fname[sizeof(fname)-1] = '\0';
|
||||||
|
|
||||||
|
st->fp = fopen(fname, "rb");
|
||||||
|
if (!st->fp) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR,
|
||||||
|
"Failed to open '%s' for calibration data.\n", fname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int calib_file_close(struct lc15l1_hdl *fl1h)
|
||||||
|
{
|
||||||
|
struct calib_send_state *st = &fl1h->st;
|
||||||
|
|
||||||
|
if (st->fp) {
|
||||||
|
fclose(st->fp);
|
||||||
|
st->fp = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iteratively download the calibration data into the L1 */
|
||||||
|
|
||||||
|
static int calib_send_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
/* send a chunk of calibration tabledata for a single specified file */
|
||||||
|
static int calib_file_send_next_chunk(struct lc15l1_hdl *fl1h)
|
||||||
|
{
|
||||||
|
struct calib_send_state *st = &fl1h->st;
|
||||||
|
Litecell15_Prim_t *prim;
|
||||||
|
struct msgb *msg;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
msg = sysp_msgb_alloc();
|
||||||
|
prim = msgb_sysprim(msg);
|
||||||
|
|
||||||
|
prim->id = Litecell15_PrimId_SetCalibTblReq;
|
||||||
|
prim->u.setCalibTblReq.offset = (uint32_t)ftell(st->fp);
|
||||||
|
n = fread(prim->u.setCalibTblReq.u8Data, 1,
|
||||||
|
sizeof(prim->u.setCalibTblReq.u8Data), st->fp);
|
||||||
|
prim->u.setCalibTblReq.length = n;
|
||||||
|
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
/* The table data has been completely sent and acknowledged */
|
||||||
|
LOGP(DL1C, LOGL_NOTICE, "L1 calibration table %s loaded\n",
|
||||||
|
calib_files[st->last_file_idx].fname);
|
||||||
|
|
||||||
|
calib_file_close(fl1h);
|
||||||
|
|
||||||
|
msgb_free(msg);
|
||||||
|
|
||||||
|
/* Send the next one if any */
|
||||||
|
st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx);
|
||||||
|
if (st->last_file_idx >= 0) {
|
||||||
|
return calib_file_send(fl1h,
|
||||||
|
&calib_files[st->last_file_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return l1if_req_compl(fl1h, msg, calib_send_compl_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send the calibration table for a single specified file */
|
||||||
|
static int calib_file_send(struct lc15l1_hdl *fl1h,
|
||||||
|
const struct calib_file_desc *desc)
|
||||||
|
{
|
||||||
|
struct calib_send_state *st = &fl1h->st;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = calib_file_open(fl1h, desc);
|
||||||
|
if (rc < 0) {
|
||||||
|
/* still, we'd like to continue trying to load
|
||||||
|
* calibration for all other bands */
|
||||||
|
st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx);
|
||||||
|
if (st->last_file_idx >= 0)
|
||||||
|
return calib_file_send(fl1h,
|
||||||
|
&calib_files[st->last_file_idx]);
|
||||||
|
|
||||||
|
LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = calib_verify(fl1h, desc);
|
||||||
|
if ( rc < 0 ) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "Verify L1 calibration table %s -> failed (%d)\n", desc->fname, rc);
|
||||||
|
st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx);
|
||||||
|
|
||||||
|
if (st->last_file_idx >= 0)
|
||||||
|
return calib_file_send(fl1h,
|
||||||
|
&calib_files[st->last_file_idx]);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGP(DL1C, LOGL_INFO, "Verify L1 calibration table %s -> done\n", desc->fname);
|
||||||
|
|
||||||
|
return calib_file_send_next_chunk(fl1h);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* completion callback after every SetCalibTbl is confirmed */
|
||||||
|
static int calib_send_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx);
|
||||||
|
struct calib_send_state *st = &fl1h->st;
|
||||||
|
Litecell15_Prim_t *prim = msgb_sysprim(l1_msg);
|
||||||
|
|
||||||
|
if (prim->u.setCalibTblCnf.status != GsmL1_Status_Success) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "L1 rejected calibration table\n");
|
||||||
|
|
||||||
|
msgb_free(l1_msg);
|
||||||
|
|
||||||
|
calib_file_close(fl1h);
|
||||||
|
|
||||||
|
/* Skip this one and try the next one */
|
||||||
|
st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx);
|
||||||
|
if (st->last_file_idx >= 0) {
|
||||||
|
return calib_file_send(fl1h,
|
||||||
|
&calib_files[st->last_file_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgb_free(l1_msg);
|
||||||
|
|
||||||
|
/* Keep sending the calibration file data */
|
||||||
|
return calib_file_send_next_chunk(fl1h);
|
||||||
|
}
|
||||||
|
|
||||||
|
int calib_load(struct lc15l1_hdl *fl1h)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct calib_send_state *st = &fl1h->st;
|
||||||
|
char *calib_path = fl1h->phy_inst->u.lc15.calib_path;
|
||||||
|
|
||||||
|
if (!calib_path) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "Calibration file path not specified\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = get_next_calib_file_idx(fl1h, -1);
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
st->last_file_idx = rc;
|
||||||
|
|
||||||
|
return calib_file_send(fl1h, &calib_files[st->last_file_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *desc)
|
||||||
|
{
|
||||||
|
int rc, sz;
|
||||||
|
struct calib_send_state *st = &fl1h->st;
|
||||||
|
struct phy_link *plink = fl1h->phy_inst->phy_link;
|
||||||
|
char *rbuf;
|
||||||
|
struct calTbl_t *calTbl;
|
||||||
|
char calChkSum ;
|
||||||
|
|
||||||
|
/* calculate file size in bytes */
|
||||||
|
fseek(st->fp, 0L, SEEK_END);
|
||||||
|
sz = ftell(st->fp);
|
||||||
|
|
||||||
|
/* rewind read poiner */
|
||||||
|
fseek(st->fp, 0L, SEEK_SET);
|
||||||
|
|
||||||
|
/* read file */
|
||||||
|
rbuf = (char *) malloc( sizeof(char) * sz );
|
||||||
|
|
||||||
|
rc = fread(rbuf, 1, sizeof(char) * sz, st->fp);
|
||||||
|
if ( rc != sz) {
|
||||||
|
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "%s reading error\n", desc->fname);
|
||||||
|
free(rbuf);
|
||||||
|
|
||||||
|
/* close file */
|
||||||
|
rc = calib_file_close(fl1h);
|
||||||
|
if (rc < 0 ) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "%s can not close\n", desc->fname);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
calTbl = (struct calTbl_t*) rbuf;
|
||||||
|
/* calculate file checksum */
|
||||||
|
calChkSum = 0;
|
||||||
|
while ( sz-- ) {
|
||||||
|
calChkSum ^= rbuf[sz];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate Tx calibration parity */
|
||||||
|
if ( calChkSum ) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "%s has invalid checksum %x.\n", desc->fname, calChkSum);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate Tx calibration header */
|
||||||
|
if ( calTbl->hdr.v1.u8Version != CALIB_HDR_V1 ) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "%s has invalid header version %u.\n", desc->fname, calTbl->hdr.v1.u8Version);
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate calibration description */
|
||||||
|
if ( calTbl->hdr.v1.toc.u32DescOfst == 0xFFFFFFFF ) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration description offset.\n", desc->fname);
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate calibration date */
|
||||||
|
if ( calTbl->hdr.v1.toc.u32DateOfst == 0xFFFFFFFF ) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration date offset.\n", desc->fname);
|
||||||
|
return -7;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGP(DL1C, LOGL_INFO, "L1 calibration table %s created on %s\n",
|
||||||
|
desc->fname,
|
||||||
|
calTbl->u8RawData + calTbl->hdr.v1.toc.u32DateOfst);
|
||||||
|
|
||||||
|
/* validate calibration station */
|
||||||
|
if ( calTbl->hdr.v1.toc.u32StationOfst == 0xFFFFFFFF ) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration station ID offset.\n", desc->fname);
|
||||||
|
return -8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate FPGA FW version */
|
||||||
|
if ( calTbl->hdr.v1.toc.u32FpgaFwVerOfst == 0xFFFFFFFF ) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "%s has invalid FPGA FW version offset.\n", desc->fname);
|
||||||
|
return -9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate DSP FW version */
|
||||||
|
if ( calTbl->hdr.v1.toc.u32DspFwVerOfst == 0xFFFFFFFF ) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "%s has invalid DSP FW version offset.\n", desc->fname);
|
||||||
|
return -10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate Tx calibration data offset */
|
||||||
|
if ( calTbl->hdr.v1.toc.u32DataOfst == 0xFFFFFFFF ) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration data offset.\n", desc->fname);
|
||||||
|
return -11;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !desc->rx ) {
|
||||||
|
|
||||||
|
/* parse min/max Tx power */
|
||||||
|
fl1h->phy_inst->u.lc15.minTxPower = calTbl->u8RawData[calTbl->hdr.v1.toc.u32DataOfst + (5 << 2)];
|
||||||
|
fl1h->phy_inst->u.lc15.maxTxPower = calTbl->u8RawData[calTbl->hdr.v1.toc.u32DataOfst + (6 << 2)];
|
||||||
|
|
||||||
|
/* override nominal Tx power of given TRX if needed */
|
||||||
|
if ( fl1h->phy_inst->trx->nominal_power > fl1h->phy_inst->u.lc15.maxTxPower) {
|
||||||
|
LOGP(DL1C, LOGL_INFO, "Set TRX %u nominal Tx power to %d dBm (%d)\n",
|
||||||
|
plink->num,
|
||||||
|
fl1h->phy_inst->u.lc15.maxTxPower,
|
||||||
|
fl1h->phy_inst->trx->nominal_power);
|
||||||
|
|
||||||
|
fl1h->phy_inst->trx->nominal_power = fl1h->phy_inst->u.lc15.maxTxPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fl1h->phy_inst->trx->nominal_power < fl1h->phy_inst->u.lc15.minTxPower) {
|
||||||
|
LOGP(DL1C, LOGL_INFO, "Set TRX %u nominal Tx power to %d dBm (%d)\n",
|
||||||
|
plink->num,
|
||||||
|
fl1h->phy_inst->u.lc15.minTxPower,
|
||||||
|
fl1h->phy_inst->trx->nominal_power);
|
||||||
|
|
||||||
|
fl1h->phy_inst->trx->nominal_power = fl1h->phy_inst->u.lc15.minTxPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm > to_mdB(fl1h->phy_inst->u.lc15.maxTxPower) ) {
|
||||||
|
LOGP(DL1C, LOGL_INFO, "Set TRX %u Tx power parameter to %d dBm (%d)\n",
|
||||||
|
plink->num,
|
||||||
|
to_mdB(fl1h->phy_inst->u.lc15.maxTxPower),
|
||||||
|
fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm);
|
||||||
|
|
||||||
|
fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm = to_mdB(fl1h->phy_inst->u.lc15.maxTxPower);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm < to_mdB(fl1h->phy_inst->u.lc15.minTxPower) ) {
|
||||||
|
LOGP(DL1C, LOGL_INFO, "Set TRX %u Tx power parameter to %d dBm (%d)\n",
|
||||||
|
plink->num,
|
||||||
|
to_mdB(fl1h->phy_inst->u.lc15.minTxPower),
|
||||||
|
fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm);
|
||||||
|
|
||||||
|
fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm = to_mdB(fl1h->phy_inst->u.lc15.minTxPower);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGP(DL1C, LOGL_DEBUG, "%s: minTxPower=%d, maxTxPower=%d\n",
|
||||||
|
desc->fname,
|
||||||
|
fl1h->phy_inst->u.lc15.minTxPower,
|
||||||
|
fl1h->phy_inst->u.lc15.maxTxPower );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rewind read pointer for subsequence tasks */
|
||||||
|
fseek(st->fp, 0L, SEEK_SET);
|
||||||
|
free(rbuf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
88
src/osmo-bts-litecell15/hw_misc.c
Normal file
88
src/osmo-bts-litecell15/hw_misc.c
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/* Misc HW routines for NuRAN Wireless Litecell 1.5 BTS */
|
||||||
|
|
||||||
|
/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com>
|
||||||
|
*
|
||||||
|
* Based on sysmoBTS:
|
||||||
|
* (C) 2012 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
|
||||||
|
#include "hw_misc.h"
|
||||||
|
|
||||||
|
int lc15bts_led_set(enum lc15bts_led_color c)
|
||||||
|
{
|
||||||
|
int fd, rc;
|
||||||
|
uint8_t cmd[2];
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case LED_OFF:
|
||||||
|
cmd[0] = 0;
|
||||||
|
cmd[1] = 0;
|
||||||
|
break;
|
||||||
|
case LED_RED:
|
||||||
|
cmd[0] = 1;
|
||||||
|
cmd[1] = 0;
|
||||||
|
break;
|
||||||
|
case LED_GREEN:
|
||||||
|
cmd[0] = 0;
|
||||||
|
cmd[1] = 1;
|
||||||
|
break;
|
||||||
|
case LED_ORANGE:
|
||||||
|
cmd[0] = 1;
|
||||||
|
cmd[1] = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open("/var/lc15/leds/led0/brightness", O_WRONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
rc = write(fd, cmd[0] ? "1" : "0", 2);
|
||||||
|
if (rc != 2) {
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
fd = open("/var/lc15/leds/led1/brightness", O_WRONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
rc = write(fd, cmd[1] ? "1" : "0", 2);
|
||||||
|
if (rc != 2) {
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
13
src/osmo-bts-litecell15/hw_misc.h
Normal file
13
src/osmo-bts-litecell15/hw_misc.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _HW_MISC_H
|
||||||
|
#define _HW_MISC_H
|
||||||
|
|
||||||
|
enum lc15bts_led_color {
|
||||||
|
LED_OFF,
|
||||||
|
LED_RED,
|
||||||
|
LED_GREEN,
|
||||||
|
LED_ORANGE,
|
||||||
|
};
|
||||||
|
|
||||||
|
int lc15bts_led_set(enum lc15bts_led_color c);
|
||||||
|
|
||||||
|
#endif
|
||||||
1584
src/osmo-bts-litecell15/l1_if.c
Normal file
1584
src/osmo-bts-litecell15/l1_if.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user