mirror of
				https://github.com/Telecominfraproject/OpenCellular.git
				synced 2025-11-04 04:17:56 +00:00 
			
		
		
		
	Merge commit 'c263ce2f41e27c99bba611763279cf434b893ed9' as 'software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts'
This commit is contained in:
		@@ -0,0 +1,82 @@
 | 
				
			|||||||
 | 
					*.o
 | 
				
			||||||
 | 
					*.a
 | 
				
			||||||
 | 
					Makefile.in
 | 
				
			||||||
 | 
					Makefile
 | 
				
			||||||
 | 
					.deps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					btsconfig.h
 | 
				
			||||||
 | 
					btsconfig.h.in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					aclocal.m4
 | 
				
			||||||
 | 
					autom4te.cache
 | 
				
			||||||
 | 
					config.log
 | 
				
			||||||
 | 
					config.status
 | 
				
			||||||
 | 
					config.guess
 | 
				
			||||||
 | 
					config.sub
 | 
				
			||||||
 | 
					configure
 | 
				
			||||||
 | 
					compile
 | 
				
			||||||
 | 
					depcomp
 | 
				
			||||||
 | 
					install-sh
 | 
				
			||||||
 | 
					missing
 | 
				
			||||||
 | 
					stamp-h1
 | 
				
			||||||
 | 
					libtool
 | 
				
			||||||
 | 
					ltmain.sh
 | 
				
			||||||
 | 
					core
 | 
				
			||||||
 | 
					core.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# git-version-gen magic
 | 
				
			||||||
 | 
					.tarball-version
 | 
				
			||||||
 | 
					.version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					src/osmo-bts-sysmo/sysmobts-calib
 | 
				
			||||||
 | 
					src/osmo-bts-sysmo/l1fwd-proxy
 | 
				
			||||||
 | 
					src/osmo-bts-sysmo/osmo-bts-sysmo
 | 
				
			||||||
 | 
					src/osmo-bts-sysmo/osmo-bts-sysmo-remote
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					src/osmo-bts-omldummy/osmo-bts-omldummy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tests/atconfig
 | 
				
			||||||
 | 
					tests/package.m4
 | 
				
			||||||
 | 
					tests/agch/agch_test
 | 
				
			||||||
 | 
					tests/paging/paging_test
 | 
				
			||||||
 | 
					tests/cipher/cipher_test
 | 
				
			||||||
 | 
					tests/sysmobts/sysmobts_test
 | 
				
			||||||
 | 
					tests/meas/meas_test
 | 
				
			||||||
 | 
					tests/misc/misc_test
 | 
				
			||||||
 | 
					tests/handover/handover_test
 | 
				
			||||||
 | 
					tests/tx_power/tx_power_test
 | 
				
			||||||
 | 
					tests/testsuite
 | 
				
			||||||
 | 
					tests/testsuite.log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Possible generated file
 | 
				
			||||||
 | 
					doc/vty_reference.xml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Backups, vi, merges
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					*.sw?
 | 
				
			||||||
 | 
					*.orig
 | 
				
			||||||
 | 
					*.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/
 | 
				
			||||||
 | 
					/tests/power/power_test
 | 
				
			||||||
@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					[gerrit]
 | 
				
			||||||
 | 
					host=gerrit.osmocom.org
 | 
				
			||||||
 | 
					project=osmo-bts
 | 
				
			||||||
@@ -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>
 | 
				
			||||||
@@ -0,0 +1,661 @@
 | 
				
			|||||||
 | 
					                    GNU AFFERO GENERAL PUBLIC LICENSE
 | 
				
			||||||
 | 
					                       Version 3, 19 November 2007
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 | 
				
			||||||
 | 
					 Everyone is permitted to copy and distribute verbatim copies
 | 
				
			||||||
 | 
					 of this license document, but changing it is not allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            Preamble
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The GNU Affero General Public License is a free, copyleft license for
 | 
				
			||||||
 | 
					software and other kinds of works, specifically designed to ensure
 | 
				
			||||||
 | 
					cooperation with the community in the case of network server software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The licenses for most software and other practical works are designed
 | 
				
			||||||
 | 
					to take away your freedom to share and change the works.  By contrast,
 | 
				
			||||||
 | 
					our General Public Licenses are intended to guarantee your freedom to
 | 
				
			||||||
 | 
					share and change all versions of a program--to make sure it remains free
 | 
				
			||||||
 | 
					software for all its users.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When we speak of free software, we are referring to freedom, not
 | 
				
			||||||
 | 
					price.  Our General Public Licenses are designed to make sure that you
 | 
				
			||||||
 | 
					have the freedom to distribute copies of free software (and charge for
 | 
				
			||||||
 | 
					them if you wish), that you receive source code or can get it if you
 | 
				
			||||||
 | 
					want it, that you can change the software or use pieces of it in new
 | 
				
			||||||
 | 
					free programs, and that you know you can do these things.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Developers that use our General Public Licenses protect your rights
 | 
				
			||||||
 | 
					with two steps: (1) assert copyright on the software, and (2) offer
 | 
				
			||||||
 | 
					you this License which gives you legal permission to copy, distribute
 | 
				
			||||||
 | 
					and/or modify the software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A secondary benefit of defending all users' freedom is that
 | 
				
			||||||
 | 
					improvements made in alternate versions of the program, if they
 | 
				
			||||||
 | 
					receive widespread use, become available for other developers to
 | 
				
			||||||
 | 
					incorporate.  Many developers of free software are heartened and
 | 
				
			||||||
 | 
					encouraged by the resulting cooperation.  However, in the case of
 | 
				
			||||||
 | 
					software used on network servers, this result may fail to come about.
 | 
				
			||||||
 | 
					The GNU General Public License permits making a modified version and
 | 
				
			||||||
 | 
					letting the public access it on a server without ever releasing its
 | 
				
			||||||
 | 
					source code to the public.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The GNU Affero General Public License is designed specifically to
 | 
				
			||||||
 | 
					ensure that, in such cases, the modified source code becomes available
 | 
				
			||||||
 | 
					to the community.  It requires the operator of a network server to
 | 
				
			||||||
 | 
					provide the source code of the modified version running there to the
 | 
				
			||||||
 | 
					users of that server.  Therefore, public use of a modified version, on
 | 
				
			||||||
 | 
					a publicly accessible server, gives the public access to the source
 | 
				
			||||||
 | 
					code of the modified version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  An older license, called the Affero General Public License and
 | 
				
			||||||
 | 
					published by Affero, was designed to accomplish similar goals.  This is
 | 
				
			||||||
 | 
					a different license, not a version of the Affero GPL, but Affero has
 | 
				
			||||||
 | 
					released a new version of the Affero GPL which permits relicensing under
 | 
				
			||||||
 | 
					this license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The precise terms and conditions for copying, distribution and
 | 
				
			||||||
 | 
					modification follow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                       TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  0. Definitions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "This License" refers to version 3 of the GNU Affero General Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "Copyright" also means copyright-like laws that apply to other kinds of
 | 
				
			||||||
 | 
					works, such as semiconductor masks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "The Program" refers to any copyrightable work licensed under this
 | 
				
			||||||
 | 
					License.  Each licensee is addressed as "you".  "Licensees" and
 | 
				
			||||||
 | 
					"recipients" may be individuals or organizations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To "modify" a work means to copy from or adapt all or part of the work
 | 
				
			||||||
 | 
					in a fashion requiring copyright permission, other than the making of an
 | 
				
			||||||
 | 
					exact copy.  The resulting work is called a "modified version" of the
 | 
				
			||||||
 | 
					earlier work or a work "based on" the earlier work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "covered work" means either the unmodified Program or a work based
 | 
				
			||||||
 | 
					on the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To "propagate" a work means to do anything with it that, without
 | 
				
			||||||
 | 
					permission, would make you directly or secondarily liable for
 | 
				
			||||||
 | 
					infringement under applicable copyright law, except executing it on a
 | 
				
			||||||
 | 
					computer or modifying a private copy.  Propagation includes copying,
 | 
				
			||||||
 | 
					distribution (with or without modification), making available to the
 | 
				
			||||||
 | 
					public, and in some countries other activities as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To "convey" a work means any kind of propagation that enables other
 | 
				
			||||||
 | 
					parties to make or receive copies.  Mere interaction with a user through
 | 
				
			||||||
 | 
					a computer network, with no transfer of a copy, is not conveying.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  An interactive user interface displays "Appropriate Legal Notices"
 | 
				
			||||||
 | 
					to the extent that it includes a convenient and prominently visible
 | 
				
			||||||
 | 
					feature that (1) displays an appropriate copyright notice, and (2)
 | 
				
			||||||
 | 
					tells the user that there is no warranty for the work (except to the
 | 
				
			||||||
 | 
					extent that warranties are provided), that licensees may convey the
 | 
				
			||||||
 | 
					work under this License, and how to view a copy of this License.  If
 | 
				
			||||||
 | 
					the interface presents a list of user commands or options, such as a
 | 
				
			||||||
 | 
					menu, a prominent item in the list meets this criterion.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  1. Source Code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The "source code" for a work means the preferred form of the work
 | 
				
			||||||
 | 
					for making modifications to it.  "Object code" means any non-source
 | 
				
			||||||
 | 
					form of a work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "Standard Interface" means an interface that either is an official
 | 
				
			||||||
 | 
					standard defined by a recognized standards body, or, in the case of
 | 
				
			||||||
 | 
					interfaces specified for a particular programming language, one that
 | 
				
			||||||
 | 
					is widely used among developers working in that language.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The "System Libraries" of an executable work include anything, other
 | 
				
			||||||
 | 
					than the work as a whole, that (a) is included in the normal form of
 | 
				
			||||||
 | 
					packaging a Major Component, but which is not part of that Major
 | 
				
			||||||
 | 
					Component, and (b) serves only to enable use of the work with that
 | 
				
			||||||
 | 
					Major Component, or to implement a Standard Interface for which an
 | 
				
			||||||
 | 
					implementation is available to the public in source code form.  A
 | 
				
			||||||
 | 
					"Major Component", in this context, means a major essential component
 | 
				
			||||||
 | 
					(kernel, window system, and so on) of the specific operating system
 | 
				
			||||||
 | 
					(if any) on which the executable work runs, or a compiler used to
 | 
				
			||||||
 | 
					produce the work, or an object code interpreter used to run it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The "Corresponding Source" for a work in object code form means all
 | 
				
			||||||
 | 
					the source code needed to generate, install, and (for an executable
 | 
				
			||||||
 | 
					work) run the object code and to modify the work, including scripts to
 | 
				
			||||||
 | 
					control those activities.  However, it does not include the work's
 | 
				
			||||||
 | 
					System Libraries, or general-purpose tools or generally available free
 | 
				
			||||||
 | 
					programs which are used unmodified in performing those activities but
 | 
				
			||||||
 | 
					which are not part of the work.  For example, Corresponding Source
 | 
				
			||||||
 | 
					includes interface definition files associated with source files for
 | 
				
			||||||
 | 
					the work, and the source code for shared libraries and dynamically
 | 
				
			||||||
 | 
					linked subprograms that the work is specifically designed to require,
 | 
				
			||||||
 | 
					such as by intimate data communication or control flow between those
 | 
				
			||||||
 | 
					subprograms and other parts of the work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The Corresponding Source need not include anything that users
 | 
				
			||||||
 | 
					can regenerate automatically from other parts of the Corresponding
 | 
				
			||||||
 | 
					Source.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The Corresponding Source for a work in source code form is that
 | 
				
			||||||
 | 
					same work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  2. Basic Permissions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  All rights granted under this License are granted for the term of
 | 
				
			||||||
 | 
					copyright on the Program, and are irrevocable provided the stated
 | 
				
			||||||
 | 
					conditions are met.  This License explicitly affirms your unlimited
 | 
				
			||||||
 | 
					permission to run the unmodified Program.  The output from running a
 | 
				
			||||||
 | 
					covered work is covered by this License only if the output, given its
 | 
				
			||||||
 | 
					content, constitutes a covered work.  This License acknowledges your
 | 
				
			||||||
 | 
					rights of fair use or other equivalent, as provided by copyright law.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may make, run and propagate covered works that you do not
 | 
				
			||||||
 | 
					convey, without conditions so long as your license otherwise remains
 | 
				
			||||||
 | 
					in force.  You may convey covered works to others for the sole purpose
 | 
				
			||||||
 | 
					of having them make modifications exclusively for you, or provide you
 | 
				
			||||||
 | 
					with facilities for running those works, provided that you comply with
 | 
				
			||||||
 | 
					the terms of this License in conveying all material for which you do
 | 
				
			||||||
 | 
					not control copyright.  Those thus making or running the covered works
 | 
				
			||||||
 | 
					for you must do so exclusively on your behalf, under your direction
 | 
				
			||||||
 | 
					and control, on terms that prohibit them from making any copies of
 | 
				
			||||||
 | 
					your copyrighted material outside their relationship with you.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Conveying under any other circumstances is permitted solely under
 | 
				
			||||||
 | 
					the conditions stated below.  Sublicensing is not allowed; section 10
 | 
				
			||||||
 | 
					makes it unnecessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  No covered work shall be deemed part of an effective technological
 | 
				
			||||||
 | 
					measure under any applicable law fulfilling obligations under article
 | 
				
			||||||
 | 
					11 of the WIPO copyright treaty adopted on 20 December 1996, or
 | 
				
			||||||
 | 
					similar laws prohibiting or restricting circumvention of such
 | 
				
			||||||
 | 
					measures.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When you convey a covered work, you waive any legal power to forbid
 | 
				
			||||||
 | 
					circumvention of technological measures to the extent such circumvention
 | 
				
			||||||
 | 
					is effected by exercising rights under this License with respect to
 | 
				
			||||||
 | 
					the covered work, and you disclaim any intention to limit operation or
 | 
				
			||||||
 | 
					modification of the work as a means of enforcing, against the work's
 | 
				
			||||||
 | 
					users, your or third parties' legal rights to forbid circumvention of
 | 
				
			||||||
 | 
					technological measures.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  4. Conveying Verbatim Copies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may convey verbatim copies of the Program's source code as you
 | 
				
			||||||
 | 
					receive it, in any medium, provided that you conspicuously and
 | 
				
			||||||
 | 
					appropriately publish on each copy an appropriate copyright notice;
 | 
				
			||||||
 | 
					keep intact all notices stating that this License and any
 | 
				
			||||||
 | 
					non-permissive terms added in accord with section 7 apply to the code;
 | 
				
			||||||
 | 
					keep intact all notices of the absence of any warranty; and give all
 | 
				
			||||||
 | 
					recipients a copy of this License along with the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may charge any price or no price for each copy that you convey,
 | 
				
			||||||
 | 
					and you may offer support or warranty protection for a fee.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  5. Conveying Modified Source Versions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may convey a work based on the Program, or the modifications to
 | 
				
			||||||
 | 
					produce it from the Program, in the form of source code under the
 | 
				
			||||||
 | 
					terms of section 4, provided that you also meet all of these conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) The work must carry prominent notices stating that you modified
 | 
				
			||||||
 | 
					    it, and giving a relevant date.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) The work must carry prominent notices stating that it is
 | 
				
			||||||
 | 
					    released under this License and any conditions added under section
 | 
				
			||||||
 | 
					    7.  This requirement modifies the requirement in section 4 to
 | 
				
			||||||
 | 
					    "keep intact all notices".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) You must license the entire work, as a whole, under this
 | 
				
			||||||
 | 
					    License to anyone who comes into possession of a copy.  This
 | 
				
			||||||
 | 
					    License will therefore apply, along with any applicable section 7
 | 
				
			||||||
 | 
					    additional terms, to the whole of the work, and all its parts,
 | 
				
			||||||
 | 
					    regardless of how they are packaged.  This License gives no
 | 
				
			||||||
 | 
					    permission to license the work in any other way, but it does not
 | 
				
			||||||
 | 
					    invalidate such permission if you have separately received it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d) If the work has interactive user interfaces, each must display
 | 
				
			||||||
 | 
					    Appropriate Legal Notices; however, if the Program has interactive
 | 
				
			||||||
 | 
					    interfaces that do not display Appropriate Legal Notices, your
 | 
				
			||||||
 | 
					    work need not make them do so.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A compilation of a covered work with other separate and independent
 | 
				
			||||||
 | 
					works, which are not by their nature extensions of the covered work,
 | 
				
			||||||
 | 
					and which are not combined with it such as to form a larger program,
 | 
				
			||||||
 | 
					in or on a volume of a storage or distribution medium, is called an
 | 
				
			||||||
 | 
					"aggregate" if the compilation and its resulting copyright are not
 | 
				
			||||||
 | 
					used to limit the access or legal rights of the compilation's users
 | 
				
			||||||
 | 
					beyond what the individual works permit.  Inclusion of a covered work
 | 
				
			||||||
 | 
					in an aggregate does not cause this License to apply to the other
 | 
				
			||||||
 | 
					parts of the aggregate.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  6. Conveying Non-Source Forms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may convey a covered work in object code form under the terms
 | 
				
			||||||
 | 
					of sections 4 and 5, provided that you also convey the
 | 
				
			||||||
 | 
					machine-readable Corresponding Source under the terms of this License,
 | 
				
			||||||
 | 
					in one of these ways:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) Convey the object code in, or embodied in, a physical product
 | 
				
			||||||
 | 
					    (including a physical distribution medium), accompanied by the
 | 
				
			||||||
 | 
					    Corresponding Source fixed on a durable physical medium
 | 
				
			||||||
 | 
					    customarily used for software interchange.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) Convey the object code in, or embodied in, a physical product
 | 
				
			||||||
 | 
					    (including a physical distribution medium), accompanied by a
 | 
				
			||||||
 | 
					    written offer, valid for at least three years and valid for as
 | 
				
			||||||
 | 
					    long as you offer spare parts or customer support for that product
 | 
				
			||||||
 | 
					    model, to give anyone who possesses the object code either (1) a
 | 
				
			||||||
 | 
					    copy of the Corresponding Source for all the software in the
 | 
				
			||||||
 | 
					    product that is covered by this License, on a durable physical
 | 
				
			||||||
 | 
					    medium customarily used for software interchange, for a price no
 | 
				
			||||||
 | 
					    more than your reasonable cost of physically performing this
 | 
				
			||||||
 | 
					    conveying of source, or (2) access to copy the
 | 
				
			||||||
 | 
					    Corresponding Source from a network server at no charge.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) Convey individual copies of the object code with a copy of the
 | 
				
			||||||
 | 
					    written offer to provide the Corresponding Source.  This
 | 
				
			||||||
 | 
					    alternative is allowed only occasionally and noncommercially, and
 | 
				
			||||||
 | 
					    only if you received the object code with such an offer, in accord
 | 
				
			||||||
 | 
					    with subsection 6b.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d) Convey the object code by offering access from a designated
 | 
				
			||||||
 | 
					    place (gratis or for a charge), and offer equivalent access to the
 | 
				
			||||||
 | 
					    Corresponding Source in the same way through the same place at no
 | 
				
			||||||
 | 
					    further charge.  You need not require recipients to copy the
 | 
				
			||||||
 | 
					    Corresponding Source along with the object code.  If the place to
 | 
				
			||||||
 | 
					    copy the object code is a network server, the Corresponding Source
 | 
				
			||||||
 | 
					    may be on a different server (operated by you or a third party)
 | 
				
			||||||
 | 
					    that supports equivalent copying facilities, provided you maintain
 | 
				
			||||||
 | 
					    clear directions next to the object code saying where to find the
 | 
				
			||||||
 | 
					    Corresponding Source.  Regardless of what server hosts the
 | 
				
			||||||
 | 
					    Corresponding Source, you remain obligated to ensure that it is
 | 
				
			||||||
 | 
					    available for as long as needed to satisfy these requirements.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    e) Convey the object code using peer-to-peer transmission, provided
 | 
				
			||||||
 | 
					    you inform other peers where the object code and Corresponding
 | 
				
			||||||
 | 
					    Source of the work are being offered to the general public at no
 | 
				
			||||||
 | 
					    charge under subsection 6d.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A separable portion of the object code, whose source code is excluded
 | 
				
			||||||
 | 
					from the Corresponding Source as a System Library, need not be
 | 
				
			||||||
 | 
					included in conveying the object code work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "User Product" is either (1) a "consumer product", which means any
 | 
				
			||||||
 | 
					tangible personal property which is normally used for personal, family,
 | 
				
			||||||
 | 
					or household purposes, or (2) anything designed or sold for incorporation
 | 
				
			||||||
 | 
					into a dwelling.  In determining whether a product is a consumer product,
 | 
				
			||||||
 | 
					doubtful cases shall be resolved in favor of coverage.  For a particular
 | 
				
			||||||
 | 
					product received by a particular user, "normally used" refers to a
 | 
				
			||||||
 | 
					typical or common use of that class of product, regardless of the status
 | 
				
			||||||
 | 
					of the particular user or of the way in which the particular user
 | 
				
			||||||
 | 
					actually uses, or expects or is expected to use, the product.  A product
 | 
				
			||||||
 | 
					is a consumer product regardless of whether the product has substantial
 | 
				
			||||||
 | 
					commercial, industrial or non-consumer uses, unless such uses represent
 | 
				
			||||||
 | 
					the only significant mode of use of the product.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "Installation Information" for a User Product means any methods,
 | 
				
			||||||
 | 
					procedures, authorization keys, or other information required to install
 | 
				
			||||||
 | 
					and execute modified versions of a covered work in that User Product from
 | 
				
			||||||
 | 
					a modified version of its Corresponding Source.  The information must
 | 
				
			||||||
 | 
					suffice to ensure that the continued functioning of the modified object
 | 
				
			||||||
 | 
					code is in no case prevented or interfered with solely because
 | 
				
			||||||
 | 
					modification has been made.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you convey an object code work under this section in, or with, or
 | 
				
			||||||
 | 
					specifically for use in, a User Product, and the conveying occurs as
 | 
				
			||||||
 | 
					part of a transaction in which the right of possession and use of the
 | 
				
			||||||
 | 
					User Product is transferred to the recipient in perpetuity or for a
 | 
				
			||||||
 | 
					fixed term (regardless of how the transaction is characterized), the
 | 
				
			||||||
 | 
					Corresponding Source conveyed under this section must be accompanied
 | 
				
			||||||
 | 
					by the Installation Information.  But this requirement does not apply
 | 
				
			||||||
 | 
					if neither you nor any third party retains the ability to install
 | 
				
			||||||
 | 
					modified object code on the User Product (for example, the work has
 | 
				
			||||||
 | 
					been installed in ROM).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The requirement to provide Installation Information does not include a
 | 
				
			||||||
 | 
					requirement to continue to provide support service, warranty, or updates
 | 
				
			||||||
 | 
					for a work that has been modified or installed by the recipient, or for
 | 
				
			||||||
 | 
					the User Product in which it has been modified or installed.  Access to a
 | 
				
			||||||
 | 
					network may be denied when the modification itself materially and
 | 
				
			||||||
 | 
					adversely affects the operation of the network or violates the rules and
 | 
				
			||||||
 | 
					protocols for communication across the network.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Corresponding Source conveyed, and Installation Information provided,
 | 
				
			||||||
 | 
					in accord with this section must be in a format that is publicly
 | 
				
			||||||
 | 
					documented (and with an implementation available to the public in
 | 
				
			||||||
 | 
					source code form), and must require no special password or key for
 | 
				
			||||||
 | 
					unpacking, reading or copying.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  7. Additional Terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "Additional permissions" are terms that supplement the terms of this
 | 
				
			||||||
 | 
					License by making exceptions from one or more of its conditions.
 | 
				
			||||||
 | 
					Additional permissions that are applicable to the entire Program shall
 | 
				
			||||||
 | 
					be treated as though they were included in this License, to the extent
 | 
				
			||||||
 | 
					that they are valid under applicable law.  If additional permissions
 | 
				
			||||||
 | 
					apply only to part of the Program, that part may be used separately
 | 
				
			||||||
 | 
					under those permissions, but the entire Program remains governed by
 | 
				
			||||||
 | 
					this License without regard to the additional permissions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When you convey a copy of a covered work, you may at your option
 | 
				
			||||||
 | 
					remove any additional permissions from that copy, or from any part of
 | 
				
			||||||
 | 
					it.  (Additional permissions may be written to require their own
 | 
				
			||||||
 | 
					removal in certain cases when you modify the work.)  You may place
 | 
				
			||||||
 | 
					additional permissions on material, added by you to a covered work,
 | 
				
			||||||
 | 
					for which you have or can give appropriate copyright permission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Notwithstanding any other provision of this License, for material you
 | 
				
			||||||
 | 
					add to a covered work, you may (if authorized by the copyright holders of
 | 
				
			||||||
 | 
					that material) supplement the terms of this License with terms:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) Disclaiming warranty or limiting liability differently from the
 | 
				
			||||||
 | 
					    terms of sections 15 and 16 of this License; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) Requiring preservation of specified reasonable legal notices or
 | 
				
			||||||
 | 
					    author attributions in that material or in the Appropriate Legal
 | 
				
			||||||
 | 
					    Notices displayed by works containing it; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) Prohibiting misrepresentation of the origin of that material, or
 | 
				
			||||||
 | 
					    requiring that modified versions of such material be marked in
 | 
				
			||||||
 | 
					    reasonable ways as different from the original version; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d) Limiting the use for publicity purposes of names of licensors or
 | 
				
			||||||
 | 
					    authors of the material; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    e) Declining to grant rights under trademark law for use of some
 | 
				
			||||||
 | 
					    trade names, trademarks, or service marks; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    f) Requiring indemnification of licensors and authors of that
 | 
				
			||||||
 | 
					    material by anyone who conveys the material (or modified versions of
 | 
				
			||||||
 | 
					    it) with contractual assumptions of liability to the recipient, for
 | 
				
			||||||
 | 
					    any liability that these contractual assumptions directly impose on
 | 
				
			||||||
 | 
					    those licensors and authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  All other non-permissive additional terms are considered "further
 | 
				
			||||||
 | 
					restrictions" within the meaning of section 10.  If the Program as you
 | 
				
			||||||
 | 
					received it, or any part of it, contains a notice stating that it is
 | 
				
			||||||
 | 
					governed by this License along with a term that is a further
 | 
				
			||||||
 | 
					restriction, you may remove that term.  If a license document contains
 | 
				
			||||||
 | 
					a further restriction but permits relicensing or conveying under this
 | 
				
			||||||
 | 
					License, you may add to a covered work material governed by the terms
 | 
				
			||||||
 | 
					of that license document, provided that the further restriction does
 | 
				
			||||||
 | 
					not survive such relicensing or conveying.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you add terms to a covered work in accord with this section, you
 | 
				
			||||||
 | 
					must place, in the relevant source files, a statement of the
 | 
				
			||||||
 | 
					additional terms that apply to those files, or a notice indicating
 | 
				
			||||||
 | 
					where to find the applicable terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Additional terms, permissive or non-permissive, may be stated in the
 | 
				
			||||||
 | 
					form of a separately written license, or stated as exceptions;
 | 
				
			||||||
 | 
					the above requirements apply either way.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  8. Termination.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may not propagate or modify a covered work except as expressly
 | 
				
			||||||
 | 
					provided under this License.  Any attempt otherwise to propagate or
 | 
				
			||||||
 | 
					modify it is void, and will automatically terminate your rights under
 | 
				
			||||||
 | 
					this License (including any patent licenses granted under the third
 | 
				
			||||||
 | 
					paragraph of section 11).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  However, if you cease all violation of this License, then your
 | 
				
			||||||
 | 
					license from a particular copyright holder is reinstated (a)
 | 
				
			||||||
 | 
					provisionally, unless and until the copyright holder explicitly and
 | 
				
			||||||
 | 
					finally terminates your license, and (b) permanently, if the copyright
 | 
				
			||||||
 | 
					holder fails to notify you of the violation by some reasonable means
 | 
				
			||||||
 | 
					prior to 60 days after the cessation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Moreover, your license from a particular copyright holder is
 | 
				
			||||||
 | 
					reinstated permanently if the copyright holder notifies you of the
 | 
				
			||||||
 | 
					violation by some reasonable means, this is the first time you have
 | 
				
			||||||
 | 
					received notice of violation of this License (for any work) from that
 | 
				
			||||||
 | 
					copyright holder, and you cure the violation prior to 30 days after
 | 
				
			||||||
 | 
					your receipt of the notice.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Termination of your rights under this section does not terminate the
 | 
				
			||||||
 | 
					licenses of parties who have received copies or rights from you under
 | 
				
			||||||
 | 
					this License.  If your rights have been terminated and not permanently
 | 
				
			||||||
 | 
					reinstated, you do not qualify to receive new licenses for the same
 | 
				
			||||||
 | 
					material under section 10.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  9. Acceptance Not Required for Having Copies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You are not required to accept this License in order to receive or
 | 
				
			||||||
 | 
					run a copy of the Program.  Ancillary propagation of a covered work
 | 
				
			||||||
 | 
					occurring solely as a consequence of using peer-to-peer transmission
 | 
				
			||||||
 | 
					to receive a copy likewise does not require acceptance.  However,
 | 
				
			||||||
 | 
					nothing other than this License grants you permission to propagate or
 | 
				
			||||||
 | 
					modify any covered work.  These actions infringe copyright if you do
 | 
				
			||||||
 | 
					not accept this License.  Therefore, by modifying or propagating a
 | 
				
			||||||
 | 
					covered work, you indicate your acceptance of this License to do so.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  10. Automatic Licensing of Downstream Recipients.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Each time you convey a covered work, the recipient automatically
 | 
				
			||||||
 | 
					receives a license from the original licensors, to run, modify and
 | 
				
			||||||
 | 
					propagate that work, subject to this License.  You are not responsible
 | 
				
			||||||
 | 
					for enforcing compliance by third parties with this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  An "entity transaction" is a transaction transferring control of an
 | 
				
			||||||
 | 
					organization, or substantially all assets of one, or subdividing an
 | 
				
			||||||
 | 
					organization, or merging organizations.  If propagation of a covered
 | 
				
			||||||
 | 
					work results from an entity transaction, each party to that
 | 
				
			||||||
 | 
					transaction who receives a copy of the work also receives whatever
 | 
				
			||||||
 | 
					licenses to the work the party's predecessor in interest had or could
 | 
				
			||||||
 | 
					give under the previous paragraph, plus a right to possession of the
 | 
				
			||||||
 | 
					Corresponding Source of the work from the predecessor in interest, if
 | 
				
			||||||
 | 
					the predecessor has it or can get it with reasonable efforts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may not impose any further restrictions on the exercise of the
 | 
				
			||||||
 | 
					rights granted or affirmed under this License.  For example, you may
 | 
				
			||||||
 | 
					not impose a license fee, royalty, or other charge for exercise of
 | 
				
			||||||
 | 
					rights granted under this License, and you may not initiate litigation
 | 
				
			||||||
 | 
					(including a cross-claim or counterclaim in a lawsuit) alleging that
 | 
				
			||||||
 | 
					any patent claim is infringed by making, using, selling, offering for
 | 
				
			||||||
 | 
					sale, or importing the Program or any portion of it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  11. Patents.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "contributor" is a copyright holder who authorizes use under this
 | 
				
			||||||
 | 
					License of the Program or a work on which the Program is based.  The
 | 
				
			||||||
 | 
					work thus licensed is called the contributor's "contributor version".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A contributor's "essential patent claims" are all patent claims
 | 
				
			||||||
 | 
					owned or controlled by the contributor, whether already acquired or
 | 
				
			||||||
 | 
					hereafter acquired, that would be infringed by some manner, permitted
 | 
				
			||||||
 | 
					by this License, of making, using, or selling its contributor version,
 | 
				
			||||||
 | 
					but do not include claims that would be infringed only as a
 | 
				
			||||||
 | 
					consequence of further modification of the contributor version.  For
 | 
				
			||||||
 | 
					purposes of this definition, "control" includes the right to grant
 | 
				
			||||||
 | 
					patent sublicenses in a manner consistent with the requirements of
 | 
				
			||||||
 | 
					this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Each contributor grants you a non-exclusive, worldwide, royalty-free
 | 
				
			||||||
 | 
					patent license under the contributor's essential patent claims, to
 | 
				
			||||||
 | 
					make, use, sell, offer for sale, import and otherwise run, modify and
 | 
				
			||||||
 | 
					propagate the contents of its contributor version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  In the following three paragraphs, a "patent license" is any express
 | 
				
			||||||
 | 
					agreement or commitment, however denominated, not to enforce a patent
 | 
				
			||||||
 | 
					(such as an express permission to practice a patent or covenant not to
 | 
				
			||||||
 | 
					sue for patent infringement).  To "grant" such a patent license to a
 | 
				
			||||||
 | 
					party means to make such an agreement or commitment not to enforce a
 | 
				
			||||||
 | 
					patent against the party.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you convey a covered work, knowingly relying on a patent license,
 | 
				
			||||||
 | 
					and the Corresponding Source of the work is not available for anyone
 | 
				
			||||||
 | 
					to copy, free of charge and under the terms of this License, through a
 | 
				
			||||||
 | 
					publicly available network server or other readily accessible means,
 | 
				
			||||||
 | 
					then you must either (1) cause the Corresponding Source to be so
 | 
				
			||||||
 | 
					available, or (2) arrange to deprive yourself of the benefit of the
 | 
				
			||||||
 | 
					patent license for this particular work, or (3) arrange, in a manner
 | 
				
			||||||
 | 
					consistent with the requirements of this License, to extend the patent
 | 
				
			||||||
 | 
					license to downstream recipients.  "Knowingly relying" means you have
 | 
				
			||||||
 | 
					actual knowledge that, but for the patent license, your conveying the
 | 
				
			||||||
 | 
					covered work in a country, or your recipient's use of the covered work
 | 
				
			||||||
 | 
					in a country, would infringe one or more identifiable patents in that
 | 
				
			||||||
 | 
					country that you have reason to believe are valid.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If, pursuant to or in connection with a single transaction or
 | 
				
			||||||
 | 
					arrangement, you convey, or propagate by procuring conveyance of, a
 | 
				
			||||||
 | 
					covered work, and grant a patent license to some of the parties
 | 
				
			||||||
 | 
					receiving the covered work authorizing them to use, propagate, modify
 | 
				
			||||||
 | 
					or convey a specific copy of the covered work, then the patent license
 | 
				
			||||||
 | 
					you grant is automatically extended to all recipients of the covered
 | 
				
			||||||
 | 
					work and works based on it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A patent license is "discriminatory" if it does not include within
 | 
				
			||||||
 | 
					the scope of its coverage, prohibits the exercise of, or is
 | 
				
			||||||
 | 
					conditioned on the non-exercise of one or more of the rights that are
 | 
				
			||||||
 | 
					specifically granted under this License.  You may not convey a covered
 | 
				
			||||||
 | 
					work if you are a party to an arrangement with a third party that is
 | 
				
			||||||
 | 
					in the business of distributing software, under which you make payment
 | 
				
			||||||
 | 
					to the third party based on the extent of your activity of conveying
 | 
				
			||||||
 | 
					the work, and under which the third party grants, to any of the
 | 
				
			||||||
 | 
					parties who would receive the covered work from you, a discriminatory
 | 
				
			||||||
 | 
					patent license (a) in connection with copies of the covered work
 | 
				
			||||||
 | 
					conveyed by you (or copies made from those copies), or (b) primarily
 | 
				
			||||||
 | 
					for and in connection with specific products or compilations that
 | 
				
			||||||
 | 
					contain the covered work, unless you entered into that arrangement,
 | 
				
			||||||
 | 
					or that patent license was granted, prior to 28 March 2007.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Nothing in this License shall be construed as excluding or limiting
 | 
				
			||||||
 | 
					any implied license or other defenses to infringement that may
 | 
				
			||||||
 | 
					otherwise be available to you under applicable patent law.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  12. No Surrender of Others' Freedom.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If conditions are imposed on you (whether by court order, agreement or
 | 
				
			||||||
 | 
					otherwise) that contradict the conditions of this License, they do not
 | 
				
			||||||
 | 
					excuse you from the conditions of this License.  If you cannot convey a
 | 
				
			||||||
 | 
					covered work so as to satisfy simultaneously your obligations under this
 | 
				
			||||||
 | 
					License and any other pertinent obligations, then as a consequence you may
 | 
				
			||||||
 | 
					not convey it at all.  For example, if you agree to terms that obligate you
 | 
				
			||||||
 | 
					to collect a royalty for further conveying from those to whom you convey
 | 
				
			||||||
 | 
					the Program, the only way you could satisfy both those terms and this
 | 
				
			||||||
 | 
					License would be to refrain entirely from conveying the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  13. Remote Network Interaction; Use with the GNU General Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Notwithstanding any other provision of this License, if you modify the
 | 
				
			||||||
 | 
					Program, your modified version must prominently offer all users
 | 
				
			||||||
 | 
					interacting with it remotely through a computer network (if your version
 | 
				
			||||||
 | 
					supports such interaction) an opportunity to receive the Corresponding
 | 
				
			||||||
 | 
					Source of your version by providing access to the Corresponding Source
 | 
				
			||||||
 | 
					from a network server at no charge, through some standard or customary
 | 
				
			||||||
 | 
					means of facilitating copying of software.  This Corresponding Source
 | 
				
			||||||
 | 
					shall include the Corresponding Source for any work covered by version 3
 | 
				
			||||||
 | 
					of the GNU General Public License that is incorporated pursuant to the
 | 
				
			||||||
 | 
					following paragraph.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Notwithstanding any other provision of this License, you have
 | 
				
			||||||
 | 
					permission to link or combine any covered work with a work licensed
 | 
				
			||||||
 | 
					under version 3 of the GNU General Public License into a single
 | 
				
			||||||
 | 
					combined work, and to convey the resulting work.  The terms of this
 | 
				
			||||||
 | 
					License will continue to apply to the part which is the covered work,
 | 
				
			||||||
 | 
					but the work with which it is combined will remain governed by version
 | 
				
			||||||
 | 
					3 of the GNU General Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  14. Revised Versions of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The Free Software Foundation may publish revised and/or new versions of
 | 
				
			||||||
 | 
					the GNU Affero General Public License from time to time.  Such new versions
 | 
				
			||||||
 | 
					will be similar in spirit to the present version, but may differ in detail to
 | 
				
			||||||
 | 
					address new problems or concerns.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Each version is given a distinguishing version number.  If the
 | 
				
			||||||
 | 
					Program specifies that a certain numbered version of the GNU Affero General
 | 
				
			||||||
 | 
					Public License "or any later version" applies to it, you have the
 | 
				
			||||||
 | 
					option of following the terms and conditions either of that numbered
 | 
				
			||||||
 | 
					version or of any later version published by the Free Software
 | 
				
			||||||
 | 
					Foundation.  If the Program does not specify a version number of the
 | 
				
			||||||
 | 
					GNU Affero General Public License, you may choose any version ever published
 | 
				
			||||||
 | 
					by the Free Software Foundation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If the Program specifies that a proxy can decide which future
 | 
				
			||||||
 | 
					versions of the GNU Affero General Public License can be used, that proxy's
 | 
				
			||||||
 | 
					public statement of acceptance of a version permanently authorizes you
 | 
				
			||||||
 | 
					to choose that version for the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Later license versions may give you additional or different
 | 
				
			||||||
 | 
					permissions.  However, no additional obligations are imposed on any
 | 
				
			||||||
 | 
					author or copyright holder as a result of your choosing to follow a
 | 
				
			||||||
 | 
					later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  15. Disclaimer of Warranty.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
 | 
				
			||||||
 | 
					APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
 | 
				
			||||||
 | 
					HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
 | 
				
			||||||
 | 
					OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
 | 
				
			||||||
 | 
					THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
				
			||||||
 | 
					PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
 | 
				
			||||||
 | 
					IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
 | 
				
			||||||
 | 
					ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  16. Limitation of Liability.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 | 
				
			||||||
 | 
					WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
 | 
				
			||||||
 | 
					THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
 | 
				
			||||||
 | 
					GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
 | 
				
			||||||
 | 
					USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
 | 
				
			||||||
 | 
					DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
 | 
				
			||||||
 | 
					PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
 | 
				
			||||||
 | 
					EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					SUCH DAMAGES.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  17. Interpretation of Sections 15 and 16.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If the disclaimer of warranty and limitation of liability provided
 | 
				
			||||||
 | 
					above cannot be given local legal effect according to their terms,
 | 
				
			||||||
 | 
					reviewing courts shall apply local law that most closely approximates
 | 
				
			||||||
 | 
					an absolute waiver of all civil liability in connection with the
 | 
				
			||||||
 | 
					Program, unless a warranty or assumption of liability accompanies a
 | 
				
			||||||
 | 
					copy of the Program in return for a fee.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                     END OF TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            How to Apply These Terms to Your New Programs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you develop a new program, and you want it to be of the greatest
 | 
				
			||||||
 | 
					possible use to the public, the best way to achieve this is to make it
 | 
				
			||||||
 | 
					free software which everyone can redistribute and change under these terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To do so, attach the following notices to the program.  It is safest
 | 
				
			||||||
 | 
					to attach them to the start of each source file to most effectively
 | 
				
			||||||
 | 
					state the exclusion of warranty; and each file should have at least
 | 
				
			||||||
 | 
					the "copyright" line and a pointer to where the full notice is found.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <one line to give the program's name and a brief idea of what it does.>
 | 
				
			||||||
 | 
					    Copyright (C) <year>  <name of author>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Also add information on how to contact you by electronic and paper mail.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If your software can interact with users remotely through a computer
 | 
				
			||||||
 | 
					network, you should also make sure that it provides a way for users to
 | 
				
			||||||
 | 
					get its source.  For example, if your program is a web application, its
 | 
				
			||||||
 | 
					interface could display a "Source" link that leads users to an archive
 | 
				
			||||||
 | 
					of the code.  There are many ways you could offer source, and different
 | 
				
			||||||
 | 
					solutions will be better for different programs; see section 13 for the
 | 
				
			||||||
 | 
					specific requirements.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You should also get your employer (if you work as a programmer) or school,
 | 
				
			||||||
 | 
					if any, to sign a "copyright disclaimer" for the program, if necessary.
 | 
				
			||||||
 | 
					For more information on this, and how to apply and follow the GNU AGPL, see
 | 
				
			||||||
 | 
					<http://www.gnu.org/licenses/>.
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SUBDIRS = include src tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# package the contrib and doc
 | 
				
			||||||
 | 
					EXTRA_DIST = \
 | 
				
			||||||
 | 
						contrib/dump_docs.py contrib/screenrc-l1fwd contrib/osmo-bts-sysmo.service \
 | 
				
			||||||
 | 
						contrib/l1fwd.init contrib/screenrc-sysmobts contrib/respawn.sh \
 | 
				
			||||||
 | 
						doc/examples/sysmo/osmo-bts.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
 | 
				
			||||||
@@ -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)
 | 
				
			||||||
@@ -0,0 +1,302 @@
 | 
				
			|||||||
 | 
					dnl Process this file with autoconf to produce a configure script
 | 
				
			||||||
 | 
					AC_INIT([osmo-bts],
 | 
				
			||||||
 | 
						m4_esyscmd([./git-version-gen .tarball-version]),
 | 
				
			||||||
 | 
						[openbsc@lists.osmocom.org])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl *This* is the root dir, even if an install-sh exists in ../ or ../../
 | 
				
			||||||
 | 
					AC_CONFIG_AUX_DIR([.])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AM_INIT_AUTOMAKE([dist-bzip2])
 | 
				
			||||||
 | 
					AC_CONFIG_TESTDIR(tests)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl kernel style compile messages
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					AC_PROG_MAKE_SET
 | 
				
			||||||
 | 
					AC_PROG_CC
 | 
				
			||||||
 | 
					AC_PROG_INSTALL
 | 
				
			||||||
 | 
					LT_INIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					AC_HEADER_STDC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl Checks for typedefs, structures and compiler characteristics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_ARG_ENABLE(sanitize,
 | 
				
			||||||
 | 
							[AS_HELP_STRING([--enable-sanitize], [Compile with address sanitizer enabled], )],
 | 
				
			||||||
 | 
							[sanitize=$enableval], [sanitize="no"])
 | 
				
			||||||
 | 
					if test x"$sanitize" = x"yes"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined"
 | 
				
			||||||
 | 
						CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_ARG_ENABLE(werror,
 | 
				
			||||||
 | 
						[AS_HELP_STRING(
 | 
				
			||||||
 | 
							[--enable-werror],
 | 
				
			||||||
 | 
							[Turn all compiler warnings into errors, with exceptions:
 | 
				
			||||||
 | 
							 a) deprecation (allow upstream to mark deprecation without breaking builds);
 | 
				
			||||||
 | 
							 b) "#warning" pragmas (allow to remind ourselves of errors without breaking builds)
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						)],
 | 
				
			||||||
 | 
						[werror=$enableval], [werror="no"])
 | 
				
			||||||
 | 
					if test x"$werror" = x"yes"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						WERROR_FLAGS="-Werror"
 | 
				
			||||||
 | 
						WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
 | 
				
			||||||
 | 
						WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
 | 
				
			||||||
 | 
						CFLAGS="$CFLAGS $WERROR_FLAGS"
 | 
				
			||||||
 | 
						CPPFLAGS="$CPPFLAGS $WERROR_FLAGS"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl checks for libraries
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore  >= 0.11.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.11.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.11.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 0.11.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 0.11.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 0.11.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.5.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.5.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(ORTP, ortp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_MSG_CHECKING([whether to enable support for sysmobts calibration tool])
 | 
				
			||||||
 | 
					AC_ARG_ENABLE(sysmobts-calib,
 | 
				
			||||||
 | 
							AC_HELP_STRING([--enable-sysmobts-calib],
 | 
				
			||||||
 | 
									[enable code for sysmobts calibration tool [default=no]]),
 | 
				
			||||||
 | 
							[enable_sysmobts_calib="yes"],[enable_sysmobts_calib="no"])
 | 
				
			||||||
 | 
					AC_MSG_RESULT([$enable_sysmobts_calib])
 | 
				
			||||||
 | 
					AM_CONDITIONAL(ENABLE_SYSMOBTS_CALIB, test "x$enable_sysmobts_calib" = "xyes")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_MSG_CHECKING([whether to enable support for sysmoBTS L1/PHY support])
 | 
				
			||||||
 | 
					AC_ARG_ENABLE(sysmocom-bts,
 | 
				
			||||||
 | 
							AC_HELP_STRING([--enable-sysmocom-bts],
 | 
				
			||||||
 | 
									[enable code for sysmoBTS L1/PHY [default=no]]),
 | 
				
			||||||
 | 
							[enable_sysmocom_bts="yes"],[enable_sysmocom_bts="no"])
 | 
				
			||||||
 | 
					AC_ARG_WITH([sysmobts], [AS_HELP_STRING([--with-sysmobts=INCLUDE_DIR], [Location of the sysmobts API header files, implies --enable-sysmocom-bts])],
 | 
				
			||||||
 | 
								 [sysmobts_incdir="$withval"],[sysmobts_incdir="$incdir"])
 | 
				
			||||||
 | 
					if test "x$sysmobts_incdir" != "x"; then
 | 
				
			||||||
 | 
						# --with-sysmobts was passed, imply enable_sysmocom_bts
 | 
				
			||||||
 | 
						enable_sysmocom_bts="yes"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					AC_SUBST([SYSMOBTS_INCDIR], -I$sysmobts_incdir)
 | 
				
			||||||
 | 
					AC_MSG_RESULT([$enable_sysmocom_bts])
 | 
				
			||||||
 | 
					AM_CONDITIONAL(ENABLE_SYSMOBTS, test "x$enable_sysmocom_bts" = "xyes")
 | 
				
			||||||
 | 
					if test "$enable_sysmocom_bts" = "yes"; then
 | 
				
			||||||
 | 
						oldCPPFLAGS=$CPPFLAGS
 | 
				
			||||||
 | 
						CPPFLAGS="$CPPFLAGS $SYSMOBTS_INCDIR -I$srcdir/include"
 | 
				
			||||||
 | 
						AC_CHECK_HEADER([sysmocom/femtobts/superfemto.h],[],
 | 
				
			||||||
 | 
								[AC_MSG_ERROR([sysmocom/femtobts/superfemto.h can not be found in $sysmobts_incdir])],
 | 
				
			||||||
 | 
								[#include <sysmocom/femtobts/superfemto.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Check for the sbts2050_header.h that was added after the 3.6 release
 | 
				
			||||||
 | 
						AC_CHECK_HEADER([sysmocom/femtobts/sbts2050_header.h], [sysmo_uc_header="yes"], [])
 | 
				
			||||||
 | 
						if test "$sysmo_uc_header" = "yes" ; then
 | 
				
			||||||
 | 
						   	AC_DEFINE(BUILD_SBTS2050, 1, [Define if we want to build SBTS2050])
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PKG_CHECK_MODULES(LIBGPS, libgps)
 | 
				
			||||||
 | 
						CPPFLAGS=$oldCPPFLAGS
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					AM_CONDITIONAL(BUILD_SBTS2050, test "x$sysmo_uc_header" = "xyes")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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], -I$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 $OCTSDR2G_INCDIR -I$srcdir/include"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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_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>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_RSP.ulClkSourceSelection],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLK_SOURCE_SELECTION],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports ulClkSourceSelection in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.lClockError],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_CLOCK_ERROR],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports lClockError in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.lDroppedCycles],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DROPPED_CYCLES],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports lDroppedCycles in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulPllFreqHz],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_PLL_FREQ_HZ],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports ulPllFreqHz in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulPllFractionalFreqHz],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_PLL_FRACTIONAL_FREQ_HZ],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports ulPllFractionalFreqHz in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulSlipCnt],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SLIP_CNT],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports ulSlipCnt in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulSyncLosseCnt],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SYNC_LOSSE_CNT],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports ulSyncLosseCnt in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulSyncLossCnt],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SYNC_LOSS_CNT],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports ulSyncLossCnt in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulSourceState],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SOURCE_STATE],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports ulSourceState in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulDacState],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DAC_STATE],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports ulDacState in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulDriftElapseTimeUs],
 | 
				
			||||||
 | 
								AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DRIFT_ELAPSE_TIME_US],
 | 
				
			||||||
 | 
								[1],
 | 
				
			||||||
 | 
								[Define to 1 if your octphy header files supports ulDriftElapseTimeUs in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
 | 
				
			||||||
 | 
								[],
 | 
				
			||||||
 | 
								[#include <octphy/octvc1/hw/octvc1_hw_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], -I$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 $LITECELL15_INCDIR -I$srcdir/include"
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_MSG_RESULT([CFLAGS="$CFLAGS"])
 | 
				
			||||||
 | 
					AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AM_CONFIG_HEADER(btsconfig.h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_OUTPUT(
 | 
				
			||||||
 | 
					    src/Makefile
 | 
				
			||||||
 | 
					    src/common/Makefile
 | 
				
			||||||
 | 
					    src/osmo-bts-virtual/Makefile
 | 
				
			||||||
 | 
					    src/osmo-bts-omldummy/Makefile
 | 
				
			||||||
 | 
					    src/osmo-bts-sysmo/Makefile
 | 
				
			||||||
 | 
					    src/osmo-bts-litecell15/Makefile
 | 
				
			||||||
 | 
					    src/osmo-bts-trx/Makefile
 | 
				
			||||||
 | 
					    src/osmo-bts-octphy/Makefile
 | 
				
			||||||
 | 
					    include/Makefile
 | 
				
			||||||
 | 
					    include/osmo-bts/Makefile
 | 
				
			||||||
 | 
					    tests/Makefile
 | 
				
			||||||
 | 
					    tests/paging/Makefile
 | 
				
			||||||
 | 
					    tests/agch/Makefile
 | 
				
			||||||
 | 
					    tests/cipher/Makefile
 | 
				
			||||||
 | 
					    tests/sysmobts/Makefile
 | 
				
			||||||
 | 
					    tests/misc/Makefile
 | 
				
			||||||
 | 
					    tests/handover/Makefile
 | 
				
			||||||
 | 
					    tests/tx_power/Makefile
 | 
				
			||||||
 | 
					    tests/power/Makefile
 | 
				
			||||||
 | 
					    tests/meas/Makefile
 | 
				
			||||||
 | 
					    Makefile)
 | 
				
			||||||
@@ -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."
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Start the process and dump the documentation to the doc dir
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import socket, subprocess, time,os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					env = os.environ
 | 
				
			||||||
 | 
					env['L1FWD_BTS_HOST'] = '127.0.0.1'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bts_proc = subprocess.Popen(["./src/osmo-bts-sysmo/sysmobts-remote",
 | 
				
			||||||
 | 
							"-c", "./doc/examples/sysmo/osmo-bts.cfg"], env = env,
 | 
				
			||||||
 | 
							stdin=None, stdout=None)
 | 
				
			||||||
 | 
					time.sleep(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					try:
 | 
				
			||||||
 | 
						sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
				
			||||||
 | 
						sck.setblocking(1)
 | 
				
			||||||
 | 
						sck.connect(("localhost", 4241))
 | 
				
			||||||
 | 
						sck.recv(4096)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Now send the command
 | 
				
			||||||
 | 
						sck.send("show online-help\r")
 | 
				
			||||||
 | 
						xml = ""
 | 
				
			||||||
 | 
						while True:
 | 
				
			||||||
 | 
							data = sck.recv(4096)
 | 
				
			||||||
 | 
							xml = "%s%s" % (xml, data)
 | 
				
			||||||
 | 
							if data.endswith('\r\nOsmoBTS> '):
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Now write everything until the end to the file
 | 
				
			||||||
 | 
						out = open('doc/vty_reference.xml', 'w')
 | 
				
			||||||
 | 
						out.write(xml[18:-11])
 | 
				
			||||||
 | 
						out.close()
 | 
				
			||||||
 | 
					finally:
 | 
				
			||||||
 | 
						# Clean-up
 | 
				
			||||||
 | 
						bts_proc.kill()
 | 
				
			||||||
 | 
						bts_proc.wait()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -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 "" --disable-doxygen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-build-dep.sh libosmo-abis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cd "$deps"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					configure_flags="\
 | 
				
			||||||
 | 
					  --with-osmo-pcu=$deps/osmo-pcu/include \
 | 
				
			||||||
 | 
					  --enable-trx \
 | 
				
			||||||
 | 
					  --enable-sanitize \
 | 
				
			||||||
 | 
					  "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build_bts "osmo-bts-trx" "$configure_flags"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-clean-workspace.sh
 | 
				
			||||||
@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					#!/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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-clean-workspace.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mkdir -p "$deps"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 libosmocore
 | 
				
			||||||
 | 
					    cd $base
 | 
				
			||||||
 | 
					    shift
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					#!/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 "" --disable-doxygen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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="--enable-sanitize --with-litecell15=$deps/layer1-headers/inc/ --enable-litecell15"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build_bts "osmo-bts-lc15" "$configure_flags"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-clean-workspace.sh
 | 
				
			||||||
@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					#!/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 "" --disable-doxygen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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="--enable-sanitize --with-octsdr-2g=$deps/layer1-headers/ --enable-octphy"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build_bts "osmo-bts-octphy" "$configure_flags"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-clean-workspace.sh
 | 
				
			||||||
@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					#!/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 "" --disable-doxygen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-build-dep.sh libosmo-abis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cd "$deps"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-clean-workspace.sh
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					#!/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 "" --disable-doxygen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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-sanitize --enable-sysmocom-bts --with-sysmobts=$inst/include/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This will not work for the femtobts
 | 
				
			||||||
 | 
					if [ $FIRMWARE_VERSION != "femtobts_v2.7" ]; then
 | 
				
			||||||
 | 
					    configure_flags="$configure_flags --enable-sysmobts-calib"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build_bts "osmo-bts-sysmo" "$configure_flags"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-clean-workspace.sh
 | 
				
			||||||
@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					### BEGIN INIT INFO
 | 
				
			||||||
 | 
					# Provides:          l1fwd
 | 
				
			||||||
 | 
					# Required-Start:    
 | 
				
			||||||
 | 
					# Required-Stop:     $local_fs
 | 
				
			||||||
 | 
					# Default-Start:     5
 | 
				
			||||||
 | 
					# Default-Stop:      0 6
 | 
				
			||||||
 | 
					# Short-Description: Start screen session with l1fwd software
 | 
				
			||||||
 | 
					# Description:       
 | 
				
			||||||
 | 
					### END INIT INFO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. /etc/default/rcS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$1" in
 | 
				
			||||||
 | 
					        start)
 | 
				
			||||||
 | 
							/usr/bin/screen -d -m -c /etc/osmocom/screenrc-l1fwd
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
						stop)
 | 
				
			||||||
 | 
							echo "This script doesn't support stop"
 | 
				
			||||||
 | 
					                exit 1
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
					        restart|reload|force-reload)
 | 
				
			||||||
 | 
					                exit 0
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
						show)
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
					        *)
 | 
				
			||||||
 | 
					                echo "Usage: sysmobts {start|stop|show|reload|restart}" >&2
 | 
				
			||||||
 | 
					                exit 1
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PID=$$
 | 
				
			||||||
 | 
					echo "-1000" > /proc/$PID/oom_score_adj
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trap "{ kill 0; kill -2 0; }" EXIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					while [ -f $1 ]; do
 | 
				
			||||||
 | 
						(echo "0" > /proc/self/oom_score_adj && exec nice -n -20 $*) &
 | 
				
			||||||
 | 
						LAST_PID=$!
 | 
				
			||||||
 | 
						wait $LAST_PID
 | 
				
			||||||
 | 
						sleep 10s
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PID=$$
 | 
				
			||||||
 | 
					echo "-1000" > /proc/$PID/oom_score_adj
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trap "kill 0" EXIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					while [ -e /etc/passwd ]; do
 | 
				
			||||||
 | 
						cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0
 | 
				
			||||||
 | 
						sleep 2s
 | 
				
			||||||
 | 
						cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0
 | 
				
			||||||
 | 
						sleep 1s
 | 
				
			||||||
 | 
						echo "0" > /sys/class/leds/activity_led/brightness
 | 
				
			||||||
 | 
						(echo "0" > /proc/self/oom_score_adj && exec nice -n -20 $*) &
 | 
				
			||||||
 | 
						LAST_PID=$!
 | 
				
			||||||
 | 
						wait $LAST_PID
 | 
				
			||||||
 | 
						sleep 10s
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					chdir /tmp
 | 
				
			||||||
 | 
					screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/l1fwd-proxy
 | 
				
			||||||
 | 
					detach
 | 
				
			||||||
@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					chdir /tmp
 | 
				
			||||||
 | 
					screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/osmo-bts-sysmo -c /etc/osmocom/osmo-bts.cfg -r 1 -M
 | 
				
			||||||
 | 
					screen -t PCU 1 /etc/osmocom/respawn-only.sh /usr/bin/osmo-pcu -c /etc/osmocom/osmo-pcu.cfg -e
 | 
				
			||||||
 | 
					screen -t MGR 2 /etc/osmocom/respawn-only.sh /usr/bin/sysmobts-mgr -n -c /etc/osmocom/sysmobts-mgr.cfg
 | 
				
			||||||
 | 
					detach
 | 
				
			||||||
@@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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*
 | 
				
			||||||
@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					[Unit]
 | 
				
			||||||
 | 
					Description=osmo-bts manager for sysmoBTS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Service]
 | 
				
			||||||
 | 
					Type=simple
 | 
				
			||||||
 | 
					ExecStart=/usr/bin/sysmobts-mgr -ns -c /etc/osmocom/sysmobts-mgr.cfg
 | 
				
			||||||
 | 
					Restart=always
 | 
				
			||||||
 | 
					RestartSec=2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Install]
 | 
				
			||||||
 | 
					WantedBy=multi-user.target
 | 
				
			||||||
 | 
					Alias=osmo-bts-mgr.service
 | 
				
			||||||
@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					### BEGIN INIT INFO
 | 
				
			||||||
 | 
					# Provides:          sysmobts
 | 
				
			||||||
 | 
					# Required-Start:    
 | 
				
			||||||
 | 
					# Required-Stop:     $local_fs
 | 
				
			||||||
 | 
					# Default-Start:     5
 | 
				
			||||||
 | 
					# Default-Stop:      0 6
 | 
				
			||||||
 | 
					# Short-Description: Start screen session with sysmobts software
 | 
				
			||||||
 | 
					# Description:       
 | 
				
			||||||
 | 
					### END INIT INFO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$1" in
 | 
				
			||||||
 | 
					        start)
 | 
				
			||||||
 | 
							/usr/bin/screen -d -m -c /etc/osmocom/screenrc-sysmobts -S sysmobts
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
						stop)
 | 
				
			||||||
 | 
							/usr/bin/screen -d -r sysmobts -X quit
 | 
				
			||||||
 | 
					                exit 1
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
					        restart|reload|force-reload)
 | 
				
			||||||
 | 
					                exit 0
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
						show)
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
					        *)
 | 
				
			||||||
 | 
					                echo "Usage: sysmobts {start|stop|show|reload|restart}" >&2
 | 
				
			||||||
 | 
					                exit 1
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					[Unit]
 | 
				
			||||||
 | 
					Description=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=osmo-bts-sysmo.service
 | 
				
			||||||
@@ -0,0 +1,755 @@
 | 
				
			|||||||
 | 
					osmo-bts (0.8.1) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * cosmetic: dyn TS: clarify rsl_tx_rf_rel_ack() with a switch
 | 
				
			||||||
 | 
					  * dyn TS: fix TCH/F_TCH/H_PDCH: properly record release of PDCH TS
 | 
				
			||||||
 | 
					  * dyn TS: rx_rf_chan_rel: properly mark PDCH rel when no PCU, clarify
 | 
				
			||||||
 | 
					  * dyn TS: clear TCH state upon reconnecting as PDCH
 | 
				
			||||||
 | 
					  * cosmetic: dyn TS: clarify chan_nr composition
 | 
				
			||||||
 | 
					  * ignore RSL RF CHAN REL for inactive lchans
 | 
				
			||||||
 | 
					  * fix RSL Chan Activ Nack messages
 | 
				
			||||||
 | 
					  * ip.access dyn ts: properly NACK a PDCH ACT on a still active lchan
 | 
				
			||||||
 | 
					  * add/improve various logging around dyn ts
 | 
				
			||||||
 | 
					  * dyn TS: be less strict on chan_nr, to allow arbitrary pchan switches
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Stefan Sperling ]
 | 
				
			||||||
 | 
					  * send a State Changed Event Report when rf is locked/unlocked
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * rsl: log errors when parsing of  encryption information fails
 | 
				
			||||||
 | 
					  * rsl: Make channel activation fail if encryption algorithm not supported
 | 
				
			||||||
 | 
					  * rsl: Properly NACK CHAN_ACKT / MODE_MODIFY
 | 
				
			||||||
 | 
					  * rsl: If CHAN ACT or MODE MODIF fails, send respective NACK
 | 
				
			||||||
 | 
					  * osmo-bts-trx: Enable A5/3 cipher support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Tue, 15 May 2018 14:08:47 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-bts (0.8.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * vty: skip installing cmds now always installed by default
 | 
				
			||||||
 | 
					  * jenkins_common.sh: fix build_bts distcheck for more than one conf_flag
 | 
				
			||||||
 | 
					  * fix build: tests/sysmobts: add missing -I$(SYSMOBTS_INCDIR)
 | 
				
			||||||
 | 
					  * fix handover: handle_ph_ra_ind(): evaluate ra_ind before msgb_trim()
 | 
				
			||||||
 | 
					  * implement support for 3-digit MNC with leading zeros
 | 
				
			||||||
 | 
					  * configure: add --enable-werror
 | 
				
			||||||
 | 
					  * use osmo_init_logging2() with proper talloc ctx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * lc15: Fix cfg indentation
 | 
				
			||||||
 | 
					  * l1sap: Fix abort on big RTP packet received
 | 
				
			||||||
 | 
					  * bts-trx: trx_ctrl_cmd: Simplify var assignment logic
 | 
				
			||||||
 | 
					  * bts-trx: Avoid enqueueing consecutive duplicate messages to TRX
 | 
				
			||||||
 | 
					  * Fix malformed Resource Indication packet
 | 
				
			||||||
 | 
					  * debian/control: Remove uneeded dep libosmo-netif-dev
 | 
				
			||||||
 | 
					  * jenkins.sh: Disable building doxygen for deps
 | 
				
			||||||
 | 
					  * oml.c: Fix use of htons instead of ntohs
 | 
				
			||||||
 | 
					  * bts-trx: trx_if.c: Log timedout+retransmitted CMD
 | 
				
			||||||
 | 
					  * bts-trx: trx_if.c: trx_ctrl_read_cb: Move error handling to end of func
 | 
				
			||||||
 | 
					  * bts-trx: trx_if.c: Improve parsing of received RSP messages from TRX
 | 
				
			||||||
 | 
					  * bts-trx: Detect duplicated responses for retransmitted commands
 | 
				
			||||||
 | 
					  * gsm_pchan2chan_nr: move warning to pragma message and track issue
 | 
				
			||||||
 | 
					  * Remove unused variables
 | 
				
			||||||
 | 
					  * bts-trx: scheduler_trx.c: Fix missing header
 | 
				
			||||||
 | 
					  * l1sap.c: l1sap_tch_rts_ind: Remove unused variables
 | 
				
			||||||
 | 
					  * octphy: octpkt.c: Remove unused static functions
 | 
				
			||||||
 | 
					  * vty.c: Remove warning message
 | 
				
			||||||
 | 
					  * virtual: l1_if.c: Remove unneeded warning message
 | 
				
			||||||
 | 
					  * main.c: bts_main: fix typo in error message
 | 
				
			||||||
 | 
					  * l1sap: Validate incoming RTP payload, drop bw-efficient AMR
 | 
				
			||||||
 | 
					  * l1sap: Avoid assumption that l1sap is at head of msgb
 | 
				
			||||||
 | 
					  * contrib: jenkins_bts_model: Fix bashism expr
 | 
				
			||||||
 | 
					  * Include missing headers for osmo_init_logging2
 | 
				
			||||||
 | 
					  * common/sysinfo.c: Fix no return on on-void function
 | 
				
			||||||
 | 
					  * gsm_data_shared.h: Remove unused enum gsm_paging_event
 | 
				
			||||||
 | 
					  * scheduler_trx: Fix signed integer overflow in clock calculations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * trx: Better be safe than sorry before calling strlen
 | 
				
			||||||
 | 
					  * trx: Avoid NULL+1 dereference in trx_ctrl_read_cb()
 | 
				
			||||||
 | 
					  * trx: Don't call osmo_fr_check_sid with negative 'rc'
 | 
				
			||||||
 | 
					  * trx: Don't assume phy_instance_by_num() returns non-NULL
 | 
				
			||||||
 | 
					  * l1sap: fix wrong return value of is_fill_frame()
 | 
				
			||||||
 | 
					  * measurement.c: Fix various typos in comments
 | 
				
			||||||
 | 
					  * Comments on individual members of struct gsm_abis_mo
 | 
				
			||||||
 | 
					  * scheduler: Harmonize log line format; Always print TS name + decoded FN
 | 
				
			||||||
 | 
					  * scheduler_trx: L1P is for PH (data), L1M for MPH (control)
 | 
				
			||||||
 | 
					  * l1sap: Fix log subsystem: Use DRTP for RTP related bits, L1C for MPH
 | 
				
			||||||
 | 
					  * measurment.c: Introduce INFO category for DMEAS logging
 | 
				
			||||||
 | 
					  * osmo-bts-octphy: Remove bogus warning about BS_AG_BLKS_RES
 | 
				
			||||||
 | 
					  * rsl.c: Log RTP socket related errors as DRTP, not DRSL
 | 
				
			||||||
 | 
					  * Put useful information in RTCP SDES.
 | 
				
			||||||
 | 
					  * osmo-bts-trx: Fix reported frame number during PRIM_INFO_MEAS
 | 
				
			||||||
 | 
					  * DTX: avoid illegal character contained in DTX FSM allocation which causes BTS crash
 | 
				
			||||||
 | 
					  * gsm_lchan: remove unused member fields
 | 
				
			||||||
 | 
					  * Add 'show (bts|trx|ts|lchan)' commands
 | 
				
			||||||
 | 
					  * Print much more information during 'show lchan'
 | 
				
			||||||
 | 
					  * vty: don't print "Bound IP / Port" if it isn't bound [yet]
 | 
				
			||||||
 | 
					  * osmo-bts: Add talloc context introspection via VTY
 | 
				
			||||||
 | 
					  * sysmo: Fix compiler warnings in eeprom.c
 | 
				
			||||||
 | 
					  * sysmo+lc15: Add missign include for readv/writev
 | 
				
			||||||
 | 
					  * trx: make l1if_fill_meas_res() static
 | 
				
			||||||
 | 
					  * RSL: Properly reject RSL CHAN_NR IE for incompatible PCHAN
 | 
				
			||||||
 | 
					  * RSL: Ensure we don't accept DCHAN messages for CCHAN
 | 
				
			||||||
 | 
					  * osmo-bts-virtual: Shut down gracefully on socket creation failure
 | 
				
			||||||
 | 
					  * osmo-bts-virtual: Generate PRIM_INFO_MEAS (with bogus values)
 | 
				
			||||||
 | 
					  * Introduce + use LOG/DEBUGP with frame number prefixing/printing
 | 
				
			||||||
 | 
					  * osmo-bts-virtual: Make use of LOGL1S() macro for context
 | 
				
			||||||
 | 
					  * osmo-bts-virtual: Make sure PRIM_INFO_MEAS have non-zero frame number
 | 
				
			||||||
 | 
					  * scheduler.c: Factor out find_sched_mframe_idx() function
 | 
				
			||||||
 | 
					  * scheduler: add trx_sched_is_sacch_fn() function
 | 
				
			||||||
 | 
					  * Revert "measurement: fix measurement computation"
 | 
				
			||||||
 | 
					  * measurement.c: Hand Frame Number into measurement computation
 | 
				
			||||||
 | 
					  * l1sap: Pass is_sub from L1 primitive into the Uplink Measurement
 | 
				
			||||||
 | 
					  * osmo-bts-trx: Add missing frame number to l1if_process_meas_res()
 | 
				
			||||||
 | 
					  * scheduler.c: Print message when burst substitution happens
 | 
				
			||||||
 | 
					  * load_indication: Fix start of load indication timer
 | 
				
			||||||
 | 
					  * RSL: Implement DELETE INDICATION on AGCH overflow
 | 
				
			||||||
 | 
					  * RSL: Send ERROR REPORT on too short/truncated messages + wrong discriminator
 | 
				
			||||||
 | 
					  * BTS: add rate_ctr about CCCH (paging, agch, pch)
 | 
				
			||||||
 | 
					  * paging: Drop + Log paging requests for non-existant paging groups
 | 
				
			||||||
 | 
					  * paging.c: Fix encoding of optional Mobile ID RR PAGING TYPE 1 / 2
 | 
				
			||||||
 | 
					  * rsl: Improve ERROR REPORTing
 | 
				
			||||||
 | 
					  * paging: Fix encoding of PAGING TYPE 3 Rest Octets
 | 
				
			||||||
 | 
					  * RSL IPA DLCX: Avoid null-pointer dereference
 | 
				
			||||||
 | 
					  * RSL: Fix encoding of ConnectionID in IPA_DLCX_ACK
 | 
				
			||||||
 | 
					  * RSL IPA DLCX: Avoid another null-pointer dereference
 | 
				
			||||||
 | 
					  * measurement.c: Fix sdcch4_meas_rep_fn102 / sdcch8_meas_rep_fn102
 | 
				
			||||||
 | 
					  * counters: split rach:sent into rach:drop, rach:ho, rach:cs and rach:ps
 | 
				
			||||||
 | 
					  * octphy: Remove code duplication for BER / RSSI conversion
 | 
				
			||||||
 | 
					  * {sysmo,lc15}: Correctly report BER to L1SAP in INFO_MEAS_IND
 | 
				
			||||||
 | 
					  * {sysmo,lc15}: Fix RACH reporting in combined CBCH case
 | 
				
			||||||
 | 
					  * split scheduler_mframe.c from scheduler.c
 | 
				
			||||||
 | 
					  * measurement: Compute RX{LEV,QUAL}-SUB for SDCCH and non-AMR TCH
 | 
				
			||||||
 | 
					  * measurement.c: Don't silently copy "FULL" measurements to "SUB"
 | 
				
			||||||
 | 
					  * scheduler: Add missing \n at end of LOG statement
 | 
				
			||||||
 | 
					  * Move rach_busy counting above L1SAP
 | 
				
			||||||
 | 
					  * RACH decoding: Use BER threshold for RACH ghost detection
 | 
				
			||||||
 | 
					  * trx/scheduler: Use integer math for TOA (Timing of Arrival)
 | 
				
			||||||
 | 
					  * measurement.c: higher-precision TA/TOA math
 | 
				
			||||||
 | 
					  * L1SAP: Increase resolution of reported burst timing
 | 
				
			||||||
 | 
					  * measurement: Keep average of high-accurate ToA value in lchan
 | 
				
			||||||
 | 
					  * Add high-accuracy ToA value to Uplink Measurement Reports
 | 
				
			||||||
 | 
					  * pcu_sock: Discard messages that are too short
 | 
				
			||||||
 | 
					  * pcu_sock: Don't overflow the timeslot array
 | 
				
			||||||
 | 
					  * pcu_sock: Log an error message and discard PCU primitives for BTS != 0
 | 
				
			||||||
 | 
					  * pcu_sock: LOG + drop DATA.req from PCU for non-PDCH timeslot
 | 
				
			||||||
 | 
					  * pcu_sock: LOG + drop PCU DATA.req for inactive lchan
 | 
				
			||||||
 | 
					  * sysinfo.c: SI1 is optional; Send SI2 at TC=0 if no SI1 exists
 | 
				
			||||||
 | 
					  * sysmobts: Compatibility with older firmware versions
 | 
				
			||||||
 | 
					  * cosmetic: Document some SI scheduling related function API
 | 
				
			||||||
 | 
					  * sysinfo: Fix scheduling of downlink SACCH information
 | 
				
			||||||
 | 
					  * gsm_data_shared: Remove unused definitions/members/functions
 | 
				
			||||||
 | 
					  * cosmetic: Move agch_queue to sub-structure of gsm_bts_role_bts
 | 
				
			||||||
 | 
					  * Get rid of 'struct gsm_bts_role_bts'
 | 
				
			||||||
 | 
					  * virtual: Correctly set+report BTS variant in OML attributes
 | 
				
			||||||
 | 
					  * Add 'osmo-bts-omldummy' to bring up only OML without RSL
 | 
				
			||||||
 | 
					  * fix inverted logic bug in omldummy patch
 | 
				
			||||||
 | 
					  * omldummy: Suppress RSL transmission errors
 | 
				
			||||||
 | 
					  * debian: Split osmo-bts-virtual from osmo-bts-trx
 | 
				
			||||||
 | 
					  * fox chan_nr_is_dchan() for RSL_CHAN_OSMO_PDCH
 | 
				
			||||||
 | 
					  * rsl_tx_dyn_pdch_ack: Add missing FRAME_NR information element
 | 
				
			||||||
 | 
					  * fix activation of osmocom-style dynamic PDCH as TCH/F or TCH/H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Philipp Maier ]
 | 
				
			||||||
 | 
					  * octphy: override firmware version check
 | 
				
			||||||
 | 
					  * cosmetic: meas_test: fix section comment
 | 
				
			||||||
 | 
					  * cosmetic: tests/Makefile.am: remove excess whitespace
 | 
				
			||||||
 | 
					  * cosmetic: tests/power: remove unused var "ret"
 | 
				
			||||||
 | 
					  * cosmetic: tests/agch: remove unused var "static_ilv"
 | 
				
			||||||
 | 
					  * octphy: l1_oml: check returncode of trx_by_l1h()
 | 
				
			||||||
 | 
					  * meas_test: fix header file references
 | 
				
			||||||
 | 
					  * rsl: fix double-free in rsl_rx_mode_modif()
 | 
				
			||||||
 | 
					  * fix nullpointer deref in rsl_tx_mode_modif_nack()
 | 
				
			||||||
 | 
					  * rsl: do not allow MODE MODIFY request with unsupp. codec/rate
 | 
				
			||||||
 | 
					  * gsm_data_shared: extend bts feature list with speech codecs
 | 
				
			||||||
 | 
					  * octphy: ensure all BTS models set features
 | 
				
			||||||
 | 
					  * vty: display bts features in vty command show bts
 | 
				
			||||||
 | 
					  * bts: use feature list instead of speech codec table
 | 
				
			||||||
 | 
					  * octphy: replace #warning with #pragma message
 | 
				
			||||||
 | 
					  * ipac: fix log output
 | 
				
			||||||
 | 
					  * rsl: remove unused variable
 | 
				
			||||||
 | 
					  * l1_tch: remove dead code
 | 
				
			||||||
 | 
					  * cosmetic: remove dead code
 | 
				
			||||||
 | 
					  * cosmetic: remove unused variable
 | 
				
			||||||
 | 
					  * cosmetic: remove unused variable in osmo-bts-omldummy/main.c
 | 
				
			||||||
 | 
					  * octphy: integrate octasics latest header release
 | 
				
			||||||
 | 
					  * osmo-bts-trx: perform error concealment for FR frames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Max ]
 | 
				
			||||||
 | 
					  * Remove leftover comments and checks
 | 
				
			||||||
 | 
					  * Log filenames on L1 errors
 | 
				
			||||||
 | 
					  * Add --enable-sanitize configure option
 | 
				
			||||||
 | 
					  * Use existing function to obtain TSC
 | 
				
			||||||
 | 
					  * Remove BSC-specific parts
 | 
				
			||||||
 | 
					  * Print FN delta on L1 errors
 | 
				
			||||||
 | 
					  * Move sysmobts-calib into osmo-bts-sysmo
 | 
				
			||||||
 | 
					  * Allow specifying sysmocom headers explicitly
 | 
				
			||||||
 | 
					  * fix build: tests/misc: missing libosmo-abis and -trau flags
 | 
				
			||||||
 | 
					  * Enable optional static builds
 | 
				
			||||||
 | 
					  * Remove unneeded LIBOSMOCORE_CFLAGS from tests
 | 
				
			||||||
 | 
					  * sysmobts: use proper includes for sbts2050 test
 | 
				
			||||||
 | 
					  * Move -I inside *INCDIR variable
 | 
				
			||||||
 | 
					  * sysmobts: remove weird default header location
 | 
				
			||||||
 | 
					  * sysmobts: move header check to appropriate place
 | 
				
			||||||
 | 
					  * CI: drop unused OsmoPCU dependency
 | 
				
			||||||
 | 
					  * Enable sanitize for CI tests
 | 
				
			||||||
 | 
					  * Add helper to get BCC from BSIC
 | 
				
			||||||
 | 
					  * osmo-bts-trx: init nbits to know value
 | 
				
			||||||
 | 
					  * osmo-bts-trx: ignore frame offset error on startup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Vadim Yanitskiy ]
 | 
				
			||||||
 | 
					  * doc/examples: add CalypsoBTS configuration example
 | 
				
			||||||
 | 
					  * common/pcu_sock.c: fix double field assignment
 | 
				
			||||||
 | 
					  * scheduler_trx.c: remove ToA (Time of Arrival) hack
 | 
				
			||||||
 | 
					  * common/l1sap.c: increase the BTS_CTR_RACH_DROP in RACH BER check
 | 
				
			||||||
 | 
					  * common/l1sap.c: increment valid RACH counter after all checks
 | 
				
			||||||
 | 
					  * common/l1sap.c: clean up noise / ghost RACH filtering
 | 
				
			||||||
 | 
					  * common/l1sap.c: perform noise / ghost filtering for handover RACH
 | 
				
			||||||
 | 
					  * common/l1sap.c: limit the minimal ToA for RACH bursts
 | 
				
			||||||
 | 
					  * common/vty.c: remove unused variables
 | 
				
			||||||
 | 
					  * common/main.c: track talloc NULL contexts by default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Alexander Huemer ]
 | 
				
			||||||
 | 
					  * cosmetic: Makefile.am whitespace
 | 
				
			||||||
 | 
					  * various Makefile.am: add missing CFLAGS
 | 
				
			||||||
 | 
					  * gitignore: add missing entries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Stefan Sperling ]
 | 
				
			||||||
 | 
					  * Cosmetic fixes for power ramping code.
 | 
				
			||||||
 | 
					  * respond with NACK for non-hopping BTS with multiple ARFCN
 | 
				
			||||||
 | 
					  * cosmetic: fix typos in src/common/oml.c
 | 
				
			||||||
 | 
					  * return NACK codes instead of errno values from oml_tx_attr_resp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Alexander Couzens ]
 | 
				
			||||||
 | 
					  * pcuif_proto: correct indention of gsm_pcu_if_data
 | 
				
			||||||
 | 
					  * pcu_if: move definition PCU_SOCK_DEFAULT into pcuif_proto.h
 | 
				
			||||||
 | 
					  * pcuif_proto: add version 8 features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Keith ]
 | 
				
			||||||
 | 
					  * osmo-bts-sysmo eeprom.c Restore ability to read/write EEPROM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Thu, 03 May 2018 17:02:19 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-bts (0.7.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Max ]
 | 
				
			||||||
 | 
					  * Use value string check from osmo-ci
 | 
				
			||||||
 | 
					  * Support sending SI13 to PCU
 | 
				
			||||||
 | 
					  * Support removing SI13 from PCU
 | 
				
			||||||
 | 
					  * trx: avoid deactivating lchan on LCHAN_REL_ACT_REACT
 | 
				
			||||||
 | 
					  * Check readv() return value to prevent crash
 | 
				
			||||||
 | 
					  * OML: print actual type of report sent to BSC
 | 
				
			||||||
 | 
					  * Replace dead code
 | 
				
			||||||
 | 
					  * vty: print version and description for each phy
 | 
				
			||||||
 | 
					  * Remove build dependency on legacy OpenBSC
 | 
				
			||||||
 | 
					  * Fix multiple SI2q reception
 | 
				
			||||||
 | 
					  * jenkins: remove openbsc dependency
 | 
				
			||||||
 | 
					  * sysmo: use clock calibration source wrapper
 | 
				
			||||||
 | 
					  * sysmo: don't override clock source with defaults
 | 
				
			||||||
 | 
					  * Fix race condition in attribute reporting
 | 
				
			||||||
 | 
					  * Move power loop to generic tests
 | 
				
			||||||
 | 
					  * Make power test more verbose
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * vty: mgr: sysmobts, lc15: install default commands for ACT_NORM_NODE
 | 
				
			||||||
 | 
					  * osmo-bts-trx: vty: various fixes of 'write file' and doc
 | 
				
			||||||
 | 
					  * jenkins: use osmo-clean-workspace.sh before and after build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * l1sap: Improve log msg when frame diff >1
 | 
				
			||||||
 | 
					  * vty: Print string for Administrative state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * Fix Downlink AMR FSM name to avoid illegal space character
 | 
				
			||||||
 | 
					  * update dependencies to latest libosmo-*
 | 
				
			||||||
 | 
					  * configure.ac: Fix Mailing list address
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Harald Welte <laforge@gnumonks.org>  Sat, 28 Oct 2017 20:53:21 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					9
 | 
				
			||||||
@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					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,
 | 
				
			||||||
 | 
					               libosmo-abis-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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: osmo-bts-virtual
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Depends: ${shlibs:Depends}, ${misc:Depends}
 | 
				
			||||||
 | 
					Description: Virtual Osmocom GSM BTS (no RF hardware; GSMTAP/UDP)
 | 
				
			||||||
 | 
					 This version of OsmoBTS doesn't use actual GSM PHY/Hardware/RF, but
 | 
				
			||||||
 | 
					 utilizes GSMTAP-over-UDP frames for the Um interface.  This is useful
 | 
				
			||||||
 | 
					 in fully virtualized setups e.g. in combination with OsmocomBB virt_phy.
 | 
				
			||||||
@@ -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.
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					usr/bin/osmo-bts-trx
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					usr/bin/osmo-bts-virtual
 | 
				
			||||||
 | 
					usr/bin/osmo-bts-omldummy
 | 
				
			||||||
@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					[Unit]
 | 
				
			||||||
 | 
					Description=Osmocom GSM BTS for virtual Um layer based on GSMTAP/UDP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Service]
 | 
				
			||||||
 | 
					Type=simple
 | 
				
			||||||
 | 
					ExecStart=/usr/bin/osmo-bts-virtual -s -c /etc/osmocom/osmo-bts-virtual.cfg
 | 
				
			||||||
 | 
					Restart=always
 | 
				
			||||||
 | 
					RestartSec=2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Let it process messages quickly enough
 | 
				
			||||||
 | 
					CPUSchedulingPolicy=rr
 | 
				
			||||||
 | 
					CPUSchedulingPriority=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Install]
 | 
				
			||||||
 | 
					WantedBy=multi-user.target
 | 
				
			||||||
@@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					3.0 (native)
 | 
				
			||||||
@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					The osmo-bts control interface is currently supporting the following operations:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h2. generic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h3. trx.0.thermal-attenuation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The idea of this paramter is to attenuate the system output power as part of
 | 
				
			||||||
 | 
					thermal management.  In some cases the PA might be passing a critical level,
 | 
				
			||||||
 | 
					so an external control process can use this attribute to reduce the system
 | 
				
			||||||
 | 
					output power.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please note that all values in the context of transmit power calculation
 | 
				
			||||||
 | 
					are integers in milli-dB (1/10000 bel), so the below example is setting
 | 
				
			||||||
 | 
					the attenuation at 3 dB:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<pre>
 | 
				
			||||||
 | 
					bsc_control.py -d localhost -p 4238 -s trx.0.thermal-attenuation 3000
 | 
				
			||||||
 | 
					Got message: SET_REPLY 1 trx.0.thermal-attenuation 3000
 | 
				
			||||||
 | 
					</pre>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<pre>
 | 
				
			||||||
 | 
					bsc_control.py -d localhost -p 4238 -g trx.0.thermal-attenuation
 | 
				
			||||||
 | 
					Got message: GET_REPLY 1 trx.0.thermal-attenuation 3000
 | 
				
			||||||
 | 
					</pre>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h2. sysmobts specific
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h3. trx.0.clock-info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					obtain information on the current clock status:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<pre>
 | 
				
			||||||
 | 
					bsc_control.py -d localhost -p 4238 -g trx.0.clock-info
 | 
				
			||||||
 | 
					Got message: GET_REPLY 1 trx.0.clock-info -100,ocxo,0,0,gps
 | 
				
			||||||
 | 
					</pre>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					which is to be interpreted as:
 | 
				
			||||||
 | 
					* current clock correction value is -100 ppb
 | 
				
			||||||
 | 
					* current clock source is OCXO
 | 
				
			||||||
 | 
					* deviation between clock source and calibration source is 0 ppb
 | 
				
			||||||
 | 
					* resolution of clock error measurement is 0 ppt (0 means no result yet)
 | 
				
			||||||
 | 
					* current calibration source is GPS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When this attribute is set, any value passed on is discarded, but the clock
 | 
				
			||||||
 | 
					calibration process is re-started.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h3. trx.0.clock-correction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This attribute can get and set the current clock correction value:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<pre>
 | 
				
			||||||
 | 
					bsc_control.py -d localhost -p 4238 -g trx.0.clock-correction
 | 
				
			||||||
 | 
					Got message: GET_REPLY 1 trx.0.clock-correction -100
 | 
				
			||||||
 | 
					</pre>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<pre>
 | 
				
			||||||
 | 
					bsc_control.py -d localhost -p 4238 -s trx.0.clock-correction -- -99
 | 
				
			||||||
 | 
					Got message: SET_REPLY 1 trx.0.clock-correction success
 | 
				
			||||||
 | 
					</pre>
 | 
				
			||||||
@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					!
 | 
				
			||||||
 | 
					! OsmoBTS configuration example for CalypsoBTS
 | 
				
			||||||
 | 
					! http://osmocom.org/projects/baseband/wiki/CalypsoBTS
 | 
				
			||||||
 | 
					!!
 | 
				
			||||||
 | 
					!
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					 osmotrx timing-advance-loop
 | 
				
			||||||
 | 
					 osmotrx ms-power-loop -65
 | 
				
			||||||
 | 
					 osmotrx legacy-setbsic
 | 
				
			||||||
 | 
					bts 0
 | 
				
			||||||
 | 
					 oml remote-ip 127.0.0.1
 | 
				
			||||||
 | 
					 ipa unit-id 1801 0
 | 
				
			||||||
 | 
					 gsmtap-sapi pdtch
 | 
				
			||||||
 | 
					 gsmtap-sapi ccch
 | 
				
			||||||
 | 
					 band 900
 | 
				
			||||||
 | 
					 trx 0
 | 
				
			||||||
 | 
					  phy 0 instance 0
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					!
 | 
				
			||||||
 | 
					! 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
 | 
				
			||||||
 | 
					 instance 0
 | 
				
			||||||
 | 
					bts 0
 | 
				
			||||||
 | 
					 band 1800
 | 
				
			||||||
 | 
					 ipa unit-id 666 0
 | 
				
			||||||
 | 
					 oml remote-ip 10.1.2.3
 | 
				
			||||||
 | 
					 trx 0
 | 
				
			||||||
 | 
					  phy 0 instance 0
 | 
				
			||||||
@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					!
 | 
				
			||||||
 | 
					! SysmoMgr (0.3.0.141-33e5) configuration saved from vty
 | 
				
			||||||
 | 
					!!
 | 
				
			||||||
 | 
					!
 | 
				
			||||||
 | 
					log stderr
 | 
				
			||||||
 | 
					  logging filter all 1
 | 
				
			||||||
 | 
					  logging color 1
 | 
				
			||||||
 | 
					  logging timestamp 0
 | 
				
			||||||
 | 
					  logging level temp info
 | 
				
			||||||
 | 
					  logging level fw info
 | 
				
			||||||
 | 
					  logging level find 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
 | 
				
			||||||
 | 
					!
 | 
				
			||||||
 | 
					line vty
 | 
				
			||||||
 | 
					 no login
 | 
				
			||||||
 | 
					!
 | 
				
			||||||
 | 
					sysmobts-mgr
 | 
				
			||||||
@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					!
 | 
				
			||||||
 | 
					! 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
 | 
				
			||||||
 | 
					 gsmtap-sapi ccch
 | 
				
			||||||
 | 
					 gsmtap-sapi pdtch
 | 
				
			||||||
 | 
					 trx 0
 | 
				
			||||||
 | 
					  phy 0 instance 0
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -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.
 | 
				
			||||||
@@ -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 | osmo_init_logging2() | 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
 | 
				
			||||||
@@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					# Print a version string.
 | 
				
			||||||
 | 
					scriptversion=2010-01-28.01
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copyright (C) 2007-2010 Free Software Foundation, Inc.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					# it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					# the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					# (at your option) any later version.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					# GNU General Public License for more details.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
 | 
				
			||||||
 | 
					# It may be run two ways:
 | 
				
			||||||
 | 
					# - from a git repository in which the "git describe" command below
 | 
				
			||||||
 | 
					#   produces useful output (thus requiring at least one signed tag)
 | 
				
			||||||
 | 
					# - from a non-git-repo directory containing a .tarball-version file, which
 | 
				
			||||||
 | 
					#   presumes this script is invoked like "./git-version-gen .tarball-version".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# In order to use intra-version strings in your project, you will need two
 | 
				
			||||||
 | 
					# separate generated version string files:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# .tarball-version - present only in a distribution tarball, and not in
 | 
				
			||||||
 | 
					#   a checked-out repository.  Created with contents that were learned at
 | 
				
			||||||
 | 
					#   the last time autoconf was run, and used by git-version-gen.  Must not
 | 
				
			||||||
 | 
					#   be present in either $(srcdir) or $(builddir) for git-version-gen to
 | 
				
			||||||
 | 
					#   give accurate answers during normal development with a checked out tree,
 | 
				
			||||||
 | 
					#   but must be present in a tarball when there is no version control system.
 | 
				
			||||||
 | 
					#   Therefore, it cannot be used in any dependencies.  GNUmakefile has
 | 
				
			||||||
 | 
					#   hooks to force a reconfigure at distribution time to get the value
 | 
				
			||||||
 | 
					#   correct, without penalizing normal development with extra reconfigures.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# .version - present in a checked-out repository and in a distribution
 | 
				
			||||||
 | 
					#   tarball.  Usable in dependencies, particularly for files that don't
 | 
				
			||||||
 | 
					#   want to depend on config.h but do want to track version changes.
 | 
				
			||||||
 | 
					#   Delete this file prior to any autoconf run where you want to rebuild
 | 
				
			||||||
 | 
					#   files to pick up a version string change; and leave it stale to
 | 
				
			||||||
 | 
					#   minimize rebuild time after unrelated changes to configure sources.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# It is probably wise to add these two files to .gitignore, so that you
 | 
				
			||||||
 | 
					# don't accidentally commit either generated file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Use the following line in your configure.ac, so that $(VERSION) will
 | 
				
			||||||
 | 
					# automatically be up-to-date each time configure is run (and note that
 | 
				
			||||||
 | 
					# since configure.ac no longer includes a version string, Makefile rules
 | 
				
			||||||
 | 
					# should not depend on configure.ac for version updates).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# AC_INIT([GNU project],
 | 
				
			||||||
 | 
					#         m4_esyscmd([build-aux/git-version-gen .tarball-version]),
 | 
				
			||||||
 | 
					#         [bug-project@example])
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Then use the following lines in your Makefile.am, so that .version
 | 
				
			||||||
 | 
					# will be present for dependencies, and so that .tarball-version will
 | 
				
			||||||
 | 
					# exist in distribution tarballs.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# BUILT_SOURCES = $(top_srcdir)/.version
 | 
				
			||||||
 | 
					# $(top_srcdir)/.version:
 | 
				
			||||||
 | 
					#	echo $(VERSION) > $@-t && mv $@-t $@
 | 
				
			||||||
 | 
					# dist-hook:
 | 
				
			||||||
 | 
					#	echo $(VERSION) > $(distdir)/.tarball-version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case $# in
 | 
				
			||||||
 | 
					    1) ;;
 | 
				
			||||||
 | 
					    *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tarball_version_file=$1
 | 
				
			||||||
 | 
					nl='
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# First see if there is a tarball-only version file.
 | 
				
			||||||
 | 
					# then try "git describe", then default.
 | 
				
			||||||
 | 
					if test -f $tarball_version_file
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					    v=`cat $tarball_version_file` || exit 1
 | 
				
			||||||
 | 
					    case $v in
 | 
				
			||||||
 | 
						*$nl*) v= ;; # reject multi-line output
 | 
				
			||||||
 | 
						[0-9]*) ;;
 | 
				
			||||||
 | 
						*) v= ;;
 | 
				
			||||||
 | 
					    esac
 | 
				
			||||||
 | 
					    test -z "$v" \
 | 
				
			||||||
 | 
						&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if test -n "$v"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					    : # use $v
 | 
				
			||||||
 | 
					elif
 | 
				
			||||||
 | 
					       v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
 | 
				
			||||||
 | 
						  || git describe --abbrev=4 HEAD 2>/dev/null` \
 | 
				
			||||||
 | 
					    && case $v in
 | 
				
			||||||
 | 
						 [0-9]*) ;;
 | 
				
			||||||
 | 
						 v[0-9]*) ;;
 | 
				
			||||||
 | 
						 *) (exit 1) ;;
 | 
				
			||||||
 | 
					       esac
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					    # Is this a new git that lists number of commits since the last
 | 
				
			||||||
 | 
					    # tag or the previous older version that did not?
 | 
				
			||||||
 | 
					    #   Newer: v6.10-77-g0f8faeb
 | 
				
			||||||
 | 
					    #   Older: v6.10-g0f8faeb
 | 
				
			||||||
 | 
					    case $v in
 | 
				
			||||||
 | 
						*-*-*) : git describe is okay three part flavor ;;
 | 
				
			||||||
 | 
						*-*)
 | 
				
			||||||
 | 
						    : git describe is older two part flavor
 | 
				
			||||||
 | 
						    # Recreate the number of commits and rewrite such that the
 | 
				
			||||||
 | 
						    # result is the same as if we were using the newer version
 | 
				
			||||||
 | 
						    # of git describe.
 | 
				
			||||||
 | 
						    vtag=`echo "$v" | sed 's/-.*//'`
 | 
				
			||||||
 | 
						    numcommits=`git rev-list "$vtag"..HEAD | wc -l`
 | 
				
			||||||
 | 
						    v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
 | 
				
			||||||
 | 
						    ;;
 | 
				
			||||||
 | 
					    esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Change the first '-' to a '.', so version-comparing tools work properly.
 | 
				
			||||||
 | 
					    # Remove the "g" in git describe's output string, to save a byte.
 | 
				
			||||||
 | 
					    v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    v=UNKNOWN
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					v=`echo "$v" |sed 's/^v//'`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Don't declare a version "dirty" merely because a time stamp has changed.
 | 
				
			||||||
 | 
					git status > /dev/null 2>&1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
 | 
				
			||||||
 | 
					case "$dirty" in
 | 
				
			||||||
 | 
					    '') ;;
 | 
				
			||||||
 | 
					    *) # Append the suffix only if there isn't one already.
 | 
				
			||||||
 | 
						case $v in
 | 
				
			||||||
 | 
						  *-dirty) ;;
 | 
				
			||||||
 | 
						  *) v="$v-dirty" ;;
 | 
				
			||||||
 | 
						esac ;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Omit the trailing newline, so that m4_esyscmd can use the result directly.
 | 
				
			||||||
 | 
					echo "$v" | tr -d '\012'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Local variables:
 | 
				
			||||||
 | 
					# eval: (add-hook 'write-file-hooks 'time-stamp)
 | 
				
			||||||
 | 
					# time-stamp-start: "scriptversion="
 | 
				
			||||||
 | 
					# time-stamp-format: "%:y-%02m-%02d.%02H"
 | 
				
			||||||
 | 
					# time-stamp-end: "$"
 | 
				
			||||||
 | 
					# End:
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					SUBDIRS = osmo-bts
 | 
				
			||||||
@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h gsm_data_shared.h logging.h measurement.h \
 | 
				
			||||||
 | 
							 oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h \
 | 
				
			||||||
 | 
							 handover.h msg_utils.h tx_power.h control_if.h cbch.h l1sap.h \
 | 
				
			||||||
 | 
							 power_control.h scheduler.h scheduler_backend.h phy_link.h \
 | 
				
			||||||
 | 
							 dtx_dl_amr_fsm.h
 | 
				
			||||||
@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					#ifndef _ABIS_H
 | 
				
			||||||
 | 
					#define _ABIS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/select.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/timer.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	OML_RETRY_TIMER		5
 | 
				
			||||||
 | 
					#define	OML_PING_TIMER		20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						LINK_STATE_IDLE = 0,
 | 
				
			||||||
 | 
						LINK_STATE_RETRYING,
 | 
				
			||||||
 | 
						LINK_STATE_CONNECTING,
 | 
				
			||||||
 | 
						LINK_STATE_CONNECT,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void abis_init(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					struct e1inp_line *abis_open(struct gsm_bts *bts, char *dst_host,
 | 
				
			||||||
 | 
								     char *model_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int abis_oml_sendmsg(struct msgb *msg);
 | 
				
			||||||
 | 
					int abis_bts_rsl_sendmsg(struct msgb *msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t get_signlink_remote_ip(struct e1inp_sign_link *link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _ABIS_H */
 | 
				
			||||||
@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					#ifndef _OSMO_BTS_AMR_H
 | 
				
			||||||
 | 
					#define _OSMO_BTS_AMR_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define AMR_TOC_QBIT	0x04
 | 
				
			||||||
 | 
					#define AMR_CMR_NONE	0xF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void amr_log_mr_conf(int ss, int logl, const char *pfx,
 | 
				
			||||||
 | 
							     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);
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _OSMO_BTS_AMR_H */
 | 
				
			||||||
@@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					#ifndef _BTS_H
 | 
				
			||||||
 | 
					#define _BTS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/rate_ctr.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum bts_global_status {
 | 
				
			||||||
 | 
						BTS_STATUS_RF_ACTIVE,
 | 
				
			||||||
 | 
						BTS_STATUS_RF_MUTE,
 | 
				
			||||||
 | 
						BTS_STATUS_LAST,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						BTS_CTR_PAGING_RCVD,
 | 
				
			||||||
 | 
						BTS_CTR_PAGING_DROP,
 | 
				
			||||||
 | 
						BTS_CTR_PAGING_SENT,
 | 
				
			||||||
 | 
						BTS_CTR_RACH_RCVD,
 | 
				
			||||||
 | 
						BTS_CTR_RACH_DROP,
 | 
				
			||||||
 | 
						BTS_CTR_RACH_HO,
 | 
				
			||||||
 | 
						BTS_CTR_RACH_CS,
 | 
				
			||||||
 | 
						BTS_CTR_RACH_PS,
 | 
				
			||||||
 | 
						BTS_CTR_AGCH_RCVD,
 | 
				
			||||||
 | 
						BTS_CTR_AGCH_SENT,
 | 
				
			||||||
 | 
						BTS_CTR_AGCH_DELETED,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void *tall_bts_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_init(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					void bts_shutdown(struct gsm_bts *bts, const char *reason);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_bts *create_bts(uint8_t num_trx, char *id);
 | 
				
			||||||
 | 
					int create_ms(struct gsm_bts_trx *trx, int maskc, uint8_t *maskv_tx,
 | 
				
			||||||
 | 
						uint8_t *maskv_rx);
 | 
				
			||||||
 | 
					void destroy_bts(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					int work_bts(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					int bts_link_estab(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					int trx_link_estab(struct gsm_bts_trx *trx);
 | 
				
			||||||
 | 
					int trx_set_available(struct gsm_bts_trx *trx, int avail);
 | 
				
			||||||
 | 
					void bts_new_si(void *arg);
 | 
				
			||||||
 | 
					void bts_setup_slot(struct gsm_bts_trx_ts *slot, uint8_t comb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg);
 | 
				
			||||||
 | 
					struct msgb *bts_agch_dequeue(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					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 is_ag_res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t *bts_sysinfo_get(struct gsm_bts *bts, const struct gsm_time *g_time);
 | 
				
			||||||
 | 
					uint8_t *lchan_sacch_get(struct gsm_lchan *lchan);
 | 
				
			||||||
 | 
					int lchan_init_lapdm(struct gsm_lchan *lchan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void load_timer_start(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					uint8_t num_agch(struct gsm_bts_trx *trx, const char * arg);
 | 
				
			||||||
 | 
					void bts_update_status(enum bts_global_status which, int on);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_time *get_time(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_main(int argc, char **argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_supports_cm(struct gsm_bts *bts, enum gsm_phys_chan_config pchan,
 | 
				
			||||||
 | 
							    enum gsm48_chan_mode cm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _BTS_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					#ifndef BTS_MODEL_H
 | 
				
			||||||
 | 
					#define BTS_MODEL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsm/tlv.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsm_utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct phy_link;
 | 
				
			||||||
 | 
					struct phy_instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* BTS model specific functions needed by the common code */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_model_init(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type,
 | 
				
			||||||
 | 
								struct tlv_parsed *old_attr, struct tlv_parsed *new_attr,
 | 
				
			||||||
 | 
								void *obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg,
 | 
				
			||||||
 | 
								struct tlv_parsed *new_attr, int obj_kind, void *obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
 | 
				
			||||||
 | 
							      void *obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo,
 | 
				
			||||||
 | 
								    void *obj, uint8_t adm_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_model_trx_deact_rf(struct gsm_bts_trx *trx);
 | 
				
			||||||
 | 
					int bts_model_trx_close(struct gsm_bts_trx *trx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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_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_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
 | 
				
			||||||
@@ -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);
 | 
				
			||||||
@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_ctrl_cmds_install(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts,
 | 
				
			||||||
 | 
										const char *bind_addr, uint16_t port);
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					#ifndef _GSM_DATA_H
 | 
				
			||||||
 | 
					#define _GSM_DATA_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/timer.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/linuxlist.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/lapdm.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsm23003.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/paging.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_DISABLE 999999
 | 
				
			||||||
 | 
					#define GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT 41
 | 
				
			||||||
 | 
					#define GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT 91
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_network {
 | 
				
			||||||
 | 
						struct llist_head bts_list;
 | 
				
			||||||
 | 
						unsigned int num_bts;
 | 
				
			||||||
 | 
						struct osmo_plmn_id plmn;
 | 
				
			||||||
 | 
						struct pcu_sock_state *pcu_state;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum lchan_ciph_state {
 | 
				
			||||||
 | 
						LCHAN_CIPH_NONE,
 | 
				
			||||||
 | 
						LCHAN_CIPH_RX_REQ,
 | 
				
			||||||
 | 
						LCHAN_CIPH_RX_CONF,
 | 
				
			||||||
 | 
						LCHAN_CIPH_RXTX_REQ,
 | 
				
			||||||
 | 
						LCHAN_CIPH_RX_CONF_TX_REQ,
 | 
				
			||||||
 | 
						LCHAN_CIPH_RXTX_CONF,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data_shared.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 */
 | 
				
			||||||
 | 
					#define CIPHER_A5(x) (1 << (x-1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_supports_cipher(struct gsm_bts *bts, int rsl_cipher);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ts_is_pdch(const struct gsm_bts_trx_ts *ts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_model_check_cm_mode(enum gsm_phys_chan_config pchan, enum gsm48_chan_mode cm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _GSM_DATA_H */
 | 
				
			||||||
@@ -0,0 +1,815 @@
 | 
				
			|||||||
 | 
					#ifndef _GSM_DATA_SHAREDH
 | 
				
			||||||
 | 
					#define _GSM_DATA_SHAREDH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <regex.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/codec/ecu.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/timer.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/bitvec.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/statistics.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/utils.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsm_utils.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/tlv.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/rxlev_stat.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/sysinfo.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/meas_rep.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_04_08.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_08_58.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_12_21.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/abis/e1_input.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/lapdm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1:
 | 
				
			||||||
 | 
					   4-bit index is used (2#1111 = 10#15) */
 | 
				
			||||||
 | 
					#define SI2Q_MAX_NUM 16
 | 
				
			||||||
 | 
					/* length in bits (for single SI2quater message) */
 | 
				
			||||||
 | 
					#define SI2Q_MAX_LEN 160
 | 
				
			||||||
 | 
					#define SI2Q_MIN_LEN 18
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Channel Request reason */
 | 
				
			||||||
 | 
					enum gsm_chreq_reason_t {
 | 
				
			||||||
 | 
						GSM_CHREQ_REASON_EMERG,
 | 
				
			||||||
 | 
						GSM_CHREQ_REASON_PAG,
 | 
				
			||||||
 | 
						GSM_CHREQ_REASON_CALL,
 | 
				
			||||||
 | 
						GSM_CHREQ_REASON_LOCATION_UPD,
 | 
				
			||||||
 | 
						GSM_CHREQ_REASON_OTHER,
 | 
				
			||||||
 | 
						GSM_CHREQ_REASON_PDCH,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* lchans 0..3 are SDCCH in combined channel configuration,
 | 
				
			||||||
 | 
					   use 4 as magic number for BCCH hack - see osmo-bts-../oml.c:opstart_compl() */
 | 
				
			||||||
 | 
					#define CCCH_LCHAN 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TRX_NR_TS	8
 | 
				
			||||||
 | 
					#define TS_MAX_LCHAN	8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HARDCODED_ARFCN 123
 | 
				
			||||||
 | 
					#define HARDCODED_BSIC	0x3f	/* NCC = 7 / BCC = 7 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* for multi-drop config */
 | 
				
			||||||
 | 
					#define HARDCODED_BTS0_TS	1
 | 
				
			||||||
 | 
					#define HARDCODED_BTS1_TS	6
 | 
				
			||||||
 | 
					#define HARDCODED_BTS2_TS	11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_VERSION_LENGTH 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_BTS_FEATURES 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gsm_hooks {
 | 
				
			||||||
 | 
						GSM_HOOK_NM_SWLOAD,
 | 
				
			||||||
 | 
						GSM_HOOK_RR_PAGING,
 | 
				
			||||||
 | 
						GSM_HOOK_RR_SECURITY,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum bts_gprs_mode {
 | 
				
			||||||
 | 
						BTS_GPRS_NONE = 0,
 | 
				
			||||||
 | 
						BTS_GPRS_GPRS = 1,
 | 
				
			||||||
 | 
						BTS_GPRS_EGPRS = 2,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_lchan;
 | 
				
			||||||
 | 
					struct osmo_rtp_socket;
 | 
				
			||||||
 | 
					struct pcu_sock_state;
 | 
				
			||||||
 | 
					struct smscb_msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Network Management State */
 | 
				
			||||||
 | 
					struct gsm_nm_state {
 | 
				
			||||||
 | 
						uint8_t operational;
 | 
				
			||||||
 | 
						uint8_t administrative;
 | 
				
			||||||
 | 
						uint8_t availability;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_abis_mo {
 | 
				
			||||||
 | 
						/* A-bis OML Object Class */
 | 
				
			||||||
 | 
						uint8_t obj_class;
 | 
				
			||||||
 | 
						/* is there still some procedure pending? */
 | 
				
			||||||
 | 
						uint8_t procedure_pending;
 | 
				
			||||||
 | 
						/* A-bis OML Object Instance */
 | 
				
			||||||
 | 
						struct abis_om_obj_inst obj_inst;
 | 
				
			||||||
 | 
						/* human-readable name */
 | 
				
			||||||
 | 
						const char *name;
 | 
				
			||||||
 | 
						/* NM State */
 | 
				
			||||||
 | 
						struct gsm_nm_state nm_state;
 | 
				
			||||||
 | 
						/* Attributes configured in this MO */
 | 
				
			||||||
 | 
						struct tlv_parsed *nm_attr;
 | 
				
			||||||
 | 
						/* BTS to which this MO belongs */
 | 
				
			||||||
 | 
						struct gsm_bts *bts;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_A5_KEY_LEN	(128/8)
 | 
				
			||||||
 | 
					#define A38_XOR_MIN_KEY_LEN	12
 | 
				
			||||||
 | 
					#define A38_XOR_MAX_KEY_LEN	16
 | 
				
			||||||
 | 
					#define A38_COMP128_KEY_LEN	16
 | 
				
			||||||
 | 
					#define RSL_ENC_ALG_A5(x)	(x+1)
 | 
				
			||||||
 | 
					#define MAX_EARFCN_LIST 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* is the data link established? who established it? */
 | 
				
			||||||
 | 
					#define LCHAN_SAPI_UNUSED	0
 | 
				
			||||||
 | 
					#define LCHAN_SAPI_MS		1
 | 
				
			||||||
 | 
					#define LCHAN_SAPI_NET		2
 | 
				
			||||||
 | 
					#define LCHAN_SAPI_REL		3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* state of a logical channel */
 | 
				
			||||||
 | 
					enum gsm_lchan_state {
 | 
				
			||||||
 | 
						LCHAN_S_NONE,		/* channel is not active */
 | 
				
			||||||
 | 
						LCHAN_S_ACT_REQ,	/* channel activation requested */
 | 
				
			||||||
 | 
						LCHAN_S_ACTIVE,		/* channel is active and operational */
 | 
				
			||||||
 | 
						LCHAN_S_REL_REQ,	/* channel release has been requested */
 | 
				
			||||||
 | 
						LCHAN_S_REL_ERR,	/* channel is in an error state */
 | 
				
			||||||
 | 
						LCHAN_S_BROKEN,		/* channel is somehow unusable */
 | 
				
			||||||
 | 
						LCHAN_S_INACTIVE,	/* channel is set inactive */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* BTS ONLY */
 | 
				
			||||||
 | 
					#define MAX_NUM_UL_MEAS	104
 | 
				
			||||||
 | 
					#define LC_UL_M_F_L1_VALID	(1 << 0)
 | 
				
			||||||
 | 
					#define LC_UL_M_F_RES_VALID	(1 << 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct bts_ul_meas {
 | 
				
			||||||
 | 
						/* BER in units of 0.01%: 10.000 == 100% ber, 0 == 0% ber */
 | 
				
			||||||
 | 
						uint16_t ber10k;
 | 
				
			||||||
 | 
						/* timing advance offset (in 1/256 bits) */
 | 
				
			||||||
 | 
						int16_t ta_offs_256bits;
 | 
				
			||||||
 | 
						/* C/I ratio in dB */
 | 
				
			||||||
 | 
						float c_i;
 | 
				
			||||||
 | 
						/* flags */
 | 
				
			||||||
 | 
						uint8_t is_sub:1;
 | 
				
			||||||
 | 
						/* RSSI in dBm * -1 */
 | 
				
			||||||
 | 
						uint8_t inv_rssi;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct bts_codec_conf {
 | 
				
			||||||
 | 
						uint8_t hr;
 | 
				
			||||||
 | 
						uint8_t efr;
 | 
				
			||||||
 | 
						uint8_t amr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct amr_mode {
 | 
				
			||||||
 | 
						uint8_t mode;
 | 
				
			||||||
 | 
						uint8_t threshold;
 | 
				
			||||||
 | 
						uint8_t hysteresis;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct amr_multirate_conf {
 | 
				
			||||||
 | 
						uint8_t gsm48_ie[2];
 | 
				
			||||||
 | 
						struct amr_mode ms_mode[4];
 | 
				
			||||||
 | 
						struct amr_mode bts_mode[4];
 | 
				
			||||||
 | 
						uint8_t num_modes;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					/* /BTS ONLY */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum lchan_csd_mode {
 | 
				
			||||||
 | 
						LCHAN_CSD_M_NT,
 | 
				
			||||||
 | 
						LCHAN_CSD_M_T_1200_75,
 | 
				
			||||||
 | 
						LCHAN_CSD_M_T_600,
 | 
				
			||||||
 | 
						LCHAN_CSD_M_T_1200,
 | 
				
			||||||
 | 
						LCHAN_CSD_M_T_2400,
 | 
				
			||||||
 | 
						LCHAN_CSD_M_T_9600,
 | 
				
			||||||
 | 
						LCHAN_CSD_M_T_14400,
 | 
				
			||||||
 | 
						LCHAN_CSD_M_T_29000,
 | 
				
			||||||
 | 
						LCHAN_CSD_M_T_32000,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* State of the SAPIs in the lchan */
 | 
				
			||||||
 | 
					enum lchan_sapi_state {
 | 
				
			||||||
 | 
						LCHAN_SAPI_S_NONE,
 | 
				
			||||||
 | 
						LCHAN_SAPI_S_REQ,
 | 
				
			||||||
 | 
						LCHAN_SAPI_S_ASSIGNED,
 | 
				
			||||||
 | 
						LCHAN_SAPI_S_REL,
 | 
				
			||||||
 | 
						LCHAN_SAPI_S_ERROR,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_lchan {
 | 
				
			||||||
 | 
						/* The TS that we're part of */
 | 
				
			||||||
 | 
						struct gsm_bts_trx_ts *ts;
 | 
				
			||||||
 | 
						/* The logical subslot number in the TS */
 | 
				
			||||||
 | 
						uint8_t nr;
 | 
				
			||||||
 | 
						/* The logical channel type */
 | 
				
			||||||
 | 
						enum gsm_chan_t type;
 | 
				
			||||||
 | 
						/* RSL channel mode */
 | 
				
			||||||
 | 
						enum rsl_cmod_spd rsl_cmode;
 | 
				
			||||||
 | 
						/* If TCH, traffic channel mode */
 | 
				
			||||||
 | 
						enum gsm48_chan_mode tch_mode;
 | 
				
			||||||
 | 
						enum lchan_csd_mode csd_mode;
 | 
				
			||||||
 | 
						/* State */
 | 
				
			||||||
 | 
						enum gsm_lchan_state state;
 | 
				
			||||||
 | 
						const char *broken_reason;
 | 
				
			||||||
 | 
						/* Power levels for MS and BTS */
 | 
				
			||||||
 | 
						uint8_t bs_power;
 | 
				
			||||||
 | 
						uint8_t ms_power;
 | 
				
			||||||
 | 
						/* Encryption information */
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint8_t alg_id;
 | 
				
			||||||
 | 
							uint8_t key_len;
 | 
				
			||||||
 | 
							uint8_t key[MAX_A5_KEY_LEN];
 | 
				
			||||||
 | 
						} encr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* AMR bits */
 | 
				
			||||||
 | 
						uint8_t mr_bts_lv[7];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Established data link layer services */
 | 
				
			||||||
 | 
						int sacch_deact;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint32_t bound_ip;
 | 
				
			||||||
 | 
							uint32_t connect_ip;
 | 
				
			||||||
 | 
							uint16_t bound_port;
 | 
				
			||||||
 | 
							uint16_t connect_port;
 | 
				
			||||||
 | 
							uint16_t conn_id;
 | 
				
			||||||
 | 
							uint8_t rtp_payload;
 | 
				
			||||||
 | 
							uint8_t rtp_payload2;
 | 
				
			||||||
 | 
							uint8_t speech_mode;
 | 
				
			||||||
 | 
							struct osmo_rtp_socket *rtp_socket;
 | 
				
			||||||
 | 
						} abis_ip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint8_t rqd_ta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Number of different GsmL1_Sapi_t used in osmo_bts_sysmo is 23.
 | 
				
			||||||
 | 
						 * Currently we don't share these headers so this is a magic number. */
 | 
				
			||||||
 | 
						struct llist_head sapi_cmds;
 | 
				
			||||||
 | 
						uint8_t sapis_dl[23];
 | 
				
			||||||
 | 
						uint8_t sapis_ul[23];
 | 
				
			||||||
 | 
						struct lapdm_channel lapdm_ch;
 | 
				
			||||||
 | 
						struct llist_head dl_tch_queue;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							/* bitmask of all SI that are present/valid in si_buf */
 | 
				
			||||||
 | 
							uint32_t valid;
 | 
				
			||||||
 | 
							uint32_t last;
 | 
				
			||||||
 | 
							/* buffers where we put the pre-computed SI:
 | 
				
			||||||
 | 
							   SI2Q_MAX_NUM is the max number of SI2quater messages (see 3GPP TS 44.018) */
 | 
				
			||||||
 | 
							sysinfo_buf_t buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM];
 | 
				
			||||||
 | 
						} si;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint8_t flags;
 | 
				
			||||||
 | 
							/* RSL measurment result number, 0 at lchan_act */
 | 
				
			||||||
 | 
							uint8_t res_nr;
 | 
				
			||||||
 | 
							/* current Tx power level of the BTS */
 | 
				
			||||||
 | 
							uint8_t bts_tx_pwr;
 | 
				
			||||||
 | 
							/* number of measurements stored in array below */
 | 
				
			||||||
 | 
							uint8_t num_ul_meas;
 | 
				
			||||||
 | 
							struct bts_ul_meas uplink[MAX_NUM_UL_MEAS];
 | 
				
			||||||
 | 
							/* last L1 header from the MS */
 | 
				
			||||||
 | 
							uint8_t l1_info[2];
 | 
				
			||||||
 | 
							struct gsm_meas_rep_unidir ul_res;
 | 
				
			||||||
 | 
							int16_t ms_toa256;
 | 
				
			||||||
 | 
						} meas;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct amr_multirate_conf amr_mr;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								struct osmo_fsm_inst *dl_amr_fsm;
 | 
				
			||||||
 | 
								/* TCH cache */
 | 
				
			||||||
 | 
								uint8_t cache[20];
 | 
				
			||||||
 | 
								/* FACCH cache */
 | 
				
			||||||
 | 
								uint8_t facch[GSM_MACBLOCK_LEN];
 | 
				
			||||||
 | 
								uint8_t len;
 | 
				
			||||||
 | 
								uint32_t fn;
 | 
				
			||||||
 | 
								bool is_update;
 | 
				
			||||||
 | 
								/* set for each SID frame to detect talkspurt for codecs
 | 
				
			||||||
 | 
								   without explicit ONSET event */
 | 
				
			||||||
 | 
								bool ul_sid;
 | 
				
			||||||
 | 
								/* indicates if DTXd was active during DL measurement
 | 
				
			||||||
 | 
								   period */
 | 
				
			||||||
 | 
								bool dl_active;
 | 
				
			||||||
 | 
							} dtx;
 | 
				
			||||||
 | 
							uint8_t last_cmr;
 | 
				
			||||||
 | 
							uint32_t last_fn;
 | 
				
			||||||
 | 
						} tch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* 3GPP TS 48.058 § 9.3.37: [0; 255] ok, -1 means invalid*/
 | 
				
			||||||
 | 
						int16_t ms_t_offs;
 | 
				
			||||||
 | 
						/* 3GPP TS 45.010 § 1.2 round trip propagation delay (in symbols) or -1 */
 | 
				
			||||||
 | 
						int16_t p_offs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* BTS-side ciphering state (rx only, bi-directional, ...) */
 | 
				
			||||||
 | 
						uint8_t ciph_state;
 | 
				
			||||||
 | 
						uint8_t ciph_ns;
 | 
				
			||||||
 | 
						uint8_t loopback;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint8_t active;
 | 
				
			||||||
 | 
							uint8_t ref;
 | 
				
			||||||
 | 
							/* T3105: PHYS INF retransmission */
 | 
				
			||||||
 | 
							struct osmo_timer_list t3105;
 | 
				
			||||||
 | 
							/* counts up to Ny1 */
 | 
				
			||||||
 | 
							unsigned int phys_info_count;
 | 
				
			||||||
 | 
						} ho;
 | 
				
			||||||
 | 
						/* S counter for link loss */
 | 
				
			||||||
 | 
						int s;
 | 
				
			||||||
 | 
						/* Kind of the release/activation. E.g. RSL or PCU */
 | 
				
			||||||
 | 
						int rel_act_kind;
 | 
				
			||||||
 | 
						/* RTP header Marker bit to indicate beginning of speech after pause  */
 | 
				
			||||||
 | 
						bool rtp_tx_marker;
 | 
				
			||||||
 | 
						/* power handling */
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint8_t current;
 | 
				
			||||||
 | 
							uint8_t fixed;
 | 
				
			||||||
 | 
						} ms_power_ctrl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct msgb *pending_rel_ind_msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* ECU (Error Concealment Unit) state */
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct osmo_ecu_fr_state fr;
 | 
				
			||||||
 | 
						} ecu_state;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct value_string lchan_ciph_state_names[];
 | 
				
			||||||
 | 
					static inline const char *lchan_ciph_state_name(uint8_t state) {
 | 
				
			||||||
 | 
						return get_value_string(lchan_ciph_state_names, state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						TS_F_PDCH_ACTIVE =		0x1000,
 | 
				
			||||||
 | 
						TS_F_PDCH_ACT_PENDING =		0x2000,
 | 
				
			||||||
 | 
						TS_F_PDCH_DEACT_PENDING =	0x4000,
 | 
				
			||||||
 | 
						TS_F_PDCH_PENDING_MASK =	0x6000 /*<
 | 
				
			||||||
 | 
								TS_F_PDCH_ACT_PENDING | TS_F_PDCH_DEACT_PENDING */
 | 
				
			||||||
 | 
					} gsm_bts_trx_ts_flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* One Timeslot in a TRX */
 | 
				
			||||||
 | 
					struct gsm_bts_trx_ts {
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx;
 | 
				
			||||||
 | 
						/* number of this timeslot at the TRX */
 | 
				
			||||||
 | 
						uint8_t nr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum gsm_phys_chan_config pchan;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							enum gsm_phys_chan_config pchan_is;
 | 
				
			||||||
 | 
							enum gsm_phys_chan_config pchan_want;
 | 
				
			||||||
 | 
							struct msgb *pending_chan_activ;
 | 
				
			||||||
 | 
						} dyn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned int flags;
 | 
				
			||||||
 | 
						struct gsm_abis_mo mo;
 | 
				
			||||||
 | 
						struct tlv_parsed nm_attr;
 | 
				
			||||||
 | 
						uint8_t nm_chan_comb;
 | 
				
			||||||
 | 
						int tsc;		/* -1 == use BTS TSC */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							/* Parameters below are configured by VTY */
 | 
				
			||||||
 | 
							int enabled;
 | 
				
			||||||
 | 
							uint8_t maio;
 | 
				
			||||||
 | 
							uint8_t hsn;
 | 
				
			||||||
 | 
							struct bitvec arfcns;
 | 
				
			||||||
 | 
							uint8_t arfcns_data[1024/8];
 | 
				
			||||||
 | 
							/* This is the pre-computed MA for channel assignments */
 | 
				
			||||||
 | 
							struct bitvec ma;
 | 
				
			||||||
 | 
							uint8_t ma_len;	/* part of ma_data that is used */
 | 
				
			||||||
 | 
							uint8_t ma_data[8];	/* 10.5.2.21: max 8 bytes value part */
 | 
				
			||||||
 | 
						} hopping;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct gsm_lchan lchan[TS_MAX_LCHAN];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* One TRX in a BTS */
 | 
				
			||||||
 | 
					struct gsm_bts_trx {
 | 
				
			||||||
 | 
						/* list header in bts->trx_list */
 | 
				
			||||||
 | 
						struct llist_head list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct gsm_bts *bts;
 | 
				
			||||||
 | 
						/* number of this TRX in the BTS */
 | 
				
			||||||
 | 
						uint8_t nr;
 | 
				
			||||||
 | 
						/* human readable name / description */
 | 
				
			||||||
 | 
						char *description;
 | 
				
			||||||
 | 
						/* how do we talk RSL with this TRX? */
 | 
				
			||||||
 | 
						uint8_t rsl_tei;
 | 
				
			||||||
 | 
						struct e1inp_sign_link *rsl_link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Some BTS (specifically Ericsson RBS) have a per-TRX OML Link */
 | 
				
			||||||
 | 
						struct e1inp_sign_link *oml_link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct gsm_abis_mo mo;
 | 
				
			||||||
 | 
						struct tlv_parsed nm_attr;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct gsm_abis_mo mo;
 | 
				
			||||||
 | 
						} bb_transc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint16_t arfcn;
 | 
				
			||||||
 | 
						int nominal_power;		/* in dBm */
 | 
				
			||||||
 | 
						unsigned int max_power_red;	/* in actual dB */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct trx_power_params power_params;
 | 
				
			||||||
 | 
						int ms_power_control;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							void *l1h;
 | 
				
			||||||
 | 
						} role_bts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								unsigned int test_state;
 | 
				
			||||||
 | 
								uint8_t test_nr;
 | 
				
			||||||
 | 
								struct rxlev_stats rxlev_stat;
 | 
				
			||||||
 | 
							} ipaccess;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct gsm_bts_trx_ts ts[TRX_NR_TS];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GSM_BTS_SI2Q(bts, i)   (struct gsm48_system_information_type_2quater *)((bts)->si_buf[SYSINFO_TYPE_2quater][i])
 | 
				
			||||||
 | 
					#define GSM_BTS_HAS_SI(bts, i) ((bts)->si_valid & (1 << i))
 | 
				
			||||||
 | 
					#define GSM_BTS_SI(bts, i)     (void *)((bts)->si_buf[i][0])
 | 
				
			||||||
 | 
					#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i][0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gsm_bts_type_variant {
 | 
				
			||||||
 | 
						BTS_UNKNOWN,
 | 
				
			||||||
 | 
						BTS_OSMO_LITECELL15,
 | 
				
			||||||
 | 
						BTS_OSMO_OCTPHY,
 | 
				
			||||||
 | 
						BTS_OSMO_SYSMO,
 | 
				
			||||||
 | 
						BTS_OSMO_TRX,
 | 
				
			||||||
 | 
						BTS_OSMO_VIRTUAL,
 | 
				
			||||||
 | 
						BTS_OSMO_OMLDUMMY,
 | 
				
			||||||
 | 
						_NUM_BTS_VARIANT
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Used by OML layer for BTS Attribute reporting */
 | 
				
			||||||
 | 
					enum bts_attribute {
 | 
				
			||||||
 | 
						BTS_TYPE_VARIANT,
 | 
				
			||||||
 | 
						BTS_SUB_MODEL,
 | 
				
			||||||
 | 
						TRX_PHY_VERSION,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct vty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* N. B: always add new features to the end of the list (right before _NUM_BTS_FEAT) to avoid breaking compatibility
 | 
				
			||||||
 | 
					   with BTS compiled against earlier version of this header. Also make sure that the description strings
 | 
				
			||||||
 | 
					   gsm_bts_features_descs[] in gsm_data_shared.c are also updated accordingly! */
 | 
				
			||||||
 | 
					enum gsm_bts_features {
 | 
				
			||||||
 | 
						BTS_FEAT_HSCSD,
 | 
				
			||||||
 | 
						BTS_FEAT_GPRS,
 | 
				
			||||||
 | 
						BTS_FEAT_EGPRS,
 | 
				
			||||||
 | 
						BTS_FEAT_ECSD,
 | 
				
			||||||
 | 
						BTS_FEAT_HOPPING,
 | 
				
			||||||
 | 
						BTS_FEAT_MULTI_TSC,
 | 
				
			||||||
 | 
						BTS_FEAT_OML_ALERTS,
 | 
				
			||||||
 | 
						BTS_FEAT_AGCH_PCH_PROP,
 | 
				
			||||||
 | 
						BTS_FEAT_CBCH,
 | 
				
			||||||
 | 
						BTS_FEAT_SPEECH_F_V1,
 | 
				
			||||||
 | 
						BTS_FEAT_SPEECH_H_V1,
 | 
				
			||||||
 | 
						BTS_FEAT_SPEECH_F_EFR,
 | 
				
			||||||
 | 
						BTS_FEAT_SPEECH_F_AMR,
 | 
				
			||||||
 | 
						BTS_FEAT_SPEECH_H_AMR,
 | 
				
			||||||
 | 
						_NUM_BTS_FEAT
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct value_string gsm_bts_features_descs[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_bts_gprs_nsvc {
 | 
				
			||||||
 | 
						struct gsm_bts *bts;
 | 
				
			||||||
 | 
						/* data read via VTY config file, to configure the BTS
 | 
				
			||||||
 | 
						 * via OML from BSC */
 | 
				
			||||||
 | 
						int id;
 | 
				
			||||||
 | 
						uint16_t nsvci;
 | 
				
			||||||
 | 
						uint16_t local_port;	/* on the BTS */
 | 
				
			||||||
 | 
						uint16_t remote_port;	/* on the SGSN */
 | 
				
			||||||
 | 
						uint32_t remote_ip;	/* on the SGSN */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct gsm_abis_mo mo;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gprs_rlc_par {
 | 
				
			||||||
 | 
						RLC_T3142,
 | 
				
			||||||
 | 
						RLC_T3169,
 | 
				
			||||||
 | 
						RLC_T3191,
 | 
				
			||||||
 | 
						RLC_T3193,
 | 
				
			||||||
 | 
						RLC_T3195,
 | 
				
			||||||
 | 
						RLC_N3101,
 | 
				
			||||||
 | 
						RLC_N3103,
 | 
				
			||||||
 | 
						RLC_N3105,
 | 
				
			||||||
 | 
						CV_COUNTDOWN,
 | 
				
			||||||
 | 
						T_DL_TBF_EXT,	/* ms */
 | 
				
			||||||
 | 
						T_UL_TBF_EXT,	/* ms */
 | 
				
			||||||
 | 
						_NUM_RLC_PAR
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gprs_cs {
 | 
				
			||||||
 | 
						GPRS_CS1,
 | 
				
			||||||
 | 
						GPRS_CS2,
 | 
				
			||||||
 | 
						GPRS_CS3,
 | 
				
			||||||
 | 
						GPRS_CS4,
 | 
				
			||||||
 | 
						GPRS_MCS1,
 | 
				
			||||||
 | 
						GPRS_MCS2,
 | 
				
			||||||
 | 
						GPRS_MCS3,
 | 
				
			||||||
 | 
						GPRS_MCS4,
 | 
				
			||||||
 | 
						GPRS_MCS5,
 | 
				
			||||||
 | 
						GPRS_MCS6,
 | 
				
			||||||
 | 
						GPRS_MCS7,
 | 
				
			||||||
 | 
						GPRS_MCS8,
 | 
				
			||||||
 | 
						GPRS_MCS9,
 | 
				
			||||||
 | 
						_NUM_GRPS_CS
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gprs_rlc_cfg {
 | 
				
			||||||
 | 
						uint16_t parameter[_NUM_RLC_PAR];
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint16_t repeat_time; /* ms */
 | 
				
			||||||
 | 
							uint8_t repeat_count;
 | 
				
			||||||
 | 
						} paging;
 | 
				
			||||||
 | 
						uint32_t cs_mask; /* bitmask of gprs_cs */
 | 
				
			||||||
 | 
						uint8_t initial_cs;
 | 
				
			||||||
 | 
						uint8_t initial_mcs;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* One BTS */
 | 
				
			||||||
 | 
					struct gsm_bts {
 | 
				
			||||||
 | 
						/* list header in net->bts_list */
 | 
				
			||||||
 | 
						struct llist_head list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Geographical location of the BTS */
 | 
				
			||||||
 | 
						struct llist_head loc_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* number of ths BTS in network */
 | 
				
			||||||
 | 
						uint8_t nr;
 | 
				
			||||||
 | 
						/* human readable name / description */
 | 
				
			||||||
 | 
						char *description;
 | 
				
			||||||
 | 
						/* Cell Identity */
 | 
				
			||||||
 | 
						uint16_t cell_identity;
 | 
				
			||||||
 | 
						/* location area code of this BTS */
 | 
				
			||||||
 | 
						uint16_t location_area_code;
 | 
				
			||||||
 | 
						/* Base Station Identification Code (BSIC), lower 3 bits is BCC,
 | 
				
			||||||
 | 
						 * which is used as TSC for the CCCH */
 | 
				
			||||||
 | 
						uint8_t bsic;
 | 
				
			||||||
 | 
						/* type of BTS */
 | 
				
			||||||
 | 
						enum gsm_bts_type_variant variant;
 | 
				
			||||||
 | 
						enum gsm_band band;
 | 
				
			||||||
 | 
						char version[MAX_VERSION_LENGTH];
 | 
				
			||||||
 | 
						char sub_model[MAX_VERSION_LENGTH];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* features of a given BTS set/reported via OML */
 | 
				
			||||||
 | 
						struct bitvec features;
 | 
				
			||||||
 | 
						uint8_t _features_data[MAX_BTS_FEATURES/8];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Connected PCU version (if any) */
 | 
				
			||||||
 | 
						char pcu_version[MAX_VERSION_LENGTH];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* maximum Tx power that the MS is permitted to use in this cell */
 | 
				
			||||||
 | 
						int ms_max_power;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* how do we talk OML with this TRX? */
 | 
				
			||||||
 | 
						uint8_t oml_tei;
 | 
				
			||||||
 | 
						struct e1inp_sign_link *oml_link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Abis network management O&M handle */
 | 
				
			||||||
 | 
						struct abis_nm_h *nmh;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct gsm_abis_mo mo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* number of this BTS on given E1 link */
 | 
				
			||||||
 | 
						uint8_t bts_nr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* DTX features of this BTS */
 | 
				
			||||||
 | 
						enum gsm48_dtx_mode dtxu;
 | 
				
			||||||
 | 
						bool dtxd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* CCCH is on C0 */
 | 
				
			||||||
 | 
						struct gsm_bts_trx *c0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct gsm_abis_mo mo;
 | 
				
			||||||
 | 
						} site_mgr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* bitmask of all SI that are present/valid in si_buf */
 | 
				
			||||||
 | 
						uint32_t si_valid;
 | 
				
			||||||
 | 
						/* 3GPP TS 44.018 Table 10.5.2.33b.1 INDEX and COUNT for SI2quater */
 | 
				
			||||||
 | 
						uint8_t si2q_index; /* distinguish individual SI2quater messages */
 | 
				
			||||||
 | 
						uint8_t si2q_count; /* si2q_index for the last (highest indexed) individual SI2quater message */
 | 
				
			||||||
 | 
						/* buffers where we put the pre-computed SI */
 | 
				
			||||||
 | 
						sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM];
 | 
				
			||||||
 | 
						/* offsets used while generating SI2quater */
 | 
				
			||||||
 | 
						size_t e_offset;
 | 
				
			||||||
 | 
						size_t u_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* ip.accesss Unit ID's have Site/BTS/TRX layout */
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								uint16_t site_id;
 | 
				
			||||||
 | 
								uint16_t bts_id;
 | 
				
			||||||
 | 
								uint32_t flags;
 | 
				
			||||||
 | 
								uint32_t rsl_ip;
 | 
				
			||||||
 | 
							} ip_access;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Not entirely sure how ip.access specific this is */
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint8_t supports_egprs_11bit_rach;
 | 
				
			||||||
 | 
							enum bts_gprs_mode mode;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								struct gsm_abis_mo mo;
 | 
				
			||||||
 | 
								uint16_t nsei;
 | 
				
			||||||
 | 
								uint8_t timer[7];
 | 
				
			||||||
 | 
							} nse;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								struct gsm_abis_mo mo;
 | 
				
			||||||
 | 
								uint16_t bvci;
 | 
				
			||||||
 | 
								uint8_t timer[11];
 | 
				
			||||||
 | 
								struct gprs_rlc_cfg rlc_cfg;
 | 
				
			||||||
 | 
							} cell;
 | 
				
			||||||
 | 
							struct gsm_bts_gprs_nsvc nsvc[2];
 | 
				
			||||||
 | 
							uint8_t rac;
 | 
				
			||||||
 | 
							uint8_t net_ctrl_ord;
 | 
				
			||||||
 | 
							bool ctrl_ack_type_use_block;
 | 
				
			||||||
 | 
						} gprs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* RACH NM values */
 | 
				
			||||||
 | 
						int rach_b_thresh;
 | 
				
			||||||
 | 
						int rach_ldavg_slots;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* transceivers */
 | 
				
			||||||
 | 
						int num_trx;
 | 
				
			||||||
 | 
						struct llist_head trx_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* SI related items */
 | 
				
			||||||
 | 
						int force_combined_si;
 | 
				
			||||||
 | 
						int bcch_change_mark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct rate_ctr_group *ctrs;
 | 
				
			||||||
 | 
						bool supp_meas_toa256;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							/* Interference Boundaries for OML */
 | 
				
			||||||
 | 
							int16_t boundary[6];
 | 
				
			||||||
 | 
							uint8_t intave;
 | 
				
			||||||
 | 
						} interference;
 | 
				
			||||||
 | 
						unsigned int t200_ms[7];
 | 
				
			||||||
 | 
						unsigned int t3105_ms;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint8_t overload_period;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								/* Input parameters from OML */
 | 
				
			||||||
 | 
								uint8_t load_ind_thresh;	/* percent */
 | 
				
			||||||
 | 
								uint8_t load_ind_period;	/* seconds */
 | 
				
			||||||
 | 
								/* Internal data */
 | 
				
			||||||
 | 
								struct osmo_timer_list timer;
 | 
				
			||||||
 | 
								unsigned int pch_total;
 | 
				
			||||||
 | 
								unsigned int pch_used;
 | 
				
			||||||
 | 
							} ccch;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								/* Input parameters from OML */
 | 
				
			||||||
 | 
								int16_t busy_thresh;		/* in dBm */
 | 
				
			||||||
 | 
								uint16_t averaging_slots;
 | 
				
			||||||
 | 
								/* Internal data */
 | 
				
			||||||
 | 
								unsigned int total;	/* total nr */
 | 
				
			||||||
 | 
								unsigned int busy;	/* above busy_thresh */
 | 
				
			||||||
 | 
								unsigned int access;	/* access bursts */
 | 
				
			||||||
 | 
							} rach;
 | 
				
			||||||
 | 
						} load;
 | 
				
			||||||
 | 
						uint8_t ny1;
 | 
				
			||||||
 | 
						uint8_t max_ta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* AGCH queuing */
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct llist_head queue;
 | 
				
			||||||
 | 
							int length;
 | 
				
			||||||
 | 
							int max_length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int thresh_level;	/* Cleanup threshold in percent of max len */
 | 
				
			||||||
 | 
							int low_level;		/* Low water mark in percent of max len */
 | 
				
			||||||
 | 
							int high_level;		/* High water mark in percent of max len */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* TODO: Use a rate counter group instead */
 | 
				
			||||||
 | 
							uint64_t dropped_msgs;
 | 
				
			||||||
 | 
							uint64_t merged_msgs;
 | 
				
			||||||
 | 
							uint64_t rejected_msgs;
 | 
				
			||||||
 | 
							uint64_t agch_msgs;
 | 
				
			||||||
 | 
							uint64_t pch_msgs;
 | 
				
			||||||
 | 
						} agch_queue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct paging_state *paging_state;
 | 
				
			||||||
 | 
						char *bsc_oml_host;
 | 
				
			||||||
 | 
						struct llist_head oml_queue;
 | 
				
			||||||
 | 
						unsigned int rtp_jitter_buf_ms;
 | 
				
			||||||
 | 
						bool rtp_jitter_adaptive;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint8_t ciphers;	/* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */
 | 
				
			||||||
 | 
						} support;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint8_t tc4_ctr;
 | 
				
			||||||
 | 
						} si;
 | 
				
			||||||
 | 
						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 */
 | 
				
			||||||
 | 
						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 */
 | 
				
			||||||
 | 
						uint16_t max_ber10k_rach;	/* Maximum permitted RACH BER in 0.01% */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							char *sock_path;
 | 
				
			||||||
 | 
						} pcu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint32_t last_fn;
 | 
				
			||||||
 | 
							struct timeval tv_clock;
 | 
				
			||||||
 | 
							struct osmo_timer_list fn_timer;
 | 
				
			||||||
 | 
						} vbts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_bts *gsm_bts_alloc(void *talloc_ctx, uint8_t bts_num);
 | 
				
			||||||
 | 
					struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum bts_attribute str2btsattr(const char *s);
 | 
				
			||||||
 | 
					const char *btsatttr2str(enum bts_attribute v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gsm_bts_type_variant str2btsvariant(const char *arg);
 | 
				
			||||||
 | 
					const char *btsvariant2str(enum gsm_bts_type_variant v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct value_string gsm_chreq_descs[];
 | 
				
			||||||
 | 
					const struct value_string gsm_pchant_names[13];
 | 
				
			||||||
 | 
					const struct value_string gsm_pchant_descs[13];
 | 
				
			||||||
 | 
					const char *gsm_pchan_name(enum gsm_phys_chan_config c);
 | 
				
			||||||
 | 
					enum gsm_phys_chan_config gsm_pchan_parse(const char *name);
 | 
				
			||||||
 | 
					const char *gsm_lchant_name(enum gsm_chan_t c);
 | 
				
			||||||
 | 
					const char *gsm_chreq_name(enum gsm_chreq_reason_t c);
 | 
				
			||||||
 | 
					char *gsm_trx_name(const struct gsm_bts_trx *trx);
 | 
				
			||||||
 | 
					char *gsm_ts_name(const struct gsm_bts_trx_ts *ts);
 | 
				
			||||||
 | 
					char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts);
 | 
				
			||||||
 | 
					char *gsm_lchan_name_compute(const struct gsm_lchan *lchan);
 | 
				
			||||||
 | 
					const char *gsm_lchans_name(enum gsm_lchan_state s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline char *gsm_lchan_name(const struct gsm_lchan *lchan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return lchan->name;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int gsm_bts_set_feature(struct gsm_bts *bts, enum gsm_bts_features feat)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
 | 
				
			||||||
 | 
						return bitvec_set_bit_pos(&bts->features, feat, 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool gsm_bts_has_feature(const struct gsm_bts *bts, enum gsm_bts_features feat)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
 | 
				
			||||||
 | 
						return bitvec_get_bit_pos(&bts->features, feat);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void gsm_abis_mo_reset(struct gsm_abis_mo *mo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_abis_mo *
 | 
				
			||||||
 | 
					gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
 | 
				
			||||||
 | 
						    const struct abis_om_obj_inst *obj_inst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_nm_state *
 | 
				
			||||||
 | 
					gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
 | 
				
			||||||
 | 
							 const struct abis_om_obj_inst *obj_inst);
 | 
				
			||||||
 | 
					void *
 | 
				
			||||||
 | 
					gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
 | 
				
			||||||
 | 
						     const struct abis_om_obj_inst *obj_inst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* reset the state of all MO in the BTS */
 | 
				
			||||||
 | 
					void gsm_bts_mo_reset(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
 | 
				
			||||||
 | 
								  uint8_t ts_nr, uint8_t lchan_nr);
 | 
				
			||||||
 | 
					uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan);
 | 
				
			||||||
 | 
					uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
 | 
				
			||||||
 | 
									   enum gsm_phys_chan_config as_pchan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* return the gsm_lchan for the CBCH (if it exists at all) */
 | 
				
			||||||
 | 
					struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * help with parsing regexps
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int gsm_parse_reg(void *ctx, regex_t *reg, char **str,
 | 
				
			||||||
 | 
							int argc, const char **argv) __attribute__ ((warn_unused_result));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define BSIC2BCC(bsic) ((bsic) & 0x3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint8_t gsm_ts_tsc(const struct gsm_bts_trx_ts *ts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (ts->tsc != -1)
 | 
				
			||||||
 | 
							return ts->tsc;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return ts->trx->bts->bsic & 7;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
 | 
				
			||||||
 | 
									   int *rc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts);
 | 
				
			||||||
 | 
					uint8_t ts_subslots(struct gsm_bts_trx_ts *ts);
 | 
				
			||||||
 | 
					bool ts_is_tch(struct gsm_bts_trx_ts *ts);
 | 
				
			||||||
 | 
					const char *gsm_trx_unit_id(struct gsm_bts_trx *trx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						HANDOVER_NONE = 0,
 | 
				
			||||||
 | 
						HANDOVER_ENABLED,
 | 
				
			||||||
 | 
						HANDOVER_WAIT_FRAME,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay);
 | 
				
			||||||
 | 
					void handover_frame(struct gsm_lchan *lchan);
 | 
				
			||||||
 | 
					void handover_reset(struct gsm_lchan *lchan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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 */
 | 
				
			||||||
@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					#ifndef _LOGGING_H
 | 
				
			||||||
 | 
					#define _LOGGING_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEBUG
 | 
				
			||||||
 | 
					#include <osmocom/core/logging.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						DRSL,
 | 
				
			||||||
 | 
						DOML,
 | 
				
			||||||
 | 
						DRLL,
 | 
				
			||||||
 | 
						DRR,
 | 
				
			||||||
 | 
						DMEAS,
 | 
				
			||||||
 | 
						DPAG,
 | 
				
			||||||
 | 
						DL1C,
 | 
				
			||||||
 | 
						DL1P,
 | 
				
			||||||
 | 
						DDSP,
 | 
				
			||||||
 | 
						DPCU,
 | 
				
			||||||
 | 
						DHO,
 | 
				
			||||||
 | 
						DTRX,
 | 
				
			||||||
 | 
						DLOOP,
 | 
				
			||||||
 | 
						DABIS,
 | 
				
			||||||
 | 
						DRTP,
 | 
				
			||||||
 | 
						DSUM,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct log_info bts_log_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* LOGP with gsm_time prefix */
 | 
				
			||||||
 | 
					#define LOGPGT(ss, lvl, gt, fmt, args...) \
 | 
				
			||||||
 | 
						LOGP(ss, lvl, "%s " fmt, osmo_dump_gsmtime(gt), ## args)
 | 
				
			||||||
 | 
					#define DEBUGPGT(ss, gt, fmt, args...) \
 | 
				
			||||||
 | 
						LOGP(ss, LOGL_DEBUG, "%s " fmt, osmo_dump_gsmtime(gt), ## args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* LOGP with frame number prefix */
 | 
				
			||||||
 | 
					#define LOGPFN(ss, lvl, fn, fmt, args...) \
 | 
				
			||||||
 | 
						LOGP(ss, lvl, "%s " fmt, gsm_fn_as_gsmtime_str(fn), ## args)
 | 
				
			||||||
 | 
					#define DEBUGPFN(ss, fn, fmt, args...) \
 | 
				
			||||||
 | 
						LOGP(ss, LOGL_DEBUG, "%s " fmt, gsm_fn_as_gsmtime_str(fn), ## args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _LOGGING_H */
 | 
				
			||||||
@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					#ifndef 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, uint32_t fn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Routines to check the structurally integrity of messages
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 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
 | 
				
			||||||
 | 
					 * messages and IPA/Osmo for manufacturer messages.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						OML_MSG_TYPE_ETSI,
 | 
				
			||||||
 | 
						OML_MSG_TYPE_IPA,
 | 
				
			||||||
 | 
						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_oml_structure(struct msgb *msg);
 | 
				
			||||||
@@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					#ifndef _OML_H
 | 
				
			||||||
 | 
					#define _OML_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_12_21.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_bts;
 | 
				
			||||||
 | 
					struct gsm_abis_mo;
 | 
				
			||||||
 | 
					struct msgb;
 | 
				
			||||||
 | 
					struct gsm_lchan;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int oml_init(struct gsm_abis_mo *mo);
 | 
				
			||||||
 | 
					int down_oml(struct gsm_bts *bts, struct msgb *msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct msgb *oml_msgb_alloc(void);
 | 
				
			||||||
 | 
					int oml_send_msg(struct msgb *msg, int is_mauf);
 | 
				
			||||||
 | 
					int oml_mo_send_msg(struct gsm_abis_mo *mo, struct msgb *msg, uint8_t msg_type);
 | 
				
			||||||
 | 
					int oml_mo_opstart_ack(struct gsm_abis_mo *mo);
 | 
				
			||||||
 | 
					int oml_mo_opstart_nack(struct gsm_abis_mo *mo, uint8_t nack_cause);
 | 
				
			||||||
 | 
					int oml_mo_statechg_ack(struct gsm_abis_mo *mo);
 | 
				
			||||||
 | 
					int oml_mo_statechg_nack(struct gsm_abis_mo *mo, uint8_t nack_cause);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Change the state and send STATE CHG REP */
 | 
				
			||||||
 | 
					int oml_mo_state_chg(struct gsm_abis_mo *mo, int op_state, int avail_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* First initialization of MO, does _not_ generate state changes */
 | 
				
			||||||
 | 
					void oml_mo_state_init(struct gsm_abis_mo *mo, int op_state, int avail_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Update admin state and send ACK/NACK */
 | 
				
			||||||
 | 
					int oml_mo_rf_lock_chg(struct gsm_abis_mo *mo, uint8_t mute_state[8],
 | 
				
			||||||
 | 
							       int success);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Transmit STATE CHG REP even if there was no state change */
 | 
				
			||||||
 | 
					int oml_tx_state_changed(struct gsm_abis_mo *mo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int oml_mo_tx_sw_act_rep(struct gsm_abis_mo *mo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int oml_mo_fom_ack_nack(struct gsm_abis_mo *mo, uint8_t orig_msg_type,
 | 
				
			||||||
 | 
								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 */
 | 
				
			||||||
@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					#ifndef OSMO_BTS_PAGING_H
 | 
				
			||||||
 | 
					#define OSMO_BTS_PAGING_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsm_utils.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_04_08.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct paging_state;
 | 
				
			||||||
 | 
					struct gsm_bts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* initialize paging code */
 | 
				
			||||||
 | 
					struct paging_state *paging_init(struct gsm_bts *bts,
 | 
				
			||||||
 | 
									 unsigned int num_paging_max,
 | 
				
			||||||
 | 
									 unsigned int paging_lifetime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (re) configure paging code */
 | 
				
			||||||
 | 
					void paging_config(struct paging_state *ps,
 | 
				
			||||||
 | 
							  unsigned int num_paging_max,
 | 
				
			||||||
 | 
							  unsigned int paging_lifetime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void paging_reset(struct paging_state *ps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The max number of paging entries */
 | 
				
			||||||
 | 
					unsigned int paging_get_queue_max(struct paging_state *ps);
 | 
				
			||||||
 | 
					void paging_set_queue_max(struct paging_state *ps, unsigned int queue_max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The lifetime of a paging entry */
 | 
				
			||||||
 | 
					unsigned int paging_get_lifetime(struct paging_state *ps);
 | 
				
			||||||
 | 
					void paging_set_lifetime(struct paging_state *ps, unsigned int lifetime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* update with new SYSTEM INFORMATION parameters */
 | 
				
			||||||
 | 
					int paging_si_update(struct paging_state *ps, struct gsm48_control_channel_descr *chan_desc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Add an identity to the paging queue */
 | 
				
			||||||
 | 
					int paging_add_identity(struct paging_state *ps, uint8_t paging_group,
 | 
				
			||||||
 | 
								const uint8_t *identity_lv, uint8_t chan_needed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Add an IMM.ASS message to the paging queue */
 | 
				
			||||||
 | 
					int paging_add_imm_ass(struct paging_state *ps, const uint8_t *data,
 | 
				
			||||||
 | 
					                       uint8_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* generate paging message for given gsm time */
 | 
				
			||||||
 | 
					int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *gt,
 | 
				
			||||||
 | 
							   int *is_empty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* inspection methods below */
 | 
				
			||||||
 | 
					int paging_group_queue_empty(struct paging_state *ps, uint8_t group);
 | 
				
			||||||
 | 
					int paging_queue_length(struct paging_state *ps);
 | 
				
			||||||
 | 
					int paging_buffer_space(struct paging_state *ps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#ifndef _PCU_IF_H
 | 
				
			||||||
 | 
					#define _PCU_IF_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int pcu_direct;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int pcu_tx_info_ind(void);
 | 
				
			||||||
 | 
					int pcu_tx_si13(const struct gsm_bts *bts, bool enable);
 | 
				
			||||||
 | 
					int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
 | 
				
			||||||
 | 
						uint16_t arfcn, uint8_t block_nr);
 | 
				
			||||||
 | 
					int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
 | 
				
			||||||
 | 
						uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len,
 | 
				
			||||||
 | 
							    int8_t rssi, uint16_t ber10k, int16_t bto, int16_t lqual);
 | 
				
			||||||
 | 
					int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
 | 
				
			||||||
 | 
						uint8_t is_11bit, enum ph_burst_type burst_type);
 | 
				
			||||||
 | 
					int pcu_tx_time_ind(uint32_t fn);
 | 
				
			||||||
 | 
					int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed);
 | 
				
			||||||
 | 
					int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int pcu_sock_init(const char *path);
 | 
				
			||||||
 | 
					void pcu_sock_exit(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool pcu_connected(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _PCU_IF_H */
 | 
				
			||||||
@@ -0,0 +1,195 @@
 | 
				
			|||||||
 | 
					#ifndef _PCUIF_PROTO_H
 | 
				
			||||||
 | 
					#define _PCUIF_PROTO_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsm/l1sap.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PCU_SOCK_DEFAULT	"/tmp/pcu_bts"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PCU_IF_VERSION		0x09
 | 
				
			||||||
 | 
					#define TXT_MAX_LEN	128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* msg_type */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_DATA_REQ	0x00	/* send data to given channel */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_DATA_CNF	0x01	/* confirm (e.g. transmission on PCH) */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_DATA_IND	0x02	/* receive data from given channel */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_RTS_REQ	0x10	/* ready to send request */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_DATA_CNF_DT	0x11	/* confirm (with direct tlli) */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_RACH_IND	0x22	/* receive RACH */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_INFO_IND	0x32	/* retrieve BTS info */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_ACT_REQ	0x40	/* activate/deactivate PDCH */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_TIME_IND	0x52	/* GSM time indication */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_PAG_REQ	0x60	/* paging request */
 | 
				
			||||||
 | 
					#define PCU_IF_MSG_TXT_IND	0x70	/* Text indication for BTS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* sapi */
 | 
				
			||||||
 | 
					#define PCU_IF_SAPI_RACH	0x01	/* channel request on CCCH */
 | 
				
			||||||
 | 
					#define PCU_IF_SAPI_AGCH	0x02	/* assignment on AGCH */
 | 
				
			||||||
 | 
					#define PCU_IF_SAPI_PCH		0x03	/* paging/assignment on PCH */
 | 
				
			||||||
 | 
					#define PCU_IF_SAPI_BCCH	0x04	/* SI on BCCH */
 | 
				
			||||||
 | 
					#define PCU_IF_SAPI_PDTCH	0x05	/* packet data/control/ccch block */
 | 
				
			||||||
 | 
					#define PCU_IF_SAPI_PRACH	0x06	/* packet random access channel */
 | 
				
			||||||
 | 
					#define PCU_IF_SAPI_PTCCH	0x07	/* packet TA control channel */
 | 
				
			||||||
 | 
					#define PCU_IF_SAPI_AGCH_DT	0x08	/* assignment on AGCH but with additional TLLI */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* flags */
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_ACTIVE	(1 << 0)/* BTS is active */
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_SYSMO	(1 << 1)/* access PDCH of sysmoBTS directly */
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_CS1		(1 << 16)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_CS2		(1 << 17)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_CS3		(1 << 18)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_CS4		(1 << 19)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_MCS1	(1 << 20)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_MCS2	(1 << 21)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_MCS3	(1 << 22)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_MCS4	(1 << 23)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_MCS5	(1 << 24)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_MCS6	(1 << 25)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_MCS7	(1 << 26)
 | 
				
			||||||
 | 
					#define PCU_IF_FLAG_MCS8	(1 << 27)
 | 
				
			||||||
 | 
					#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 {
 | 
				
			||||||
 | 
						uint8_t		sapi;
 | 
				
			||||||
 | 
						uint8_t		len;
 | 
				
			||||||
 | 
						uint8_t		data[162];
 | 
				
			||||||
 | 
						uint32_t	fn;
 | 
				
			||||||
 | 
						uint16_t	arfcn;
 | 
				
			||||||
 | 
						uint8_t		trx_nr;
 | 
				
			||||||
 | 
						uint8_t		ts_nr;
 | 
				
			||||||
 | 
						uint8_t		block_nr;
 | 
				
			||||||
 | 
						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));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* data confirmation with direct tlli (instead of raw mac block with tlli) */
 | 
				
			||||||
 | 
					struct gsm_pcu_if_data_cnf_dt {
 | 
				
			||||||
 | 
						uint8_t		sapi;
 | 
				
			||||||
 | 
						uint32_t	tlli;
 | 
				
			||||||
 | 
						uint32_t	fn;
 | 
				
			||||||
 | 
						uint16_t	arfcn;
 | 
				
			||||||
 | 
						uint8_t		trx_nr;
 | 
				
			||||||
 | 
						uint8_t		ts_nr;
 | 
				
			||||||
 | 
						uint8_t		block_nr;
 | 
				
			||||||
 | 
						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));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_pcu_if_rts_req {
 | 
				
			||||||
 | 
						uint8_t		sapi;
 | 
				
			||||||
 | 
						uint8_t		spare[3];
 | 
				
			||||||
 | 
						uint32_t	fn;
 | 
				
			||||||
 | 
						uint16_t	arfcn;
 | 
				
			||||||
 | 
						uint8_t		trx_nr;
 | 
				
			||||||
 | 
						uint8_t		ts_nr;
 | 
				
			||||||
 | 
						uint8_t		block_nr;
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_pcu_if_rach_ind {
 | 
				
			||||||
 | 
						uint8_t		sapi;
 | 
				
			||||||
 | 
						uint16_t	ra;
 | 
				
			||||||
 | 
						int16_t		qta;
 | 
				
			||||||
 | 
						uint32_t	fn;
 | 
				
			||||||
 | 
						uint16_t	arfcn;
 | 
				
			||||||
 | 
						uint8_t		is_11bit;
 | 
				
			||||||
 | 
						uint8_t		burst_type;
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_pcu_if_info_trx {
 | 
				
			||||||
 | 
						uint16_t	arfcn;
 | 
				
			||||||
 | 
						uint8_t		pdch_mask;		/* PDCH channels per TS */
 | 
				
			||||||
 | 
						uint8_t		spare;
 | 
				
			||||||
 | 
						uint8_t		tsc[8];			/* TSC per channel */
 | 
				
			||||||
 | 
						uint32_t	hlayer1;
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_pcu_if_info_ind {
 | 
				
			||||||
 | 
						uint32_t	version;
 | 
				
			||||||
 | 
						uint32_t	flags;
 | 
				
			||||||
 | 
						struct gsm_pcu_if_info_trx trx[8];	/* TRX infos per BTS */
 | 
				
			||||||
 | 
						uint8_t		bsic;
 | 
				
			||||||
 | 
						/* RAI */
 | 
				
			||||||
 | 
						uint16_t	mcc, mnc;
 | 
				
			||||||
 | 
						uint8_t		mnc_3_digits;
 | 
				
			||||||
 | 
						uint16_t	lac, rac;
 | 
				
			||||||
 | 
						/* NSE */
 | 
				
			||||||
 | 
						uint16_t	nsei;
 | 
				
			||||||
 | 
						uint8_t		nse_timer[7];
 | 
				
			||||||
 | 
						uint8_t		cell_timer[11];
 | 
				
			||||||
 | 
						/* cell */
 | 
				
			||||||
 | 
						uint16_t	cell_id;
 | 
				
			||||||
 | 
						uint16_t	repeat_time;
 | 
				
			||||||
 | 
						uint8_t		repeat_count;
 | 
				
			||||||
 | 
						uint16_t	bvci;
 | 
				
			||||||
 | 
						uint8_t		t3142;
 | 
				
			||||||
 | 
						uint8_t		t3169;
 | 
				
			||||||
 | 
						uint8_t		t3191;
 | 
				
			||||||
 | 
						uint8_t		t3193_10ms;
 | 
				
			||||||
 | 
						uint8_t		t3195;
 | 
				
			||||||
 | 
						uint8_t		n3101;
 | 
				
			||||||
 | 
						uint8_t		n3103;
 | 
				
			||||||
 | 
						uint8_t		n3105;
 | 
				
			||||||
 | 
						uint8_t		cv_countdown;
 | 
				
			||||||
 | 
						uint16_t	dl_tbf_ext;
 | 
				
			||||||
 | 
						uint16_t	ul_tbf_ext;
 | 
				
			||||||
 | 
						uint8_t		initial_cs;
 | 
				
			||||||
 | 
						uint8_t		initial_mcs;
 | 
				
			||||||
 | 
						/* NSVC */
 | 
				
			||||||
 | 
						uint16_t	nsvci[2];
 | 
				
			||||||
 | 
						uint16_t	local_port[2];
 | 
				
			||||||
 | 
						uint16_t	remote_port[2];
 | 
				
			||||||
 | 
						uint32_t	remote_ip[2];
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_pcu_if_act_req {
 | 
				
			||||||
 | 
						uint8_t		activate;
 | 
				
			||||||
 | 
						uint8_t		trx_nr;
 | 
				
			||||||
 | 
						uint8_t		ts_nr;
 | 
				
			||||||
 | 
						uint8_t		spare;
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_pcu_if_time_ind {
 | 
				
			||||||
 | 
						uint32_t	fn;
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_pcu_if_pag_req {
 | 
				
			||||||
 | 
						uint8_t		sapi;
 | 
				
			||||||
 | 
						uint8_t		chan_needed;
 | 
				
			||||||
 | 
						uint8_t		identity_lv[9];
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_pcu_if {
 | 
				
			||||||
 | 
						/* context based information */
 | 
				
			||||||
 | 
						uint8_t		msg_type;	/* message type */
 | 
				
			||||||
 | 
						uint8_t		bts_nr;		/* bts number */
 | 
				
			||||||
 | 
						uint8_t		spare[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct gsm_pcu_if_data		data_req;
 | 
				
			||||||
 | 
							struct gsm_pcu_if_data		data_cnf;
 | 
				
			||||||
 | 
							struct gsm_pcu_if_data_cnf_dt	data_cnf_dt;
 | 
				
			||||||
 | 
							struct gsm_pcu_if_data		data_ind;
 | 
				
			||||||
 | 
							struct gsm_pcu_if_rts_req	rts_req;
 | 
				
			||||||
 | 
							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_act_req	act_req;
 | 
				
			||||||
 | 
							struct gsm_pcu_if_time_ind	time_ind;
 | 
				
			||||||
 | 
							struct gsm_pcu_if_pag_req	pag_req;
 | 
				
			||||||
 | 
						} u;
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _PCUIF_PROTO_H */
 | 
				
			||||||
@@ -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);
 | 
				
			||||||
@@ -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);
 | 
				
			||||||
@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					#ifndef _RSL_H
 | 
				
			||||||
 | 
					#define _RSL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * What kind of release/activation is done? A silent one for
 | 
				
			||||||
 | 
					 * the PDCH or one triggered through RSL?
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						LCHAN_REL_ACT_RSL,
 | 
				
			||||||
 | 
						LCHAN_REL_ACT_PCU,
 | 
				
			||||||
 | 
						LCHAN_REL_ACT_OML,
 | 
				
			||||||
 | 
						LCHAN_REL_ACT_REACT, /* remove once auto-activation hack is removed from opstart_compl() */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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 rsl_tx_rf_res(struct gsm_bts_trx *trx);
 | 
				
			||||||
 | 
					int rsl_tx_chan_rqd(struct gsm_bts_trx *trx, struct gsm_time *gtime,
 | 
				
			||||||
 | 
							    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_chan_act_acknack(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_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 */
 | 
				
			||||||
 | 
					int lapdm_rll_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int rsl_tx_ipac_dlcx_ind(struct gsm_lchan *lchan, uint8_t cause);
 | 
				
			||||||
 | 
					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,
 | 
				
			||||||
 | 
								      uint16_t busy, uint16_t access);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -0,0 +1,224 @@
 | 
				
			|||||||
 | 
					#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 */
 | 
				
			||||||
 | 
						int32_t			toa256_sum;	/* sum of TOA values (1/256 symbol) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* 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 */
 | 
				
			||||||
 | 
							int32_t		toa256_sum;	/* sum of TOA values (1/256 symbol) */
 | 
				
			||||||
 | 
							int		toa_num;	/* number of TOA value */
 | 
				
			||||||
 | 
						} meas;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* handover */
 | 
				
			||||||
 | 
						uint8_t			ho_rach_detect;	/* if rach detection is on */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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, int16_t 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* frame structures */
 | 
				
			||||||
 | 
					struct trx_sched_frame {
 | 
				
			||||||
 | 
						/*! \brief downlink TRX channel type */
 | 
				
			||||||
 | 
						enum trx_chan_type		dl_chan;
 | 
				
			||||||
 | 
						/*! \brief downlink block ID */
 | 
				
			||||||
 | 
						uint8_t				dl_bid;
 | 
				
			||||||
 | 
						/*! \brief uplink TRX channel type */
 | 
				
			||||||
 | 
						enum trx_chan_type		ul_chan;
 | 
				
			||||||
 | 
						/*! \brief uplink block ID */
 | 
				
			||||||
 | 
						uint8_t				ul_bid;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* multiframe structure */
 | 
				
			||||||
 | 
					struct trx_sched_multiframe {
 | 
				
			||||||
 | 
						/*! \brief physical channel config (channel combination) */
 | 
				
			||||||
 | 
						enum gsm_phys_chan_config	pchan;
 | 
				
			||||||
 | 
						/*! \brief applies to which timeslots? */
 | 
				
			||||||
 | 
						uint8_t				slotmask;
 | 
				
			||||||
 | 
						/*! \brief repeats how many frames */
 | 
				
			||||||
 | 
						uint8_t				period;
 | 
				
			||||||
 | 
						/*! \brief pointer to scheduling structure */
 | 
				
			||||||
 | 
						const struct trx_sched_frame	*frames;
 | 
				
			||||||
 | 
						/*! \brief human-readable name */
 | 
				
			||||||
 | 
						const char 			*name;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int find_sched_mframe_idx(enum gsm_phys_chan_config pchan, uint8_t tn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Determine if given frame number contains SACCH (true) or other (false) burst */
 | 
				
			||||||
 | 
					bool trx_sched_is_sacch_fn(struct gsm_bts_trx_ts *ts, uint32_t fn, bool uplink);
 | 
				
			||||||
 | 
					extern const struct trx_sched_multiframe trx_sched_multiframes[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* TRX_SCHEDULER_H */
 | 
				
			||||||
@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOGL1S(subsys, level, l1t, tn, chan, fn, fmt, args ...)	\
 | 
				
			||||||
 | 
							LOGP(subsys, level, "%s %s %s: " fmt,		\
 | 
				
			||||||
 | 
								gsm_fn_as_gsmtime_str(fn),		\
 | 
				
			||||||
 | 
								gsm_ts_name(&(l1t)->trx->ts[tn]),	\
 | 
				
			||||||
 | 
								chan >=0 ? trx_chan_desc[chan].name : "", ## args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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, int16_t toa256);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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_256bits, 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, int16_t toa256);
 | 
				
			||||||
 | 
					int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
 | 
				
			||||||
 | 
						enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
 | 
				
			||||||
 | 
						int8_t rssi, int16_t toa256);
 | 
				
			||||||
 | 
					int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
 | 
				
			||||||
 | 
						enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
 | 
				
			||||||
 | 
						int8_t rssi, int16_t toa256);
 | 
				
			||||||
 | 
					int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
 | 
				
			||||||
 | 
						enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
 | 
				
			||||||
 | 
						int8_t rssi, int16_t toa256);
 | 
				
			||||||
 | 
					int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
 | 
				
			||||||
 | 
						enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
 | 
				
			||||||
 | 
						int8_t rssi, int16_t toa256);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					#ifndef OSMO_BTS_SIGNAL_H
 | 
				
			||||||
 | 
					#define OSMO_BTS_SIGNAL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/signal.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum sig_subsys {
 | 
				
			||||||
 | 
						SS_GLOBAL,
 | 
				
			||||||
 | 
						SS_FAIL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum signals_global {
 | 
				
			||||||
 | 
						S_NEW_SYSINFO,
 | 
				
			||||||
 | 
						S_NEW_OP_STATE,
 | 
				
			||||||
 | 
						S_NEW_NSE_ATTR,
 | 
				
			||||||
 | 
						S_NEW_CELL_ATTR,
 | 
				
			||||||
 | 
						S_NEW_NSVC_ATTR,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/timer.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* our unit is 'milli dB" or "milli dBm", i.e. 1/1000 of a dB(m) */
 | 
				
			||||||
 | 
					#define to_mdB(x)	(x * 1000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* PA calibration table */
 | 
				
			||||||
 | 
					struct pa_calibration {
 | 
				
			||||||
 | 
						int delta_mdB[1024];		/* gain delta at given ARFCN */
 | 
				
			||||||
 | 
						/* FIXME: thermal calibration */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* representation of a RF power amplifier */
 | 
				
			||||||
 | 
					struct power_amp {
 | 
				
			||||||
 | 
						/* nominal gain of the PA */
 | 
				
			||||||
 | 
						int nominal_gain_mdB;
 | 
				
			||||||
 | 
						/* table with calibrated actual gain for each ARFCN */
 | 
				
			||||||
 | 
						struct pa_calibration calib;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Transmit power related parameters of a transceiver */
 | 
				
			||||||
 | 
					struct trx_power_params {
 | 
				
			||||||
 | 
						/* specified maximum output of TRX at full power, has to be
 | 
				
			||||||
 | 
						 * initialized by BTS model at startup*/
 | 
				
			||||||
 | 
						int trx_p_max_out_mdBm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* intended current total system output power */
 | 
				
			||||||
 | 
						int p_total_tgt_mdBm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* actual current total system output power, filled in by tx_power code */
 | 
				
			||||||
 | 
						int p_total_cur_mdBm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* current temporary attenuation due to thermal management,
 | 
				
			||||||
 | 
						 * set by thermal management code via control interface */
 | 
				
			||||||
 | 
						int thermal_attenuation_mdB;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* external gain (+) or attenuation (-) added by the user, configured
 | 
				
			||||||
 | 
						 * by the user via VTY */
 | 
				
			||||||
 | 
						int user_gain_mdB;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* calibration table of internal PA */
 | 
				
			||||||
 | 
						struct power_amp pa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* calibration table of user PA */
 | 
				
			||||||
 | 
						struct power_amp user_pa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* power ramping related data */
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							/* maximum initial Pout including all PAs */
 | 
				
			||||||
 | 
							int max_initial_pout_mdBm;
 | 
				
			||||||
 | 
							/* temporary attenuation due to power ramping */
 | 
				
			||||||
 | 
							int attenuation_mdB;
 | 
				
			||||||
 | 
							unsigned int step_size_mdB;
 | 
				
			||||||
 | 
							unsigned int step_interval_sec;
 | 
				
			||||||
 | 
							struct osmo_timer_list step_timer;
 | 
				
			||||||
 | 
						} ramp;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int get_p_max_out_mdBm(struct gsm_bts_trx *trx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int get_p_nominal_mdBm(struct gsm_bts_trx *trx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int get_p_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie);
 | 
				
			||||||
 | 
					int get_p_target_mdBm_lchan(struct gsm_lchan *lchan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int get_p_trxout_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie);
 | 
				
			||||||
 | 
					int get_p_trxout_target_mdBm_lchan(struct gsm_lchan *lchan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int get_p_trxout_actual_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie);
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					#ifndef OSMOBTS_VTY_H
 | 
				
			||||||
 | 
					#define OSMOBTS_VTY_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/vty/vty.h>
 | 
				
			||||||
 | 
					#include <osmocom/vty/command.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum bts_vty_node {
 | 
				
			||||||
 | 
						/* 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,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct cmd_element ournode_exit_cmd;
 | 
				
			||||||
 | 
					extern struct cmd_element ournode_end_cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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_init(struct gsm_bts *bts, const struct log_info *cat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct vty_app_info bts_vty_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					SUBDIRS = common osmo-bts-virtual osmo-bts-omldummy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ENABLE_SYSMOBTS
 | 
				
			||||||
 | 
					SUBDIRS += osmo-bts-sysmo
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
 | 
				
			||||||
 | 
					AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOCODEC_CFLAGS)
 | 
				
			||||||
 | 
					LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOCODEC_LIBS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ENABLE_LC15BTS
 | 
				
			||||||
 | 
					AM_CFLAGS += -DENABLE_LC15BTS
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					noinst_LIBRARIES = libbts.a libl1sched.a
 | 
				
			||||||
 | 
					libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
 | 
				
			||||||
 | 
							   rsl.c vty.c paging.c measurement.c amr.c lchan.c \
 | 
				
			||||||
 | 
							   load_indication.c pcu_sock.c handover.c msg_utils.c \
 | 
				
			||||||
 | 
							   tx_power.c bts_ctrl_commands.c bts_ctrl_lookup.c \
 | 
				
			||||||
 | 
							   l1sap.c cbch.c power_control.c main.c phy_link.c \
 | 
				
			||||||
 | 
							   dtx_dl_amr_fsm.c scheduler_mframe.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libl1sched_a_SOURCES = scheduler.c
 | 
				
			||||||
@@ -0,0 +1,276 @@
 | 
				
			|||||||
 | 
					/* Abis/IP interface routines utilizing libosmo-abis (Pablo) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
 | 
				
			||||||
 | 
					 * (C) 2011-2013 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 "btsconfig.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <sys/ioctl.h>
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/select.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/timer.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/msgb.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/signal.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/macaddr.h>
 | 
				
			||||||
 | 
					#include <osmocom/abis/abis.h>
 | 
				
			||||||
 | 
					#include <osmocom/abis/e1_input.h>
 | 
				
			||||||
 | 
					#include <osmocom/abis/ipaccess.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/ipa.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/logging.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/bts.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/rsl.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/oml.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/bts_model.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct gsm_bts *g_bts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int abis_oml_sendmsg(struct msgb *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts *bts = msg->trx->bts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!bts->oml_link) {
 | 
				
			||||||
 | 
							llist_add_tail(&msg->list, &bts->oml_queue);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* osmo-bts uses msg->trx internally, but libosmo-abis uses
 | 
				
			||||||
 | 
							 * the signalling link at msg->dst */
 | 
				
			||||||
 | 
							msg->dst = bts->oml_link;
 | 
				
			||||||
 | 
							return abis_sendmsg(msg);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void drain_oml_queue(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct msgb *msg, *msg2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry_safe(msg, msg2, &bts->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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						OSMO_ASSERT(msg->trx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (msg->trx->bts->variant == BTS_OSMO_OMLDUMMY) {
 | 
				
			||||||
 | 
							msgb_free(msg);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* osmo-bts uses msg->trx internally, but libosmo-abis uses
 | 
				
			||||||
 | 
						 * the signalling link at msg->dst */
 | 
				
			||||||
 | 
						msg->dst = msg->trx->rsl_link;
 | 
				
			||||||
 | 
						return abis_sendmsg(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
 | 
				
			||||||
 | 
										    enum e1inp_sign_type type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct e1inp_sign_link *sign_link = NULL;
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx;
 | 
				
			||||||
 | 
						int trx_nr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (type) {
 | 
				
			||||||
 | 
						case E1INP_SIGN_OML:
 | 
				
			||||||
 | 
							LOGP(DABIS, LOGL_INFO, "OML Signalling link up\n");
 | 
				
			||||||
 | 
							e1inp_ts_config_sign(&line->ts[E1INP_SIGN_OML-1], line);
 | 
				
			||||||
 | 
							sign_link = g_bts->oml_link =
 | 
				
			||||||
 | 
								e1inp_sign_link_create(&line->ts[E1INP_SIGN_OML-1],
 | 
				
			||||||
 | 
											E1INP_SIGN_OML, NULL, 255, 0);
 | 
				
			||||||
 | 
							drain_oml_queue(g_bts);
 | 
				
			||||||
 | 
							sign_link->trx = g_bts->c0;
 | 
				
			||||||
 | 
							bts_link_estab(g_bts);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sign_link;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void sign_link_down(struct e1inp_line *line)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx;
 | 
				
			||||||
 | 
						LOGP(DABIS, LOGL_ERROR, "Signalling link down\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* First remove the OML signalling link */
 | 
				
			||||||
 | 
						if (g_bts->oml_link)
 | 
				
			||||||
 | 
							e1inp_sign_link_destroy(g_bts->oml_link);
 | 
				
			||||||
 | 
						g_bts->oml_link = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* 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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* callback for incoming mesages from A-bis/IP */
 | 
				
			||||||
 | 
					static int sign_link_cb(struct msgb *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct e1inp_sign_link *link = msg->dst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* osmo-bts code assumes msg->trx is set, but libosmo-abis works
 | 
				
			||||||
 | 
						 * with the sign_link stored in msg->dst, so we have to convert
 | 
				
			||||||
 | 
						 * here */
 | 
				
			||||||
 | 
						msg->trx = link->trx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (link->type) {
 | 
				
			||||||
 | 
						case E1INP_SIGN_OML:
 | 
				
			||||||
 | 
							down_oml(link->trx->bts, msg);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case E1INP_SIGN_RSL:
 | 
				
			||||||
 | 
							down_rsl(link->trx, msg);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							msgb_free(msg);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t get_signlink_remote_ip(struct e1inp_sign_link *link)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int fd = link->ts->driver.ipaccess.fd.fd;
 | 
				
			||||||
 | 
						struct sockaddr_in sin;
 | 
				
			||||||
 | 
						socklen_t slen = sizeof(sin);
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = getpeername(fd, (struct sockaddr *)&sin, &slen);
 | 
				
			||||||
 | 
						if (rc < 0) {
 | 
				
			||||||
 | 
							LOGP(DOML, LOGL_ERROR, "Cannot determine remote IP Addr: %s\n",
 | 
				
			||||||
 | 
								strerror(errno));
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* we assume that the soket is AF_INET.  As Abis/IP contains
 | 
				
			||||||
 | 
						 * lots of hard-coded IPv4 addresses, this safe */
 | 
				
			||||||
 | 
						OSMO_ASSERT(sin.sin_family == AF_INET);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ntohl(sin.sin_addr.s_addr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int inp_s_cbfn(unsigned int subsys, unsigned int signal,
 | 
				
			||||||
 | 
							      void *hdlr_data, void *signal_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (subsys != SS_L_INPUT)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DEBUGP(DABIS, "Input Signal %u received\n", signal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ipaccess_unit bts_dev_info = {
 | 
				
			||||||
 | 
						.unit_name	= "sysmoBTS",
 | 
				
			||||||
 | 
						.equipvers	= "",	/* FIXME: read this from hw */
 | 
				
			||||||
 | 
						.swversion	= PACKAGE_VERSION,
 | 
				
			||||||
 | 
						.location1	= "",
 | 
				
			||||||
 | 
						.location2	= "",
 | 
				
			||||||
 | 
						.serno		= "",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct e1inp_line_ops line_ops = {
 | 
				
			||||||
 | 
						.cfg = {
 | 
				
			||||||
 | 
							.ipa = {
 | 
				
			||||||
 | 
								.role	= E1INP_LINE_R_BTS,
 | 
				
			||||||
 | 
								.dev	= &bts_dev_info,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						.sign_link_up	= sign_link_up,
 | 
				
			||||||
 | 
						.sign_link_down	= sign_link_down,
 | 
				
			||||||
 | 
						.sign_link	= sign_link_cb,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void abis_init(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						g_bts = bts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						oml_init(&bts->mo);
 | 
				
			||||||
 | 
						libosmo_abis_init(NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_signal_register_handler(SS_L_INPUT, &inp_s_cbfn, bts);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct e1inp_line *abis_open(struct gsm_bts *bts, char *dst_host,
 | 
				
			||||||
 | 
								     char *model_name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct e1inp_line *line;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* patch in various data from VTY and othe sources */
 | 
				
			||||||
 | 
						line_ops.cfg.ipa.addr = dst_host;
 | 
				
			||||||
 | 
						osmo_get_macaddr(bts_dev_info.mac_addr, "eth0");
 | 
				
			||||||
 | 
						bts_dev_info.site_id = bts->ip_access.site_id;
 | 
				
			||||||
 | 
						bts_dev_info.bts_id = bts->ip_access.bts_id;
 | 
				
			||||||
 | 
						bts_dev_info.unit_name = model_name;
 | 
				
			||||||
 | 
						if (bts->description)
 | 
				
			||||||
 | 
							bts_dev_info.unit_name = bts->description;
 | 
				
			||||||
 | 
						bts_dev_info.location2 = model_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						line = e1inp_line_find(0);
 | 
				
			||||||
 | 
						if (!line)
 | 
				
			||||||
 | 
							line = e1inp_line_create(0, "ipa");
 | 
				
			||||||
 | 
						if (!line)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						e1inp_line_bind_ops(line, &line_ops);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* This will open the OML connection now */
 | 
				
			||||||
 | 
						if (e1inp_line_update(line) < 0)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return line;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,170 @@
 | 
				
			|||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/logging.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/logging.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/amr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void amr_log_mr_conf(int ss, int logl, const char *pfx,
 | 
				
			||||||
 | 
							     struct amr_multirate_conf *amr_mrc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(ss, logl, "%s AMR MR Conf: num_modes=%u",
 | 
				
			||||||
 | 
							pfx, amr_mrc->num_modes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < amr_mrc->num_modes; i++)
 | 
				
			||||||
 | 
							LOGPC(ss, logl, ", mode[%u] = %u/%u/%u",
 | 
				
			||||||
 | 
								i, amr_mrc->bts_mode[i].mode,
 | 
				
			||||||
 | 
								amr_mrc->bts_mode[i].threshold,
 | 
				
			||||||
 | 
								amr_mrc->bts_mode[i].hysteresis);
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					 * comfortable internal data structure */
 | 
				
			||||||
 | 
					int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
 | 
				
			||||||
 | 
							      const uint8_t *mr_conf, unsigned int len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t mr_version = mr_conf[0] >> 5;
 | 
				
			||||||
 | 
						uint8_t num_codecs = 0;
 | 
				
			||||||
 | 
						int i, j = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mr_version != 1) {
 | 
				
			||||||
 | 
							LOGP(DRSL, LOGL_ERROR, "AMR Multirate Version %u unknown\n",
 | 
				
			||||||
 | 
								mr_version);
 | 
				
			||||||
 | 
							goto ret_einval;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* check number of active codecs */
 | 
				
			||||||
 | 
						for (i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
							if (mr_conf[1] & (1 << i))
 | 
				
			||||||
 | 
								num_codecs++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* check for minimum length */
 | 
				
			||||||
 | 
						if (num_codecs == 0 ||
 | 
				
			||||||
 | 
						    (num_codecs == 1 && len < 2) ||
 | 
				
			||||||
 | 
						    (num_codecs == 2 && len < 4) ||
 | 
				
			||||||
 | 
						    (num_codecs == 3 && len < 5) ||
 | 
				
			||||||
 | 
						    (num_codecs == 4 && len < 6) ||
 | 
				
			||||||
 | 
						    (num_codecs > 4)) {
 | 
				
			||||||
 | 
							LOGP(DRSL, LOGL_ERROR, "AMR Multirate with %u modes len=%u "
 | 
				
			||||||
 | 
							     "not possible\n", num_codecs, len);
 | 
				
			||||||
 | 
							goto ret_einval;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* copy the first two octets of the IE */
 | 
				
			||||||
 | 
						amr_mrc->gsm48_ie[0] = mr_conf[0];
 | 
				
			||||||
 | 
						amr_mrc->gsm48_ie[1] = mr_conf[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amr_mrc->num_modes = num_codecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
							if (mr_conf[1] & (1 << i)) {
 | 
				
			||||||
 | 
								amr_mrc->bts_mode[j++].mode = i;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (num_codecs >= 2) {
 | 
				
			||||||
 | 
							amr_mrc->bts_mode[0].threshold = mr_conf[1] & 0x3F;
 | 
				
			||||||
 | 
							amr_mrc->bts_mode[0].hysteresis = mr_conf[2] >> 4;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (num_codecs >= 3) {
 | 
				
			||||||
 | 
							amr_mrc->bts_mode[1].threshold =
 | 
				
			||||||
 | 
								((mr_conf[2] & 0xF) << 2) | (mr_conf[3] >> 6);
 | 
				
			||||||
 | 
							amr_mrc->bts_mode[1].hysteresis = (mr_conf[3] >> 2) & 0xF;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (num_codecs >= 4) {
 | 
				
			||||||
 | 
							amr_mrc->bts_mode[2].threshold =
 | 
				
			||||||
 | 
								((mr_conf[3] & 0x3) << 4) | (mr_conf[4] >> 4);
 | 
				
			||||||
 | 
							amr_mrc->bts_mode[2].hysteresis = mr_conf[4] & 0xF;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return num_codecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ret_einval:
 | 
				
			||||||
 | 
						return -EINVAL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! \brief determine AMR initial codec mode for given logical channel 
 | 
				
			||||||
 | 
					 *  \returns integer between 0..3 for AMR codce mode 1..4 */
 | 
				
			||||||
 | 
					unsigned int amr_get_initial_mode(struct gsm_lchan *lchan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						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 (mr_conf->icmi) {
 | 
				
			||||||
 | 
							/* initial mode given, coding in TS 05.09 3.4.1 */
 | 
				
			||||||
 | 
							return mr_conf->smod;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* implicit rule according to TS 05.09 Chapter 3.4.3 */
 | 
				
			||||||
 | 
							switch (amr_mrc->num_modes) {
 | 
				
			||||||
 | 
							case 2:
 | 
				
			||||||
 | 
							case 3:
 | 
				
			||||||
 | 
								/* return the most robust */
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							case 4:
 | 
				
			||||||
 | 
								/* return the second-most robust */
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								/* return the only mode we have */
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,740 @@
 | 
				
			|||||||
 | 
					/* BTS support code common to all supported BTS models */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
 | 
				
			||||||
 | 
					 * (C) 2011 by Harald Welte <laforge@gnumonks.org>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU 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 <unistd.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/select.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/timer.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/msgb.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/talloc.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/stats.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/rate_ctr.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_12_21.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/lapdm.h>
 | 
				
			||||||
 | 
					#include <osmocom/trau/osmo_ortp.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/logging.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/abis.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/bts.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/bts_model.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/dtx_dl_amr_fsm.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/pcuif_proto.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/rsl.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/oml.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 = {
 | 
				
			||||||
 | 
						.bts_list = { &bts_gsmnet.bts_list, &bts_gsmnet.bts_list },
 | 
				
			||||||
 | 
						.num_bts = 0,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *tall_bts_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 3.1 TS 04.08: Values of parameter S */
 | 
				
			||||||
 | 
					static const uint8_t tx_integer[] = {
 | 
				
			||||||
 | 
						3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 25, 32, 50,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint8_t s_values[][2] = {
 | 
				
			||||||
 | 
						{ 55, 41 }, { 76, 52 }, { 109, 58 }, { 163, 86 }, { 217, 115 },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int bts_signal_cbfn(unsigned int subsys, unsigned int signal,
 | 
				
			||||||
 | 
								   void *hdlr_data, void *signal_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (subsys == SS_GLOBAL && signal == S_NEW_SYSINFO) {
 | 
				
			||||||
 | 
							struct gsm_bts *bts = signal_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bts_update_agch_max_queue_length(bts);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct rate_ctr_desc bts_ctr_desc[] = {
 | 
				
			||||||
 | 
						[BTS_CTR_PAGING_RCVD] =		{"paging:rcvd", "Received paging requests (Abis)"},
 | 
				
			||||||
 | 
						[BTS_CTR_PAGING_DROP] =		{"paging:drop", "Dropped paging requests (Abis)"},
 | 
				
			||||||
 | 
						[BTS_CTR_PAGING_SENT] =		{"paging:sent", "Sent paging requests (Um)"},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[BTS_CTR_RACH_RCVD] =		{"rach:rcvd", "Received RACH requests (Um)"},
 | 
				
			||||||
 | 
						[BTS_CTR_RACH_DROP] =		{"rach:drop", "Dropped RACH requests (Um)"},
 | 
				
			||||||
 | 
						[BTS_CTR_RACH_HO] =		{"rach:handover", "Received RACH requests (Handover)"},
 | 
				
			||||||
 | 
						[BTS_CTR_RACH_CS] =		{"rach:cs", "Received RACH requests (CS/Abis)"},
 | 
				
			||||||
 | 
						[BTS_CTR_RACH_PS] =		{"rach:ps", "Received RACH requests (PS/PCU)"},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[BTS_CTR_AGCH_RCVD] =		{"agch:rcvd", "Received AGCH requests (Abis)"},
 | 
				
			||||||
 | 
						[BTS_CTR_AGCH_SENT] =		{"agch:sent", "Sent AGCH requests (Abis)"},
 | 
				
			||||||
 | 
						[BTS_CTR_AGCH_DELETED] =	{"agch:delete", "Sent AGCH DELETE IND (Abis)"},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					static const struct rate_ctr_group_desc bts_ctrg_desc = {
 | 
				
			||||||
 | 
						"bts",
 | 
				
			||||||
 | 
						"base transceiver station",
 | 
				
			||||||
 | 
						OSMO_STATS_CLASS_GLOBAL,
 | 
				
			||||||
 | 
						ARRAY_SIZE(bts_ctr_desc),
 | 
				
			||||||
 | 
						bts_ctr_desc
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Initialize the BTS (and TRX) data structures, called before config
 | 
				
			||||||
 | 
					 * file reading */
 | 
				
			||||||
 | 
					int bts_init(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx;
 | 
				
			||||||
 | 
						int rc, i;
 | 
				
			||||||
 | 
						static int initialized = 0;
 | 
				
			||||||
 | 
						void *tall_rtp_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* add to list of BTSs */
 | 
				
			||||||
 | 
						llist_add_tail(&bts->list, &bts_gsmnet.bts_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bts->band = GSM_BAND_1800;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LLIST_HEAD(&bts->agch_queue.queue);
 | 
				
			||||||
 | 
						bts->agch_queue.length = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bts->ctrs = rate_ctr_group_alloc(bts, &bts_ctrg_desc, bts->nr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* enable management with default levels,
 | 
				
			||||||
 | 
						 * raise threshold to GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DISABLE to
 | 
				
			||||||
 | 
						 * disable this feature.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						bts->agch_queue.low_level = GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT;
 | 
				
			||||||
 | 
						bts->agch_queue.high_level = GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT;
 | 
				
			||||||
 | 
						bts->agch_queue.thresh_level = GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* configurable via VTY */
 | 
				
			||||||
 | 
						bts->paging_state = paging_init(bts, 200, 0);
 | 
				
			||||||
 | 
						bts->ul_power_target = -75;	/* dBm default */
 | 
				
			||||||
 | 
						bts->rtp_jitter_adaptive = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* configurable via OML */
 | 
				
			||||||
 | 
						bts->load.ccch.load_ind_period = 112;
 | 
				
			||||||
 | 
						load_timer_start(bts);
 | 
				
			||||||
 | 
						bts->rtp_jitter_buf_ms = 100;
 | 
				
			||||||
 | 
						bts->max_ta = 63;
 | 
				
			||||||
 | 
						bts->ny1 = 4;
 | 
				
			||||||
 | 
						bts->t3105_ms = 300;
 | 
				
			||||||
 | 
						bts->min_qual_rach = MIN_QUAL_RACH;
 | 
				
			||||||
 | 
						bts->min_qual_norm = MIN_QUAL_NORM;
 | 
				
			||||||
 | 
						bts->max_ber10k_rach = 1707; /* 7 of 41 bits is Eb/N0 of 0 dB = 0.1707 */
 | 
				
			||||||
 | 
						bts->pcu.sock_path = talloc_strdup(bts, PCU_SOCK_DEFAULT);
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_SIZE(bts->t200_ms); i++)
 | 
				
			||||||
 | 
							bts->t200_ms[i] = oml_default_t200_ms[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* default RADIO_LINK_TIMEOUT */
 | 
				
			||||||
 | 
						bts->radio_link_timeout = 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Start with the site manager */
 | 
				
			||||||
 | 
						oml_mo_state_init(&bts->site_mgr.mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* set BTS to dependency */
 | 
				
			||||||
 | 
						oml_mo_state_init(&bts->mo, -1, NM_AVSTATE_DEPENDENCY);
 | 
				
			||||||
 | 
						oml_mo_state_init(&bts->gprs.nse.mo, -1, NM_AVSTATE_DEPENDENCY);
 | 
				
			||||||
 | 
						oml_mo_state_init(&bts->gprs.cell.mo, -1, NM_AVSTATE_DEPENDENCY);
 | 
				
			||||||
 | 
						oml_mo_state_init(&bts->gprs.nsvc[0].mo, -1, NM_AVSTATE_DEPENDENCY);
 | 
				
			||||||
 | 
						oml_mo_state_init(&bts->gprs.nsvc[1].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* initialize bts data structure */
 | 
				
			||||||
 | 
						llist_for_each_entry(trx, &bts->trx_list, list) {
 | 
				
			||||||
 | 
							struct trx_power_params *tpp = &trx->power_params;
 | 
				
			||||||
 | 
							int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
 | 
				
			||||||
 | 
								struct gsm_bts_trx_ts *ts = &trx->ts[i];
 | 
				
			||||||
 | 
								int k;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (k = 0; k < ARRAY_SIZE(ts->lchan); k++) {
 | 
				
			||||||
 | 
									struct gsm_lchan *lchan = &ts->lchan[k];
 | 
				
			||||||
 | 
									INIT_LLIST_HEAD(&lchan->dl_tch_queue);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							/* Default values for the power adjustments */
 | 
				
			||||||
 | 
							tpp->ramp.max_initial_pout_mdBm = to_mdB(0);
 | 
				
			||||||
 | 
							tpp->ramp.step_size_mdB = to_mdB(2);
 | 
				
			||||||
 | 
							tpp->ramp.step_interval_sec = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* 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);
 | 
				
			||||||
 | 
						if (rc < 0) {
 | 
				
			||||||
 | 
							llist_del(&bts->list);
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bts_gsmnet.num_bts++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!initialized) {
 | 
				
			||||||
 | 
							osmo_signal_register_handler(SS_GLOBAL, bts_signal_cbfn, NULL);
 | 
				
			||||||
 | 
							initialized = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LLIST_HEAD(&bts->smscb_state.queue);
 | 
				
			||||||
 | 
						INIT_LLIST_HEAD(&bts->oml_queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* register DTX DL FSM */
 | 
				
			||||||
 | 
						rc = osmo_fsm_register(&dtx_dl_amr_fsm);
 | 
				
			||||||
 | 
						OSMO_ASSERT(rc == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void shutdown_timer_cb(void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						fprintf(stderr, "Shutdown timer expired\n");
 | 
				
			||||||
 | 
						exit(42);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct osmo_timer_list shutdown_timer = {
 | 
				
			||||||
 | 
						.cb = &shutdown_timer_cb,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void bts_shutdown(struct gsm_bts *bts, const char *reason)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (osmo_timer_pending(&shutdown_timer)) {
 | 
				
			||||||
 | 
							LOGP(DOML, LOGL_NOTICE,
 | 
				
			||||||
 | 
								"BTS is already being shutdown.\n");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DOML, LOGL_NOTICE, "Shutting down BTS %u, Reason %s\n",
 | 
				
			||||||
 | 
							bts->nr, reason);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry_reverse(trx, &bts->trx_list, list) {
 | 
				
			||||||
 | 
							bts_model_trx_deact_rf(trx);
 | 
				
			||||||
 | 
							bts_model_trx_close(trx);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* shedule a timer to make sure select loop logic can run again
 | 
				
			||||||
 | 
						 * to dispatch any pending primitives */
 | 
				
			||||||
 | 
						osmo_timer_schedule(&shutdown_timer, 3, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* main link is established, send status report */
 | 
				
			||||||
 | 
					int bts_link_estab(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DSUM, LOGL_INFO, "Main link established, sending Status'.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* BTS and SITE MGR are EANBLED, BTS is DEPENDENCY */
 | 
				
			||||||
 | 
						oml_tx_state_changed(&bts->site_mgr.mo);
 | 
				
			||||||
 | 
						oml_tx_state_changed(&bts->mo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* those should all be in DEPENDENCY */
 | 
				
			||||||
 | 
						oml_tx_state_changed(&bts->gprs.nse.mo);
 | 
				
			||||||
 | 
						oml_tx_state_changed(&bts->gprs.cell.mo);
 | 
				
			||||||
 | 
						oml_tx_state_changed(&bts->gprs.nsvc[0].mo);
 | 
				
			||||||
 | 
						oml_tx_state_changed(&bts->gprs.nsvc[1].mo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* All other objects start off-line until the BTS Model code says otherwise */
 | 
				
			||||||
 | 
						for (i = 0; i < bts->num_trx; i++) {
 | 
				
			||||||
 | 
							struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							oml_tx_state_changed(&trx->mo);
 | 
				
			||||||
 | 
							oml_tx_state_changed(&trx->bb_transc.mo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (j = 0; j < ARRAY_SIZE(trx->ts); j++) {
 | 
				
			||||||
 | 
								struct gsm_bts_trx_ts *ts = &trx->ts[j];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								oml_tx_state_changed(&ts->mo);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return bts_model_oml_estab(bts);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RSL link is established, send status report */
 | 
				
			||||||
 | 
					int trx_link_estab(struct gsm_bts_trx *trx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct e1inp_sign_link *link = trx->rsl_link;
 | 
				
			||||||
 | 
						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",
 | 
				
			||||||
 | 
							trx->nr, link ? "up" : "down");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						oml_mo_state_chg(&trx->mo, radio_state, NM_AVSTATE_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (link)
 | 
				
			||||||
 | 
							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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int lchan_init_lapdm(struct gsm_lchan *lchan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct lapdm_channel *lc = &lchan->lapdm_ch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lapdm_channel_init(lc, LAPDM_MODE_BTS);
 | 
				
			||||||
 | 
						lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
 | 
				
			||||||
 | 
						lapdm_channel_set_l1(lc, NULL, lchan);
 | 
				
			||||||
 | 
						lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
 | 
				
			||||||
 | 
						oml_set_lchan_t200(lchan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CCCH_RACH_RATIO_COMBINED256      (256*1/9)
 | 
				
			||||||
 | 
					#define CCCH_RACH_RATIO_SEPARATE256      (256*10/55)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_agch_max_queue_length(int T, int bcch_conf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int S, ccch_rach_ratio256, i;
 | 
				
			||||||
 | 
						int T_group = 0;
 | 
				
			||||||
 | 
						int is_ccch_comb = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bcch_conf == RSL_BCCH_CCCH_CONF_1_C)
 | 
				
			||||||
 | 
							is_ccch_comb = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * The calculation is based on the ratio of the number RACH slots and
 | 
				
			||||||
 | 
						 * CCCH blocks per time:
 | 
				
			||||||
 | 
						 *   Lmax = (T + 2*S) / R_RACH * R_CCCH
 | 
				
			||||||
 | 
						 * where
 | 
				
			||||||
 | 
						 *   T3126_min = (T + 2*S) / R_RACH, as defined in GSM 04.08, 11.1.1
 | 
				
			||||||
 | 
						 *   R_RACH is the RACH slot rate (e.g. RACHs per multiframe)
 | 
				
			||||||
 | 
						 *   R_CCCH is the CCCH block rate (same time base like R_RACH)
 | 
				
			||||||
 | 
						 *   S and T are defined in GSM 04.08, 3.3.1.1.2
 | 
				
			||||||
 | 
						 * The ratio is mainly influenced by the downlink only channels
 | 
				
			||||||
 | 
						 * (BCCH, FCCH, SCH, CBCH) that can not be used for CCCH.
 | 
				
			||||||
 | 
						 * An estimation with an error of < 10% is used:
 | 
				
			||||||
 | 
						 *   ~ 1/9 if CCCH is combined with SDCCH, and
 | 
				
			||||||
 | 
						 *   ~ 1/5.5 otherwise.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						ccch_rach_ratio256 = is_ccch_comb ?
 | 
				
			||||||
 | 
							CCCH_RACH_RATIO_COMBINED256 :
 | 
				
			||||||
 | 
							CCCH_RACH_RATIO_SEPARATE256;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_SIZE(tx_integer); i++) {
 | 
				
			||||||
 | 
							if (tx_integer[i] == T) {
 | 
				
			||||||
 | 
								T_group = i % 5;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						S = s_values[T_group][is_ccch_comb];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (T + 2 * S) * ccch_rach_ratio256 / 256;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void bts_update_agch_max_queue_length(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm48_system_information_type_3 *si3;
 | 
				
			||||||
 | 
						int old_max_length = bts->agch_queue.max_length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(bts->si_valid & (1<<SYSINFO_TYPE_3)))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						si3 = GSM_BTS_SI(bts, SYSINFO_TYPE_3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bts->agch_queue.max_length =
 | 
				
			||||||
 | 
							bts_agch_max_queue_length(si3->rach_control.tx_integer,
 | 
				
			||||||
 | 
										  si3->control_channel_desc.ccch_conf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bts->agch_queue.max_length != old_max_length)
 | 
				
			||||||
 | 
							LOGP(DRSL, LOGL_INFO, "Updated AGCH max queue length to %d\n",
 | 
				
			||||||
 | 
							     bts->agch_queue.max_length);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define REQ_REFS_PER_IMM_ASS_REJ 4
 | 
				
			||||||
 | 
					static int store_imm_ass_rej_refs(struct gsm48_imm_ass_rej *rej,
 | 
				
			||||||
 | 
									    struct gsm48_req_ref *req_refs,
 | 
				
			||||||
 | 
									    uint8_t *wait_inds,
 | 
				
			||||||
 | 
									    int count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (count) {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							/* TODO: Warning ? */
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							count = 4;
 | 
				
			||||||
 | 
							rej->req_ref4 = req_refs[3];
 | 
				
			||||||
 | 
							rej->wait_ind4 = wait_inds[3];
 | 
				
			||||||
 | 
							/* fall through */
 | 
				
			||||||
 | 
						case 3:
 | 
				
			||||||
 | 
							rej->req_ref3 = req_refs[2];
 | 
				
			||||||
 | 
							rej->wait_ind3 = wait_inds[2];
 | 
				
			||||||
 | 
							/* fall through */
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							rej->req_ref2 = req_refs[1];
 | 
				
			||||||
 | 
							rej->wait_ind2 = wait_inds[1];
 | 
				
			||||||
 | 
							/* fall through */
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							rej->req_ref1 = req_refs[0];
 | 
				
			||||||
 | 
							rej->wait_ind1 = wait_inds[0];
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (count) {
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							rej->req_ref2 = req_refs[0];
 | 
				
			||||||
 | 
							rej->wait_ind2 = wait_inds[0];
 | 
				
			||||||
 | 
							/* fall through */
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							rej->req_ref3 = req_refs[0];
 | 
				
			||||||
 | 
							rej->wait_ind3 = wait_inds[0];
 | 
				
			||||||
 | 
							/* fall through */
 | 
				
			||||||
 | 
						case 3:
 | 
				
			||||||
 | 
							rej->req_ref4 = req_refs[0];
 | 
				
			||||||
 | 
							rej->wait_ind4 = wait_inds[0];
 | 
				
			||||||
 | 
							/* fall through */
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int extract_imm_ass_rej_refs(struct gsm48_imm_ass_rej *rej,
 | 
				
			||||||
 | 
									    struct gsm48_req_ref *req_refs,
 | 
				
			||||||
 | 
									    uint8_t *wait_inds)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int count = 0;
 | 
				
			||||||
 | 
						req_refs[count] = rej->req_ref1;
 | 
				
			||||||
 | 
						wait_inds[count] = rej->wait_ind1;
 | 
				
			||||||
 | 
						count++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (memcmp(&rej->req_ref1, &rej->req_ref2, sizeof(rej->req_ref2))) {
 | 
				
			||||||
 | 
							req_refs[count] = rej->req_ref2;
 | 
				
			||||||
 | 
							wait_inds[count] = rej->wait_ind2;
 | 
				
			||||||
 | 
							count++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (memcmp(&rej->req_ref1, &rej->req_ref3, sizeof(rej->req_ref3)) &&
 | 
				
			||||||
 | 
						    memcmp(&rej->req_ref2, &rej->req_ref3, sizeof(rej->req_ref3))) {
 | 
				
			||||||
 | 
							req_refs[count] = rej->req_ref3;
 | 
				
			||||||
 | 
							wait_inds[count] = rej->wait_ind3;
 | 
				
			||||||
 | 
							count++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (memcmp(&rej->req_ref1, &rej->req_ref4, sizeof(rej->req_ref4)) &&
 | 
				
			||||||
 | 
						    memcmp(&rej->req_ref2, &rej->req_ref4, sizeof(rej->req_ref4)) &&
 | 
				
			||||||
 | 
						    memcmp(&rej->req_ref3, &rej->req_ref4, sizeof(rej->req_ref4))) {
 | 
				
			||||||
 | 
							req_refs[count] = rej->req_ref4;
 | 
				
			||||||
 | 
							wait_inds[count] = rej->wait_ind4;
 | 
				
			||||||
 | 
							count++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int try_merge_imm_ass_rej(struct gsm48_imm_ass_rej *old_rej,
 | 
				
			||||||
 | 
									 struct gsm48_imm_ass_rej *new_rej)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm48_req_ref req_refs[2 * REQ_REFS_PER_IMM_ASS_REJ];
 | 
				
			||||||
 | 
						uint8_t wait_inds[2 * REQ_REFS_PER_IMM_ASS_REJ];
 | 
				
			||||||
 | 
						int count = 0;
 | 
				
			||||||
 | 
						int stored = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (new_rej->msg_type != GSM48_MT_RR_IMM_ASS_REJ)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						if (old_rej->msg_type != GSM48_MT_RR_IMM_ASS_REJ)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* GSM 08.58, 5.7
 | 
				
			||||||
 | 
						 * -> The BTS may combine serveral IMM.ASS.REJ messages
 | 
				
			||||||
 | 
						 * -> Identical request refs in one message may be squeezed
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * GSM 04.08, 9.1.20.2
 | 
				
			||||||
 | 
						 * -> Request ref and wait ind are duplicated to fill the message
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Extract all entries */
 | 
				
			||||||
 | 
						count = extract_imm_ass_rej_refs(old_rej,
 | 
				
			||||||
 | 
										 &req_refs[count], &wait_inds[count]);
 | 
				
			||||||
 | 
						if (count == REQ_REFS_PER_IMM_ASS_REJ)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count += extract_imm_ass_rej_refs(new_rej,
 | 
				
			||||||
 | 
										  &req_refs[count], &wait_inds[count]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Store entries into old message */
 | 
				
			||||||
 | 
						stored = store_imm_ass_rej_refs(old_rej,
 | 
				
			||||||
 | 
										&req_refs[stored], &wait_inds[stored],
 | 
				
			||||||
 | 
										count);
 | 
				
			||||||
 | 
						count -= stored;
 | 
				
			||||||
 | 
						if (count == 0)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Store remaining entries into new message */
 | 
				
			||||||
 | 
						stored += store_imm_ass_rej_refs(new_rej,
 | 
				
			||||||
 | 
										 &req_refs[stored], &wait_inds[stored],
 | 
				
			||||||
 | 
										 count);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int hard_limit = 1000;
 | 
				
			||||||
 | 
						struct gsm48_imm_ass_rej *imm_ass_cmd = msgb_l3(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bts->agch_queue.length > hard_limit) {
 | 
				
			||||||
 | 
							LOGP(DSUM, LOGL_ERROR,
 | 
				
			||||||
 | 
							     "AGCH: too many messages in queue, "
 | 
				
			||||||
 | 
							     "refusing message type 0x%02x, length = %d/%d\n",
 | 
				
			||||||
 | 
							     ((struct gsm48_imm_ass *)msgb_l3(msg))->msg_type,
 | 
				
			||||||
 | 
							     bts->agch_queue.length, bts->agch_queue.max_length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bts->agch_queue.rejected_msgs++;
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bts->agch_queue.length > 0) {
 | 
				
			||||||
 | 
							struct msgb *last_msg =
 | 
				
			||||||
 | 
								llist_entry(bts->agch_queue.queue.prev, struct msgb, list);
 | 
				
			||||||
 | 
							struct gsm48_imm_ass_rej *last_imm_ass_rej = msgb_l3(last_msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (try_merge_imm_ass_rej(last_imm_ass_rej, imm_ass_cmd)) {
 | 
				
			||||||
 | 
								bts->agch_queue.merged_msgs++;
 | 
				
			||||||
 | 
								msgb_free(msg);
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msgb_enqueue(&bts->agch_queue.queue, msg);
 | 
				
			||||||
 | 
						bts->agch_queue.length++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct msgb *bts_agch_dequeue(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct msgb *msg = msgb_dequeue(&bts->agch_queue.queue);
 | 
				
			||||||
 | 
						if (!msg)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bts->agch_queue.length--;
 | 
				
			||||||
 | 
						return msg;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Remove lower prio messages if the queue has grown too long.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \return 0 iff the number of messages in the queue would fit into the AGCH
 | 
				
			||||||
 | 
					 *         reserved part of the CCCH.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void compact_agch_queue(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct msgb *msg, *msg2;
 | 
				
			||||||
 | 
						int max_len, slope, offs;
 | 
				
			||||||
 | 
						int level_low = bts->agch_queue.low_level;
 | 
				
			||||||
 | 
						int level_high = bts->agch_queue.high_level;
 | 
				
			||||||
 | 
						int level_thres = bts->agch_queue.thresh_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						max_len = bts->agch_queue.max_length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (max_len == 0)
 | 
				
			||||||
 | 
							max_len = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bts->agch_queue.length < max_len * level_thres / 100)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* p^
 | 
				
			||||||
 | 
						 * 1+      /'''''
 | 
				
			||||||
 | 
						 *  |     /
 | 
				
			||||||
 | 
						 *  |    /
 | 
				
			||||||
 | 
						 * 0+---/--+----+--> Q length
 | 
				
			||||||
 | 
						 *    low high max_len
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						offs = max_len * level_low / 100;
 | 
				
			||||||
 | 
						if (level_high > level_low)
 | 
				
			||||||
 | 
							slope = 0x10000 * 100 / (level_high - level_low);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							slope = 0x10000 * max_len; /* p_drop >= 1 if len > offs */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry_safe(msg, msg2, &bts->agch_queue.queue, list) {
 | 
				
			||||||
 | 
							struct gsm48_imm_ass *imm_ass_cmd = msgb_l3(msg);
 | 
				
			||||||
 | 
							int p_drop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (imm_ass_cmd->msg_type != GSM48_MT_RR_IMM_ASS_REJ)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* IMMEDIATE ASSIGN REJECT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p_drop = (bts->agch_queue.length - offs) * slope / max_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ((random() & 0xffff) >= p_drop)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							llist_del(&msg->list);
 | 
				
			||||||
 | 
							bts->agch_queue.length--;
 | 
				
			||||||
 | 
							msgb_free(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bts->agch_queue.dropped_msgs++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt,
 | 
				
			||||||
 | 
							      int is_ag_res)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct msgb *msg = NULL;
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
 | 
						int is_empty = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Do queue house keeping.
 | 
				
			||||||
 | 
						 * This needs to be done every time a CCCH message is requested, since
 | 
				
			||||||
 | 
						 * the queue max length is calculated based on the CCCH block rate and
 | 
				
			||||||
 | 
						 * PCH messages also reduce the drain of the AGCH queue.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						compact_agch_queue(bts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check for paging messages first if this is PCH */
 | 
				
			||||||
 | 
						if (!is_ag_res)
 | 
				
			||||||
 | 
							rc = paging_gen_msg(bts->paging_state, out_buf, gt, &is_empty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check whether the block may be overwritten */
 | 
				
			||||||
 | 
						if (!is_empty)
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg = bts_agch_dequeue(bts);
 | 
				
			||||||
 | 
						if (!msg)
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rate_ctr_inc2(bts->ctrs, BTS_CTR_AGCH_SENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Copy AGCH message */
 | 
				
			||||||
 | 
						memcpy(out_buf, msgb_l3(msg), msgb_l3len(msg));
 | 
				
			||||||
 | 
						rc = msgb_l3len(msg);
 | 
				
			||||||
 | 
						msgb_free(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (is_ag_res)
 | 
				
			||||||
 | 
							bts->agch_queue.agch_msgs++;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							bts->agch_queue.pch_msgs++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_supports_cipher(struct gsm_bts *bts, int rsl_cipher)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int sup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rsl_cipher < 1 || rsl_cipher > 8)
 | 
				
			||||||
 | 
							return -ENOTSUP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* No encryption is always supported */
 | 
				
			||||||
 | 
						if (rsl_cipher == 1)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sup =  (1 << (rsl_cipher - 2)) & bts->support.ciphers;
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return &bts->gsm_time;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bts_supports_cm(struct gsm_bts *bts, enum gsm_phys_chan_config pchan,
 | 
				
			||||||
 | 
							    enum gsm48_chan_mode cm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum gsm_bts_features feature = _NUM_BTS_FEAT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Before the requested pchan/cm combination can be checked, we need to
 | 
				
			||||||
 | 
						 * convert it to a feature identifier we can check */
 | 
				
			||||||
 | 
						if (pchan == GSM_PCHAN_TCH_F) {
 | 
				
			||||||
 | 
							switch(cm) {
 | 
				
			||||||
 | 
							case GSM48_CMODE_SPEECH_V1:
 | 
				
			||||||
 | 
								feature	= BTS_FEAT_SPEECH_F_V1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case GSM48_CMODE_SPEECH_EFR:
 | 
				
			||||||
 | 
								feature	= BTS_FEAT_SPEECH_F_EFR;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case GSM48_CMODE_SPEECH_AMR:
 | 
				
			||||||
 | 
								feature = BTS_FEAT_SPEECH_F_AMR;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								/* Invalid speech codec type => Not supported! */
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (pchan == GSM_PCHAN_TCH_H) {
 | 
				
			||||||
 | 
							switch(cm) {
 | 
				
			||||||
 | 
							case GSM48_CMODE_SPEECH_V1:
 | 
				
			||||||
 | 
								feature	= BTS_FEAT_SPEECH_H_V1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case GSM48_CMODE_SPEECH_AMR:
 | 
				
			||||||
 | 
								feature = BTS_FEAT_SPEECH_H_AMR;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								/* Invalid speech codec type => Not supported! */
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check if the feature is supported by this BTS */
 | 
				
			||||||
 | 
						if (gsm_bts_has_feature(bts, feature))
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					/* Control Interface for osmo-bts */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (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 <stdint.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_12_21.h>
 | 
				
			||||||
 | 
					#include <osmocom/ctrl/control_cmd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/logging.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.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");
 | 
				
			||||||
 | 
					static int get_therm_att(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx = cmd->node;
 | 
				
			||||||
 | 
						struct trx_power_params *tpp = &trx->power_params;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd->reply = talloc_asprintf(cmd, "%d", tpp->thermal_attenuation_mdB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int set_therm_att(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx = cmd->node;
 | 
				
			||||||
 | 
						struct trx_power_params *tpp = &trx->power_params;
 | 
				
			||||||
 | 
						int val = atoi(cmd->value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf("set_therm_att(trx=%p, tpp=%p)\n", trx, tpp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tpp->thermal_attenuation_mdB = val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						power_ramp_start(trx, tpp->p_total_cur_mdBm, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return get_therm_att(cmd, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int verify_therm_att(struct ctrl_cmd *cmd, const char *value, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int val = atoi(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* permit between 0 to 40 dB attenuation */
 | 
				
			||||||
 | 
						if (val < 0 || val > to_mdB(40))
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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 rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_therm_att);
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_oml_alert);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					/* Control Interface for osmo-bts */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (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/vty/command.h>
 | 
				
			||||||
 | 
					#include <osmocom/ctrl/control_if.h>
 | 
				
			||||||
 | 
					#include <osmocom/ctrl/ports.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/bts_model.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/logging.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/control_if.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern vector ctrl_node_vec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! \brief control interface lookup function for bsc/bts gsm_data
 | 
				
			||||||
 | 
					 * \param[in] data Private data passed to controlif_setup()
 | 
				
			||||||
 | 
					 * \param[in] vline Vector of the line holding the command string
 | 
				
			||||||
 | 
					 * \param[out] node_type type (CTRL_NODE_) that was determined
 | 
				
			||||||
 | 
					 * \param[out] node_data private dta of node that was determined
 | 
				
			||||||
 | 
					 * \param i Current index into vline, up to which it is parsed
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int bts_ctrl_node_lookup(void *data, vector vline, int *node_type,
 | 
				
			||||||
 | 
									void **node_data, int *i)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts *bts = data;
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx = NULL;
 | 
				
			||||||
 | 
						struct gsm_bts_trx_ts *ts = NULL;
 | 
				
			||||||
 | 
						char *token = vector_slot(vline, *i);
 | 
				
			||||||
 | 
						long num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* TODO: We need to make sure that the following chars are digits
 | 
				
			||||||
 | 
						 * and/or use strtol to check if number conversion was successful
 | 
				
			||||||
 | 
						 * Right now something like net.bts_stats will not work */
 | 
				
			||||||
 | 
						if (!strcmp(token, "trx")) {
 | 
				
			||||||
 | 
							if (*node_type != CTRL_NODE_ROOT || !*node_data)
 | 
				
			||||||
 | 
								goto err_missing;
 | 
				
			||||||
 | 
							bts = *node_data;
 | 
				
			||||||
 | 
							(*i)++;
 | 
				
			||||||
 | 
							if (!ctrl_parse_get_num(vline, *i, &num))
 | 
				
			||||||
 | 
								goto err_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							trx = gsm_bts_trx_num(bts, num);
 | 
				
			||||||
 | 
							if (!trx)
 | 
				
			||||||
 | 
								goto err_missing;
 | 
				
			||||||
 | 
							*node_data = trx;
 | 
				
			||||||
 | 
							*node_type = CTRL_NODE_TRX;
 | 
				
			||||||
 | 
						} else if (!strcmp(token, "ts")) {
 | 
				
			||||||
 | 
							if (*node_type != CTRL_NODE_TRX || !*node_data)
 | 
				
			||||||
 | 
								goto err_missing;
 | 
				
			||||||
 | 
							trx = *node_data;
 | 
				
			||||||
 | 
							(*i)++;
 | 
				
			||||||
 | 
							if (!ctrl_parse_get_num(vline, *i, &num))
 | 
				
			||||||
 | 
								goto err_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ((num >= 0) && (num < TRX_NR_TS))
 | 
				
			||||||
 | 
								ts = &trx->ts[num];
 | 
				
			||||||
 | 
							if (!ts)
 | 
				
			||||||
 | 
								goto err_missing;
 | 
				
			||||||
 | 
							*node_data = ts;
 | 
				
			||||||
 | 
							*node_type = CTRL_NODE_TS;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					err_missing:
 | 
				
			||||||
 | 
						return -ENODEV;
 | 
				
			||||||
 | 
					err_index:
 | 
				
			||||||
 | 
						return -ERANGE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts,
 | 
				
			||||||
 | 
										const char *bind_addr, uint16_t port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ctrl_handle *hdl;
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hdl = ctrl_interface_setup_dynip(bts, bind_addr, port,
 | 
				
			||||||
 | 
										 bts_ctrl_node_lookup);
 | 
				
			||||||
 | 
						if (!hdl)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = bts_ctrl_cmds_install(bts);
 | 
				
			||||||
 | 
						if (rc) {
 | 
				
			||||||
 | 
							/* FIXME: close control interface */
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = bts_model_ctrl_cmds_install(bts);
 | 
				
			||||||
 | 
						if (rc) {
 | 
				
			||||||
 | 
							/* FIXME: cleanup generic control commands */
 | 
				
			||||||
 | 
							/* FIXME: close control interface */
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return hdl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,192 @@
 | 
				
			|||||||
 | 
					/* 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 gsm412_block_type *block_type;
 | 
				
			||||||
 | 
						struct smscb_msg *msg = bts->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(bts->smscb_state.cur_msg);
 | 
				
			||||||
 | 
							bts->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 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, &bts->smscb_state.queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct smscb_msg *select_next_smscb(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct smscb_msg *msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (llist_empty(&bts->smscb_state.queue))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg = llist_entry(bts->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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						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 */
 | 
				
			||||||
 | 
							bts->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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -0,0 +1,829 @@
 | 
				
			|||||||
 | 
					/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/linuxlist.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/talloc.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsm_utils.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/abis_nm.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/statistics.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void gsm_abis_mo_reset(struct gsm_abis_mo *mo)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						mo->nm_state.operational = NM_OPSTATE_NULL;
 | 
				
			||||||
 | 
						mo->nm_state.availability = NM_AVSTATE_POWER_OFF;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts,
 | 
				
			||||||
 | 
								uint8_t obj_class, uint8_t p1, uint8_t p2, uint8_t p3)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						mo->bts = bts;
 | 
				
			||||||
 | 
						mo->obj_class = obj_class;
 | 
				
			||||||
 | 
						mo->obj_inst.bts_nr = p1;
 | 
				
			||||||
 | 
						mo->obj_inst.trx_nr = p2;
 | 
				
			||||||
 | 
						mo->obj_inst.ts_nr = p3;
 | 
				
			||||||
 | 
						gsm_abis_mo_reset(mo);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct value_string bts_attribute_names[] = {
 | 
				
			||||||
 | 
						OSMO_VALUE_STRING(BTS_TYPE_VARIANT),
 | 
				
			||||||
 | 
						OSMO_VALUE_STRING(BTS_SUB_MODEL),
 | 
				
			||||||
 | 
						OSMO_VALUE_STRING(TRX_PHY_VERSION),
 | 
				
			||||||
 | 
						{ 0, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum bts_attribute str2btsattr(const char *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_string_value(bts_attribute_names, s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *btsatttr2str(enum bts_attribute v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_value_string(bts_attribute_names, v);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct value_string osmo_bts_variant_names[_NUM_BTS_VARIANT + 1] = {
 | 
				
			||||||
 | 
						{ BTS_UNKNOWN,		"unknown" },
 | 
				
			||||||
 | 
						{ BTS_OSMO_LITECELL15,	"osmo-bts-lc15" },
 | 
				
			||||||
 | 
						{ BTS_OSMO_OCTPHY,	"osmo-bts-octphy" },
 | 
				
			||||||
 | 
						{ BTS_OSMO_SYSMO,	"osmo-bts-sysmo" },
 | 
				
			||||||
 | 
						{ BTS_OSMO_TRX,		"omso-bts-trx" },
 | 
				
			||||||
 | 
						{ BTS_OSMO_VIRTUAL,	"omso-bts-virtual" },
 | 
				
			||||||
 | 
						{ BTS_OSMO_OMLDUMMY,	"omso-bts-omldummy" },
 | 
				
			||||||
 | 
						{ 0, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gsm_bts_type_variant str2btsvariant(const char *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_string_value(osmo_bts_variant_names, arg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *btsvariant2str(enum gsm_bts_type_variant v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_value_string(osmo_bts_variant_names, v);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct value_string gsm_bts_features_descs[] = {
 | 
				
			||||||
 | 
						{ BTS_FEAT_HSCSD,		"HSCSD" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_GPRS,		"GPRS" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_EGPRS,		"EGPRS" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_ECSD,		"ECSD" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_HOPPING,		"Frequency Hopping" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_MULTI_TSC,		"Multi-TSC" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_OML_ALERTS,		"OML Alerts" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_AGCH_PCH_PROP,	"AGCH/PCH proportional allocation" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_CBCH,		"CBCH" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_SPEECH_F_V1,		"Fullrate speech V1" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_SPEECH_H_V1,		"Halfrate speech V1" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_SPEECH_F_EFR,	"Fullrate speech EFR" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_SPEECH_F_AMR,	"Fullrate speech AMR" },
 | 
				
			||||||
 | 
						{ BTS_FEAT_SPEECH_H_AMR,	"Halfrate speech AMR" },
 | 
				
			||||||
 | 
						{ 0, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct value_string gsm_chreq_descs[] = {
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_EMERG,	"emergency call" },
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_PAG,		"answer to paging" },
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_CALL,	"call re-establishment" },
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_LOCATION_UPD,"Location updating" },
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_PDCH,	"one phase packet access" },
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_OTHER,	"other" },
 | 
				
			||||||
 | 
						{ 0,				NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct value_string gsm_pchant_names[13] = {
 | 
				
			||||||
 | 
						{ GSM_PCHAN_NONE,	"NONE" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_CCCH,	"CCCH" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_CCCH_SDCCH4,"CCCH+SDCCH4" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_TCH_F,	"TCH/F" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_TCH_H,	"TCH/H" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_SDCCH8_SACCH8C, "SDCCH8" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_PDCH,	"PDCH" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_TCH_F_PDCH,	"TCH/F_PDCH" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_UNKNOWN,	"UNKNOWN" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_CCCH_SDCCH4_CBCH, "CCCH+SDCCH4+CBCH" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_SDCCH8_SACCH8C_CBCH, "SDCCH8+CBCH" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_TCH_F_TCH_H_PDCH, "TCH/F_TCH/H_PDCH" },
 | 
				
			||||||
 | 
						{ 0,			NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct value_string gsm_pchant_descs[13] = {
 | 
				
			||||||
 | 
						{ GSM_PCHAN_NONE,	"Physical Channel not configured" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_CCCH,	"FCCH + SCH + BCCH + CCCH (Comb. IV)" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_CCCH_SDCCH4,
 | 
				
			||||||
 | 
							"FCCH + SCH + BCCH + CCCH + 4 SDCCH + 2 SACCH (Comb. V)" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_TCH_F,	"TCH/F + FACCH/F + SACCH (Comb. I)" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_TCH_H,	"2 TCH/H + 2 FACCH/H + 2 SACCH (Comb. II)" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_SDCCH8_SACCH8C, "8 SDCCH + 4 SACCH (Comb. VII)" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_PDCH,	"Packet Data Channel for GPRS/EDGE" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_TCH_F_PDCH,	"Dynamic TCH/F or GPRS PDCH" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_UNKNOWN,	"Unknown / Unsupported channel combination" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_CCCH_SDCCH4_CBCH, "FCCH + SCH + BCCH + CCCH + CBCH + 3 SDCCH + 2 SACCH (Comb. V)" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_SDCCH8_SACCH8C_CBCH, "7 SDCCH + 4 SACCH + CBCH (Comb. VII)" },
 | 
				
			||||||
 | 
						{ GSM_PCHAN_TCH_F_TCH_H_PDCH, "Dynamic TCH/F or TCH/H or GPRS PDCH" },
 | 
				
			||||||
 | 
						{ 0,			NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *gsm_pchan_name(enum gsm_phys_chan_config c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_value_string(gsm_pchant_names, c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gsm_phys_chan_config gsm_pchan_parse(const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_string_value(gsm_pchant_names, name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* TODO: move to libosmocore, next to gsm_chan_t_names? */
 | 
				
			||||||
 | 
					const char *gsm_lchant_name(enum gsm_chan_t c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_value_string(gsm_chan_t_names, c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct value_string lchan_s_names[] = {
 | 
				
			||||||
 | 
						{ LCHAN_S_NONE,		"NONE" },
 | 
				
			||||||
 | 
						{ LCHAN_S_ACT_REQ,	"ACTIVATION REQUESTED" },
 | 
				
			||||||
 | 
						{ LCHAN_S_ACTIVE,	"ACTIVE" },
 | 
				
			||||||
 | 
						{ LCHAN_S_INACTIVE,	"INACTIVE" },
 | 
				
			||||||
 | 
						{ LCHAN_S_REL_REQ,	"RELEASE REQUESTED" },
 | 
				
			||||||
 | 
						{ LCHAN_S_REL_ERR,	"RELEASE DUE ERROR" },
 | 
				
			||||||
 | 
						{ LCHAN_S_BROKEN,	"BROKEN UNUSABLE" },
 | 
				
			||||||
 | 
						{ 0,			NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *gsm_lchans_name(enum gsm_lchan_state s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_value_string(lchan_s_names, s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct value_string chreq_names[] = {
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_EMERG,	"EMERGENCY" },
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_PAG,		"PAGING" },
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_CALL,	"CALL" },
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_LOCATION_UPD,"LOCATION_UPDATE" },
 | 
				
			||||||
 | 
						{ GSM_CHREQ_REASON_OTHER,	"OTHER" },
 | 
				
			||||||
 | 
						{ 0,				NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *gsm_chreq_name(enum gsm_chreq_reason_t c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_value_string(chreq_names, c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts *bts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (num >= net->num_bts)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry(bts, &net->bts_list, list) {
 | 
				
			||||||
 | 
							if (bts->nr == num)
 | 
				
			||||||
 | 
								return bts;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
 | 
				
			||||||
 | 
						int k;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!trx)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						trx->bts = bts;
 | 
				
			||||||
 | 
						trx->nr = bts->num_trx++;
 | 
				
			||||||
 | 
						trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gsm_mo_init(&trx->mo, bts, NM_OC_RADIO_CARRIER,
 | 
				
			||||||
 | 
							    bts->nr, trx->nr, 0xff);
 | 
				
			||||||
 | 
						gsm_mo_init(&trx->bb_transc.mo, bts, NM_OC_BASEB_TRANSC,
 | 
				
			||||||
 | 
							    bts->nr, trx->nr, 0xff);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (k = 0; k < TRX_NR_TS; k++) {
 | 
				
			||||||
 | 
							struct gsm_bts_trx_ts *ts = &trx->ts[k];
 | 
				
			||||||
 | 
							int l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ts->trx = trx;
 | 
				
			||||||
 | 
							ts->nr = k;
 | 
				
			||||||
 | 
							ts->pchan = GSM_PCHAN_NONE;
 | 
				
			||||||
 | 
							ts->dyn.pchan_is = GSM_PCHAN_NONE;
 | 
				
			||||||
 | 
							ts->dyn.pchan_want = GSM_PCHAN_NONE;
 | 
				
			||||||
 | 
							ts->tsc = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							gsm_mo_init(&ts->mo, bts, NM_OC_CHANNEL,
 | 
				
			||||||
 | 
								    bts->nr, trx->nr, ts->nr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data);
 | 
				
			||||||
 | 
							ts->hopping.arfcns.data = ts->hopping.arfcns_data;
 | 
				
			||||||
 | 
							ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data);
 | 
				
			||||||
 | 
							ts->hopping.ma.data = ts->hopping.ma_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (l = 0; l < TS_MAX_LCHAN; l++) {
 | 
				
			||||||
 | 
								struct gsm_lchan *lchan;
 | 
				
			||||||
 | 
								char *name;
 | 
				
			||||||
 | 
								lchan = &ts->lchan[l];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								lchan->ts = ts;
 | 
				
			||||||
 | 
								lchan->nr = l;
 | 
				
			||||||
 | 
								lchan->type = GSM_LCHAN_NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								name = gsm_lchan_name_compute(lchan);
 | 
				
			||||||
 | 
								lchan->name = talloc_strdup(trx, name);
 | 
				
			||||||
 | 
								INIT_LLIST_HEAD(&lchan->sapi_cmds);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (trx->nr != 0)
 | 
				
			||||||
 | 
							trx->nominal_power = bts->c0->nominal_power;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_add_tail(&trx->list, &bts->trx_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return trx;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 };
 | 
				
			||||||
 | 
					static const uint8_t bts_cell_timer_default[] =
 | 
				
			||||||
 | 
									{ 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 };
 | 
				
			||||||
 | 
					static const struct gprs_rlc_cfg rlc_cfg_default = {
 | 
				
			||||||
 | 
						.parameter = {
 | 
				
			||||||
 | 
							[RLC_T3142] = 20,
 | 
				
			||||||
 | 
							[RLC_T3169] = 5,
 | 
				
			||||||
 | 
							[RLC_T3191] = 5,
 | 
				
			||||||
 | 
							[RLC_T3193] = 160, /* 10ms */
 | 
				
			||||||
 | 
							[RLC_T3195] = 5,
 | 
				
			||||||
 | 
							[RLC_N3101] = 10,
 | 
				
			||||||
 | 
							[RLC_N3103] = 4,
 | 
				
			||||||
 | 
							[RLC_N3105] = 8,
 | 
				
			||||||
 | 
							[CV_COUNTDOWN] = 15,
 | 
				
			||||||
 | 
							[T_DL_TBF_EXT] = 250 * 10, /* ms */
 | 
				
			||||||
 | 
							[T_UL_TBF_EXT] = 250 * 10, /* ms */
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						.paging = {
 | 
				
			||||||
 | 
							.repeat_time = 5 * 50, /* ms */
 | 
				
			||||||
 | 
							.repeat_count = 3,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						.cs_mask = 0x1fff,
 | 
				
			||||||
 | 
						.initial_cs = 2,
 | 
				
			||||||
 | 
						.initial_mcs = 6,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_bts *gsm_bts_alloc(void *ctx, uint8_t bts_num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts *bts = talloc_zero(ctx, struct gsm_bts);
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!bts)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bts->nr = bts_num;
 | 
				
			||||||
 | 
						bts->num_trx = 0;
 | 
				
			||||||
 | 
						INIT_LLIST_HEAD(&bts->trx_list);
 | 
				
			||||||
 | 
						bts->ms_max_power = 15;	/* dBm */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gsm_mo_init(&bts->mo, bts, NM_OC_BTS,
 | 
				
			||||||
 | 
								bts->nr, 0xff, 0xff);
 | 
				
			||||||
 | 
						gsm_mo_init(&bts->site_mgr.mo, bts, NM_OC_SITE_MANAGER,
 | 
				
			||||||
 | 
								0xff, 0xff, 0xff);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
 | 
				
			||||||
 | 
							bts->gprs.nsvc[i].bts = bts;
 | 
				
			||||||
 | 
							bts->gprs.nsvc[i].id = i;
 | 
				
			||||||
 | 
							gsm_mo_init(&bts->gprs.nsvc[i].mo, bts, NM_OC_GPRS_NSVC,
 | 
				
			||||||
 | 
									bts->nr, i, 0xff);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						memcpy(&bts->gprs.nse.timer, bts_nse_timer_default,
 | 
				
			||||||
 | 
							sizeof(bts->gprs.nse.timer));
 | 
				
			||||||
 | 
						gsm_mo_init(&bts->gprs.nse.mo, bts, NM_OC_GPRS_NSE,
 | 
				
			||||||
 | 
								bts->nr, 0xff, 0xff);
 | 
				
			||||||
 | 
						memcpy(&bts->gprs.cell.timer, bts_cell_timer_default,
 | 
				
			||||||
 | 
							sizeof(bts->gprs.cell.timer));
 | 
				
			||||||
 | 
						gsm_mo_init(&bts->gprs.cell.mo, bts, NM_OC_GPRS_CELL,
 | 
				
			||||||
 | 
								bts->nr, 0xff, 0xff);
 | 
				
			||||||
 | 
						memcpy(&bts->gprs.cell.rlc_cfg, &rlc_cfg_default,
 | 
				
			||||||
 | 
							sizeof(bts->gprs.cell.rlc_cfg));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* create our primary TRX */
 | 
				
			||||||
 | 
						bts->c0 = gsm_bts_trx_alloc(bts);
 | 
				
			||||||
 | 
						if (!bts->c0) {
 | 
				
			||||||
 | 
							talloc_free(bts);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bts->rach_b_thresh = -1;
 | 
				
			||||||
 | 
						bts->rach_ldavg_slots = -1;
 | 
				
			||||||
 | 
						bts->features.data = &bts->_features_data[0];
 | 
				
			||||||
 | 
						bts->features.data_len = sizeof(bts->_features_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* si handling */
 | 
				
			||||||
 | 
						bts->bcch_change_mark = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return bts;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* reset the state of all MO in the BTS */
 | 
				
			||||||
 | 
					void gsm_bts_mo_reset(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx;
 | 
				
			||||||
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gsm_abis_mo_reset(&bts->mo);
 | 
				
			||||||
 | 
						gsm_abis_mo_reset(&bts->site_mgr.mo);
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++)
 | 
				
			||||||
 | 
							gsm_abis_mo_reset(&bts->gprs.nsvc[i].mo);
 | 
				
			||||||
 | 
						gsm_abis_mo_reset(&bts->gprs.nse.mo);
 | 
				
			||||||
 | 
						gsm_abis_mo_reset(&bts->gprs.cell.mo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry(trx, &bts->trx_list, list) {
 | 
				
			||||||
 | 
							gsm_abis_mo_reset(&trx->mo);
 | 
				
			||||||
 | 
							gsm_abis_mo_reset(&trx->bb_transc.mo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
 | 
				
			||||||
 | 
								struct gsm_bts_trx_ts *ts = &trx->ts[i];
 | 
				
			||||||
 | 
								gsm_abis_mo_reset(&ts->mo);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (num >= bts->num_trx)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry(trx, &bts->trx_list, list) {
 | 
				
			||||||
 | 
							if (trx->nr == num)
 | 
				
			||||||
 | 
								return trx;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char ts2str[255];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *gsm_trx_name(const struct gsm_bts_trx *trx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!trx)
 | 
				
			||||||
 | 
							snprintf(ts2str, sizeof(ts2str), "(trx=NULL)");
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
 | 
				
			||||||
 | 
								 trx->bts->nr, trx->nr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ts2str;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *gsm_ts_name(const struct gsm_bts_trx_ts *ts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",
 | 
				
			||||||
 | 
							 ts->trx->bts->nr, ts->trx->nr, ts->nr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ts2str;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Log timeslot number with full pchan information */
 | 
				
			||||||
 | 
					char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (ts->pchan) {
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_F_TCH_H_PDCH:
 | 
				
			||||||
 | 
							if (ts->dyn.pchan_is == ts->dyn.pchan_want)
 | 
				
			||||||
 | 
								snprintf(ts2str, sizeof(ts2str),
 | 
				
			||||||
 | 
									 "(bts=%d,trx=%d,ts=%d,pchan=%s as %s)",
 | 
				
			||||||
 | 
									 ts->trx->bts->nr, ts->trx->nr, ts->nr,
 | 
				
			||||||
 | 
									 gsm_pchan_name(ts->pchan),
 | 
				
			||||||
 | 
									 gsm_pchan_name(ts->dyn.pchan_is));
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								snprintf(ts2str, sizeof(ts2str),
 | 
				
			||||||
 | 
									 "(bts=%d,trx=%d,ts=%d,pchan=%s"
 | 
				
			||||||
 | 
									 " switching %s -> %s)",
 | 
				
			||||||
 | 
									 ts->trx->bts->nr, ts->trx->nr, ts->nr,
 | 
				
			||||||
 | 
									 gsm_pchan_name(ts->pchan),
 | 
				
			||||||
 | 
									 gsm_pchan_name(ts->dyn.pchan_is),
 | 
				
			||||||
 | 
									 gsm_pchan_name(ts->dyn.pchan_want));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_F_PDCH:
 | 
				
			||||||
 | 
							if ((ts->flags & TS_F_PDCH_PENDING_MASK) == 0)
 | 
				
			||||||
 | 
								snprintf(ts2str, sizeof(ts2str),
 | 
				
			||||||
 | 
									 "(bts=%d,trx=%d,ts=%d,pchan=%s as %s)",
 | 
				
			||||||
 | 
									 ts->trx->bts->nr, ts->trx->nr, ts->nr,
 | 
				
			||||||
 | 
									 gsm_pchan_name(ts->pchan),
 | 
				
			||||||
 | 
									 (ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
 | 
				
			||||||
 | 
												       : "TCH/F");
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								snprintf(ts2str, sizeof(ts2str),
 | 
				
			||||||
 | 
									 "(bts=%d,trx=%d,ts=%d,pchan=%s"
 | 
				
			||||||
 | 
									 " switching %s -> %s)",
 | 
				
			||||||
 | 
									 ts->trx->bts->nr, ts->trx->nr, ts->nr,
 | 
				
			||||||
 | 
									 gsm_pchan_name(ts->pchan),
 | 
				
			||||||
 | 
									 (ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
 | 
				
			||||||
 | 
												       : "TCH/F",
 | 
				
			||||||
 | 
									 (ts->flags & TS_F_PDCH_ACT_PENDING)? "PDCH"
 | 
				
			||||||
 | 
													    : "TCH/F");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,pchan=%s)",
 | 
				
			||||||
 | 
								 ts->trx->bts->nr, ts->trx->nr, ts->nr,
 | 
				
			||||||
 | 
								 gsm_pchan_name(ts->pchan));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ts2str;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *gsm_lchan_name_compute(const struct gsm_lchan *lchan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx_ts *ts = lchan->ts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,ss=%d)",
 | 
				
			||||||
 | 
							 ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ts2str;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* obtain the MO structure for a given object instance */
 | 
				
			||||||
 | 
					struct gsm_abis_mo *
 | 
				
			||||||
 | 
					gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
 | 
				
			||||||
 | 
						    const struct abis_om_obj_inst *obj_inst)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx;
 | 
				
			||||||
 | 
						struct gsm_abis_mo *mo = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (obj_class) {
 | 
				
			||||||
 | 
						case NM_OC_BTS:
 | 
				
			||||||
 | 
							mo = &bts->mo;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_RADIO_CARRIER:
 | 
				
			||||||
 | 
							if (obj_inst->trx_nr >= bts->num_trx) {
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
 | 
				
			||||||
 | 
							mo = &trx->mo;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_BASEB_TRANSC:
 | 
				
			||||||
 | 
							if (obj_inst->trx_nr >= bts->num_trx) {
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
 | 
				
			||||||
 | 
							mo = &trx->bb_transc.mo;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_CHANNEL:
 | 
				
			||||||
 | 
							if (obj_inst->trx_nr >= bts->num_trx) {
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
 | 
				
			||||||
 | 
							if (obj_inst->ts_nr >= TRX_NR_TS)
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							mo = &trx->ts[obj_inst->ts_nr].mo;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_SITE_MANAGER:
 | 
				
			||||||
 | 
							mo = &bts->site_mgr.mo;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_GPRS_NSE:
 | 
				
			||||||
 | 
							mo = &bts->gprs.nse.mo;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_GPRS_CELL:
 | 
				
			||||||
 | 
							mo = &bts->gprs.cell.mo;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_GPRS_NSVC:
 | 
				
			||||||
 | 
							if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc))
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							mo = &bts->gprs.nsvc[obj_inst->trx_nr].mo;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return mo;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* obtain the gsm_nm_state data structure for a given object instance */
 | 
				
			||||||
 | 
					struct gsm_nm_state *
 | 
				
			||||||
 | 
					gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
 | 
				
			||||||
 | 
							 const struct abis_om_obj_inst *obj_inst)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_abis_mo *mo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mo = gsm_objclass2mo(bts, obj_class, obj_inst);
 | 
				
			||||||
 | 
						if (!mo)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &mo->nm_state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* obtain the in-memory data structure of a given object instance */
 | 
				
			||||||
 | 
					void *
 | 
				
			||||||
 | 
					gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
 | 
				
			||||||
 | 
						     const struct abis_om_obj_inst *obj_inst)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx;
 | 
				
			||||||
 | 
						void *obj = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (obj_class) {
 | 
				
			||||||
 | 
						case NM_OC_BTS:
 | 
				
			||||||
 | 
							obj = bts;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_RADIO_CARRIER:
 | 
				
			||||||
 | 
							if (obj_inst->trx_nr >= bts->num_trx) {
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
 | 
				
			||||||
 | 
							obj = trx;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_BASEB_TRANSC:
 | 
				
			||||||
 | 
							if (obj_inst->trx_nr >= bts->num_trx) {
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
 | 
				
			||||||
 | 
							obj = &trx->bb_transc;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_CHANNEL:
 | 
				
			||||||
 | 
							if (obj_inst->trx_nr >= bts->num_trx) {
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
 | 
				
			||||||
 | 
							if (obj_inst->ts_nr >= TRX_NR_TS)
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							obj = &trx->ts[obj_inst->ts_nr];
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_SITE_MANAGER:
 | 
				
			||||||
 | 
							obj = &bts->site_mgr;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_GPRS_NSE:
 | 
				
			||||||
 | 
							obj = &bts->gprs.nse;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_GPRS_CELL:
 | 
				
			||||||
 | 
							obj = &bts->gprs.cell;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NM_OC_GPRS_NSVC:
 | 
				
			||||||
 | 
							if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc))
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							obj = &bts->gprs.nsvc[obj_inst->trx_nr];
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return obj;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* See Table 10.5.25 of GSM04.08 */
 | 
				
			||||||
 | 
					uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
 | 
				
			||||||
 | 
								  uint8_t ts_nr, uint8_t lchan_nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t cbits, chan_nr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH);
 | 
				
			||||||
 | 
						OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (pchan) {
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_F:
 | 
				
			||||||
 | 
							OSMO_ASSERT(lchan_nr == 0);
 | 
				
			||||||
 | 
							cbits = 0x01;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_PCHAN_PDCH:
 | 
				
			||||||
 | 
							OSMO_ASSERT(lchan_nr == 0);
 | 
				
			||||||
 | 
							cbits = RSL_CHAN_OSMO_PDCH >> 3;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_H:
 | 
				
			||||||
 | 
							OSMO_ASSERT(lchan_nr < 2);
 | 
				
			||||||
 | 
							cbits = 0x02;
 | 
				
			||||||
 | 
							cbits += lchan_nr;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_PCHAN_CCCH_SDCCH4:
 | 
				
			||||||
 | 
						case GSM_PCHAN_CCCH_SDCCH4_CBCH:
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * As a special hack for BCCH, lchan_nr == 4 may be passed
 | 
				
			||||||
 | 
							 * here. This should never be sent in an RSL message.
 | 
				
			||||||
 | 
							 * See osmo-bts-xxx/oml.c:opstart_compl().
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (lchan_nr == CCCH_LCHAN)
 | 
				
			||||||
 | 
								chan_nr = 0;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								OSMO_ASSERT(lchan_nr < 4);
 | 
				
			||||||
 | 
							cbits = 0x04;
 | 
				
			||||||
 | 
							cbits += lchan_nr;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_PCHAN_SDCCH8_SACCH8C:
 | 
				
			||||||
 | 
						case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
 | 
				
			||||||
 | 
							OSMO_ASSERT(lchan_nr < 8);
 | 
				
			||||||
 | 
							cbits = 0x08;
 | 
				
			||||||
 | 
							cbits += lchan_nr;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_PCHAN_CCCH:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							/* OSMO_ASSERT(lchan_nr == 0);
 | 
				
			||||||
 | 
							 * FIXME: On octphy and litecell, we hit above assertion (see
 | 
				
			||||||
 | 
							 * Max's comment at https://gerrit.osmocom.org/589 ); disabled
 | 
				
			||||||
 | 
							 * for BTS until this is clarified; remove the #ifdef when it
 | 
				
			||||||
 | 
							 * is fixed. Tracked in OS#2906.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
					#pragma message "fix caller that passes lchan_nr != 0"
 | 
				
			||||||
 | 
							cbits = 0x10;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chan_nr = (cbits << 3) | (ts_nr & 0x7);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return chan_nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (lchan->ts->pchan) {
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_F_TCH_H_PDCH:
 | 
				
			||||||
 | 
							/* Return chan_nr reflecting the current TS pchan, either a standard TCH kind, or the
 | 
				
			||||||
 | 
							 * nonstandard value reflecting PDCH for Osmocom style dyn TS. */
 | 
				
			||||||
 | 
							return gsm_lchan_as_pchan2chan_nr(lchan,
 | 
				
			||||||
 | 
											  lchan->ts->dyn.pchan_is);
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_F_PDCH:
 | 
				
			||||||
 | 
							/* For ip.access style dyn TS, we always want to use the chan_nr as if it was TCH/F.
 | 
				
			||||||
 | 
							 * We're using custom PDCH ACT and DEACT messages that use the usual chan_nr values. */
 | 
				
			||||||
 | 
							return gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_TCH_F);
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return gsm_pchan2chan_nr(lchan->ts->pchan, lchan->ts->nr, lchan->nr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
 | 
				
			||||||
 | 
									   enum gsm_phys_chan_config as_pchan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
 | 
				
			||||||
 | 
						    && as_pchan == GSM_PCHAN_PDCH)
 | 
				
			||||||
 | 
							return RSL_CHAN_OSMO_PDCH | (lchan->ts->nr & ~RSL_CHAN_NR_MASK);
 | 
				
			||||||
 | 
						return gsm_pchan2chan_nr(as_pchan, lchan->ts->nr, lchan->nr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* return the gsm_lchan for the CBCH (if it exists at all) */
 | 
				
			||||||
 | 
					struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_lchan *lchan = NULL;
 | 
				
			||||||
 | 
						struct gsm_bts_trx *trx = bts->c0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (trx->ts[0].pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH)
 | 
				
			||||||
 | 
							lchan = &trx->ts[0].lchan[2];
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							int i;
 | 
				
			||||||
 | 
							for (i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
								if (trx->ts[i].pchan == GSM_PCHAN_SDCCH8_SACCH8C_CBCH) {
 | 
				
			||||||
 | 
									lchan = &trx->ts[i].lchan[2];
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return lchan;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* determine logical channel based on TRX and channel number IE */
 | 
				
			||||||
 | 
					struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
 | 
				
			||||||
 | 
									   int *rc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t ts_nr = chan_nr & 0x07;
 | 
				
			||||||
 | 
						uint8_t cbits = chan_nr >> 3;
 | 
				
			||||||
 | 
						uint8_t lch_idx;
 | 
				
			||||||
 | 
						struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
 | 
				
			||||||
 | 
						bool ok = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rc)
 | 
				
			||||||
 | 
							*rc = -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cbits == 0x01) {
 | 
				
			||||||
 | 
							lch_idx = 0;	/* TCH/F */	
 | 
				
			||||||
 | 
							if (ts->pchan != GSM_PCHAN_TCH_F &&
 | 
				
			||||||
 | 
							    ts->pchan != GSM_PCHAN_PDCH &&
 | 
				
			||||||
 | 
							    ts->pchan != GSM_PCHAN_TCH_F_PDCH &&
 | 
				
			||||||
 | 
							    ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH)
 | 
				
			||||||
 | 
								ok = false;
 | 
				
			||||||
 | 
						} else if ((cbits & 0x1e) == 0x02) {
 | 
				
			||||||
 | 
							lch_idx = cbits & 0x1;	/* TCH/H */
 | 
				
			||||||
 | 
							if (ts->pchan != GSM_PCHAN_TCH_H &&
 | 
				
			||||||
 | 
							    ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH)
 | 
				
			||||||
 | 
								ok = false;
 | 
				
			||||||
 | 
						} else if ((cbits & 0x1c) == 0x04) {
 | 
				
			||||||
 | 
							lch_idx = cbits & 0x3;	/* SDCCH/4 */
 | 
				
			||||||
 | 
							if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4 &&
 | 
				
			||||||
 | 
							    ts->pchan != GSM_PCHAN_CCCH_SDCCH4_CBCH)
 | 
				
			||||||
 | 
								ok = false;
 | 
				
			||||||
 | 
						} else if ((cbits & 0x18) == 0x08) {
 | 
				
			||||||
 | 
							lch_idx = cbits & 0x7;	/* SDCCH/8 */
 | 
				
			||||||
 | 
							if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C &&
 | 
				
			||||||
 | 
							    ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C_CBCH)
 | 
				
			||||||
 | 
								ok = false;
 | 
				
			||||||
 | 
						} else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
 | 
				
			||||||
 | 
							lch_idx = 0;
 | 
				
			||||||
 | 
							if (ts->pchan != GSM_PCHAN_CCCH &&
 | 
				
			||||||
 | 
							    ts->pchan != GSM_PCHAN_CCCH_SDCCH4 &&
 | 
				
			||||||
 | 
							    ts->pchan != GSM_PCHAN_CCCH_SDCCH4_CBCH)
 | 
				
			||||||
 | 
								ok = false;
 | 
				
			||||||
 | 
							/* FIXME: we should not return first sdcch4 !!! */
 | 
				
			||||||
 | 
						} else if ((chan_nr & RSL_CHAN_NR_MASK) == RSL_CHAN_OSMO_PDCH) {
 | 
				
			||||||
 | 
							lch_idx = 0;
 | 
				
			||||||
 | 
							if (ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH)
 | 
				
			||||||
 | 
								ok = false;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rc && ok)
 | 
				
			||||||
 | 
							*rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &ts->lchan[lch_idx];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint8_t subslots_per_pchan[] = {
 | 
				
			||||||
 | 
						[GSM_PCHAN_NONE] = 0,
 | 
				
			||||||
 | 
						[GSM_PCHAN_CCCH] = 0,
 | 
				
			||||||
 | 
						[GSM_PCHAN_PDCH] = 0,
 | 
				
			||||||
 | 
						[GSM_PCHAN_CCCH_SDCCH4] = 4,
 | 
				
			||||||
 | 
						[GSM_PCHAN_TCH_F] = 1,
 | 
				
			||||||
 | 
						[GSM_PCHAN_TCH_H] = 2,
 | 
				
			||||||
 | 
						[GSM_PCHAN_SDCCH8_SACCH8C] = 8,
 | 
				
			||||||
 | 
						[GSM_PCHAN_CCCH_SDCCH4_CBCH] = 4,
 | 
				
			||||||
 | 
						[GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = 8,
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * GSM_PCHAN_TCH_F_PDCH and GSM_PCHAN_TCH_F_TCH_H_PDCH should not be
 | 
				
			||||||
 | 
						 * part of this, those TS are handled according to their dynamic state.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Return the actual pchan type, also heeding dynamic TS. */
 | 
				
			||||||
 | 
					enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (ts->pchan) {
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_F_TCH_H_PDCH:
 | 
				
			||||||
 | 
							return ts->dyn.pchan_is;
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_F_PDCH:
 | 
				
			||||||
 | 
							if (ts->flags & TS_F_PDCH_ACTIVE)
 | 
				
			||||||
 | 
								return GSM_PCHAN_PDCH;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								return GSM_PCHAN_TCH_F;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return ts->pchan;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! According to ts->pchan and possibly ts->dyn_pchan, return the number of
 | 
				
			||||||
 | 
					 * logical channels available in the timeslot. */
 | 
				
			||||||
 | 
					uint8_t ts_subslots(struct gsm_bts_trx_ts *ts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return subslots_per_pchan[ts_pchan(ts)];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool pchan_is_tch(enum gsm_phys_chan_config pchan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (pchan) {
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_F:
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_H:
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ts_is_tch(struct gsm_bts_trx_ts *ts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return pchan_is_tch(ts_pchan(ts));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *gsm_trx_unit_id(struct gsm_bts_trx *trx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static char buf[23];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snprintf(buf, sizeof(buf), "%u/%u/%u", trx->bts->ip_access.site_id,
 | 
				
			||||||
 | 
							trx->bts->ip_access.bts_id, trx->nr);
 | 
				
			||||||
 | 
						return buf;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct value_string lchan_ciph_state_names[] = {
 | 
				
			||||||
 | 
						{ LCHAN_CIPH_NONE,	"NONE" },
 | 
				
			||||||
 | 
						{ LCHAN_CIPH_RX_REQ,	"RX_REQ" },
 | 
				
			||||||
 | 
						{ LCHAN_CIPH_RX_CONF,	"RX_CONF" },
 | 
				
			||||||
 | 
						{ LCHAN_CIPH_RXTX_REQ,	"RXTX_REQ" },
 | 
				
			||||||
 | 
						{ LCHAN_CIPH_RX_CONF_TX_REQ,	"RX_CONF_TX_REQ" },
 | 
				
			||||||
 | 
						{ LCHAN_CIPH_RXTX_CONF,	"RXTX_CONF" },
 | 
				
			||||||
 | 
						{ 0, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -0,0 +1,164 @@
 | 
				
			|||||||
 | 
					/* Paging message encoding + queue management */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2012-2013 by Harald Welte <laforge@gnumonks.org>
 | 
				
			||||||
 | 
					 *                  Andreas Eversberg <jolly@eversberg.eu>
 | 
				
			||||||
 | 
					 * (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 <stdlib.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_04_08.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/rsl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/bts.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/bts_model.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/rsl.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/logging.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/handover.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/l1sap.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Transmit a handover related PHYS INFO on given lchan */
 | 
				
			||||||
 | 
					static int ho_tx_phys_info(struct gsm_lchan *lchan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct msgb *msg = msgb_alloc_headroom(1024, 128, "PHYS INFO");
 | 
				
			||||||
 | 
						struct gsm48_hdr *gh;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DHO, LOGL_INFO,
 | 
				
			||||||
 | 
							"%s Sending PHYSICAL INFORMATION to MS.\n",
 | 
				
			||||||
 | 
							gsm_lchan_name(lchan));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Build RSL UNITDATA REQUEST message with 04.08 PHYS INFO */
 | 
				
			||||||
 | 
						msg->l3h = msg->data;
 | 
				
			||||||
 | 
						gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 | 
				
			||||||
 | 
						gh->proto_discr = GSM48_PDISC_RR;
 | 
				
			||||||
 | 
						gh->msg_type = GSM48_MT_RR_HANDO_INFO;
 | 
				
			||||||
 | 
						msgb_put_u8(msg, lchan->rqd_ta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rsl_rll_push_l3(msg, RSL_MT_UNIT_DATA_REQ, gsm_lchan2chan_nr(lchan),
 | 
				
			||||||
 | 
							0x00, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lapdm_rslms_recvmsg(msg, &lchan->lapdm_ch);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* timer call-back for T3105 (handover PHYS INFO re-transmit) */
 | 
				
			||||||
 | 
					static void ho_t3105_cb(void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_lchan *lchan = data;
 | 
				
			||||||
 | 
						struct gsm_bts *bts = lchan->ts->trx->bts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DHO, LOGL_INFO, "%s T3105 timeout (%d resends left)\n",
 | 
				
			||||||
 | 
							gsm_lchan_name(lchan), bts->ny1 - lchan->ho.phys_info_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (lchan->state != LCHAN_S_ACTIVE) {
 | 
				
			||||||
 | 
							LOGP(DHO, LOGL_NOTICE,
 | 
				
			||||||
 | 
								"%s is in not active. It is in state %s. Ignoring\n",
 | 
				
			||||||
 | 
								gsm_lchan_name(lchan), gsm_lchans_name(lchan->state));
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (lchan->ho.phys_info_count >= bts->ny1) {
 | 
				
			||||||
 | 
							/* HO Abort */
 | 
				
			||||||
 | 
							LOGP(DHO, LOGL_NOTICE, "%s NY1 reached, sending CONNection "
 | 
				
			||||||
 | 
								"FAILure to BSC.\n", gsm_lchan_name(lchan));
 | 
				
			||||||
 | 
							rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ho_tx_phys_info(lchan);
 | 
				
			||||||
 | 
						lchan->ho.phys_info_count++;
 | 
				
			||||||
 | 
						osmo_timer_schedule(&lchan->ho.t3105, 0, bts->t3105_ms * 1000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* received random access on dedicated channel */
 | 
				
			||||||
 | 
					void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts *bts = lchan->ts->trx->bts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Ignore invalid handover ref */
 | 
				
			||||||
 | 
						if (lchan->ho.ref != ra) {
 | 
				
			||||||
 | 
							LOGP(DHO, LOGL_INFO, "%s RACH on dedicated channel received, but "
 | 
				
			||||||
 | 
								"ra=0x%02x != expected ref=0x%02x. (This is no bug)\n",
 | 
				
			||||||
 | 
								gsm_lchan_name(lchan), ra, lchan->ho.ref);
 | 
				
			||||||
 | 
							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,
 | 
				
			||||||
 | 
						     "%s RACH on dedicated channel type %s received with TA=%u, ref=%u\n",
 | 
				
			||||||
 | 
						     gsm_lchan_name(lchan), gsm_lchant_name(lchan->type), acc_delay, ra);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Set timing advance */
 | 
				
			||||||
 | 
						lchan->rqd_ta = acc_delay;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Stop handover detection, wait for valid frame */
 | 
				
			||||||
 | 
						lchan->ho.active = HANDOVER_WAIT_FRAME;
 | 
				
			||||||
 | 
						if (l1sap_chan_modify(lchan->ts->trx, gsm_lchan2chan_nr(lchan)) != 0) {
 | 
				
			||||||
 | 
							LOGP(DHO, LOGL_ERROR,
 | 
				
			||||||
 | 
								"%s failed to modify channel after handover\n",
 | 
				
			||||||
 | 
								gsm_lchan_name(lchan));
 | 
				
			||||||
 | 
							rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Send HANDover DETect to BSC */
 | 
				
			||||||
 | 
						rsl_tx_hando_det(lchan, &lchan->rqd_ta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Send PHYS INFO */
 | 
				
			||||||
 | 
						lchan->ho.phys_info_count = 1;
 | 
				
			||||||
 | 
						ho_tx_phys_info(lchan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Start T3105 */
 | 
				
			||||||
 | 
						LOGP(DHO, LOGL_DEBUG,
 | 
				
			||||||
 | 
							"%s Starting T3105 with %u ms\n",
 | 
				
			||||||
 | 
							gsm_lchan_name(lchan), bts->t3105_ms);
 | 
				
			||||||
 | 
						lchan->ho.t3105.cb = ho_t3105_cb;
 | 
				
			||||||
 | 
						lchan->ho.t3105.data = lchan;
 | 
				
			||||||
 | 
						osmo_timer_schedule(&lchan->ho.t3105, 0, bts->t3105_ms * 1000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* received frist valid data frame on dedicated channel */
 | 
				
			||||||
 | 
					void handover_frame(struct gsm_lchan *lchan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						LOGP(DHO, LOGL_INFO,
 | 
				
			||||||
 | 
							"%s First valid frame detected\n", gsm_lchan_name(lchan));
 | 
				
			||||||
 | 
						handover_reset(lchan);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* release handover state */
 | 
				
			||||||
 | 
					void handover_reset(struct gsm_lchan *lchan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* Stop T3105 */
 | 
				
			||||||
 | 
						osmo_timer_del(&lchan->ho.t3105);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Handover process is done */
 | 
				
			||||||
 | 
						lchan->ho.active = HANDOVER_NONE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					/* OsmoBTS lchan interface */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2012 by Holger Hans Peter Freyther
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU 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 <osmocom/core/logging.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/logging.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					/* Support for generating RSL Load Indication */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2011 by Harald Welte <laforge@gnumonks.org>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU 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 <osmocom/core/timer.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/msgb.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/rsl.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/paging.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void reset_load_counters(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* re-set the counters */
 | 
				
			||||||
 | 
						bts->load.ccch.pch_used = bts->load.ccch.pch_total = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void load_timer_cb(void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_bts *bts = data;
 | 
				
			||||||
 | 
						unsigned int pch_percent, rach_percent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* compute percentages */
 | 
				
			||||||
 | 
						if (bts->load.ccch.pch_total == 0)
 | 
				
			||||||
 | 
							pch_percent = 0;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							pch_percent = (bts->load.ccch.pch_used * 100) /
 | 
				
			||||||
 | 
										bts->load.ccch.pch_total;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pch_percent >= bts->load.ccch.load_ind_thresh) {
 | 
				
			||||||
 | 
							/* send RSL load indication message to BSC */
 | 
				
			||||||
 | 
							uint16_t buffer_space = paging_buffer_space(bts->paging_state);
 | 
				
			||||||
 | 
							rsl_tx_ccch_load_ind_pch(bts, buffer_space);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* This is an extenstion of TS 08.58.  We don't only
 | 
				
			||||||
 | 
							 * send load indications if the load is above threshold,
 | 
				
			||||||
 | 
							 * but we also explicitly indicate that we are below
 | 
				
			||||||
 | 
							 * threshold by using the magic value 0xffff */
 | 
				
			||||||
 | 
							rsl_tx_ccch_load_ind_pch(bts, 0xffff);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bts->load.rach.total == 0)
 | 
				
			||||||
 | 
							rach_percent = 0;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							rach_percent = (bts->load.rach.busy * 100) /
 | 
				
			||||||
 | 
										bts->load.rach.total;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rach_percent >= bts->load.ccch.load_ind_thresh) {
 | 
				
			||||||
 | 
							/* send RSL load indication message to BSC */
 | 
				
			||||||
 | 
							rsl_tx_ccch_load_ind_rach(bts, bts->load.rach.total,
 | 
				
			||||||
 | 
										  bts->load.rach.busy,
 | 
				
			||||||
 | 
										  bts->load.rach.access);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reset_load_counters(bts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* re-schedule the timer */
 | 
				
			||||||
 | 
						osmo_timer_schedule(&bts->load.ccch.timer,
 | 
				
			||||||
 | 
								    bts->load.ccch.load_ind_period, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void load_timer_start(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!bts->load.ccch.timer.data) {
 | 
				
			||||||
 | 
							bts->load.ccch.timer.data = bts;
 | 
				
			||||||
 | 
							bts->load.ccch.timer.cb = load_timer_cb;
 | 
				
			||||||
 | 
							reset_load_counters(bts);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						osmo_timer_schedule(&bts->load.ccch.timer, bts->load.ccch.load_ind_period, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void load_timer_stop(struct gsm_bts *bts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						osmo_timer_del(&bts->load.ccch.timer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					/* libosmocore logging support */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
 | 
				
			||||||
 | 
					 * (C) 2011 by Harald Welte <laforge@gnumonks.org>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU 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/logging.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/application.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/bts.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/logging.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct log_info_cat bts_log_info_cat[] = {
 | 
				
			||||||
 | 
						[DRSL] = {
 | 
				
			||||||
 | 
							.name = "DRSL",
 | 
				
			||||||
 | 
							.description = "A-bis Radio Siganlling Link (RSL)",
 | 
				
			||||||
 | 
							.color = "\033[1;35m",
 | 
				
			||||||
 | 
							.enabled = 1, .loglevel = LOGL_INFO,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DOML] =	{
 | 
				
			||||||
 | 
							.name = "DOML",
 | 
				
			||||||
 | 
							.description = "A-bis Network Management / O&M (NM/OML)",
 | 
				
			||||||
 | 
							.color = "\033[1;36m",
 | 
				
			||||||
 | 
							.enabled = 1, .loglevel = LOGL_INFO,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DRLL] = {
 | 
				
			||||||
 | 
							.name = "DRLL",
 | 
				
			||||||
 | 
							.description = "A-bis Radio Link Layer (RLL)",
 | 
				
			||||||
 | 
							.color = "\033[1;31m",
 | 
				
			||||||
 | 
							.enabled = 1, .loglevel = LOGL_NOTICE,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DRR] = {
 | 
				
			||||||
 | 
							.name = "DRR",
 | 
				
			||||||
 | 
							.description = "Layer3 Radio Resource (RR)",
 | 
				
			||||||
 | 
							.color = "\033[1;34m",
 | 
				
			||||||
 | 
							.enabled = 1, .loglevel = LOGL_NOTICE,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DMEAS] = {
 | 
				
			||||||
 | 
							.name = "DMEAS",
 | 
				
			||||||
 | 
							.description = "Radio Measurement Processing",
 | 
				
			||||||
 | 
							.enabled = 1, .loglevel = LOGL_NOTICE,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DPAG]	= {
 | 
				
			||||||
 | 
							.name = "DPAG",
 | 
				
			||||||
 | 
							.description = "Paging Subsystem",
 | 
				
			||||||
 | 
							.color = "\033[1;38m",
 | 
				
			||||||
 | 
							.enabled = 1, .loglevel = LOGL_INFO,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DL1C] = {
 | 
				
			||||||
 | 
							.name = "DL1C",
 | 
				
			||||||
 | 
							.description = "Layer 1 Control (MPH)",
 | 
				
			||||||
 | 
							.loglevel = LOGL_INFO,
 | 
				
			||||||
 | 
							.enabled = 1,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DL1P] = {
 | 
				
			||||||
 | 
							.name = "DL1P",
 | 
				
			||||||
 | 
							.description = "Layer 1 Primitives (PH)",
 | 
				
			||||||
 | 
							.loglevel = LOGL_INFO,
 | 
				
			||||||
 | 
							.enabled = 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DDSP] = {
 | 
				
			||||||
 | 
							.name = "DDSP",
 | 
				
			||||||
 | 
							.description = "DSP Trace Messages",
 | 
				
			||||||
 | 
							.loglevel = LOGL_DEBUG,
 | 
				
			||||||
 | 
							.enabled = 1,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DABIS] = {
 | 
				
			||||||
 | 
							.name = "DABIS",
 | 
				
			||||||
 | 
							.description = "A-bis Intput Subsystem",
 | 
				
			||||||
 | 
							.enabled = 1, .loglevel = LOGL_NOTICE,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DRTP] = {
 | 
				
			||||||
 | 
							.name = "DRTP",
 | 
				
			||||||
 | 
							.description = "Realtime Transfer Protocol",
 | 
				
			||||||
 | 
							.loglevel = LOGL_NOTICE,
 | 
				
			||||||
 | 
							.enabled = 1,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DPCU] = {
 | 
				
			||||||
 | 
							.name = "DPCU",
 | 
				
			||||||
 | 
							.description = "PCU interface",
 | 
				
			||||||
 | 
							.loglevel = LOGL_NOTICE,
 | 
				
			||||||
 | 
							.enabled = 1,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DHO] = {
 | 
				
			||||||
 | 
							.name = "DHO",
 | 
				
			||||||
 | 
							.description = "Handover",
 | 
				
			||||||
 | 
							.color = "\033[0;37m",
 | 
				
			||||||
 | 
							.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
 | 
				
			||||||
 | 
						[DNS] = {
 | 
				
			||||||
 | 
							.name = "DNS",
 | 
				
			||||||
 | 
							.description = "GPRS Network Service (NS)",
 | 
				
			||||||
 | 
							.enabled = 1, .loglevel = LOGL_INFO,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DBSSGP] = {
 | 
				
			||||||
 | 
							.name = "DBSSGP",
 | 
				
			||||||
 | 
							.description = "GPRS BSS Gateway Protocol (BSSGP)",
 | 
				
			||||||
 | 
							.enabled = 1, .loglevel = LOGL_DEBUG,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[DLLC] = {
 | 
				
			||||||
 | 
							.name = "DLLC",
 | 
				
			||||||
 | 
							.description = "GPRS Logical Link Control Protocol (LLC)",
 | 
				
			||||||
 | 
							.enabled = 1, .loglevel = LOGL_DEBUG,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						[DSUM] = {
 | 
				
			||||||
 | 
							.name = "DSUM",
 | 
				
			||||||
 | 
							.description = "DSUM",
 | 
				
			||||||
 | 
							.loglevel = LOGL_NOTICE,
 | 
				
			||||||
 | 
							.enabled = 1,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct log_info bts_log_info = {
 | 
				
			||||||
 | 
						.cat = bts_log_info_cat,
 | 
				
			||||||
 | 
						.num_cat = ARRAY_SIZE(bts_log_info_cat),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -0,0 +1,368 @@
 | 
				
			|||||||
 | 
					/* 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_trx *trx;
 | 
				
			||||||
 | 
						struct e1inp_line *line;
 | 
				
			||||||
 | 
						int rc, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf("((*))\n  |\n / \\ OsmoBTS\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Track the use of talloc NULL memory contexts */
 | 
				
			||||||
 | 
						talloc_enable_null_tracking();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context");
 | 
				
			||||||
 | 
						msgb_talloc_ctx_init(tall_bts_ctx, 100*1024);
 | 
				
			||||||
 | 
						bts_vty_info.tall_ctx = tall_bts_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_init_logging2(tall_bts_ctx, &bts_log_info);
 | 
				
			||||||
 | 
						vty_init(&bts_vty_info);
 | 
				
			||||||
 | 
						ctrl_vty_init(tall_bts_ctx);
 | 
				
			||||||
 | 
						rate_ctr_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);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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(bts->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 (!bts->bsc_oml_host) {
 | 
				
			||||||
 | 
							fprintf(stderr, "Cannot start BTS without knowing BSC OML IP\n");
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						line = abis_open(bts, bts->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 to 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,418 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsm_utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmo-bts/gsm_data.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/logging.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/measurement.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/scheduler.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Tables as per TS 45.008 Section 8.3 */
 | 
				
			||||||
 | 
					static const uint8_t ts45008_83_tch_f[] = { 52, 53, 54, 55, 56, 57, 58, 59 };
 | 
				
			||||||
 | 
					static const uint8_t ts45008_83_tch_hs0[] = { 0, 2, 4, 6, 52, 54, 56, 58 };
 | 
				
			||||||
 | 
					static const uint8_t ts45008_83_tch_hs1[] = { 14, 16, 18, 29, 66, 68, 70, 72 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* find out if an array contains a given key as element */
 | 
				
			||||||
 | 
					#define ARRAY_CONTAINS(arr, val) array_contains(arr, ARRAY_SIZE(arr), val)
 | 
				
			||||||
 | 
					static bool array_contains(const uint8_t *arr, unsigned int len, uint8_t val) {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < len; i++) {
 | 
				
			||||||
 | 
							if (arr[i] == val)
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Decide if a given frame number is part of the "-SUB" measurements (true) or not (false) */
 | 
				
			||||||
 | 
					static bool ts45008_83_is_sub(struct gsm_lchan *lchan, uint32_t fn, bool is_amr_sid_update)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t fn104 = fn % 104;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* See TS 45.008 Sections 8.3 and 8.4 for a detailed descriptions of the rules
 | 
				
			||||||
 | 
						 * implemented here. We only implement the logic for Voice, not CSD */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (lchan->type) {
 | 
				
			||||||
 | 
						case GSM_LCHAN_TCH_F:
 | 
				
			||||||
 | 
							switch (lchan->tch_mode) {
 | 
				
			||||||
 | 
							case GSM48_CMODE_SIGN:
 | 
				
			||||||
 | 
							case GSM48_CMODE_SPEECH_V1:
 | 
				
			||||||
 | 
							case GSM48_CMODE_SPEECH_EFR:
 | 
				
			||||||
 | 
								if (trx_sched_is_sacch_fn(lchan->ts, fn, true))
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								if (ARRAY_CONTAINS(ts45008_83_tch_f, fn104))
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case GSM48_CMODE_SPEECH_AMR:
 | 
				
			||||||
 | 
								if (trx_sched_is_sacch_fn(lchan->ts, fn, true))
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								if (is_amr_sid_update)
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								LOGPFN(DMEAS, LOGL_ERROR, fn, "%s: Unsupported lchan->tch_mode %u\n",
 | 
				
			||||||
 | 
									gsm_lchan_name(lchan), lchan->tch_mode);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_LCHAN_TCH_H:
 | 
				
			||||||
 | 
							switch (lchan->tch_mode) {
 | 
				
			||||||
 | 
							case GSM48_CMODE_SPEECH_V1:
 | 
				
			||||||
 | 
								if (trx_sched_is_sacch_fn(lchan->ts, fn, true))
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								switch (lchan->nr) {
 | 
				
			||||||
 | 
								case 0:
 | 
				
			||||||
 | 
									if (ARRAY_CONTAINS(ts45008_83_tch_hs0, fn104))
 | 
				
			||||||
 | 
										return true;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case 1:
 | 
				
			||||||
 | 
									if (ARRAY_CONTAINS(ts45008_83_tch_hs1, fn104))
 | 
				
			||||||
 | 
										return true;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									OSMO_ASSERT(0);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case GSM48_CMODE_SPEECH_AMR:
 | 
				
			||||||
 | 
								if (trx_sched_is_sacch_fn(lchan->ts, fn, true))
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								if (is_amr_sid_update)
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case GSM48_CMODE_SIGN:
 | 
				
			||||||
 | 
								/* No DTX allowed; SUB=FULL, therefore measurements at all frame numbers are
 | 
				
			||||||
 | 
								 * SUB */
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								LOGPFN(DMEAS, LOGL_ERROR, fn, "%s: Unsupported lchan->tch_mode %u\n",
 | 
				
			||||||
 | 
									gsm_lchan_name(lchan), lchan->tch_mode);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_LCHAN_SDCCH:
 | 
				
			||||||
 | 
							/* No DTX allowed; SUB=FULL, therefore measurements at all frame numbers are SUB */
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Measurement reporting period and mapping of SACCH message block for TCHF
 | 
				
			||||||
 | 
					 * and TCHH chan As per in 3GPP TS 45.008, section 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[] = {
 | 
				
			||||||
 | 
						[0] =	90,
 | 
				
			||||||
 | 
						[1] =	103,
 | 
				
			||||||
 | 
						[2] =	12,
 | 
				
			||||||
 | 
						[3] =	25,
 | 
				
			||||||
 | 
						[4] =	38,
 | 
				
			||||||
 | 
						[5] =	51,
 | 
				
			||||||
 | 
						[6] =	64,
 | 
				
			||||||
 | 
						[7] =	77,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					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,
 | 
				
			||||||
 | 
						[1] =	103,
 | 
				
			||||||
 | 
						[2] =	25,
 | 
				
			||||||
 | 
						[3] =	25,
 | 
				
			||||||
 | 
						[4] =	51,
 | 
				
			||||||
 | 
						[5] =	51,
 | 
				
			||||||
 | 
						[6] =	77,
 | 
				
			||||||
 | 
						[7] =	77,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Measurement reporting period for SDCCH8 and SDCCH4 chan
 | 
				
			||||||
 | 
					 * As per in 3GPP TS 45.008, section 8.4.2.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Logical Chan		TDMA frame number
 | 
				
			||||||
 | 
					 *			(FN) modulo 102
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SDCCH/8		12 to 11
 | 
				
			||||||
 | 
					 * SDCCH/4		37 to 36
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* FN of the first burst whose block completes before reaching fn%102=11 */
 | 
				
			||||||
 | 
					static const uint8_t sdcch8_meas_rep_fn102[] = {
 | 
				
			||||||
 | 
						[0] = 66,	/* 15(SDCCH), 47(SACCH), 66(SDCCH) */
 | 
				
			||||||
 | 
						[1] = 70,	/* 19(SDCCH), 51(SACCH), 70(SDCCH) */
 | 
				
			||||||
 | 
						[2] = 74,	/* 23(SDCCH), 55(SACCH), 74(SDCCH) */
 | 
				
			||||||
 | 
						[3] = 78,	/* 27(SDCCH), 59(SACCH), 78(SDCCH) */
 | 
				
			||||||
 | 
						[4] = 98,	/* 31(SDCCH), 98(SACCH), 82(SDCCH) */
 | 
				
			||||||
 | 
						[5] = 0,	/* 35(SDCCH),  0(SACCH), 86(SDCCH) */
 | 
				
			||||||
 | 
						[6] = 4,	/* 39(SDCCH),  4(SACCH), 90(SDCCH) */
 | 
				
			||||||
 | 
						[7] = 8,	/* 43(SDCCH),  8(SACCH), 94(SDCCH) */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* FN of the first burst whose block completes before reaching fn%102=37 */
 | 
				
			||||||
 | 
					static const uint8_t sdcch4_meas_rep_fn102[] = {
 | 
				
			||||||
 | 
						[0] = 88,	/* 37(SDCCH), 57(SACCH), 88(SDCCH) */
 | 
				
			||||||
 | 
						[1] = 92,	/* 41(SDCCH), 61(SACCH), 92(SDCCH) */
 | 
				
			||||||
 | 
						[2] = 6,	/*  6(SACCH), 47(SDCCH), 98(SDCCH) */
 | 
				
			||||||
 | 
						[3] = 10	/* 10(SACCH),  0(SDCCH), 51(SDCCH) */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Note: The reporting of the measurement results is done via the SACCH channel.
 | 
				
			||||||
 | 
					 * The measurement interval is not aligned with the interval in which the
 | 
				
			||||||
 | 
					 * SACCH is transmitted. When we receive the measurement indication with the
 | 
				
			||||||
 | 
					 * SACCH block, the corresponding 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, section 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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
 | 
						enum gsm_phys_chan_config pchan = ts_pchan(lchan->ts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (lchan->ts->nr >= 8)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						if (pchan >= _GSM_PCHAN_MAX)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (pchan) {
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_F:
 | 
				
			||||||
 | 
							fn_mod = translate_tch_meas_rep_fn104(fn % 104);
 | 
				
			||||||
 | 
							if (tchf_meas_rep_fn104[lchan->ts->nr] == fn_mod)
 | 
				
			||||||
 | 
								rc = 1;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_PCHAN_TCH_H:
 | 
				
			||||||
 | 
							fn_mod = translate_tch_meas_rep_fn104(fn % 104);
 | 
				
			||||||
 | 
							if (lchan->nr == 0)
 | 
				
			||||||
 | 
								tbl = tchh0_meas_rep_fn104;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								tbl = tchh1_meas_rep_fn104;
 | 
				
			||||||
 | 
							if (tbl[lchan->ts->nr] == fn_mod)
 | 
				
			||||||
 | 
								rc = 1;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_PCHAN_SDCCH8_SACCH8C:
 | 
				
			||||||
 | 
						case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
 | 
				
			||||||
 | 
							fn_mod = fn % 102;
 | 
				
			||||||
 | 
							if (sdcch8_meas_rep_fn102[lchan->nr] == fn_mod)
 | 
				
			||||||
 | 
								rc = 1;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case GSM_PCHAN_CCCH_SDCCH4:
 | 
				
			||||||
 | 
						case GSM_PCHAN_CCCH_SDCCH4_CBCH:
 | 
				
			||||||
 | 
							fn_mod = fn % 102;
 | 
				
			||||||
 | 
							if (sdcch4_meas_rep_fn102[lchan->nr] == fn_mod)
 | 
				
			||||||
 | 
								rc = 1;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							rc = 0;
 | 
				
			||||||
 | 
							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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* receive a L1 uplink measurement from L1 */
 | 
				
			||||||
 | 
					int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm, uint32_t fn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (lchan->state != LCHAN_S_ACTIVE) {
 | 
				
			||||||
 | 
							LOGPFN(DMEAS, LOGL_NOTICE, fn,
 | 
				
			||||||
 | 
							     "%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)) {
 | 
				
			||||||
 | 
							LOGPFN(DMEAS, LOGL_NOTICE, fn,
 | 
				
			||||||
 | 
							     "%s no space for uplink measurement, num_ul_meas=%d\n",
 | 
				
			||||||
 | 
							     gsm_lchan_name(lchan), lchan->meas.num_ul_meas);
 | 
				
			||||||
 | 
							return -ENOSPC;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* We expect the lower layers to mark AMR SID_UPDATE frames already as such.
 | 
				
			||||||
 | 
						 * In this function, we only deal with the comon logic as per the TS 45.008 tables */
 | 
				
			||||||
 | 
						if (!ulm->is_sub)
 | 
				
			||||||
 | 
							ulm->is_sub = ts45008_83_is_sub(lchan, fn, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DEBUGPFN(DMEAS, fn, "%s adding measurement (is_sub=%u), num_ul_meas=%d\n",
 | 
				
			||||||
 | 
							gsm_lchan_name(lchan), ulm->is_sub, lchan->meas.num_ul_meas);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(&lchan->meas.uplink[lchan->meas.num_ul_meas++], ulm,
 | 
				
			||||||
 | 
							sizeof(*ulm));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* input: BER in steps of .01%, i.e. percent/100 */
 | 
				
			||||||
 | 
					static uint8_t ber10k_to_rxqual(uint32_t ber10k)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* 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)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						if (ber10k < 40)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						if (ber10k < 80)
 | 
				
			||||||
 | 
							return 2;
 | 
				
			||||||
 | 
						if (ber10k < 160)
 | 
				
			||||||
 | 
							return 3;
 | 
				
			||||||
 | 
						if (ber10k < 320)
 | 
				
			||||||
 | 
							return 4;
 | 
				
			||||||
 | 
						if (ber10k < 640)
 | 
				
			||||||
 | 
							return 5;
 | 
				
			||||||
 | 
						if (ber10k < 1280)
 | 
				
			||||||
 | 
							return 6;
 | 
				
			||||||
 | 
						return 7;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gsm_meas_rep_unidir *mru;
 | 
				
			||||||
 | 
						uint32_t ber_full_sum = 0;
 | 
				
			||||||
 | 
						uint32_t irssi_full_sum = 0;
 | 
				
			||||||
 | 
						uint32_t ber_sub_sum = 0;
 | 
				
			||||||
 | 
						uint32_t irssi_sub_sum = 0;
 | 
				
			||||||
 | 
						int32_t ta256b_sum = 0;
 | 
				
			||||||
 | 
						unsigned int num_meas_sub = 0;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* if measurement period is not complete, abort */
 | 
				
			||||||
 | 
						if (!is_meas_complete(lchan, fn))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* if there are no measurements, skip computation */
 | 
				
			||||||
 | 
						if (lchan->meas.num_ul_meas == 0)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* compute the actual measurements */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* step 1: add up */
 | 
				
			||||||
 | 
						for (i = 0; i < lchan->meas.num_ul_meas; i++) {
 | 
				
			||||||
 | 
							struct bts_ul_meas *m = &lchan->meas.uplink[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ber_full_sum += m->ber10k;
 | 
				
			||||||
 | 
							irssi_full_sum += m->inv_rssi;
 | 
				
			||||||
 | 
							ta256b_sum += m->ta_offs_256bits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (m->is_sub) {
 | 
				
			||||||
 | 
								num_meas_sub++;
 | 
				
			||||||
 | 
								ber_sub_sum += m->ber10k;
 | 
				
			||||||
 | 
								irssi_sub_sum += m->inv_rssi;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* step 2: divide */
 | 
				
			||||||
 | 
						ber_full_sum = ber_full_sum / lchan->meas.num_ul_meas;
 | 
				
			||||||
 | 
						irssi_full_sum = irssi_full_sum / lchan->meas.num_ul_meas;
 | 
				
			||||||
 | 
						ta256b_sum = ta256b_sum / lchan->meas.num_ul_meas;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (num_meas_sub) {
 | 
				
			||||||
 | 
							ber_sub_sum = ber_sub_sum / num_meas_sub;
 | 
				
			||||||
 | 
							irssi_sub_sum = irssi_sub_sum / num_meas_sub;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							LOGP(DMEAS, LOGL_ERROR, "%s No measurements for SUB!!!\n", gsm_lchan_name(lchan));
 | 
				
			||||||
 | 
							/* The only situation in which this can occur is if the related uplink burst/block was
 | 
				
			||||||
 | 
							 * missing, so let's set BER to 100% and level to lowest possible. */
 | 
				
			||||||
 | 
							ber_sub_sum = 10000; /* 100% */
 | 
				
			||||||
 | 
							irssi_sub_sum = 120; /* -120 dBm */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DMEAS, LOGL_INFO, "%s Computed TA256(% 4d) BER-FULL(%2u.%02u%%), RSSI-FULL(-%3udBm), "
 | 
				
			||||||
 | 
							"BER-SUB(%2u.%02u%%), RSSI-SUB(-%3udBm)\n", gsm_lchan_name(lchan),
 | 
				
			||||||
 | 
							ta256b_sum, ber_full_sum/100,
 | 
				
			||||||
 | 
							ber_full_sum%100, irssi_full_sum, ber_sub_sum/100, ber_sub_sum%100,
 | 
				
			||||||
 | 
							irssi_sub_sum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* store results */
 | 
				
			||||||
 | 
						mru = &lchan->meas.ul_res;
 | 
				
			||||||
 | 
						mru->full.rx_lev = dbm2rxlev((int)irssi_full_sum * -1);
 | 
				
			||||||
 | 
						mru->sub.rx_lev = dbm2rxlev((int)irssi_sub_sum * -1);
 | 
				
			||||||
 | 
						mru->full.rx_qual = ber10k_to_rxqual(ber_full_sum);
 | 
				
			||||||
 | 
						mru->sub.rx_qual = ber10k_to_rxqual(ber_sub_sum);
 | 
				
			||||||
 | 
						lchan->meas.ms_toa256 = ta256b_sum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DMEAS, LOGL_INFO, "%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.num_ul_meas = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* send a signal indicating computation is complete */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,603 @@
 | 
				
			|||||||
 | 
					/* (C) 2014 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/msg_utils.h>
 | 
				
			||||||
 | 
					#include <osmo-bts/logging.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/gsm_12_21.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/abis_nm.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/msgb.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/fsm.h>
 | 
				
			||||||
 | 
					#include <osmocom/trau/osmo_ortp.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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (omh->length != len) {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR, "Incorrect OM hdr length value %d %zu\n",
 | 
				
			||||||
 | 
							     omh->length, len);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (len < sizeof(struct abis_om_fom_hdr)) {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR, "FOM header insufficient space %zu %zu\n",
 | 
				
			||||||
 | 
							     len, sizeof(struct abis_om_fom_hdr));
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int check_manuf(struct msgb *msg, struct abis_om_hdr *omh, size_t msg_size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int type;
 | 
				
			||||||
 | 
						size_t size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (msg_size < 1) {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR, "No ManId Length Indicator %zu\n",
 | 
				
			||||||
 | 
							     msg_size);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (omh->data[0] >= msg_size - 1) {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR,
 | 
				
			||||||
 | 
							     "Insufficient message space for this ManId Length %d %zu\n",
 | 
				
			||||||
 | 
							     omh->data[0], msg_size - 1);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (omh->data[0] == sizeof(abis_nm_ipa_magic) &&
 | 
				
			||||||
 | 
							strncmp(abis_nm_ipa_magic, (const char *)omh->data + 1,
 | 
				
			||||||
 | 
								sizeof(abis_nm_ipa_magic)) == 0) {
 | 
				
			||||||
 | 
							type = OML_MSG_TYPE_IPA;
 | 
				
			||||||
 | 
							size = sizeof(abis_nm_ipa_magic) + 1;
 | 
				
			||||||
 | 
						} else if (omh->data[0] == sizeof(abis_nm_osmo_magic) &&
 | 
				
			||||||
 | 
							strncmp(abis_nm_osmo_magic, (const char *) omh->data + 1,
 | 
				
			||||||
 | 
								sizeof(abis_nm_osmo_magic)) == 0) {
 | 
				
			||||||
 | 
							type = OML_MSG_TYPE_OSMO;
 | 
				
			||||||
 | 
							size = sizeof(abis_nm_osmo_magic) + 1;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR, "Manuf Label Unknown\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* we have verified that the vendor string fits */
 | 
				
			||||||
 | 
						msg->l3h = omh->data + size;
 | 
				
			||||||
 | 
						if (check_fom(omh, msgb_l3len(msg)) != 0)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					 * case the l2h will be set to the beginning of the data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int msg_verify_ipa_structure(struct msgb *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipaccess_head *hh;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (msgb_l1len(msg) < sizeof(struct ipaccess_head)) {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR,
 | 
				
			||||||
 | 
								"Ipa header insufficient space %d %zu\n",
 | 
				
			||||||
 | 
								msgb_l1len(msg), sizeof(struct ipaccess_head));
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hh = (struct ipaccess_head *) msg->l1h;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ntohs(hh->len) != msgb_l1len(msg) - sizeof(struct ipaccess_head)) {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR,
 | 
				
			||||||
 | 
								"Incorrect ipa header msg size %d %zu\n",
 | 
				
			||||||
 | 
								ntohs(hh->len), msgb_l1len(msg) - sizeof(struct ipaccess_head));
 | 
				
			||||||
 | 
							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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief Verify the structure of the OML message and set l3h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function verifies that the data in \param in msg is a proper
 | 
				
			||||||
 | 
					 * OML message. This code assumes that msg->l2h points to the
 | 
				
			||||||
 | 
					 * beginning of the OML message. In the successful case the msg->l3h
 | 
				
			||||||
 | 
					 * will be set and will point to the FOM header. The value is undefined
 | 
				
			||||||
 | 
					 * in all other cases.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \param msg The message to analyze starting from msg->l2h.
 | 
				
			||||||
 | 
					 * \return In case the structure is correct a positive number will be
 | 
				
			||||||
 | 
					 * returned and msg->l3h will point to the FOM. The number is a
 | 
				
			||||||
 | 
					 * classification of the vendor type of the message.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int msg_verify_oml_structure(struct msgb *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct abis_om_hdr *omh;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (msgb_l2len(msg) < sizeof(*omh)) {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %zu\n",
 | 
				
			||||||
 | 
							     msgb_l2len(msg), sizeof(*omh));
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						omh = (struct abis_om_hdr *) msg->l2h;
 | 
				
			||||||
 | 
						if (omh->mdisc != ABIS_OM_MDISC_FOM &&
 | 
				
			||||||
 | 
						    omh->mdisc != ABIS_OM_MDISC_MANUF) {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x\n",
 | 
				
			||||||
 | 
							     omh->mdisc);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (omh->placement != ABIS_OM_PLACEMENT_ONLY) {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value %x %x\n",
 | 
				
			||||||
 | 
							     omh->placement, ABIS_OM_PLACEMENT_ONLY);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (omh->sequence != 0) {
 | 
				
			||||||
 | 
							LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value %d\n",
 | 
				
			||||||
 | 
							     omh->sequence);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (omh->mdisc == ABIS_OM_MDISC_MANUF)
 | 
				
			||||||
 | 
							return check_manuf(msg, omh, msgb_l2len(msg) - sizeof(*omh));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg->l3h = omh->data;
 | 
				
			||||||
 | 
						if (check_fom(omh, msgb_l3len(msg)) != 0)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						return OML_MSG_TYPE_ETSI;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user